Hanna
Sourcecode Batteriemanagementsystem
display_ausgabe.c
gehe zur Dokumentation dieser Datei
1 
15 #include "display_ausgabe.h"
16 
17 #include "usb_cdc.h"
18 //#include "config_clock.h"
19 #include "usb_stdio.h"
20 #include "gfx_draw_bms_demo.h"
21 
22 /* Include symbols and bitmaps */
23 #include "lib_icons.h"
24 #include "sysfont.h"
25 #include "lib_gfx_bms.h"
26 
27 #include "SD-Card/sdcard_demo.h"
28 //#include "int32MHz.h"
29 #include "config_clock.h"
31 #include "screens_gfx.h"
32 #include "Hardware/taster.h"
33 #include "Hardware/com74HC595.h"
34 #include "Hardware/temp_mcp9843.h"
35 #include "Hardware/ds1388_rtc.h"
36 #include "Hardware/ventilator.h"
37 #include "Hardware/bms_mosfet.h"
38 #include "Hardware/ad7997.h"
39 #include "BMS-Basic.h"
40 
41 bool messwert_flag = false;
42 
54 {
55  int amp_akt = 0;
56  float volt_akt = 0.0;
57  int gesamt_SOC = 0;
58 
59 // if ( PORTD_IN & LADE_POWER_IN_INT_bm )
60 // laden = true;
61 // else
62 // laden = false;
63 
64  if ( PORTE_IN & LAST_bm )
65  last = true;
66  else
67  last = false;
68 
69  if ( !(betriebsart == LEERLAUF) )
71  else
72  leerlauf_voltage_get_data ();
73 
75 
76 // Screen Betrieb: aktuelle Spannung und Stromstärke berechnen
77  volt_akt = voltage[aktuelle_zelle_P1] + voltage[aktuelle_zelle_P2];
78  amp_akt = (current[aktuelle_zelle_P1] + current[aktuelle_zelle_P2]) / 2;
79 
80 // Screen Betrieb: Status zuweisen
81  scr_betrieb.mAmp = amp_akt;
82  scr_betrieb.volt = volt_akt;
83  scr_betrieb.vent1 = vent_1;
84  scr_betrieb.vent2 = vent_2;
85  scr_betrieb.verbraucher = last;
86 
87 // Screen Betrieb: Akkufarben zuweisen
88  for ( int i = 0; i <= 3; i++ )
89  {
90  if ( akku_an[i] )
91  scr_betrieb.battery_color[i] = USED_AKKU;
92  else if ( !akku[i] )
93  scr_betrieb.battery_color[i] = NO_AKKU;
94  else
95  {
96  scr_betrieb.battery_color[i] = UNUSED_AKKU;
97  if ( akku_laden[i] ) scr_betrieb.battery_color[i] = LADE_AKKU;
98  }
99  }
100  for ( int i = 4; i <= 7; i++ )
101  {
102  if ( akku_an[i] )
103  scr_betrieb.battery_color[i] = USED_AKKU;
104  else if ( !akku[i] )
105  scr_betrieb.battery_color[i] = NO_AKKU;
106  else
107  {
108  scr_betrieb.battery_color[i] = UNUSED_AKKU;
109  if ( akku_laden[i] ) scr_betrieb.battery_color[i] = LADE_AKKU;
110  }
111  }
112 
113 // Screen Betrieb: Spannung je Akku
114  for ( int i = 0; i <= 7; i++ )
115  {
116  scr_betrieb.bat_voltage[i] = voltage[i];
117  }
118 
119 
120 // Screen Akku_Info: Status zuweisen
121  for ( int i = 0; i <= 7; i++ )
122  {
123 // Screen Akku_Info: Ventilatoren
124  if ( i <= 3 )
125  scr_akku_info[i].vent = vent_1;
126  else
127  scr_akku_info[i].vent = vent_2;
128 
129 // Screen Akku_Info: Status
130  scr_akku_info[i].verbraucher = last;
131  scr_akku_info[i].mAmp = current[i];
132  scr_akku_info[i].volt = voltage[i];
133  scr_akku_info[i].soc = SOC[i];
134  scr_akku_info[i].soh = SOH[i];
135  scr_akku_info[i].temperatur = temp[i];
136 
137 // Standard Akku ist grau, aktiver Akku grün, nicht durchgestrichen. Ist ein Akku nicht angesteckt, wird er durchgestrichen und weiß.
138  if ( akku[i] )
139  {
140  if ( akku_an[i] )
141  {
142  scr_akku_info[i].top_bat_color = GFX_COLOR_GREEN;
143  scr_akku_info[i].top_bat_cross = GFX_BAT_NO_CROSS;
144  }
145  else
146  {
147  scr_akku_info[i].top_bat_color = GFX_COLOR_LT_GRAY;
148  scr_akku_info[i].top_bat_cross = GFX_BAT_NO_CROSS;
149  }
150  }
151  else
152  {
153  scr_akku_info[i].top_bat_color = GFX_COLOR_WHITE;
154  scr_akku_info[i].top_bat_cross = GFX_BAT_CROSS;
155  }
156 
157 // Screen Akku_Info: SOC Akkufarbe
158  if ( SOC[i] >= 90 )
159  scr_akku_info[i].soc_color = GFX_CHARGE_FULL;
160  else if ( SOC[i] >= 70 )
161  scr_akku_info[i].soc_color = GFX_CHARGE_3_4;
162  else if ( SOC[i] >= 50 )
163  scr_akku_info[i].soc_color = GFX_CHARGE_2_4;
164  else if ( SOC[i] >= 30 )
165  scr_akku_info[i].soc_color = GFX_CHARGE_WARN;
166  else
167  scr_akku_info[i].soc_color = GFX_CHARGE_CRIT;
168 
169 // Screen Akku_Info: Temperatur Farbe auswählen
170  if ( flag_tcrit[i] )
171  scr_akku_info[i].temp_color = TEMP_HIGH;
172  else if ( flag_tupper[i] )
173  scr_akku_info[i].temp_color = TEMP_MIDDLE;
174  else
175  scr_akku_info[i].temp_color = TEMP_LOW;
176 
177 // Screen Akku_Info: Akkunummer bestimmen
178  if ( i <= 3 )
179  sprintf ( scr_akku_info[i].name, "1.%1i", i + 1 );
180  else
181  sprintf ( scr_akku_info[i].name, "2.%1i", i - 3 );
182  }
183 
184 // Screen Laden: Ventilatoren
185  scr_laden.vent1 = vent_1;
186  scr_laden.vent2 = vent_2;
187 
188 // Screen Laden: Batteriefarbe ermitteln
189  for ( int i = 0; i <= 7; i++ )
190  {
191  if ( SOC[i] >= 95 )
192  scr_laden.battery_color[i] = SOC_HIGH_C;
193  else if ( SOC[i] >= 70 )
194  scr_laden.battery_color[i] = SOC_MIDDLE_C;
195  else
196  scr_laden.battery_color[i] = SOC_LOW_C;
197 // Screen Laden: SOC der Anlage berechnen
198  gesamt_SOC = gesamt_SOC + SOC[i];
199  }
200 
201  // Screen Laden: Stromstärke je Akku
202  for ( int i = 0; i <= 7; i++ )
203  {
204  scr_laden.mAmp[i] = current[i];
205  }
206 
207 // Screen Laden: SOC Farbe ermitteln
208  if ( gesamt_SOC >= 720 )
209  scr_laden.soc_color = GFX_CHARGE_FULL;
210  else if ( gesamt_SOC >= 560 )
211  scr_laden.soc_color = GFX_CHARGE_3_4;
212  else if ( gesamt_SOC >= 400 )
213  scr_laden.soc_color = GFX_CHARGE_2_4;
214  else if ( gesamt_SOC >= 240 )
215  scr_laden.soc_color = GFX_CHARGE_WARN;
216  else
217  scr_laden.soc_color = GFX_CHARGE_CRIT;
218 
219 // Screen Warnung
220  uint8_t soc_nr = 0;
221  int8_t warn_nr = -1;
222  uint8_t warn_anz = 0;
223 
224  scr_akku_warning.temp_color = TEMP_LOW;
225  scr_akku_warning.temperatur = TNORM;
226  scr_akku_warning.volt = false;
227  scr_akku_warning.soc = false;
228  scr_akku_warning.soh = false;
229  scr_betrieb.warnung = false;
230 
231  for ( int i = 0; i <= 7; i++ )
232  {
233 // Screen Warnung: Temperaturinfo für > TUPPER
234  if ( flag_tupper[i] )
235  {
236  scr_akku_warning.temp_color = TEMP_MIDDLE;
237  scr_akku_warning.temperatur = TUPPER;
238  scr_betrieb.warnung = true;
239  if ( i != warn_nr ) warn_anz++;
240  warn_nr = i;
241  }
242 
243 // Screen Warnung: Spannungsinfo
244  if ( voltage[i] <= VOLTAGE_LOW )
245  {
246  scr_akku_warning.volt = true;
247  scr_betrieb.warnung = true;
248  if ( i != warn_nr ) warn_anz++;
249  warn_nr = i;
250  }
251 
252 // Screen Warnung: SOC Warnung
253  if ( SOC[i] <= SOC_LOW )
254  {
255  scr_akku_warning.soc = true;
256  scr_betrieb.warnung = true;
257  if ( i != warn_nr ) warn_anz++;
258  warn_nr = i;
259  }
260 
261 // Screen Warnung: SOH Warnung
262  if ( SOH[i] <= SOH_LOW )
263  {
264  scr_akku_warning.soh = true;
265  scr_betrieb.warnung = true;
266  if ( i != warn_nr ) warn_anz++;
267  warn_nr = i;
268  }
269  }
270 
271 // Screen Warnung: SOC Status
272  for ( int i = 0; i < 8; i++ )
273  {
274  if ( SOC[i] < SOC[soc_nr] ) soc_nr = i;
275  }
276  if ( SOC[soc_nr] >= 90 )
277  scr_akku_warning.soc_color = GFX_CHARGE_FULL;
278  else if ( SOC[soc_nr] >= 70 )
279  scr_akku_warning.soc_color = GFX_CHARGE_3_4;
280  else if ( SOC[soc_nr] >= 50 )
281  scr_akku_warning.soc_color = GFX_CHARGE_2_4;
282  else if ( SOC[soc_nr] >= 30 )
283  {
284  scr_akku_warning.soc_color = GFX_CHARGE_WARN;
285  scr_betrieb.warnung = true;
286  if ( soc_nr != warn_nr ) warn_anz++;
287  warn_nr = soc_nr;
288  }
289  else
290  {
291  scr_akku_warning.soc_color = GFX_CHARGE_CRIT;
292  scr_betrieb.warnung = true;
293  if ( soc_nr != warn_nr ) warn_anz++;
294  warn_nr = soc_nr;
295  }
296 
297 // Screen Warnung: Temperaturinfo für > TKRIT
298  for ( int i = 0; i <= 7; i++ )
299  {
300  if ( flag_tcrit[i] )
301  {
302  scr_akku_warning.temp_color = TEMP_HIGH;
303  scr_akku_warning.temperatur = TCRIT;
304  scr_betrieb.warnung = true;
305  if ( i != warn_nr ) warn_anz++;
306  warn_nr = i;
307  }
308  }
309 
310 // Screen Warnung: Batteriename ermitteln
311  if ( warn_anz == 1 )
312  {
313  if ( warn_nr <= 3 )
314  sprintf ( scr_akku_warning.name, "1.%1i", warn_nr + 1 );
315  else
316  sprintf ( scr_akku_warning.name, "2.%1i", warn_nr - 3 );
317  }
318  else
319  sprintf ( scr_akku_warning.name, "+++" );
320 
321 // Ab hier wird geprüft, welche Bildschirme aufgerufen werden sollen
322 // -----------------------------------------------------------------
323 
324 // Displaytaster werden über Interrupt erfasst, aber erst hier in der Schleife über Polling abgefragt.
325  if ( taster_nr || messwert_flag )
326  {
327  if ( taster_nr && msgbox_notaus )
328  {
329  taster_nr = 0;
330  msgbox_notaus = false; // Notaus-Message verschwindet, sobald irgendein Taster gedrückt wurde.
331  gfx_draw_filled_rect( 0, 0, gfx_get_width (), gfx_get_height (), GFX_COLOR_WHITE );
332  }
333 
334  messwert_flag = false;
335  if ( screen_flag == SCREEN_FLAG_BETRIEB || (screen_flag == 0 && !laden) )
336  {
337  switch (taster_nr)
338  {
339  case 1: // Taster 1 startet den Home-Screen
340  auswahl_nr = -1;
341  taster_nr = 0;
342  screen_home ();
343  break;
344  case 2: // Auswahl einer Batterie, für die der Info-Screen gestartet wird.
345  auswahl_nr++;
346  if ( auswahl_nr % 8 == 0 )
347  gfx_draw_filled_circle( auswahl_batterie[7].x, auswahl_batterie[7].y, 5, GFX_COLOR_WHITE, GFX_WHOLE );
348  else
349  gfx_draw_filled_circle( auswahl_batterie[auswahl_nr % 8 - 1].x, auswahl_batterie[auswahl_nr % 8 - 1].y, 5, GFX_COLOR_WHITE, GFX_WHOLE );
350  gfx_draw_filled_circle( auswahl_batterie[auswahl_nr % 8].x, auswahl_batterie[auswahl_nr % 8].y, 5, GFX_COLOR_RED, GFX_WHOLE );
351  taster_nr = 0;
352  break;
353  case 3: // "Enter" bestätigt die Auswahl.
354  if ( auswahl_nr == -1 ) auswahl_nr = 0; // Bei "Enter" ohne vorherige Auswahl wird Akku 1 gesetzt.
355  if ( (auswahl_nr % 8) < 4 )
356  sprintf ( scr_akku_info[auswahl_nr % 8].name, "1.%1i", auswahl_nr % 8 + 1 );
357  else
358  sprintf ( scr_akku_info[auswahl_nr % 8].name, "2.%1i", (auswahl_nr % 8) - 3 );
359  taster_nr = 0;
360  screen_return = SCREEN_RETURN_BETRIEB;
361  screen_akku_info ( scr_akku_info[auswahl_nr % 8] );
362  break;
363  case 4: // Taster 4 startet den Warnung-Screen
364  if ( scr_betrieb.warnung )
365  {
366  auswahl_nr = -1;
367  taster_nr = 0;
368  screen_return = SCREEN_RETURN_BETRIEB;
369  screen_akku_warnung ( scr_akku_warning );
370  }
371  break;
372  default:
373  screen_betrieb ( scr_betrieb );
374  break;
375  }
376  }
377 
378  else if ( screen_flag == SCREEN_FLAG_AKKU_INFO )
379  {
380  switch (taster_nr)
381  {
382  case 1: // Taster 1 startet den Home-Screen
383  auswahl_nr = -1;
384  taster_nr = 0;
385  screen_home ();
386  break;
387  case 2: // Blättert zur Infoseite der nächsten Batterie
388  auswahl_nr++;
389  taster_nr = 0;
390  if ( (auswahl_nr % 8) < 4 )
391  sprintf ( scr_akku_info[auswahl_nr % 8].name, "1.%1i", auswahl_nr % 8 + 1 );
392  else
393  sprintf ( scr_akku_info[auswahl_nr % 8].name, "2.%1i", (auswahl_nr % 8) - 3 );
394  screen_akku_info ( scr_akku_info[auswahl_nr % 8] );
395  break;
396  case 3: // Taster 3 kehrt zum Startpunkt zurück
397  auswahl_nr = -1;
398  taster_nr = 0;
399  if ( screen_return )
400  screen_betrieb ( scr_betrieb );
401  else
402  screen_laden ( scr_laden );
403  break;
404  case 4: // Taster 4 startet den Warnung-Screen
405  if ( scr_betrieb.warnung )
406  {
407  auswahl_nr = -1;
408  taster_nr = 0;
409  screen_akku_warnung ( scr_akku_warning );
410  }
411  break;
412  default:
413  screen_akku_info ( scr_akku_info[auswahl_nr % 8] );
414  break;
415  }
416  }
417 
418  else if ( screen_flag == SCREEN_FLAG_WARNUNG )
419  {
420  switch (taster_nr)
421  {
422  case 1: // Taster 1 startet den Home-Screen
423  taster_nr = 0;
424  screen_home ();
425  break;
426  case 2: // Jeder andere Taster kehrt zum Startpunkt zurück
427  taster_nr = 0;
428  if ( screen_return )
429  screen_betrieb ( scr_betrieb );
430  else
431  screen_laden ( scr_laden );
432  break;
433  case 3: // Jeder andere Taster kehrt zum Startpunkt zurück
434  taster_nr = 0;
435  if ( screen_return )
436  screen_betrieb ( scr_betrieb );
437  else
438  screen_laden ( scr_laden );
439  break;
440  case 4: // Jeder andere Taster kehrt zum Startpunkt zurück
441  taster_nr = 0;
442  if ( screen_return )
443  screen_betrieb ( scr_betrieb );
444  else
445  screen_laden ( scr_laden );
446  break;
447  default:
448  break;
449  }
450  }
451 
452  else if ( screen_flag == SCREEN_FLAG_HOME )
453  {
454  switch (taster_nr)
455  {
456  case 1: // Taster 1 startet den Home-Screen
457  taster_nr = 0;
458  screen_home ();
459  break;
460  case 3: // Taster 3 startet den Betriebsmodus und den Betrieb-Screen
461  taster_nr = 0;
462  betriebsart = BETRIEB;
463  entlade_start = true;
464  entlade_steuerung ();
465  zeit_counter = 10;
466  screen_betrieb ( scr_betrieb );
467  break;
468  case 2: // Taster 2 startet den Lademodus und den Lade-Screen
469  if ( laden )
470  {
471  taster_nr = 0;
472  betriebsart = LADEN;
473  mosfet_charge_on ();
475  for ( int i = 0; i <= 7; i++ )
476  {
477  h[aktuelle_zelle_P1][0] = now.hours;
478  m[aktuelle_zelle_P1][0] = now.minutes;
479  s[aktuelle_zelle_P1][0] = now.seconds;
480  }
481  zeit_counter = 10;
482  screen_laden ( scr_laden );
483  }
484  break;
485  case 4: // Taster 4 startet den Leerlaufmodus und den Betrieb-Screen
486  taster_nr = 0;
487  betriebsart = LEERLAUF;
488  zeit_counter = 10;
489  screen_betrieb ( scr_betrieb );
490  break;
491  default:
492  break;
493  }
494  }
495 
496  else if ( screen_flag == SCREEN_FLAG_LADEN || (screen_flag == 0 && laden) )
497  {
498  switch (taster_nr)
499  {
500  case 1: // Taster 1 startet den Home-Screen
501  auswahl_nr = -1;
502  taster_nr = 0;
503  screen_home ();
504  break;
505  case 2: // Auswahl einer Batterie, für die der Info-Screen gestartet wird.
506  auswahl_nr++;
507  if ( auswahl_nr % 8 == 0 )
508  gfx_draw_filled_circle( auswahl_batterie[7].x, auswahl_batterie[7].y + 20, 5, GFX_COLOR_WHITE, GFX_WHOLE );
509  else
510  gfx_draw_filled_circle( auswahl_batterie[auswahl_nr % 8 - 1].x, auswahl_batterie[auswahl_nr % 8 - 1].y + 20, 5, GFX_COLOR_WHITE, GFX_WHOLE );
511  gfx_draw_filled_circle( auswahl_batterie[auswahl_nr % 8].x, auswahl_batterie[auswahl_nr % 8].y + 20, 5, GFX_COLOR_RED, GFX_WHOLE );
512  taster_nr = 0;
513  break;
514  case 4: // Taster 4 startet den Warnung-Screen
515  if ( scr_betrieb.warnung )
516  {
517  screen_return = SCREEN_RETURN_LADEN;
518  auswahl_nr = -1;
519  taster_nr = 0;
520  screen_akku_warnung ( scr_akku_warning );
521  }
522  break;
523  case 3: // "Enter" bestätigt die Auswahl.
524  if ( auswahl_nr == -1 ) auswahl_nr = 0; // Bei "Enter" ohne vorherige Auswahl wird Akku 1 gesetzt.
525  if ( (auswahl_nr % 8) < 4 )
526  sprintf ( scr_akku_info[auswahl_nr % 8].name, "1.%1i", auswahl_nr % 8 + 1 );
527  else
528  sprintf ( scr_akku_info[auswahl_nr % 8].name, "2.%1i", (auswahl_nr % 8) - 3 );
529  taster_nr = 0;
530  screen_return = SCREEN_RETURN_LADEN;
531  screen_akku_info ( scr_akku_info[auswahl_nr % 8] );
532  break;
533  default:
534  screen_laden ( scr_laden );
535  break;
536  }
537  }
538  }
539 }
Konstanten, Filter und Commands für den Temperatursensor MCP 9843.
Header, Definition der Konstanten und Commands für DS1388.
void DS1388_get_datetime(void)
Die Uhrzeit und das Datum werden ausgelesen.
Definition: ds1388_rtc.c:107
uint8_t taster_nr
Globale Definition. Die Variable wird aus der ISR gesetzt und gibt an, welcher der vier Taster am Dis...
Definition: taster.c:23
void screen_akku_warnung(scr_warning_t icon)
Der Warnung-Screen.
Definition: screens_gfx.c:400
bool verbraucher
Verbraucher ein- oder ausgeschaltet.
Definition: screens_gfx.h:105
void screen_akku_info(scr_info_t icon)
Der Infoscreen.
Definition: screens_gfx.c:198
Standardheader.
Bibliothek zur USB-Kommunikation von Jürgen W.
Standardheader.
void screen_laden(scr_laden_t icon)
Der Ladescreen.
Definition: screens_gfx.c:284
void bildschirm_ausgabe()
Belegung der Icon-Parameter für die Displayausgabe und Aufruf der verschiedenen Screens.
void screen_betrieb(scr_betrieb_t icon)
Der Standard Betriebsscreen.
Definition: screens_gfx.c:55
Graphical System Font system.
Standard Header Datei, Definition der Batteriekonstanten und Grenzwerte.
Standardheader und Auswahl der Übertragungsgeschwindigkeit.
#define gfx_draw_filled_circle(x, y, radius, color, quadrant_mask)
Definition: gfx_ili9341.h:192
Standardheader.
void mosfet_charge_on(void)
Die Ladefunktion wird aktiviert.
Definition: bms_mosfet.c:75
void AD7997_voltage_get_data(void)
Ermittelt die Spannungen der Batterien.
Definition: ad7997.c:211
#define GFX_WHOLE
Definition: gfx.h:172
void screen_home(void)
Der Home-Screen.
Definition: screens_gfx.c:507
Standardheader. Definition der Iconfarben.
Standardheader.
Definition der Schalterstellungen für die einzelnen MOSFETs.
uint8_t zeit_counter
Main.
Definition: main.c:53
void AD7997_current_get_data(void)
Ermittelt die Stromstärke in den Batteriestromkreisen.
Definition: ad7997.c:128
Standardheader.
#define gfx_draw_filled_rect(x, y, width, height, color)
Definition: gfx_ili9341.h:178
Standardheader.
Standardheader und Positionen der Zeilen und Spalten auf den jeweiligen Screens.
Bibliothek zur USB-Kommunikation von Jürgen W.
Header für ADC AD7997, Definition der Register und Commands.