Re: code timing (was ADC sampling)

Started by npoz0 March 12, 2006
Hey Tom,

Thank you for your help and suggestions.  I took out the ascii
conversion.  and I'm currently using this code to write to my sdcard:

Do Until (GetPin(8) = 0)

	ADCdata(0) = GetADC(14)	
	ADCData(1) = GetADC(15)
	Call PutQueue(OutputQueue, ADCdata(0),2)
	Call PutQueueStr(OutputQueue, ",")

	Call PutQueue(OutputQueue, ADCdata(1),2)

	Call PutQueueStr(OutputQueue, Chr(13) & Chr(10) )

	Although when I check the text files, there is garbage there, no
binary 0's and 1's like I was expecting.  Is there more to do?  And
converting it back can I just use my converter functions I was using
before but this time on the .txt file /w the binary results?

Also, I would like to implement the usage of counting of ticks, but I
was wondering how many ticks are in a second?  On your interrupt
suggestion, I would set an interrupt to fire once the amount of ticks
to 30Hz or whatever my sample rate occurs?  I know how to set
interrupts on an hc11, but not on the basicx.  Could you provide a
little help if you get a chance?  

Thank you very much,

	--- In basicx@basi..., Tom Becker <gtbecker@...> wrote:
>  > ... 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
> 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
> 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
  > ... when I check the text files, there is garbage there...

The 10-bit data from each ADC read is still in binary (as a 16-bit 
integer) when you write to and, later of course, read from the file. 
Those binary values can be operated upon or converted for display, as 
you wish, with another program run on another machine, perhaps a 
notebook or PDA that you insert your SD card into.

In the interest of speed, I suggest that the Basic-X burden be to 
collect and store data - and another machine be assigned the task of 
analysis and presentation.  The comma between samples, and even the CR 
and LF, are not necessary.  The analysis program just needs to take 
pairs of bytes and form them into integers to process or display.  You 
might need an identifier (X or Y, or channel number) byte preceding each 

> ... how many ticks are in a second?

512, early in the documentation.

 > ... I would set an interrupt to fire once the amount of ticks to 30Hz 
or whatever my sample rate occurs?

Close.  I suggested two methods earlier in this thread.  Also go back a few 
days to a thread about generating 20Hz.

I believe that the BX-24 will have sufficient speed to easily take 50 
pairs of ADC samples per second, provided that the file system you've 
chosen is fast enough.  200 bytes per second doesn't sound challenging. 
  If that's so, you can simply spin until the next event time, take and 
store a pair of samples and wait for the next event time - and you 
_will_ take 50 samples per second, by design.  You won't need to use a 
more complex hardware interrupt, I suspect.

Earlier, you said that you needed to prove you've taken samples at 50Hz. 
  If you tag your sample pairs with a timestamp, the data is 
self-documented and the sampling periods can be analyzed, should you 
need it.  That will, in this case, double your data rate and capacity 
requirement but you could truncate the timestamp to two bytes or even a 
byte to save some space.

If you just need to know that the sample rate is 50Hz, though, you can 
make it so.

Thank you Tom for all your help,

I'm getting there :)  Ok, I added the spinning counting ticks,
actually made it 16 ticks or 32 Hz before sampling.  But, I found out
but outputting the time at the beginning and end of the sample loop
that I can keep my ascii conversion in and still have 25.6 Hz sampling
within spinning at all.  I think this will be affected by the ADC
sample as it can be 0-1024, and I've had the adc pins connected to
ground so far.  But, I'm not sure how much time the Call
GetTimestamp() uses up, and actually this sampling rate is sufficient.
 But I have another problem now.  I have chosen to use the uMMC
TTL-SDCard board as my logging instrument and I can only write in 512
byte segments.  This is fine, except when I send another command to
write another 512 bytes my sample rate drops to 14Hz just for that one
sample.  I'm not sure how this will affect my output if much at all,
hopefully not.  I was thinking of then buffering the adc samples into
eeprom on the basicx and then write to the sdcard as sampling occurs,
but I'm not sure if the eeprom read/write time is fast enough.  I was
thinking you might have some suggestions?  Here's my code thus far:
	Do Until (GetPin(8) = 0)

Call GetTimestamp(Year,Month,Day,Hour,Minute,Second)
	Debug.Print Cstr(Second)

'	LongTimeInTicks = 0
'	register.RTCTick = 0 'set to midnight

'	Do Until ( LongTimeInTicks = 16 )
'		LongTimeInTicks = register.RTCTick  'get current time in ticks
		ADCdata(0) = GetADC(14)	
	ADCData(1) = GetADC(15)
 	Call IntToString(ADCdata(0), 10)
	Call PutQueueStr(OutputQueue, ",")

	Call IntToString(ADCdata(1), 10)

Call GetTimestamp(Year,Month,Day,Hour,Minute,Second)
Debug.Print "."
Debug.Print Cstr(Second)
'Debug.Print Cstr(M)


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

                J = J + 1
                X(J) = HexConv(CByte(Abs(V Mod Base)))
                V = V \ Base
                If V = 0 Then
                        Exit Do
                End If
	        For J = J To 1 Step -1
                Call PutQueue(OutputQueue, X(J), 1)

        End Sub

'Part of the IntToString sub
Function HexConv(ByVal B As Byte) As Byte

        If B > 9 Then
                HexConv = B + 55
                HexConv = B + &H30
        End If

End Function
	--- In basicx@basi..., Tom Becker <gtbecker@...> wrote:
> Call GetTimestamp(Year,Month,Day,Hour,Minute,Second)
Function GetTimestamp is expensive and would not be my first choice of a 
time source; I would use register.RTCTick, as you see I did in that 20Hz 
example code.  E.g.:
  lNow = register.RTCTick

The fractional-seconds tick count would be (register.RTCTick mod 512). 
At 50Hz (your original target rate), you should see a tick count 
difference of about 10 between samples.

>  	Call IntToString(ADCdata(0), 10)
You took a long road here, I think.  How does IntToString(32767, 10) 
differ from PutQueueStr(Qx, cStr(32767)) ?

Of greater concern is the 512-byte SD card write.  You don't have 512 
bytes of space to work with in a BX-24.  This is a problem.  Atmel's 
DataFlash, which is available is SD form, might help since it has a 
built-in work area that allows buffering and unbuffering on the chip or 
card, allowing single-byte reads and writes.  The AT45DCB008, for 
instance, has two 1056-byte buffers in the card in addition to 8Mb for 

I just looked through the SDCard document and see that it permits
writes _up to_ 512 bytes; size is not a problem, then.

It talks serially, though, so comm speed and write overhead time might
remain a problem.  Anecdotally, Google shows someone boasts of
achieving 7.5kBps write speed with this device; that's using 512 byte
writes, I'd guess.  That'd be ~14 writes/second, maybe a concern.