Hanna
Sourcecode Batteriemanagementsystem
BMS-Basic.c
gehe zur Dokumentation dieser Datei
1 
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <avr/io.h>
17 #include <avr/interrupt.h>
18 #include <util/delay.h>
19 #include <stdbool.h>
20 
21 #include "board_init.h"
22 #include "BMS-Basic.h"
23 #include "Hardware/ad7997.h"
24 #include "Hardware/bms_mosfet.h"
25 #include "Hardware/com74hc595.h"
26 #include "Hardware/ds1388_rtc.h"
27 #include "Hardware/temp_mcp9843.h"
30 #include "ventilator.h"
31 #include "display_ausgabe.h"
32 #include "Hardware/taster.h"
33 #include "screens_gfx.h"
34 #include "sdcard_bms.h"
35 
36 unsigned char com74hc595[COM74HC595_SIZE];
37 
38 //TWI_Master_t twiMCP9843;
39 
40 uint8_t sendRegData[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
41 
42 bool laden = false, last = false, vent_1 = false, vent_2 = false;
43 int aktuelle_zelle_P1 = 4, aktuelle_zelle_P2 = 0;
44 
45 //float voltage[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
46 //float current[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
47 
48 int einlese_zeit[2] = { 0x00, 0x00 };
49 float charge[8] = { 600, 600, 600, 600, 600, 600, 600, 600 };
50 //int16_t c_max[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
51 int16_t c_max[8] = { 750, 750, 750, 750, 750, 750, 750, 750 };
52 int SOC[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
53 int SOH[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
54 float ladezyklus[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
55 bool flag_tcrit[8] = { false, false, false, false, false, false, false, false };
56 bool flag_tupper[8] = { false, false, false, false, false, false, false, false };
57 bool flag_tlower[8] = { false, false, false, false, false, false, false, false };
58 bool akku_an[8] = { false, false, false, false, false, false, false, false };
59 bool reset_eingabe[8] = { false, false, false, false, false, false, false, false };
60 bool akku_laden[8] = { false, false, false, false, false, false, false, false };
61 bool akku[8] = { false, false, false, false, false, false, false, false };
62 bool entlade_start = false;
63 bool usb_versorgung = false;
64 float voltage_rechnen[8][5];
65 uint8_t max_volt = 0, min_volt = 0;
66 float gesamt_volt = 0.00;
67 uint32_t betriebszeit_s[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
68 uint32_t ladezeit_s[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
69 uint8_t state_counter = 0;
70 int h[8][2], m[8][2], s[8][2];
71 
72 void lade_steuerung ( void )
73 {
76 
77 // for ( int i = 0; i <= 7; i++ )
78 // {
79 // voltage_rechnen[i][0] = voltage_rechnen[i][1];
80 // voltage_rechnen[i][1] = voltage_rechnen[i][2];
81 // voltage_rechnen[i][2] = voltage_rechnen[i][3];
82 // voltage_rechnen[i][3] = voltage_rechnen[i][4];
83 // voltage_rechnen[i][4] = voltage[i];
84 //
85 // for ( int k = 0; k <= 4; k++ )
86 // {
87 // if ( voltage_rechnen[i][k] < voltage_rechnen[i][min_volt] )
88 // min_volt = k;
89 // else if ( voltage_rechnen[i][k] > voltage_rechnen[i][max_volt] ) max_volt = k;
90 //
91 // gesamt_volt = voltage_rechnen[i][0] + voltage_rechnen[i][1] + voltage_rechnen[i][2] + voltage_rechnen[i][3] + voltage_rechnen[i][4];
92 // gesamt_volt = gesamt_volt - voltage_rechnen[i][min_volt] - voltage_rechnen[i][max_volt];
93 // voltage[i] = gesamt_volt / 3;
94 // }
95 // }
96 
98  messwert_flag = true;
99 
100  SOC_berechnung ();
101  SOH_berechnung ();
102 
103  temperatur_laden ();
104 
105  terminal_ausgabe();
106 // excel_ausgabe();
107 
110 
111  zeit_berechnung ();
112 }
113 
114 void entlade_steuerung ( void )
115 {
116 // entlade_start = true nach Auswahl "Betrieb" in Hauptmenu
117  if ( entlade_start )
118  leerlauf_voltage_get_data ();
119  else
121 
122 // for ( int i = 0; i <= 7; i++ )
123 // {
124 // voltage_rechnen[i][0] = voltage_rechnen[i][1];
125 // voltage_rechnen[i][1] = voltage_rechnen[i][2];
126 // voltage_rechnen[i][2] = voltage_rechnen[i][3];
127 // voltage_rechnen[i][3] = voltage_rechnen[i][4];
128 // voltage_rechnen[i][4] = voltage[i];
129 //
130 // for ( int k = 0; k <= 4; k++ )
131 // {
132 // if ( voltage_rechnen[i][k] < voltage_rechnen[i][min_volt] )
133 // min_volt = k;
134 // else if ( voltage_rechnen[i][k] > voltage_rechnen[i][max_volt] ) max_volt = k;
135 //
136 // gesamt_volt = voltage_rechnen[i][0] + voltage_rechnen[i][1] + voltage_rechnen[i][2] + voltage_rechnen[i][3] + voltage_rechnen[i][4];
137 // gesamt_volt = gesamt_volt - voltage_rechnen[i][min_volt] - voltage_rechnen[i][max_volt];
138 // voltage[i] = gesamt_volt / 3;
139 // }
140 // }
141 
143  mcp9843_get_data ();
144  messwert_flag = true; // Flag: neue Messwerte vorhanden, für Display-Ausgabe
145 
146  SOC_berechnung ();
147 
148  lade_bestimmung ();
149  temperatur_entladen ();
150 
151  if ( entlade_start || last )
152  akkuauswahl ();
153  else if ( voltage[aktuelle_zelle_P1] < VOLTAGE_LOW || voltage[aktuelle_zelle_P2] < VOLTAGE_LOW ) akkuauswahl ();
154 
155  terminal_usb_ausgabe ();
156 // terminal_ausgabe ();
157 // excel_ausgabe();
158 
161 }
162 
163 void leerlauf_steuerung ( void )
164 {
165  notstrom ();
166 
168  leerlauf_voltage_get_data ();
169  mcp9843_get_data ();
170  messwert_flag = true;
171 
172  SOC_berechnung ();
173 
174  temperatur_laden ();
175 
176  terminal_ausgabe ();
177 // excel_ausgabe();
178 
179  if ( state_counter >= 6 )
180  {
181 // sdcard_bms_write_state ();
182  state_counter = 0;
183  }
184 }
185 
186 void control_check ( void )
187 {
188 // if ( PORTD_IN & LADE_POWER_IN_INT_bm )
189 // laden = true;
190 // else
191 // laden = false;
192 //
193 // if ( PORTD_IN & USB_POWER_IN_INT_bm )
194 // usb_versorgung = true;
195 // else
196 // usb_versorgung = false;
197 
198 // Akkus angeschlossen ?
199  leerlauf_voltage_get_data ();
200  for ( int i = 0; i <= 7; i++ )
201  {
202  if ( voltage[i] > 1 )
203  akku[i] = true; // Wenn die Spannung über 1 V, dann ist der Akku angesteckt
204  else
205  akku[i] = false;
206  }
207 
208  if ( PORTD_IN & LADE_POWER_IN_INT_bm )
209  {
210  laden = true;
212  mosfet_notstrom ( NOTSTROM_AUS );
213  }
214  else if ( PORTD_IN & USB_POWER_IN_INT_bm )
215  {
216  usb_versorgung = true;
218  mosfet_notstrom ( NOTSTROM_AUS );
219  }
220  else
221  {
222  laden = false;
223  usb_versorgung = false;
224  entlade_start = true;
225  akkuauswahl ();
226  }
227 
229 
230  betriebsart = LEERLAUF;
231 }
232 
233 void temperatur_entladen ( void )
234 {
235  int t_norm;
236  static int kritische_temp[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
237  static int kritischer_durchlauf[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
238 
239  for ( int sensor_nummer = 0; sensor_nummer <= 3; sensor_nummer++ ) //Für die Zellen von P1
240  {
241  if ( vent_1 ) // Wenn der Ventilator läuft, dann ist vent = true
242  {
243  if ( !flag_tupper[sensor_nummer] ) // Temperatur unter Obergrenze
244  {
245  t_norm = 0; // Wenn alle Zellen kühl genug sind,
246  for ( int sensor = 0; sensor <= 3; sensor++ ) // kann der Ventilator ausgeschaltet werden
247  {
248  if ( !flag_tupper[sensor] ) t_norm++;
249  }
250  if ( t_norm == 4 ) ventilator ( MOSFET_VENT1, VENT_AUS );
251  }
252  else if ( flag_tcrit[sensor_nummer] ) // Bei einer kritischen Temperatur,
253  {
254  if ( akku[sensor_nummer] ) // Ist die Zelle benutzt,
255  { // soll die Zelle abgeschaltet werden
256  akkuauswahl ();
257  mosfet_battery ( sensor_nummer, AKKU_1_AUS ); // und eine neue Zelle ausgewählt werden
258  }
259  else // Läuft die Zelle nicht
260  {
261  if ( kritischer_durchlauf[sensor_nummer] >= 2 ) // und wenn 20s vergangen sind,
262  { // seit der Vent angeschaltet wurde
263  if ( temp[sensor_nummer] >= kritische_temp[sensor_nummer] ) // die temp nicht gesunken ist,
264  {
265  kritischer_durchlauf[sensor_nummer] = 0;
266  kritische_temp[sensor_nummer] = 0.00;
267  notstrom (); // wird ein Notaus aktiviert
268  }
269  }
270  else
271  kritischer_durchlauf[sensor_nummer]++;
272  }
273  }
274  else if ( flag_tupper[sensor_nummer] )
275  {
276  if ( akku_an[sensor_nummer] )
277  {
278  akkuauswahl ();
279  mosfet_battery ( sensor_nummer, AKKU_1_AUS );
280  }
281  }
282  }
283  else // Ventilator 1 läuft nicht
284  {
285  if ( flag_tcrit[sensor_nummer] )
286  {
287  kritische_temp[sensor_nummer] = temp[sensor_nummer]; // ein Abkühleffekt eintritt;
288  kritischer_durchlauf[sensor_nummer] = 0;
289  ventilator ( MOSFET_VENT1, VENT_AN ); // Abkühlung muss innerhalb einer bestimmten Zeitspanne erfolgen.
290  }
291  else if ( flag_tupper[sensor_nummer] )
292  {
293  ventilator ( MOSFET_VENT1, VENT_AN );
294  }
295  }
296  }
297 
298  for ( int sensor_nummer = 4; sensor_nummer <= 7; sensor_nummer++ ) //Für die Zellen von P1
299  {
300  if ( vent_2 ) // Wenn der Ventilator läuft, dann ist vent = true
301  {
302  if ( !flag_tupper[sensor_nummer] ) // Temperatur unter Obergrenze
303  {
304  t_norm = 0; // Wenn alle Zellen kühl genug sind,
305  for ( int sensor = 0; sensor <= 3; sensor++ ) // kann der Ventilator ausgeschaltet werden
306  {
307  if ( !flag_tupper[sensor] ) t_norm++;
308  }
309  if ( t_norm == 4 ) ventilator ( MOSFET_VENT2, VENT_AUS );
310  }
311  else if ( flag_tcrit[sensor_nummer] ) // Bei einer kritischen Temperatur,
312  {
313  if ( akku[sensor_nummer] ) // Ist die Zelle benutzt,
314  { // soll die Zelle abgeschaltet werden
315  akkuauswahl ();
316  mosfet_battery ( sensor_nummer, AKKU_2_AUS ); // und eine neue Zelle ausgewählt werden
317  }
318  else // Läuft die Zelle nicht
319  {
320  if ( kritischer_durchlauf[sensor_nummer] >= 2 ) // und wenn 20s vergangen sind,
321  { // seit der Vent angeschaltet wurde
322  if ( temp[sensor_nummer] >= kritische_temp[sensor_nummer] ) // die temp nicht gesunken ist,
323  {
324  kritischer_durchlauf[sensor_nummer] = 0;
325  kritische_temp[sensor_nummer] = 0.00;
326  notstrom (); // wird ein Notaus aktiviert
327  }
328  }
329  else
330  kritischer_durchlauf[sensor_nummer]++;
331  }
332  }
333  else if ( flag_tupper[sensor_nummer] )
334  {
335  if ( akku_an[sensor_nummer] )
336  {
337  akkuauswahl ();
338  mosfet_battery ( sensor_nummer, AKKU_2_AUS );
339  }
340  }
341  }
342  else // Ventilator 1 läuft nicht
343  {
344  if ( flag_tcrit[sensor_nummer] )
345  {
346  kritischer_durchlauf[sensor_nummer] = 0;
347  kritische_temp[sensor_nummer] = temp[sensor_nummer]; // ein Abkühleffekt eintritt;
348  ventilator ( MOSFET_VENT2, VENT_AN ); // Abkühlung muss innerhalb einer bestimmten Zeitspanne erfolgen.
349  }
350  else if ( flag_tupper[sensor_nummer] )
351  {
352  ventilator ( MOSFET_VENT2, VENT_AN );
353  }
354  }
355  }
356 }
357 
358 void temperatur_laden ( void )
359 {
360  int t_norm;
361  static int kritische_temp[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
362  static int kritischer_durchlauf[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
363 
364  for ( int sensor_nummer = 0; sensor_nummer <= 3; sensor_nummer++ )
365  {
366  if ( vent_1 ) // Wenn der Ventilator läuft, dann ist vent = true
367  {
368  if ( !flag_tupper[sensor_nummer] ) // Temperatur unter Obergrenze
369  {
370  t_norm = 0; // Wenn alle Zellen kühl genug sind,
371  for ( int sensor = 0; sensor <= 3; sensor++ ) // kann der Ventilator ausgeschaltet werden
372  {
373  if ( !flag_tupper[sensor] ) t_norm++;
374  }
375  if ( t_norm == 4 ) ventilator ( MOSFET_VENT1, VENT_AUS );
376  }
377  else if ( flag_tcrit[sensor_nummer] ) // Bei einer kritischen Temperatur,
378  {
379  if ( kritischer_durchlauf[sensor_nummer] >= 2 ) // und wenn 20s vergangen sind,
380  { // seit der Vent angeschaltet wurde
381  if ( temp[sensor_nummer] >= kritische_temp[sensor_nummer] ) // die temp nicht gesunken ist,
382  {
383  kritischer_durchlauf[sensor_nummer] = 0;
384  kritische_temp[sensor_nummer] = 0.00;
385  notstrom (); // wird ein Notaus aktiviert
386  }
387  }
388  else
389  kritischer_durchlauf[sensor_nummer]++;
390  }
391  }
392  else // Ventilator läuft nicht
393  {
394  if ( flag_tcrit[sensor_nummer] )
395  {
396  kritischer_durchlauf[sensor_nummer] = 0; // Flag für t_krit wird gesetzt, im nächsten Durchlauf darf die Temperatur nicht höher sein
397  kritische_temp[sensor_nummer] = temp[sensor_nummer]; // Vergleichstemperatur sichern
398  ventilator ( MOSFET_VENT1, VENT_AN );
399  }
400  else if ( flag_tupper[sensor_nummer] )
401  {
402  ventilator ( MOSFET_VENT1, VENT_AN );
403  }
404  }
405  }
406 
407  for ( int sensor_nummer = 4; sensor_nummer <= 7; sensor_nummer++ )
408  {
409  if ( vent_2 ) // Wenn der Ventilator läuft, dann ist vent = true
410  {
411  if ( !flag_tupper[sensor_nummer] ) // Temperatur unter Obergrenze
412  {
413  t_norm = 0; // Wenn alle Zellen kühl genug sind,
414  for ( int sensor = 4; sensor <= 7; sensor++ ) // kann der Ventilator ausgeschaltet werden
415  {
416  if ( !flag_tupper[sensor] ) t_norm++;
417  }
418  if ( t_norm == 4 ) ventilator ( MOSFET_VENT2, VENT_AUS );
419  }
420  else if ( flag_tcrit[sensor_nummer] ) // Bei einer kritischen Temperatur,
421  {
422  if ( kritischer_durchlauf[sensor_nummer] >= 2 ) // und wenn 20s vergangen sind,
423  { // seit der Vent angeschaltet wurde
424  if ( temp[sensor_nummer] >= kritische_temp[sensor_nummer] ) // die temp nicht gesunken ist,
425  {
426  kritischer_durchlauf[sensor_nummer] = 0;
427  kritische_temp[sensor_nummer] = 0.00;
428  notstrom (); // wird ein Notaus aktiviert
429  }
430  }
431  else
432  kritischer_durchlauf[sensor_nummer]++;
433  }
434  }
435  else // Ventilator läuft nicht
436  {
437  if ( flag_tcrit[sensor_nummer] )
438  {
439  kritischer_durchlauf[sensor_nummer] = 0; // Flag für t_krit wird gesetzt, im nächsten Durchlauf darf die Temperatur nicht höher sein
440  kritische_temp[sensor_nummer] = temp[sensor_nummer]; // Vergleichstemperatur sichern
441  ventilator ( MOSFET_VENT2, VENT_AN );
442  }
443  else if ( flag_tupper[sensor_nummer] )
444  {
445  ventilator ( MOSFET_VENT2, VENT_AN );
446  }
447  }
448  }
449 
450 }
451 
452 void akkuauswahl ( void )
453 {
454  float akku_voltage_P1 = 0.00, akku_voltage_P2 = 0.00; // Spannung der aktiven Batterie wird als Vergleichswert
455  float max_voltage_P1 = 0.00, max_voltage_P2 = 0.00; // höchste Spannung je Säule
456  uint8_t zelle_P1 = 0, zelle_P2 = 4; // Batterienummer mit der maximalen Spannung
457  float toleranz = 0.10;
458 
459  akku_voltage_P1 = voltage[aktuelle_zelle_P1]; // Die aktuelle Spannung der aktiven Batterie wird als Vergleichswert gesetzt.
460  akku_voltage_P2 = voltage[aktuelle_zelle_P2]; // Die aktuelle Spannung der aktiven Batterie wird als Vergleichswert gesetzt.
461 
462  if ( entlade_start ) // entlade_start = true nach Auswahl "Betrieb" in Hauptmenü, wird hier auf false gesetzt.
463  { // In jeder Säule wird als Startwert der letzte angesteckte Akku gesetzt und eingeschaltet.
464  for ( int i = 0; i <= 3; i++ )
465  {
466  if ( akku[i] )
467  {
468  aktuelle_zelle_P1 = i;
469  akku_voltage_P1 = voltage[i];
470  }
471  }
472 
473  for ( int i = 4; i <= 7; i++ )
474  {
475  if ( akku[i] )
476  {
477  aktuelle_zelle_P2 = i;
478  akku_voltage_P2 = voltage[i];
479  }
480  }
481 
482  mosfet_battery ( aktuelle_zelle_P1, AKKU_1_AN ); // In jeder Säule wird als Startwert der letzte angesteckte Akku gesetzt und eingeschaltet.
483  mosfet_battery ( aktuelle_zelle_P2, AKKU_2_AN ); // In jeder Säule wird als Startwert der letzte angesteckte Akku gesetzt und eingeschaltet.
484 
486 
487  h[aktuelle_zelle_P1][0] = now.hours;
488  m[aktuelle_zelle_P1][0] = now.minutes;
489  s[aktuelle_zelle_P1][0] = now.seconds;
490 
491  h[aktuelle_zelle_P2][0] = now.hours;
492  m[aktuelle_zelle_P2][0] = now.minutes;
493  s[aktuelle_zelle_P2][0] = now.seconds;
494 
495  entlade_start = false;
496  }
497 
498 // Batterie mit maximaler Spannung in jeder Säule wird ausgesucht (fehlende, entladene oder überhitzte Batterien werden ausgeschlossen)
499 
500  for ( int i = 0; i <= 3; i++ )
501  {
502  if ( akku[i] ) // Akku vorhanden
503  {
504  if ( !akku_laden[i] ) // Akku noch ausreichend geladen
505  {
506  if ( !flag_tupper[i] ) // Akku nicht zu warm
507  {
508  if ( voltage[i] > max_voltage_P1 )
509  {
510  max_voltage_P1 = voltage[i];
511  zelle_P1 = i;
512  }
513  }
514  }
515  }
516  }
517 
518  for ( int i = 4; i <= 7; i++ )
519  {
520  if ( akku[i] ) // Akku vorhanden
521  {
522  if ( !akku_laden[i] ) // Akku noch ausreichend geladen
523  {
524  if ( !flag_tupper[i] ) // Akku nicht zu warm
525  {
526  if ( voltage[i] > max_voltage_P2 )
527  {
528  max_voltage_P2 = voltage[i];
529  zelle_P2 = i;
530  }
531  }
532  }
533  }
534  }
535 
536 // Batterie mit höchster Spannung wird mit der aktiven Batterie verglichen, die B. mit höherer Spannung (inkl. Toleranz) wird ausgewählt.
537 
538  zeit_berechnung (); // Berechnung der Zeit, vor umschalten des aktiven Akkus
539 
541 
542  if ( zelle_P1 != aktuelle_zelle_P1 ) // Wenn die aktuelle Batterie schon die höchste Spannung hat, bleibt alles unverändert.
543  {
544  if ( max_voltage_P1 > (akku_voltage_P1 + toleranz) ) // Wenn die neue Batterie eine höhere Spannung als die aktive Batterie zzgl. Toleranz hat, wird gewechselt.
545  {
546  mosfet_battery ( zelle_P1, AKKU_1_AN );
547  mosfet_battery ( aktuelle_zelle_P1, AKKU_1_AUS );
548  aktuelle_zelle_P1 = zelle_P1;
549  }
550  h[aktuelle_zelle_P1][0] = now.hours;
551  m[aktuelle_zelle_P1][0] = now.minutes;
552  s[aktuelle_zelle_P1][0] = now.seconds;
553  }
554 
555  if ( zelle_P2 != aktuelle_zelle_P2 ) // Wenn die aktuelle Batterie schon die höchste Spannung hat, bleibt alles unverändert.
556  {
557  if ( max_voltage_P2 > (akku_voltage_P2 + toleranz) ) // Wenn die neue Batterie eine höhere Spannung als die aktive Batterie zzgl. Toleranz hat, wird gewechselt.
558  {
559  mosfet_battery ( zelle_P2, AKKU_2_AN );
560  mosfet_battery ( aktuelle_zelle_P2, AKKU_2_AUS );
561  aktuelle_zelle_P2 = zelle_P2;
562  }
563  h[aktuelle_zelle_P2][0] = now.hours;
564  m[aktuelle_zelle_P2][0] = now.minutes;
565  s[aktuelle_zelle_P2][0] = now.seconds;
566  }
567 
568  PORTB.OUTSET = PIN1_bm;
569 }
570 
571 void SOC_berechnung ( void )
572 {
574  /*
575  float delta_time = 0;
576 
577  if ( (einlese_zeit[NEUE_ZEIT] - einlese_zeit[ALTE_ZEIT]) < 0 )
578  delta_time = 60 - einlese_zeit[ALTE_ZEIT] + einlese_zeit[NEUE_ZEIT];
579  else
580  delta_time = einlese_zeit[NEUE_ZEIT] - einlese_zeit[ALTE_ZEIT];
581 
582  delta_time /= 3600.0;
583 
584  for ( int i = 0; i <= 7; i++ )
585  {
586  charge[i] = charge[i] + current[i] * delta_time;
587  if ( laden )
588  {
589  if ( current[i] <= 10 ) c_max[i] = charge[i];
590  }
591  SOC[i] = charge[i] * 100 / c_max[i]; //um auf die % zu kommen, c*100/750 --> gekürzt c/7.5
592  }
593  */
594 
595  for ( int i = 0; i <= 7; i++ )
596  {
597  charge[i] = charge[i] + current[i] * (WARTEZEIT / 3600.0);
598  if ( laden )
599  {
600  if ( current[i] <= 10 ) c_max[i] = charge[i];
601  }
602  SOC[i] = charge[i] * 100 / c_max[i]; //um auf die % zu kommen, c*100/750 --> gekürzt c/7.5
603  }
604 }
605 
606 void lade_bestimmung ( void )
607 {
608  uint8_t B1 = 0, B2 = 0;
609 
610  for ( int i = 0; i <= 3; i++ )
611  {
612  akku_laden[i] = false;
613 
614  if ( akku[i] )
615  {
616  if ( voltage[i] <= VOLTAGE_CRIT )
617  {
618  akku_laden[i] = true;
619  notstrom ();
620  }
621  else if ( SOC[i] <= SOC_CRIT )
622  {
623  akku_laden[i] = true;
624  notstrom ();
625  }
626  else if ( voltage[i] <= VOLTAGE_LOW )
627  {
628  akku_laden[i] = true;
629  B1++;
630  }
631  else if ( SOC[i] <= SOC_LOW )
632  {
633  akku_laden[i] = true;
634  B1++;
635  }
636  }
637  }
638 
639  if ( B1 == 4 ) notstrom ();
640 
641  for ( int i = 4; i <= 7; i++ )
642  {
643  akku_laden[i] = false;
644 
645  if ( akku[i] )
646  {
647  if ( voltage[i] <= VOLTAGE_CRIT )
648  {
649  akku_laden[i] = true;
650  notstrom ();
651  }
652  else if ( SOC[i] <= SOC_CRIT )
653  {
654  akku_laden[i] = true;
655  notstrom ();
656  }
657  else if ( voltage[i] <= VOLTAGE_LOW )
658  {
659  akku_laden[i] = true;
660  B2++;
661  }
662  else if ( SOC[i] <= SOC_LOW )
663  {
664  akku_laden[i] = true;
665  B2++;
666  }
667  }
668  }
669 
670  if ( B2 == 4 ) notstrom ();
671 }
672 
673 void notstrom ( void )
674 {
675 // Alles ausschalten um jeden Strom aus dem Stromkreis zu nehmen
676 // Alle Akkus ausschalten
677 
678  laden = false;
679  usb_versorgung = false;
680 
681  if ( PORTD_IN & LADE_POWER_IN_INT_bm )
682  {
683  laden = true;
685  mosfet_notstrom ( NOTSTROM_AUS );
686  }
687  else if ( PORTD_IN & USB_POWER_IN_INT_bm )
688  {
689  usb_versorgung = true;
691  mosfet_notstrom ( NOTSTROM_AUS );
692  }
693  else if ( akku[4] && (voltage[4] >= VOLTAGE_CRIT) && !flag_tcrit[4] )
694  {
695  mosfet_notstrom ( NOTSTROM_AN );
697  }
698  else
700 
701  if ( !(betriebsart == LEERLAUF) )
702  {
703  message_notaus ();
704  msgbox_notaus = true;
705  }
706 }
707 
708 void SOH_berechnung ( void )
709 {
710  for ( int i = 0; i <= 7; i++ )
711  {
712  if ( current[i] <= 10 )
713  {
714  SOH[i] = c_max[i] * 100 / CHARGE_MAX_CAPACITY; //zur Umrechnung in Prozent
715  }
716  }
717 }
718 
719 void terminal_ausgabe ()
720 {
721  if ( !(betriebsart == LEERLAUF) )
723  else
724  leerlauf_voltage_get_data ();
725 
727 
728  printf ( "\x1B[2J\x1B[2;1H" );
729  printf ( "\x1B[1;33mB A T M A N\x1B[0m\r\n\r\n\r\n" );
730 
731  if ( betriebsart == BETRIEB )
732  printf ( "\x1B[2;33mBETRIEB\x1B[0m\r\n\r\n" );
733  else if ( betriebsart == LADEN )
734  printf ( "\x1B[2;33mLADEN\x1B[0m\r\n\r\n" );
735  else
736  printf ( "\x1B[2;33mLEERLAUF\x1B[0m\r\n\r\n" );
737 
738  printf ( "\x1B[2;31mBlock 1\x1B[0m\r\n" );
739  for ( int i = 0; i <= 3; i++ )
740  {
741  printf ( "\x1B[2;37mNummer \x1B[0m \x1B[1;37m%i\x1B[0m ", i );
742  printf ( "\x1B[2;37mCurrent\x1B[0m \x1B[1;37m%5imA\x1B[0m ", current[i] );
743  printf ( "\x1B[2;37mVoltage\x1B[0m \x1B[1;37m%5.2fV\x1B[0m ", voltage[i] );
744  printf ( "\x1B[2;37mTemperatur\x1B[0m \x1B[1;37m%i°C\x1B[0m ", temp[i] );
745  printf ( "\r\n" );
746  }
747 
748  printf ( "\r\n\r\n" );
749 
750  printf ( "\x1B[2;31mBlock 2\x1B[0m\r\n" );
751  for ( int i = 4; i <= 7; i++ )
752  {
753  printf ( "\x1B[2;37mNummer \x1B[0m \x1B[1;37m%i\x1B[0m ", i );
754  printf ( "\x1B[2;37mCurrent\x1B[0m \x1B[1;37m%5imA\x1B[0m ", current[i] );
755  printf ( "\x1B[2;37mVoltage\x1B[0m \x1B[1;37m%5.2fV\x1B[0m ", voltage[i] );
756  printf ( "\x1B[2;37mTemperatur\x1B[0m \x1B[1;37m%i°C\x1B[0m ", temp[i] );
757  printf ( "\r\n" );
758  }
759 }
760 
761 void terminal_usb_ausgabe ()
762 {
763  if ( !(betriebsart == LEERLAUF) )
765  else
766  leerlauf_voltage_get_data ();
767 
769 
770  fprintf ( &usbout, "\x1B[2J\x1B[2;1H" );
771  fprintf ( &usbout, "\x1B[1;33mB A T M A N\x1B[0m\r\n\r\n\r\n" );
772 
773  if ( betriebsart == BETRIEB )
774  fprintf ( &usbout, "\x1B[2;33mBETRIEB\x1B[0m\r\n\r\n" );
775  else if ( betriebsart == LADEN )
776  fprintf ( &usbout, "\x1B[2;33mLADEN\x1B[0m\r\n\r\n" );
777  else
778  fprintf ( &usbout, "\x1B[2;33mLEERLAUF\x1B[0m\r\n\r\n" );
779 
780  fprintf ( &usbout, "\x1B[2;31mBlock 1\x1B[0m\r\n" );
781  for ( int i = 0; i <= 3; i++ )
782  {
783  fprintf ( &usbout, "\x1B[2;37mNummer \x1B[0m \x1B[1;37m%i\x1B[0m ", i );
784  fprintf ( &usbout, "\x1B[2;37mCurrent\x1B[0m \x1B[1;37m%5imA\x1B[0m ", current[i] );
785  fprintf ( &usbout, "\x1B[2;37mVoltage\x1B[0m \x1B[1;37m%5.2fV\x1B[0m ", voltage[i] );
786  fprintf ( &usbout, "\x1B[2;37mTemperatur\x1B[0m \x1B[1;37m%i°C\x1B[0m ", temp[i] );
787  fprintf ( &usbout, "\r\n" );
788  }
789 
790  fprintf ( &usbout, "\r\n\r\n" );
791 
792  fprintf ( &usbout, "\x1B[2;31mBlock 2\x1B[0m\r\n" );
793  for ( int i = 4; i <= 7; i++ )
794  {
795  fprintf ( &usbout, "\x1B[2;37mNummer \x1B[0m \x1B[1;37m%i\x1B[0m ", i );
796  fprintf ( &usbout, "\x1B[2;37mCurrent\x1B[0m \x1B[1;37m%5imA\x1B[0m ", current[i] );
797  fprintf ( &usbout, "\x1B[2;37mVoltage\x1B[0m \x1B[1;37m%5.2fV\x1B[0m ", voltage[i] );
798  fprintf ( &usbout, "\x1B[2;37mTemperatur\x1B[0m \x1B[1;37m%i°C\x1B[0m ", temp[i] );
799  fprintf ( &usbout, "\r\n" );
800  }
801 }
802 
803 void excel_ausgabe ()
804 {
805  static bool einmal = false;
806 
807  if ( !einmal )
808  {
809  printf ( "Zeit;Zelle;Vorhanden;Benutzung;Current;Voltage;Temperatur;Charge;SOC;SOH\n\r" );
810  einmal = true;
811  }
812 
814  for ( int battery_nmr = 0; battery_nmr <= 7; battery_nmr++ )
815  {
816  printf ( "%02i:%02i:%02i;%i;%i;%i;", now.hours, now.minutes, now.seconds, battery_nmr, akku[battery_nmr], akku_an[battery_nmr] );
817  printf ( "%i;%2.2f;%i;%2.2f;", current[battery_nmr], voltage[battery_nmr], temp[battery_nmr], charge[battery_nmr] );
818  printf ( "%i;%i\n\r", SOC[battery_nmr], SOH[battery_nmr] );
819  }
820 
821 }
822 
823 void zeit_berechnung ( void )
824 {
826 
827  for ( int i = 0; i <= 7; i++ )
828  {
829  h[i][1] = now.hours;
830  m[i][1] = now.minutes;
831  s[i][1] = now.seconds;
832  }
833 
834  if ( betriebsart == LADEN )
835  {
836  for ( int i = 0; i <= 7; i++ )
837  {
838  ladezeit_s[i] += ((h[i][1] - h[i][0]) * 3600) + ((m[i][1] - m[i][0]) * 60) + (s[i][1] - s[i][0]);
839  h[i][0] = now.hours;
840  m[i][0] = now.minutes;
841  s[i][0] = now.seconds;
842  }
843  }
844  else if ( betriebsart == BETRIEB )
845  {
846  for ( int i = 0; i <= 7; i++ )
847  {
848  if ( akku_an[i] )
849  {
850  betriebszeit_s[i] += ((h[i][1] - h[i][0]) * 3600) + ((m[i][1] - m[i][0]) * 60) + (s[i][1] - s[i][0]);
851  h[i][0] = now.hours;
852  m[i][0] = now.minutes;
853  s[i][0] = now.seconds;
854  }
855  }
856  }
857 }
858 
859 //Laden
860 ISR( PORTD_INT1_vect )
861 {
862 
863  /* if ( PORTE.IN & LADE_INT )
864  {
865  mosfet_charge_on ();
866  if ( PORTE.IN & TEMPERATURE_INT ) temperatur_laden ();
867  lade_steuerung ();
868  }
869  else
870  {
871  SOC_berechnung ();
872  if ( PORTE.IN & TEMPERATURE_INT ) temperatur_entladen ();
873  mosfet_charge_off ();
874  entlade_steuerung ();
875  }*/
876  _delay_ms ( 300 );
877  if ( PORTD.IN & LADE_POWER_IN_INT_bm )
878  {
879  laden = true;
880  screen_home ();
881  }
882  else
883  {
884  laden = false;
885  betriebsart = LEERLAUF;
887  mosfet_battery ( MOSFET_B_1_1, AKKU_1_AN );
888  mosfet_battery ( MOSFET_B_2_1, AKKU_2_AN );
890  zeit_counter = 10;
891  }
892 
893 }
894 
895 //Last
896 ISR( PORTE_INT0_vect )
897 {
898  if ( PORTE_IN & LAST_bm )
899  last = true;
900  else
901  last = false;
902 }
Konstanten, Filter und Commands für den Temperatursensor MCP 9843.
Header, Definition der Konstanten und Commands für DS1388.
void mcp9843_get_data(void)
Die Daten des Temperatursensors werden ausgelesen.
Definition: temp_mcp9843.c:185
void DS1388_get_datetime(void)
Die Uhrzeit und das Datum werden ausgelesen.
Definition: ds1388_rtc.c:107
Standard board header file. Diese Datei enthält die Standardparameter und Pinbelegungen für das BMS B...
void ventilator(uint8_t ventNumber, bool set)
Schaltet einen Ventilator ein oder aus.
Definition: ventilator.c:39
void sdcard_bms_read_state(void)
Zustandsdaten der Batterien werden gelesen.
Definition: sdcard_bms.c:88
FILE usbout
Filestreams für USB Kommunikation.
Definition: board_init.c:32
void bildschirm_ausgabe()
Belegung der Icon-Parameter für die Displayausgabe und Aufruf der verschiedenen Screens.
Standard Header Datei, Definition der Batteriekonstanten und Grenzwerte.
void message_notaus(void)
Messagebox mit Text NOTAUS.
Definition: screens_gfx.c:557
void sdcard_bms_write_state(void)
Zustandsdaten der Batterien werden gespeichert.
Definition: sdcard_bms.c:50
Standardheader und Auswahl der Übertragungsgeschwindigkeit.
XMEGA TWI master driver header file.
void sdcard_bms_daten_laden(void)
Daten im Modus "Laden" werden auf die SD-Karte geschrieben.
Definition: sdcard_bms.c:298
Standardheader.
void AD7997_voltage_get_data(void)
Ermittelt die Spannungen der Batterien.
Definition: ad7997.c:211
void screen_home(void)
Der Home-Screen.
Definition: screens_gfx.c:507
Standardheader. Definition der Iconfarben.
Standardheader.
void SOC_berechnung(void)
Definition: BMS-Basic.c:571
Definition der Schalterstellungen für die einzelnen MOSFETs.
Standardheader. Datenmanagement für BMS-Daten mit SD Card Reader.
uint8_t zeit_counter
Main.
Definition: main.c:53
void mosfet_safeschaltung(void)
Sicherheitsschaltung der BMS-Platine, alle Funktionen sind aus.
Definition: bms_mosfet.c:37
void sdcard_bms_daten_betrieb(void)
Daten im Modus "Betrieb" werden auf die SD-Karte geschrieben.
Definition: sdcard_bms.c:225
void AD7997_current_get_data(void)
Ermittelt die Stromstärke in den Batteriestromkreisen.
Definition: ad7997.c:128
#define COM74HC595_SIZE
Anzahl der über diesen Port anzusteuernden 74HC595 Bausteine.
Definition: com74HC595.h:21
Standardheader.
void mosfet_charge_off(void)
Die Ladefunktion wird ausgeschaltet.
Definition: bms_mosfet.c:107
void mosfet_battery(uint8_t batteryNumber, bool set)
Einzelne Akkus werden in den Stromkreis zu- oder abgeschaltet.
Definition: bms_mosfet.c:141
Standardheader und Positionen der Zeilen und Spalten auf den jeweiligen Screens.
Header für ADC AD7997, Definition der Register und Commands.