1 | // RA0 = Analog Input RC0 = LCD RS-Pin
|
2 | // RA1 = Output Relais Laden RC1 = LCD E-Pin R/W = GND
|
3 | // RA2 = Output Relais Entladen RC2 = LCD D4
|
4 | // RA3 = Input Taster RC3 = LCD D5
|
5 | // RA4 = Output n.n RC4 = LCD D6
|
6 | // RA5 = Output LED RC5 = LCD D7
|
7 |
|
8 |
|
9 | #include "16F688.H"
|
10 | #pragma config |= 0b11.0011.1101.0100 // Konfigurations-Wort
|
11 |
|
12 | uns16 AD_DEZ, ZAHL;
|
13 | uns16 EIN, ZEH, HUN, TSD;
|
14 | uns16 MERKER1, MERKER2, SEK;
|
15 | bit LADEN @ PORTA.1;
|
16 | bit ENTLADEN @ PORTA.2;
|
17 | bit START @ PORTA.3;
|
18 | char WAS; // N=Nichts ; L=Laden ; E=Entladen
|
19 | uns8 LAUF; // Anzahl Durchlauf
|
20 | float24 mAh; // Kapazität in mAh
|
21 |
|
22 |
|
23 |
|
24 | #include "int16CXX.H"
|
25 | #pragma origin 4
|
26 | interrupt ISR( void)
|
27 | {
|
28 | int_save_registers // W, WAS (and PCLATH)
|
29 | GIE = 0; // Interrupts global aus
|
30 | TMR1ON=0;
|
31 | if (TMR1IF)
|
32 | {
|
33 | SEK++;
|
34 | TMR1IF = 0; // Timer1 Interruptflag Löschen;
|
35 | TMR1H = 11; // preset for timer1 MSB register
|
36 | TMR1L = 71; // preset for timer1 LSB register
|
37 | }
|
38 | TMR1ON=1;
|
39 | GIE = 1; // Interrupts global an
|
40 | int_restore_registers // W, WAS (and PCLATH)
|
41 | }
|
42 |
|
43 | #define LCD_RS 0b0000.0001 //RS-Pin ist Bit0, LCD Register Select (RC0)
|
44 | #define LCD_CS 0b0000.0010 //E-Pin ist Bit1, LCD Chip Select (RC1)
|
45 |
|
46 | #pragma char PORTQ @ PORTC //PORT auswählen, DB7-Bit5, DB6-Bit4, DB5-Bit3, DB4-Bit2
|
47 |
|
48 | #include "delay4.c"
|
49 | #include "math16.h"
|
50 | #include "lcd.c"
|
51 | #include "MATH24F.H"
|
52 |
|
53 |
|
54 | void ADC(void)
|
55 | {
|
56 | uns16 ADWERT; // 16 Bit Variable
|
57 | uns16 ADSUM;
|
58 | int i;
|
59 | uns16 AD_64;
|
60 | uns16 AD_128;
|
61 | ADSUM=0;
|
62 | for(i=1;i<65;i++) // Mittelwert über 64 Messungen
|
63 | {
|
64 | GO=1; // Wandlung wird gestartet
|
65 | while (GO); // Hier wird gewartet bis die Wandlung beendet ist
|
66 | ADWERT = ADRESH; // Wert aus Registern zusammenbasteln
|
67 | ADWERT = ADWERT << 8; // Ergebnis steht im adwert 5V / 10 bit = 5/1024 = 4,8mV Auflösung
|
68 | ADWERT = ADWERT | ADRESL;
|
69 | ADSUM = ADSUM + ADWERT;
|
70 | Delay1ms(1);
|
71 | }
|
72 | ADSUM = ADSUM >> 6; // 16-Bit Variable = Mittelwert obere 10 Bit
|
73 | AD_DEZ = ADSUM + ADSUM ;
|
74 | AD_DEZ = AD_DEZ + AD_DEZ;
|
75 | AD_DEZ = AD_DEZ + ADSUM; // AD_DEZ = (ADWERT * 5) / 1,024
|
76 | AD_64 = AD_DEZ;
|
77 | AD_128 = AD_DEZ;
|
78 | AD_64 = AD_64 >> 6;
|
79 | AD_128 = AD_128 >> 7;
|
80 | AD_DEZ = AD_DEZ - AD_64 ;
|
81 | AD_DEZ = AD_DEZ - AD_128 ;
|
82 |
|
83 | ZAHL = AD_DEZ;
|
84 | TSD=(ZAHL % 10); // Modulo rechnen, dann den ASCII-Code von '0' addieren
|
85 | ZAHL /= 10;
|
86 | HUN=(ZAHL % 10); // Modulo rechnen, dann den ASCII-Code von '0' addieren
|
87 | ZAHL /= 10;
|
88 | ZEH=(ZAHL % 10); // Modulo rechnen, dann den ASCII-Code von '0' addieren
|
89 | ZAHL /= 10;
|
90 | EIN=ZAHL; // Modulo rechnen, dann den ASCII-Code von '0' addieren
|
91 | }
|
92 |
|
93 |
|
94 |
|
95 | void main(void) // Hauptprogramm
|
96 | {
|
97 |
|
98 | INTCON = 0b.0000.0000; // erst einmal Interupts aus
|
99 | CMCON0 = 0b.0000.0111; // Comparators Off
|
100 | ANSEL = 0b.0000.0001; // RA0 = Input / Rest Output
|
101 | TRISA = 0b.0000.0001; // RA0 = Input / Rest Output
|
102 | TRISC = 0b.0000.0000; // PORT C alles Ausgänge
|
103 | PORTC = 0; // alle Ausgänge auf 0
|
104 | ADCON1 = 0b.0000.0010; // A/D Conversion Clock 000 = FOSC/32
|
105 |
|
106 | MERKER1=0;
|
107 | MERKER2=0;
|
108 |
|
109 | //lcdport=0;
|
110 | //Delay1ms(1000); // 1s warten
|
111 | LCDInit(); // LCD Initialisieren
|
112 | Delay1ms(1000);
|
113 | LCDCls(); // Bildschirm löschen
|
114 | Delay1ms(1000);
|
115 |
|
116 |
|
117 | T1CON = 0b0011.0000; // Teiler = 1:8 ; Fosc/4
|
118 | TMR1ON = 0; // Timer 1 stoppen
|
119 | TMR1H = 11; // preset for timer1 MSB register
|
120 | TMR1L = 71; // preset for timer1 LSB register
|
121 | TMR1IF = 0; // Timer1 Interruptflag Löschen;
|
122 | TMR1IE = 1; // Timer1 Interrupt erlauben
|
123 | T0IE = 0; // Timer0 Interrupt verbieten
|
124 | PEIE = 1; // Pereferie Interrupt erlauben
|
125 | GIE = 1; // Interrups global einschalten
|
126 | WAS ='N';
|
127 | mAh = 0;
|
128 | SEK = 0;
|
129 | LAUF = 0;
|
130 | while (1)
|
131 |
|
132 | {
|
133 |
|
134 | ADCON0 = 0b.1000.0001; // Channel 000 ADC global einschalten
|
135 | Delay1ms(1);
|
136 | ADC();
|
137 |
|
138 | LCDPos(2,2); // Position der ersten Zeichen 2 Zeile, Position 0
|
139 | LCDWriteChar((char)EIN+0x30); // String Anzeigen
|
140 | LCDPos(2,3);
|
141 | LCDString(".");
|
142 | LCDPos(2,4);
|
143 | LCDWriteChar((char)ZEH+0x30);
|
144 | LCDPos(2,5);
|
145 | LCDWriteChar((char)HUN+0x30);
|
146 | LCDPos(2,6);
|
147 | LCDWriteChar((char)TSD+0x30);
|
148 | LCDPos(2,7);
|
149 | LCDString("V");
|
150 | if (SEK != MERKER1) // blinkende LED ... mal sehen ob das Prog noch läuft
|
151 | {
|
152 | if (PORTA.5)
|
153 | PORTA.5=0;
|
154 | else
|
155 | PORTA.5=1;
|
156 | MERKER1=SEK;
|
157 | }
|
158 | if (START)
|
159 | {
|
160 | SEK=0;
|
161 | mAh=0;
|
162 | WAS='L';
|
163 | LAUF=0;
|
164 | }
|
165 |
|
166 | // Laden erfolgt mit einer Konstantspannungsquelle 4,15 V mit Strombegrenzung 0,5 A.
|
167 | // Entladen erfolgt mit Konstanstspromsenke 0,5 A bis 3,75 V.
|
168 | // Nach dem Drücken des Starttasters so lange laden, bis die Akkuspannung >= 4,15V ist. Dann weiter 1h laden.
|
169 | // Entladen (Konstantstromsenke 0,5 A ) und die Zeit messen. Fällt die Spannung unter 3,75V Entladen stoppen.
|
170 | // Gemessene Zeit in SEK * 0,5 A / 3600 (60 Min * 60 Sek) = Kapazität in mAh
|
171 | // Zum Lagern sollen LIPO-Akku nur 3,9 V haben. Somit wird nach dem Messen der Akku nur auf 3,9V geladen.
|
172 |
|
173 |
|
174 | switch (WAS)
|
175 | {
|
176 | case 'N':
|
177 | LADEN=0;
|
178 | Delay1ms(500); // 0,5 Sek. warten
|
179 | ENTLADEN=0;
|
180 | if (LAUF == 1 && SEK > 0 )
|
181 | {
|
182 | mAh=(SEK*5)/72; // = Sekunden (doppelt da 2Hz) * 500 (mAh) / 360 S (*2)
|
183 | LCDPos(1,0);
|
184 | ZahlString(mAh);
|
185 | LCDPos(1,5);
|
186 | LCDString("mAh");
|
187 | }
|
188 | else
|
189 | {
|
190 | LCDPos(1,0);
|
191 | LCDString("Start");
|
192 | }
|
193 | break;
|
194 |
|
195 | case 'L': // Solange warten bis die Spannung >= 4,15 V ist dann 1 Stunde warten anschl. trennen und WAS
|
196 | ENTLADEN=0; // Relais für die Konstantstronsenke ausschalten
|
197 | Delay1ms(500); // 0,5 Sek. warten
|
198 | LADEN=1; // Relais für die Ladung einschalten
|
199 | LCDPos(1,0);
|
200 | LCDString("L: ");
|
201 | if (AD_DEZ >= 3900 && LAUF == 1) // im zweiten Ladezyklus und Ladeschlußspannung erreicht
|
202 | {
|
203 | LADEN=0; // Stoppe laden
|
204 | Delay1ms(500); // 0,5 Sek. warten
|
205 | WAS='N';
|
206 | mAh=(SEK*5)/72; // = Sekunden (doppelt da 2Hz) * 500 (mAh) / 3600 S (*2)
|
207 | LCDPos(1,0);
|
208 | LCDString("F");
|
209 | LCDPos(1,2);
|
210 | ZahlString(mAh);
|
211 | }
|
212 |
|
213 | if (AD_DEZ >= 4150 && LAUF == 0) // im ersten Ladezyklus und Ladeschlußspannung erreicht
|
214 | { // Spannung größer gleich 4,15 V Start Wartezeit 1h
|
215 | if (TMR1ON) // Timer läuft bereits
|
216 | {
|
217 | if (SEK >= 720) // Ruhezeit abgelaufen Starte Entladung
|
218 | {
|
219 | LAUF=1;
|
220 | WAS='E';
|
221 | TMR1ON=0; // Stoppe Timer
|
222 | }
|
223 | else
|
224 | {
|
225 | LCDPos(1,2);
|
226 | ZahlString(SEK/2);
|
227 | }
|
228 | }
|
229 | else // Timer läuft noch nicht -> Starten
|
230 | {
|
231 | SEK=0;
|
232 | TMR1IF=0; // Interruptflag löschen
|
233 | TMR1ON=1; // Starte Timer bis 3600 Sek = 1h
|
234 | }
|
235 | }
|
236 | break;
|
237 |
|
238 | case 'E':
|
239 | LADEN=0;
|
240 | Delay1ms(500); // 0,5 Sek. warten
|
241 | if (AD_DEZ >= 3750 ) // > 3,75V
|
242 | {
|
243 | if (!TMR1ON) // Timer gestopt ?
|
244 | {
|
245 | SEK=0; // Sekundenzähler löschen
|
246 | TMR1IF=0; // Interruptflag löschen
|
247 | TMR1ON=1; // Timer starten
|
248 | }
|
249 | ENTLADEN=1;
|
250 | }
|
251 | else
|
252 | {
|
253 | TMR1ON=0; // Timer stoppen
|
254 | ENTLADEN=0; // Stoppe Entladung
|
255 | Delay1ms(500); // 0,5 Sek. warten
|
256 | LAUF=1; // 1. Zyklus beendet
|
257 | WAS='L'; // Laden wieder einschalten
|
258 | }
|
259 | mAh=(SEK*5)/72;
|
260 | LCDPos(1,0);
|
261 | LCDString("E:");
|
262 | LCDPos(1,2);
|
263 | ZahlString(mAh);
|
264 | break;
|
265 | }
|
266 |
|
267 |
|
268 | }
|
269 |
|
270 |
|
271 | }
|