ADC
We have seen in the previous documents (available here) how to read and monitor a varying power source from the Raspberry PI using a chip MCP3008.
The power source was in those cases provided by the Raspberry PI itself. Those voltages range from 1.2 Volt (at the CPU level), to 5 Volts (power supply, pin #2 on the GPIO Header), the GPIO pins deliver a 3.3 Volts output.
The MCP3008 itself would not take any current greater than 5 Volts.
If we want to monitor a 12 Volt system (on a boat, an RV, a solar panel...), we will need to use some voltage divider, in order not to overload - and fry - the components we will use.
This divider will sit between the power source to monitor, and the pins CH0 to CH7 of the MCP3008.
The divider
Vin
is the 12 Volt system to monitor. It can go up to 15 Volts.Vout
is what will be used from the MCP3008 standpoint. The + terminal will go to its CH[0-7]
pins.V1
is the tension across the resistor R1
.
Vout
(which can also be named V2
) is the tension across the resistor R2
.
We (should) know that
V1 = Vin × | R1 | and | V2 = Vin × | R2 |
R1 + R2 | R1 + R2 |
Vin | V |
R1 | kΩ |
R2 | kΩ |
Vout | 3.72 V |
Here is the full setup. Notice the following elements:
The MCP3008 returns values ranging from 0 to 1023 (210 = 1024).
We need to calibrate the hardware so we can directly read the voltage from the program running on the Raspberry PI.
To do so, with the setup above, on the Raspberry PI, start the following script:
Prompt> ./battery.monitor -calibrationTurn the potentiometer all the way counter-clockwise
Prompt> ./battery.monitor -calibration Read an ADC Parameters are: -calibration or -cal -debug=y|n|yes|no|true|false - example -debug=y (default is n) -ch=[0-7] - example -ch=0 (default is 0) -min=minADC:minVolt - example -min=280:3.75 (default is 0:0.0) -max=maxADC:maxVolt - example -min=879:11.25 (default is 1023:15.0) -tune=ADC:volt - example -tune=973:12.6 (default is 1023:15.0) -scale=y|n - example -scale=y (default is n) -log=[log-file-name] - example -log=[batt.csv] (default is battery.log) Prms: ADC Channel:0 MinADC:0, MinVolt:0.0, MaxADC:1023, maxVolt:15.0 readAdc:286 (0x11E, 0&100011110) Volume:27% (286) Volt:4.193548 readAdc:293 (0x125, 0&100100101) Volume:28% (293) Volt:4.296188 readAdc:283 (0x11B, 0&100011011) Volume:27% (283) Volt:4.14956 readAdc:289 (0x121, 0&100100001) Volume:28% (289) Volt:4.2375364Read the voltmeter: In this example, let's say that it displays 3.75 Volts, when the ADC value is at 289.
... readAdc:606 (0x25E, 0&1001011110) Volume:59% (606) Volt:8.885631 readAdc:654 (0x28E, 0&1010001110) Volume:63% (654) Volt:9.589443 readAdc:717 (0x2CD, 0&1011001101) Volume:70% (717) Volt:10.513197 readAdc:808 (0x328, 0&1100101000) Volume:78% (808) Volt:11.847507 readAdc:872 (0x368, 0&1101101000) Volume:85% (872) Volt:12.785924In this example, the voltmeter reads 11.75 Volts when the ADC says 872.
ADC | Voltmeter | |
Mini | 289 | 3.75 |
Maxi | 872 | 11.75 |
-min
and -max
parameters, and how they relate to the table above. Move the potentiometer back and forth.
Prompt> ./battery.monitor -min=289:3.75 -max=872:11.75 -debug=y Read an ADC Parameters are: -calibration or -cal -debug=y|n|yes|no|true|false - example -debug=y (default is n) -ch=[0-7] - example -ch=0 (default is 0) -min=minADC:minVolt - example -min=280:3.75 (default is 0:0.0) -max=maxADC:maxVolt - example -min=879:11.25 (default is 1023:15.0) -tune=ADC:volt - example -tune=973:12.6 (default is 1023:15.0) -scale=y|n - example -scale=y (default is n) -log=[log-file-name] - example -log=[batt.csv] (default is battery.log) Prms: ADC Channel:0 MinADC:289, MinVolt:3.75, MaxADC:872, maxVolt:11.75 readAdc:759 (0x2F7, 0&1011110111) Volume:74% (759) Volt:10.1994 readAdc:746 (0x2EA, 0&1011101010) Volume:72% (746) Volt:10.021011 readAdc:711 (0x2C7, 0&1011000111) Volume:69% (711) Volt:9.540737 readAdc:667 (0x29B, 0&1010011011) Volume:65% (667) Volt:8.936964 readAdc:642 (0x282, 0&1010000010) Volume:62% (642) Volt:8.59391 readAdc:617 (0x269, 0&1001101001) Volume:60% (617) Volt:8.250858 readAdc:601 (0x259, 0&1001011001) Volume:58% (601) Volt:8.031303 readAdc:593 (0x251, 0&1001010001) Volume:57% (593) Volt:7.9215264 readAdc:609 (0x261, 0&1001100001) Volume:59% (609) Volt:8.141081 readAdc:625 (0x271, 0&1001110001) Volume:61% (625) Volt:8.360635 readAdc:647 (0x287, 0&1010000111) Volume:63% (647) Volt:8.662521 readAdc:681 (0x2A9, 0&1010101001) Volume:66% (681) Volt:9.129074 readAdc:716 (0x2CC, 0&1011001100) Volume:69% (716) Volt:9.609348 readAdc:754 (0x2F2, 0&1011110010) Volume:73% (754) Volt:10.130789 readAdc:794 (0x31A, 0&1100011010) Volume:77% (794) Volt:10.679674 readAdc:842 (0x34A, 0&1101001010) Volume:82% (842) Volt:11.338336 readAdc:862 (0x35E, 0&1101011110) Volume:84% (862) Volt:11.612779 readAdc:808 (0x328, 0&1100101000) Volume:78% (808) Volt:10.871784 readAdc:756 (0x2F4, 0&1011110100) Volume:73% (756) Volt:10.158234 readAdc:716 (0x2CC, 0&1011001100) Volume:69% (716) Volt:9.609348 readAdc:680 (0x2A8, 0&1010101000) Volume:66% (680) Volt:9.115352 readAdc:648 (0x288, 0&1010001000) Volume:63% (648) Volt:8.676244 readAdc:629 (0x275, 0&1001110101) Volume:61% (629) Volt:8.415524 readAdc:615 (0x267, 0&1001100111) Volume:60% (615) Volt:8.223413 readAdc:602 (0x25A, 0&1001011010) Volume:58% (602) Volt:8.045026 readAdc:586 (0x24A, 0&1001001010) Volume:57% (586) Volt:7.825472 readAdc:580 (0x244, 0&1001000100) Volume:56% (580) Volt:7.7431393 readAdc:587 (0x24B, 0&1001001011) Volume:57% (587) Volt:7.839194 readAdc:605 (0x25D, 0&1001011101) Volume:59% (605) Volt:8.086192 readAdc:630 (0x276, 0&1001110110) Volume:61% (630) Volt:8.429245 readAdc:669 (0x29D, 0&1010011101) Volume:65% (669) Volt:8.964409The voltage displayed on the screen should match what's read on the voltmeter.
You can use 2 points as above, or one only.
In the case you use only one, we will assume that for 0 ADC, we have 0 Volts.
Let us see.
If we use the following calibration parameters:
-min=695:9.1 -max=973:12.6 -scale=yThe voltage ranges from
-0.3500028 V
for ADC=0, to 13.265468 V
for ADC=1023.
This produces the following figure.
-tune=973:12.6 -scale=yThe voltage ranges from
0.0 V
to 13.247482 V
for ADC=1023, and produces the following figure.
Run the script without the -debug
parameter.
Prompt>./battery.monitor -tune=973:12.6 Read an ADC Parameters are: -calibration or -cal -debug=y|n|yes|no|true|false - example -debug=y (default is n) -ch=[0-7] - example -ch=0 (default is 0) -min=minADC:minVolt - example -min=280:3.75 (default is 0:0.0) -max=maxADC:maxVolt - example -min=879:11.25 (default is 1023:15.0) -tune=ADC:volt - example -tune=973:12.6 (default is 1023:15.0) -scale=y|n - example -scale=y (default is n) -log=[log-file-name] - example -log=[batt.csv] (default is battery.log) Prms: ADC Channel:0, tuningADC:973, tuningVolt:12.6 .... ^C Shutting down Closing log file Shutting down... Prompt>Let it run as long as you want, and stop it with a SIGTERM (Ctrl+C).
battery.log
, as CSV data. Columns are date
, ADC
, Volts
.
Prompt> tail battery.log 2014-04-19 11:45:39.804;523;6.9609776 2014-04-19 11:45:39.907;558;7.441252 2014-04-19 11:45:40.009;589;7.866638 2014-04-19 11:45:40.112;636;8.511578 2014-04-19 11:45:40.229;681;9.129074 2014-04-19 11:45:40.331;736;9.883791 2014-04-19 11:45:40.439;788;10.597342 2014-04-19 11:45:40.542;850;11.448113 2014-04-19 11:45:40.645;875;11.791166 2014-04-19 11:45:41.455;869;11.708834 Prompt>
Once the prototyping phase is validated, all the components are set on a Slice of PI.
One terminal is used to hook up the 12v system to monitor, the other is used for calibration, with the voltmeter.The logging is performed as above.
The data in red are raw data, the blue curve is the result of a smoothing process.
After a couple of tests, there was some room for improvement, on the software side mostly.
On the hardware side though, a smaller potentiometer considerably reduced the height of the device, and it fits in the chart table.
Also, it could be a good idea to leave some possibility to use some I2C board. As the Slice of PI uses the full GPIO header, four wires have been soldered (GND, 3V3, SCL, SDA), they could be plugged onto a breadboard to use breakout boards like a BMP180, for example.
In the chart table. Smaller potentiometer, an I2C extension. NMEA Logging.
$IIMTW,+14.5,C*38 $IIMWV,151,R,04.4,N,A*16 $IIMWV,150,T,04.5,N,A*10 $IIRMC,030143,A,3730.078,N,12228.856,W,00.0,148,230514,15,E,A*1B $IIVHW,,,359,M,00.0,N,,*6B $XXBAT,14.16,V,966,94*19 $IIVLW,08189,N,000.0,N*5B $IIVWR,151,R,04.4,N,,,,*64 $IIGLL,3730.078,N,12228.856,W,030143,A,A*4F $IIHDG,359,,,15,E*19 $IIMTW,+14.5,C*38 $IIMWV,152,R,05.1,N,A*11 $IIMWV,151,T,04.4,N,A*10 $IIRMB,A,0.23,R,,HMB-3 ,,,,,001.20,184,,V,A*1F $IIRMC,030145,A,3730.078,N,12228.857,W,00.0,148,230514,15,E,A*1C $IIVHW,,,359,M,00.0,N,,*6B $IIVLW,08189,N,000.0,N*5B $IIVWR,152,R,05.1,N,,,,*63 $IIGLL,3730.078,N,12228.857,W,030145,A,A*48 $IIHDG,000,,,15,E*16 $IIMTW,+14.5,C*38 $IIMWV,150,R,05.0,N,A*12 $IIMWV,152,T,05.1,N,A*17 $IIRMC,030145,A,3730.078,N,12228.857,W,00.0,148,230514,15,E,A*1CFrom there, it's all downhill, data can be analyzed... The downward notches correspond to the periods when the fridge is on. The global tension goes up with the sun (solar panel).
All set, Raspberry PI B, USB Hub, and a breadboard.
The connectors plugged on the breadboard are I2C ones.
I used it with a BMP180 (Air temperature & Pressure).
As of April 2014, here is what it takes:
A Slice of PI | $ 9.05 | from Amazon |
A 50K potentiometer | $ 0.95 | from Adafruit |
An MCP3008 | $ 3.75 | from Adafruit |
2 connector terminals | 5 for $ 2.95 | from Adafruit |
Resistors, wires, etc | ||
Total | $ 16.70 |
Fritzing schema available here.