I brought my UNO to work yesterday and played with this code a bit. (Yes, I just can't leave well enough alone...) I made a few discoveries.
At first I was noticing that the averages were coming out higher than the maximum. Seems that unsigned int
wasn't large enough for counting all the analogRead()
s so I upped it to unsigned long
. Now, even with a 60 second update interval the averages appear to be good.
Then I was noticing an odd behavior with map()
. Consider the line of code:
bargraphDisplay = map(finalAverage, sensorHigh, sensorLow, 0, bargraphCount);
All the variables are unsigned. (bargraphDisplay
and bargraphCount
are byte
and the other three are all unsigned int
.) Replacing the constant variables with values that line becomes:
bargraphDisplay = map(finalAverage, 1024, 0, 0, 5);
Oh, hey... looks like I have the sensorHigh and sensorLow backwards... Lets fix that...
bargraphDisplay = map(finalAverage, 0, 1024, 0, 5);
Now the interesting part is that the only time the map()
function would give me a 5 is if finalAverage
== 1024. I would have expected that given a range of 6 values (0 through 5) map()
would create 6 equal sized 'bins' of the input range. I haven't done any math or testing to see where the changes occur other than replacing finalAverage
with 1023 and 1024. The only time when the output of map()
was 5 is when finalAverage
== 1024. So to kludge this I forced an offset on the input range. I'm not sure how well this will hold up to expanding the output range to more LEDs, but basically I took the input range (sensorHigh
- sensorLow
) divided by the number of output values (bargraphCount
+ 1), and subtracted the quotient from sensorHigh
to use as the high of the input range of map()
. So now the (working?) map()
statement reads:
bargraphDisplay = map(finalAverage, sensorLow, sensorHigh - ((sensorHigh - sensorLow) / (bargraphCount + 1)), 0, bargraphCount);
While figuring this out I noted an odd thing with my UNO. During many of my tests I had A0 jumpered to the +5VDC output and the average ADC counts were 1022. Must be an odd ADC and/or noise issue on my board as summing many 1024 instead of the analogRead()
s results in an average of 1024.
I wanted to add a couple more diagnostic lines (especially since there is no code to drive a LED barcode display yet...) and decided that updateDisplay()
was getting too cluttered with diagnostics lines. So I moved all the diagnostic lines to a new function, updateDiagnostics()
.
At this stage I allowed the sketch to run overnight at work with displayInterval
set to 30000 (30 seconds). This morning when I returned to work I didn't see any indication of overflows or crashes. Yay!
One thing that bugged me was the way I was calculating the timer. It seemed to spam the serial port once for each iteration of loop()
until the length of time of the interval. Going back to sources I looked at the if statement in BlinkWithoutDelay.ino and noticed that it was subtracting the last captured time from the current time and comparing that with the interval. Whereas, I was subtracting the interval from the current time and comparing it to the last captured time. I changed the method to the BlinkWithoutDelay.ino style and it now seems to work. I think the issue was until the current time was greater than the interval, my original subtraction was rolling around and returning an exceedingly large number. But the method from BlinkWithoutDelay.ino, the last captured time will never be larger than the current time, so the subtraction will never try to be negative (which results in a very large number with unsigned datatypes...) While playing around with this, I decided that we don't need a conditional to take a reading. So the first few lines of loop() now read:
readSensor(); // Always want to take a reading
if(millis() - averageStart > displayInterval) // Check to see if it is time to update the display
{
updateDisplay();
}
I may have made a few other minor changes so I'll attach the full code to this post for the insanely curious. Here is some output with the current code:
Actual output after the cut line.
The update interval is 30000ms (30.000 seconds).
The first two updates are with A0 connected to +5V
During the data collection period for the third update, the jumper from A0 to +5V was removed
The fourth update A0 is floating
During the data collection period for the fifth update, A0 is jumpered to +3.3V
The sixth and seventh updates are with A0 connected to +3.3V
------------------------8<------------------------
Average calculations:
Accumulated sum of analogRead() = 254659464
Number of analogRead()s = 248934
Calculated average = 1022
Number of LEDs to light up = 5
Number of reads per second since last update = 8297.80
Number of reads per second since start = 8297.80
-*-*-*-*-*-*-*-*-*-*-*-*-*-
Average calculations:
Accumulated sum of analogRead() = 254631852
Number of analogRead()s = 248907
Calculated average = 1022
Number of LEDs to light up = 5
Number of reads per second since last update = 8296.90
Number of reads per second since start = 8297.35
-*-*-*-*-*-*-*-*-*-*-*-*-*-
Average calculations:
Accumulated sum of analogRead() = 128993638
Number of analogRead()s = 248908
Calculated average = 518
Number of LEDs to light up = 3
Number of reads per second since last update = 8296.93
Number of reads per second since start = 8297.21
-*-*-*-*-*-*-*-*-*-*-*-*-*-
Average calculations:
Accumulated sum of analogRead() = 252
Number of analogRead()s = 248899
Calculated average = 0
Number of LEDs to light up = 0
Number of reads per second since last update = 8296.63
Number of reads per second since start = 8297.07
-*-*-*-*-*-*-*-*-*-*-*-*-*-
Average calculations:
Accumulated sum of analogRead() = 102654376
Number of analogRead()s = 248906
Calculated average = 412
Number of LEDs to light up = 2
Number of reads per second since last update = 8296.87
Number of reads per second since start = 8297.03
-*-*-*-*-*-*-*-*-*-*-*-*-*-
Average calculations:
Accumulated sum of analogRead() = 170236541
Number of analogRead()s = 248907
Calculated average = 683
Number of LEDs to light up = 3
Number of reads per second since last update = 8296.90
Number of reads per second since start = 8297.01
-*-*-*-*-*-*-*-*-*-*-*-*-*-
Average calculations:
Accumulated sum of analogRead() = 170231831
Number of analogRead()s = 248909
Calculated average = 683
Number of LEDs to light up = 3
Number of reads per second since last update = 8296.97
Number of reads per second since start = 8297.00
-*-*-*-*-*-*-*-*-*-*-*-*-*-
Fuel_Gauge_signal_smoothing_with_arduino.ino (5.96 KB)