Constant ADC scan rate

MFB

Senior Member
If you need to monitor a number of analog inputs and transmit the ASCII data over a serial link, the following 18X code is unable to maintain a constant scan rate. As the loop time will be dependant on the analog input levels, due to higher ADC input voltages generating more ASCII characters per sample. When running the example code at 8MHz, reading three zero inputs results in a scan rate of 70Hz but this drops to only 40Hz when reading three full-scale voltage inputs.

setfreq m8

start:
readadc10 0,w0
readadc10 1,w1
readadc10 2,w2
sertxd (#w0,",",#w1,",",#w2,cr)
goto start


This potential problem can be overcome by triggering each scan from an external clock pulse, via a digital input. However, if you don’t want to add another chip (e.g. 555) I have developed an alternative three 'passive' component solution. A resistor is connected between a PICAXE output and one of its (Schmitt) inputs, with a capacitor between the input and ground. A diode is placed in parallel with the resistor with the anode towards the capacitor.

The following code is revised to discharge the capacitor (via the diode) at the start of each scan. The capacitor then starts to charge, through the resistor, whilst data is being transmitted. At the end of transmission the PICAXE monitors the input and triggers the next scan when the voltage across the capacitor exceeds the 'logic 1' threshold. As an example, a 100K resistor and 0.33uF capacitor will result in a scan rate of about 30Hz, which provide an adequate margin for the worst-case condition (e.g. all analog inputs at full scale).


setfreq m8
high 7

start:
pulsout 7, 200
readadc10 0,w0
readadc10 1,w1
readadc10 2,w2
sertxd (#w0,",",#w1,",",#w2,cr)

tick:
if pin6 = 0 then : goto tick : else : goto start: endif


Tests show that this approach offers timing stability that is at least as good as the 18X internal clock (using a polypropolene capacitor, thin film resistor and BAT 85 diode). To better this you would need to use a 28X1 and crystal, with each scan triggered from the internal timer.
 

womai

Senior Member
A much easier solution is to avoid sending different length messages for different readadc values. You can do this by sending the data in binary format instead of ASCII format - in this case it is always 2 bytes per word variable. The only downside is that you can't simply use a terminal program to monitor it, but need to write your own little receive routine (e.g. in Visual Basic).

Here is the modified code:

Code:
setfreq m8

start:
readadc10 0,w0
readadc10 1,w1
readadc10 2,w2
sertxd (w0,",",w1,",",w2)
goto start
Wolfgang

PS: in your original (ASCII-format) code, if you want to avoid issues with some editors and terminal programs, you should add a line-feed character (lf) in addition to the carriage return (cr).
 

hippy

Technical Support
Staff member
Alternatively, convert the values to send into five separate digits using BIN2ASCII and send those. That will be a consistent number of characters sent every time and the receiver can strip off the leading zeroes.
 

MFB

Senior Member
StampPlot comapatible serial data

Thanks for the comments. Maybe I should have explained that the output had to be directly compatible with StampPlot Pro. This logging and real-time plotting application, for serial input data, does have a binary option but it is limited to one byte per sample.

A free evaluation copy of StampPlot Pro, together with very extensive documentation, may be downloaded from www.selmaware.com.
 

womai

Senior Member
In this case I'd assume Hippy's solution would still work, as all it does is adding leading zeroes - normally programs don't have an issue with that.

Wolfgang
 

hippy

Technical Support
Staff member
The only case I know of leading zeroes having any adverse effect on the intent is the C programming language where what follows is to be treated as octal - that catches many a person out who have nicely formatted decimal tables with leading zeroes for alignment.

It follows that any C library routine reading numeric strings might interpret a leading zero as indicating octal but I would have expected any programmer dealing with the real world ( where octal is largely unused and meaningless - file attributes under unix and linux are legitimate places for octal ) would have used library code or replaced them with their own to support leading zeroes for decimals.
 

MFB

Senior Member
Thanks, it works

Hippy & Womai,
You are correct! I tried the following code and StampPlot Pro strips the leading zeros without any problem.

setfreq m8

start:
readadc 1, b0
bintoascii b0,b1,b2,b4
sertxd (b1,b2,b4,cr)
pause 2000
goto start

This is of course a much better solution than my RC background timer, as it saves on three components and two I/O pins (I'll keep this approach for other PICAXE applications that may need an additional background timer).

Now, please could you tell me how to add leading zeros to a readadc10 reading?
 

womai

Senior Member
The Picaxe Basic user guide is your friend :)

Practically the same as with a byte variable, except that you need two more digits (and don't forget w0 is overlaid on b0 and b1):

Code:
setfreq m8

start:
readadc10 1, w0
bintoascii w0,b2,b3,b4,b5,b6
sertxd (b2,b3,b4,b5,b6,cr)
pause 2000
goto start
On an 28X1, another good approach is to set up a timer interrupt that calls your interrupt routine at regular intervals. In this case the code does not need to have constant execution time and you can even perform other tasks inbetween. See this recent thread:

http://www.picaxeforum.co.uk/showthread.php?t=8541

Wolfgang
 

MFB

Senior Member
Womia,

Many thanks. However, I don't think there are enough variables (in the 18X) to build a StampPlot compatible (CSV) output string for more than two 10-bit ADC channels.
 

hippy

Technical Support
Staff member
You can get your raw data, store it in SFR (POKE), then when you come to output, take one item of data at a time (PEEK), expand it to digits, send that, send a comma and repeat, only put a CR after the last.
 

MFB

Senior Member
I am greatful for the very informative feedback, but I now think that the original simple code and RC timer apparoach still has merit. For example, it can also be used to output five 10-bit ADC channels from a 14M in StampPlot format at a constant scan rate (the RC circuit can operate with a standard, non-Schmitt, 14M digital input).
 
Top