SLOW readADC required please

The bear

Senior Member
Hi Everyone,
I would appreciate a pointer, in order to get a reading from an ADC input,
not instantly, but over a period of seconds (Say 30secs).
I've tried a 100k resistor & 10uF capacitor from ADC input to 0 volts.
That is series resistor.
Code is what I would prefer.

___/\/\/\____>ADC
l
= Long way to go with this!
l
_ 0v
 

hippy

Technical Support
Staff member
It might help if you could explain what you are measuring or what the application is. You could possibly do it without external hardware using a rolling average of some kind in software, a rather simplistic example below ...

Code:
Do
  ReadAdc ADC_PIN, w0
  time = 0
  Do
    ReadAdc ADC_PIN, w1
    w0 = w0 + w1 / 2
  Loop Until time >= 30
  SerTxd( #w0, CR, LF )
Loop
 

The bear

Senior Member
Thank you hippy.
Its not an actual project, but would be incorporated within some of my projects, such as Three LDR controlled blinds and LDR controlled indoor lights.
Your 'simplistic example' will be seriously studied and simulated. Long live the Picaxe!

Regards, Bear..
 

premelec

Senior Member
@TBear - note that when you use a resistor capacitor filter the Time Constant is useful to calculate possible delay - R x C = TC which is about the time to reach 2/3 of final value as the capacitor charges up [ohms and farads units TC in seconds...]
 

inglewoodpete

Senior Member
I have made a couple of pubic artworks with LED lighting that use an LDR or solar cell to detect sunset and sunrise. I use the PICAXE's timer to initiate a ReadADC10 of the LDR or solar cell every 5 seconds. The value is added to an accumulator. After 12 reads (1 minute), the accumulator is compared to a reference value to determine if the sun has set or risen. At that point, the accumulator is cleared in preparation for the next minute. The system is very reliable.

You could use a similar system spanning over 30 seconds.
 

The bear

Senior Member
@premelec,
Thank you for your suggestion, I was looking for an alterative, rather than using a time constant with resistor & capacitors. Had to use these in the past, pre Picaxe.

@ IWP,
Your suggestion sounds great, unfortunately, I'm sure I would have trouble getting my brain around it. A few lines of code would be nice, I could always frame it.

hippys input looks good, I'm going to test it out on a real Picaxe.

My mode of operation is, look in Snippets & past examples/problems on the forum, then modify the code to suit my projects.

Regards, Bear..
 

inglewoodpete

Senior Member
@ IWP,
Your suggestion sounds great, unfortunately, I'm sure I would have trouble getting my brain around it. A few lines of code would be nice, I could always frame it.
Try this. I've snipped this from a working program.
Code:
[color=Navy]#PICAXE [/color][color=Black]08M2[/color]
[color=Navy]#Terminal 4800[/color]
[color=Green]'[/color]
[color=Blue]Symbol iLightInput   [/color][color=DarkCyan]= [/color][color=Blue]C.2    [/color][color=Green]' 5 ADC2 Light Level (LDR)
'[/color]
[color=Blue]Symbol [/color][color=Purple]bReadTimer    [/color][color=DarkCyan]= [/color][color=Purple]b13    [/color][color=Green]'w6   Perm 5-second timer for determining when Light Level is to be checked[/color]
[color=Blue]Symbol [/color][color=Purple]bLightLevel   [/color][color=DarkCyan]= [/color][color=Purple]b14    [/color][color=Green]'w7   Value reading from LDR[/color]
[color=Blue]Symbol [/color][color=Purple]wLightAccum   [/color][color=DarkCyan]= [/color][color=Purple]w10    [/color][color=Green]'b20/21 Perm Accumulator for one-minute's worth of light readings
'
'[/color]
[color=Black]Init: [/color][color=Blue]Enabletime              [/color][color=Green]'Set the internal 1-second timer ticking
      [/color][color=Purple]bReadTimer [/color][color=DarkCyan]= [/color][color=Navy]12         [/color][color=Green]'Initialise: 12 x 5-second periods per minute
      '[/color]
[color=Black]Main: [/color][color=Blue]Do
         Gosub [/color][color=Black]ManageTimer
         [/color][color=Green]'your other code
      [/color][color=Blue]Loop[/color]
[color=Green]'
' **** Subroutines ** ** ** ** ** ** ** ** ** **
'[/color]
[color=Black]ManageTimer:[/color][color=Blue]If [/color][color=Purple]Time [/color][color=DarkCyan]>= [/color][color=Navy]5 [/color][color=Blue]Then                   [/color][color=Green]'Primary period has expired (5 seconds)
               [/color][color=Purple]Time [/color][color=DarkCyan]= [/color][color=Navy]0                         [/color][color=Green]'Reset for next 5-second period
               [/color][color=Blue]ReadADC iLightInput[/color][color=Black], [/color][color=Purple]bLightLevel [/color][color=Green]'Get current light level (every 5 seconds)
               [/color][color=Purple]wLightAccum [/color][color=DarkCyan]= [/color][color=Purple]wLightAccum [/color][color=DarkCyan]+ [/color][color=Purple]bLightLevel [/color][color=Green]'Accumulate 12 values over a minute
               [/color][color=Blue]Dec [/color][color=Purple]bReadTimer
               [/color][color=Blue]If [/color][color=Purple]bReadTimer [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]Then           [/color][color=Green]'Secondary period has expired (1 minute)
                  '
                  [/color][color=Blue]SerTxd ([/color][color=Red]"Light value is: "[/color][color=Black], #[/color][color=Purple]wLightAccum)
                  bReadTimer [/color][color=DarkCyan]= [/color][color=Navy]12               [/color][color=Green]'Reset for next minute
                  [/color][color=Blue]If [/color][color=Purple]wLightAccum [/color][color=DarkCyan]> [/color][color=Navy]1234 [/color][color=Blue]Then
                     Low B.1                    [/color][color=Green]'Turn something off
                  [/color][color=Blue]ElseIf [/color][color=Purple]wLightAccum [/color][color=DarkCyan]< [/color][color=Navy]1000 [/color][color=Blue]Then[/color][color=Green]'Include some hysteresis
                     [/color][color=Blue]High B.1                   [/color][color=Green]'Turn something on
                  [/color][color=Blue]EndIf
                  [/color][color=Purple]wLightAccum [/color][color=DarkCyan]= [/color][color=Navy]0               [/color][color=Green]'Clear accumulator for the next minute
               [/color][color=Blue]EndIf
            EndIf
            Return[/color]
If using an LDR, you'll need to arrange it with a resistor to form a voltage divider. Refer to manual 3: Input Device 3 - Light Dependant Resistor.
 
Last edited:

AllyCat

Senior Member
Hi,

If you only need one "average" (filtered) value every 30 seconds, then you could just take one measurement every 3 seconds, accumulate and divide by 10:

Code:
symbol pin = c.1
do
	w2 = 0    			; accumulator
	for b1 = 0 to 9
		readadc pin,w1
		w2 = w2 + w1
		pause 3000
	next
	w2 = w2 / 10
	sertxd(cr,lf,#w2)
loop
However, a "rolling average" may fit better into a "continuous" process, but note that the more recent values have a greater significance in the overall average. Typically one might add 20% of the "latest" value to 80% of the rolling average:

Code:
readadc pin,w2    	  ; prime the rolling average
do
	pause 3000
	readadc pin,w1
	w2 = w2 * 4 + w1 / 5
	sertxd(cr,lf,#w2)
loop
With either method yoiu need to be a little careful about overflows and/or loss of resolution; you will probably need to use Word variables.

Cheers, Alan.
 

The bear

Senior Member
@IWP, Thank you for your code snippet, I will do my best to understand it.

@Alleycat, Thanks for your code too, I will work on it. The 30 secs was just for instance.

Rest assured, these snippets will be printed & studied.

Regards, Bear..
 
Top