Discussion forum for the BasicX family of microcontroller chips.
ADC sampling 4 channels at 50 Hz problem - npoz0 - Jan 2 21:34:00 2006
Hello, I am using the Bx-24 for a datalogging application. I
modified the data logging software I found from basicx's site, and I'm
having problems sampling fast enough. I was wondering if anyone knew
a faster way to sample to increase my sampling time? I took my
sampling concept and applied it to a simple program to output
everytime it sampled. I tested it accurately down to 20 Hz.... My
sampling code snippet is as follows:
Public Sub Main()
Dim StopWatch As Single
Const Sample_Rate As Single = 0.02
Call Puttime(0,0,0.0000000000)
Do
StopWatch = Timer
If StopWatch >= Sample_Rate Then
Debug.Print "0.02"
Call PutTime(0, 0, 0.0)
End if
Loop
End Sub
Thank anyone for any help.
John
P.S. later I will be logging to a SDcard instead of the external
eeprom, and the write speed should be faster enough to not hinder the
sampling...but who knows...

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: ADC sampling 4 channels at 50 Hz problem - Tom Becker - Jan 2 22:32:00 2006
> Debug.Print "0.02"
Debug.Print is a diagnostic tool that is heavy and slow; it's really a
cheat to get some easy output. You will probably improve your
performance significantly by writing to an output queue on COM1 at 115200.
Tom

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: ADC sampling 4 channels at 50 Hz problem - Mike Perks - Jan 2 23:05:00 2006
npoz0 wrote:
> Hello, I am using the Bx-24 for a datalogging application. I
> modified the data logging software I found from basicx's site, and I'm
> having problems sampling fast enough. I was wondering if anyone knew
> a faster way to sample to increase my sampling time? I took my
> sampling concept and applied it to a simple program to output
> everytime it sampled. I tested it accurately down to 20 Hz....
Every 0.02 seconds is 50Hz not 20Hz.
> My sampling code snippet is as follows:
>
> <snip>
I have cleaned up your code and made it work correctly. See the "busy"
loop below which gets up to a count of 172 on a BX24/35. The BX-24p is
about 25% faster so you will be able to do more work.
Public Sub Main()
Dim StopWatch As Single
Dim i as Integer
Const Sample_Rate As Single = 0.02
Call Puttime(0,0,0.0000000000)
StopWatch = Timer()
Do
' do work here
For i=1 to 172 ' count of 173 exceeds Sample_Rate
Next
If Timer()-StopWatch > Sample_Rate Then
Debug.Print "0.02"
'Call PutTime(0, 0, 0.0) not necessary
End if
StopWatch = Timer()
Loop
End Sub
Mike
http://home.austin.rr.com/perks/micros/

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: ADC sampling 4 channels at 50 Hz problem - npoz0 - Jan 3 19:01:00 2006
--- In basicx@basi..., Tom Becker <gtbecker@r...> wrote:
> > Debug.Print "0.02"
>
> Debug.Print is a diagnostic tool that is heavy and slow; it's really a
> cheat to get some easy output. You will probably improve your
> performance significantly by writing to an output queue on COM1 at
115200.
> Tom
Cool, thanks Tom will do. I think that code from the basicx site
uploads via com1 to something like hyperterminal. Do you know
anywhere I can get the speed it takes for various instruction
executions for the bx-24p?
ty,
john

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: ADC sampling 4 channels at 50 Hz problem - npoz0 - Jan 3 19:08:00 2006
Hey thank you for your help Mike.
One question though, the counter to 172, that is equivalent to 0.02
seconds? Where did you find out the info how long the loop increments
take? So if I wanted to change my sample rate to say 60Hz or 0.0167
seconds I could change the counter number to the equivalent value?
Thank you,
john
--- In basicx@basi..., Mike Perks <basicx@a...> wrote:
>
> npoz0 wrote:
>
> > Hello, I am using the Bx-24 for a datalogging application. I
> > modified the data logging software I found from basicx's site, and I'm
> > having problems sampling fast enough. I was wondering if anyone knew
> > a faster way to sample to increase my sampling time? I took my
> > sampling concept and applied it to a simple program to output
> > everytime it sampled. I tested it accurately down to 20 Hz....
>
> Every 0.02 seconds is 50Hz not 20Hz.
>
> > My sampling code snippet is as follows:
> >
> > <snip>
>
> I have cleaned up your code and made it work correctly. See the "busy"
> loop below which gets up to a count of 172 on a BX24/35. The BX-24p is
> about 25% faster so you will be able to do more work.
>
> Public Sub Main()
>
> Dim StopWatch As Single
> Dim i as Integer
> Const Sample_Rate As Single = 0.02
>
> Call Puttime(0,0,0.0000000000)
> StopWatch = Timer()
> Do
> ' do work here
> For i=1 to 172 ' count of 173 exceeds Sample_Rate
> Next
> If Timer()-StopWatch > Sample_Rate Then
> Debug.Print "0.02"
> 'Call PutTime(0, 0, 0.0) not necessary
> End if
> StopWatch = Timer()
> Loop
> End Sub
>
> Mike
> http://home.austin.rr.com/perks/micros/

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: Re: ADC sampling 4 channels at 50 Hz problem - Mike Perks - Jan 3 19:42:00 2006
npoz0 wrote:
> One question though, the counter to 172, that is equivalent to 0.02
> seconds? Where did you find out the info how long the loop increments
> take? So if I wanted to change my sample rate to say 60Hz or 0.0167
> seconds I could change the counter number to the equivalent value?
I came up with 172 from trial and error. For 60Hz the counter should be
around 143. The 6 BasicX instructions in the loop are:
pushI test.main.i ' push i on stack
pushI test.main.tmp~0001 ' push precalculated loop max value (173)
gtI ' compare
jmpTrue test.main+65 ' end loop
incI test.main.i ' increment i
jmp test.main+49 ' loop back
This gives an instruction rate of approximately 172*50*6 = 51,600 per
second which is not too shabby. Performance on the BX24p or ZX series is
even better.
Obviously you would replace this loop by the real work you to do to
capture the data and save it. Writing to EEPROM is notoriously slow so
some people have used FRAMs.
Mike
http://home.austin.rr.com/perks/micros/
http://home.austin.rr.com/perks/micros/bxDism/

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: ADC sampling 4 channels at 50 Hz problem - Tom Becker - Jan 3 20:39:00 2006
> ... via com1 to something like Hyperterminal.
You can use the BasicX IDE monitor, too; just open the port at 115200.
> ... the speed it takes for various instruction executions for the
bx-24p?
If you mean an instruction timing chart, it been been long discussed
and never generated. Since BasicX multitasks, absolute timing could
only apply to a single task, too, but a chart could still be useful.
You can time most any code you like, though, yourself, on the object
machine. Most approaches note the current machine time, runs some
number of iterations of the code-to-be-timed, then displays the
average time per iteration.
Tom

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: code timing (was ADC sampling) - Don Kinzer - Jan 3 23:09:00 2006
--- In basicx@basi..., "Tom Becker" <gtbecker@r...> wrote:
> ... If you mean an instruction timing chart, it been been long
> discussed and never generated.
Such a timing chart would be difficult to produce in any useful form.
The problem is that the number and type of p-code instructions that
are generated from a single source code line depends on the complexity
of the source code line and the (few) optimizations that the BasicX
compiler performs. For any but the simplest instructions (e.g. a = 1)
it would be nigh well impossible. With compilers that have more
sophisticated optimizers, it would be even more problematic.
Your best bet is, as Tom mentioned, to time your actual code if it is
important.
Don

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: code timing (was ADC sampling) - npoz0 - Jan 4 3:01:00 2006
Thank you Don,
I was just thinking that I need to somehow prove that the bx-24 is
indeed sampling at 50Hz instead of 51Hz or 54Hz. I'm sampling an
accelerometer and would like to get as accurate a representation of
the waveforms produced during action as possible as the accelerometer
will be attached to a person and I'm looking at a 5Hz signal, so 50Hz
should do the trick. If you have any suggestions or advice please
feel free to share :)
John
--- In basicx@basi..., "Don Kinzer" <dkinzer@e...> wrote:
>
> --- In basicx@basi..., "Tom Becker" <gtbecker@r...> wrote:
> > ... If you mean an instruction timing chart, it been been long
> > discussed and never generated.
>
> Such a timing chart would be difficult to produce in any useful form.
> The problem is that the number and type of p-code instructions that
> are generated from a single source code line depends on the complexity
> of the source code line and the (few) optimizations that the BasicX
> compiler performs. For any but the simplest instructions (e.g. a = 1)
> it would be nigh well impossible. With compilers that have more
> sophisticated optimizers, it would be even more problematic.
>
> Your best bet is, as Tom mentioned, to time your actual code if it is
> important.
>
> Don

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: code timing (was ADC sampling) - Tom Becker - Jan 9 21:16:00 2006
> ... I need to somehow prove that the BX-24 is indeed sampling at 50Hz...
On rereading your message, John, I have the thought that you will
tailor your code loop so that it consumes as close to (1/50) second as
possible. That's poor practice, I suggest.
Instead, if you need to sample at 50Hz, you should trigger your
sampling process at 50Hz. I can propose two methods:
- spin in Main() until the RTC tick has advanced 20mS, or
- tie pin 25, 26 or 27 to pin 11, run Timer2 or Timer1 to generate
50Hz or a multiple, and use WaitForInterrupt() to restrain your sample
loop.
Either method - and others - can make the sample rate deterministic,
if not proven. If that is still insufficient, you will need a
calibrated external instrument to verify the sample rate. You can
toggle a pin in your sample loop that the instrument can count.
Tom

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: code timing (was ADC sampling) - npoz0 - Jan 23 11:43:00 2006
Tom,
thank you for your suggestion, albeit I thought that was what I was
sort of doing right now, as I look until my sample rate of 0.2s is
hit, then initiate sampling. Although things are a little more
complicated now because I have interfaced the bx24 with a uMMC
serial-sdcard interface from roguerobotics. I am just transmitting to
the sdcard interface via strings, and right now as it runs I get about
10Hz sampling rate, I think due to the large bogginess of my code.
What I have is listed below. Any suggestions would be greatly
appreciated. The sampling rate just needs to be around 50Hz, and I
have been checking my sampling rate but putting in a small 100 mhz
sinewave into the ADCs and sampling at different rates and plot them.
I then compare the plots under a light board to see if there are more
samples being taken.... Sort of archaic but it seems to work alright.
Here is what I have as code: I currently set the total sampling to be
2000 samples, but will change that later on as needed. Also a loop
will be added to check to see if some I/O pin has been pushed to stop
the recording.
'Modified datalogger.bxp from basicx.com
'Last edit January 21st,2006
Attribute VB_Name = "Module1"
Private InputQueue(1 to 30) As Byte
Private OutputQueue(1 To 40) As Byte
Dim ADCdata(0 To 1) As Integer
Dim Sample_Rate As Single
Dim StopWatch As Single
Dim ADCPin As Byte
Dim M as Integer
'Dim EEPROM_Start_Address As Long
'Const EEPROM_End_Address As Long = 32767
'Const UpLoad_Switch_Pin As Byte = 12
'*********************************************************************
Sub Main()
Dim stizzle As Integer
'Set count M to 0 initially
M = 0
stizzle = 0
'Transmit pin on DAQ is 5, recieve pin on DAQ is 6, non-inverted
logic, 8 bits, no parity, 1 stop bit, no echo
'p33 of bx24p library functions doc
'http://www.roguerobotics.com/products/electronics/ummc states
non-inverted simple serial, = TTL?
Call OpenQueue(InputQueue, 30)
Call OpenQueue(OutputQueue, 40)
Call DefineCom3(5, 6, bx0000_1000)
Call OpenCom(3, 9600, InputQueue, OutputQueue)
'Open up datafile for logging
'ADD CHECK FOR CARD NOT INSERTED OR ERRORCHECKING, ETC?
Delay 0.5
Call PutQueueStr(OutputQueue, Chr(13) & Chr(10))
Debug.Print "Initialize SDcard"
'Set baud rate to 9600, 200mS time limit for time out
Call PutQueueStr(OutputQueue, "s o 20" & Chr(13) & Chr(10))
Debug.Print "erase previously existing file"
Call PutQueueStr(OutputQueue, "e /LOG.TXT" & Chr(13) & Chr(10))
Debug.Print "Make new in write mode"
Call PutQueueStr(OutputQueue, "o 1 w /LOG.TXT" & Chr(13) & Chr(10))
Debug.Print "write mode"
'Set card to write mode, 512bytes default
Call PutQueueStr(OutputQueue, "w 1" & Chr(13) & Chr(10) )
'Wait for the chip to stabilize after power-up
Call Sleep(5)
Do
'Set the clock to midnight
Call PutTime(0, 0, 0.0)
'Sets the data sample rate in seconds
Sample_Rate = 0.2
Do
'Get the seconds past midnight
StopWatch = Timer
'If stopwatch is greater or equal to "Sample_Rate" read each ADC
channel and store the data
If StopWatch >= Sample_Rate Then
stizzle = stizzle + 1
'Set the clock to midnight
Call PutTime(0, 0, 0.0)
'Read the ADC pins
ADCdata(0) = GetADC(14)
ADCData(1) = GetADC(15)
Call IntToString(ADCdata(0), 10)
Call PutQueueStr(OutputQueue, ",")
Call IntToString(ADCdata(1), 10)
Call PutQueueStr(OutputQueue, Chr(13) & Chr(10) )
end if
'Just take 2000 points for now and stop.
if stizzle > 2000 then
Call PutQueueStr(OutputQueue, "c 1" & Chr(13) & Chr(10) )
Debug.print "Done"
Do
Sleep(256)
Loop
end if
Loop
Loop
End Sub
'*********************************************************************
'This Sub coverts the integers into printable ASCII strings before
sticking
'them in the outgoing serial queue (Com1_Out_Buffer) for uploading
Sub IntToString(ByVal I As Integer, ByVal Base As Integer)
Dim X(1 To 16) As Byte
Dim V As Integer
Dim J As Integer
J = 0
V = I
Do
J = J + 1
X(J) = HexConv(CByte(Abs(V Mod Base)))
V = V \ Base
If V = 0 Then
Exit Do
End If
Loop
For J = J To 1 Step -1
M = M + 1
if M > 512 then
Debug.print "Reset write mode"
Call PutQueueStr(OutputQueue, "w 1 " & Chr(13) & Chr(10) )
M = 0
else
Call PutQueue(OutputQueue, X(J), 1)
end if
Next
End Sub
'Part of the IntToString sub
Function HexConv(ByVal B As Byte) As Byte
If B > 9 Then
HexConv = B + 55
Else
HexConv = B + &H30
End If
End Function
--- In basicx@basi..., "Tom Becker" <gtbecker@r...> wrote:
>
> > ... I need to somehow prove that the BX-24 is indeed sampling at
50Hz...
>
> On rereading your message, John, I have the thought that you will
> tailor your code loop so that it consumes as close to (1/50) second as
> possible. That's poor practice, I suggest.
>
> Instead, if you need to sample at 50Hz, you should trigger your
> sampling process at 50Hz. I can propose two methods:
> - spin in Main() until the RTC tick has advanced 20mS, or
> - tie pin 25, 26 or 27 to pin 11, run Timer2 or Timer1 to generate
> 50Hz or a multiple, and use WaitForInterrupt() to restrain your sample
> loop.
>
> Either method - and others - can make the sample rate deterministic,
> if not proven. If that is still insufficient, you will need a
> calibrated external instrument to verify the sample rate. You can
> toggle a pin in your sample loop that the instrument can count.
> Tom

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )
Re: Re: code timing (was ADC sampling) - Tom Becker - Jan 23 14:15:00 2006
> ... I get about 10Hz sampling rate...
It will be increasingly difficult to produce ASCII output at higher
rates, John. I'd be thinking about dumping real time data in binary and
making it readable later, if you really need to. Machines don't think
in ASCII so, if the data is going to another machine that can accept it
in binary, your conversion process consumes much wasted time making and
manipulating strings.
You can also avoid relatively-slow singles (Timer and PutTime(), for
instance) and should for time functions that need resolution. Because a
single is floating point, as the value increases - the available
resolution decreases; times after about 09:00:00 lose a fraction bit,
for example, so the resolution drops to 1/256 second after that, and it
gets worse at about 18:00:00. You will avoid that by continually
resetting the clock to 00:00:00.0, as you do, but you can also work with
time directly in ticks. Consider:
register.RTCTick = 0 'set to midnight
lLongTimeInTicks = register.RTCTick 'get current time in ticks
These are much faster than PutTime() and Timer and do not suffer the
resolution loss of later times.
Still, I think you'll see better results by triggering your sampling
with a hardware-generated interrupt.
Tom

(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )