]> git.friedersdorff.com Git - max/battery_tester.git/blob - battery_tester.ino
Add readme
[max/battery_tester.git] / battery_tester.ino
1 #include <LightChrono.h>
2 #include <Chrono.h>
3
4 const float APPARENT_SHUNT_RESISTANCE = 0.453;
5 const float VOLTAGE_REFERENCE = 2.494;
6
7 float ampseconds = 0;
8 float wattseconds = 0;
9
10 const int digits[] = {2, 3, 4, 5};
11 const int segments[] = {6, 7, 8, 9, 10, 11, 12, 13};
12
13 const bool one[7] = {false, true, true, false, false, false, false};
14 const bool two[7] = {true, true, false, true, true, false, true};
15 const bool three[7] = {true, true, true, true, false, false, true};
16 const bool four[7] = {false, true, true, false, false, true, true};
17 const bool five[7] = {true, false, true, true, false, true, true};
18 const bool six[7] = {true, false, true, true, true, true, true};
19 const bool seven[7] = {true, true, true, false, false, false, false};
20 const bool eight[7] = {true, true, true, true, true, true, true};
21 const bool nine[7] = {true, true, true, true, false, true, true};
22 const bool zero[7] = {true, true, true, true, true, true, false};
23
24 const bool U[7] = {false, true, true, true, true, true, false};
25 const bool A[7] = {true, true, true, false, true, true, true};
26 const bool E[7] = {true, false, false, true, true, true, true};
27
28 unsigned char display_state = 0;
29
30 Chrono timer;
31 Chrono debounce;
32 Chrono blank_timer;
33
34 float shunt_voltage = 0;
35 float shunt_current = 0;
36 float battery_voltage = 0;
37 float amps_in_period = 0;
38 float watts_in_period = 0;
39 float mamphours = 0;
40 float mwatthours = 0;
41
42
43 void writeDigit(char d, char val, bool dec) {
44     const bool *segs;
45     switch (val) {
46         case 0:
47             segs = zero;
48             break;
49         case 1:
50             segs = one;
51             break;
52         case 2:
53             segs = two;
54             break;
55         case 3:
56             segs = three;
57             break;
58         case 4:
59             segs = four;
60             break;
61         case 5:
62             segs = five;
63             break;
64         case 6:
65             segs = six;
66             break;
67         case 7:
68             segs = seven;
69             break;
70         case 8:
71             segs = eight;
72             break;
73         case 9:
74             segs = nine;
75             break;
76     }
77     for (int i = 0; i < 7; ++i) {
78         if (segs[i]) {
79             digitalWrite(segments[i], HIGH);
80         } else {
81             digitalWrite(segments[i], LOW);
82         }
83     }
84     if (dec) {
85       digitalWrite(segments[7], HIGH);
86     }
87     digitalWrite(digits[d], LOW);
88     delay(1);
89     digitalWrite(digits[d], HIGH);
90     digitalWrite(segments[7], LOW);
91 }
92
93 void writeLetter(char d, const bool val[]) {
94     for (int i = 0; i < 7; ++i) {
95         if (val[i]) {
96             digitalWrite(segments[i], HIGH);
97         } else {
98             digitalWrite(segments[i], LOW);
99         }
100     }
101     digitalWrite(digits[d], LOW);
102     delay(1);
103     digitalWrite(digits[d], HIGH);
104 }
105
106 void showNumber(float number) {
107     int n = number;
108     writeDigit(0, (n/1000U) % 10, false);
109     writeDigit(1, (n/100U) % 10, false);
110     writeDigit(2, (n/10U) % 10, false);
111     writeDigit(3, n % 10, false);
112 }
113
114 void showVoltage(float volts) {
115     int cvolts = volts * 100;
116     writeDigit(0, (cvolts/100U) % 10, true);
117     writeDigit(1, (cvolts/10U) % 10, false);
118     writeDigit(2, cvolts % 10, false);
119     writeLetter(3, U);
120 }
121
122 void showCurrent(float current) {
123     int camp = current * 100;
124     writeDigit(0, (camp/100U) % 10, true);
125     writeDigit(1, (camp/10U) % 10, false);
126     writeDigit(2, camp % 10, false);
127     writeLetter(3, A);
128 }
129
130 void showWh(float watthours) {
131   int w = watthours;
132   writeDigit(0, (w/1000U) % 10, true);
133   writeDigit(1, (w/100U) % 10, false);
134   writeDigit(2, (w/10U) % 10, false);
135   writeLetter(3, E);
136 }
137
138
139 void setup() {
140     // put your setup code here, to run once:
141     Serial.begin(9600);
142     analogReference(EXTERNAL);
143
144     for (int i = 0; i < 4; ++i) {
145         pinMode(digits[i], OUTPUT);
146         digitalWrite(digits[i], HIGH);
147     }
148     for (int i = 0; i < 8; ++i) {
149         pinMode(segments[i], OUTPUT);
150         digitalWrite(segments[i], LOW);
151     }
152
153     pinMode(15, OUTPUT);
154     digitalWrite(15, LOW);
155
156     pinMode(19, INPUT_PULLUP);
157     pinMode(20, INPUT_PULLUP);
158     pinMode(21, INPUT_PULLUP);
159 }
160
161 void loop() {
162     
163
164     if (timer.hasPassed(1000)) {
165         unsigned long passed = timer.elapsed();
166         timer.restart();
167         battery_voltage = readVoltage(A0);
168
169         if (battery_voltage < 0.8) {
170             blank_timer.restart();
171         } else {
172             shunt_voltage = readVoltage(A1);
173             shunt_current = shunt_voltage/APPARENT_SHUNT_RESISTANCE;
174
175
176             amps_in_period = shunt_current * passed/1000;
177             watts_in_period = amps_in_period * battery_voltage;
178
179             ampseconds += amps_in_period;
180             wattseconds += watts_in_period;
181             mamphours = ampseconds/3.6;
182             mwatthours = wattseconds/3.6;
183         }
184     }
185     if (debounce.hasPassed(300) && !digitalRead(19)) {
186         display_state = (display_state + 1) % 4;
187         debounce.restart();
188     } else if (blank_timer.hasPassed(200)) {
189         switch (display_state) {
190           case 0:
191             showNumber(mamphours);
192             break;
193           case 1:
194             showVoltage(battery_voltage);
195             break;
196           case 2:
197             showCurrent(shunt_current);
198             break;
199           case 3:
200             showWh(mwatthours);
201             break;
202         }
203     }
204 }
205
206 float readVoltage(int pin) {
207
208     int val = 0;
209     for (int i = 0; i < 4; ++i) {
210         val = val + analogRead(pin);
211         delay(0.5);
212     }
213
214     return (val / 4) * VOLTAGE_REFERENCE/1023.0;
215 }