Forum: Mikrocontroller und Digitale Elektronik uC bleibt hängen - Ursache unklar - Fehler nicht reproduzierbar


von Tim B. (tim_b84)


Lesenswert?

Moin Leute,
ich habe hier eine Schaltung mit einem Atmega 32U4. Letzterer 
kommuniziert mit einem PC. Die Schaltung und auch die Software habe ich 
hier tausendfach getestet und es gab keinerlei Schwierigkeiten. Nun 
bleibt der uC bei einem Kunden immer wieder hängen. Die Leiterplatte 
habe ich schon ausgetauscht, sodass ich etwa eine schlechte Lötstelle 
als Fehler ausschließen möchte. Leider scheint der Fehler wie zufällig 
aufzutreten. Ich kann keine Ursache ausmachen - auf keine zeitliche - 
einmal trat der Fehler hier nun auch auf aber ohne, dass ich eine 
Ursache erkennen konnte...

Darum meine Frage: Weiß jemand eine Quelle für eine Art Checkliste was 
bei einem hängenden uC zu prüfen ist?

von Einer K. (Gast)


Lesenswert?

In Zeile 42 schreibst du über Arraygrenzen hinweg.

von Dunkelseher (Gast)


Lesenswert?

Ja ich seh's auch ganz deutlich.

von Ingo Less (Gast)


Lesenswert?

Tim B. schrieb:
> Darum meine Frage: Weiß jemand eine Quelle für eine Art Checkliste was
> bei einem hängenden uC zu prüfen ist?
- Resetbeschaltung
- Abblockung
- Versorgung gepuffert
- Programmfehler (Atomic, Arraygrenzen z.B.)
- Taktausfall (wegen "bleibt stehen")
- Endlos-While-Schleifen die etwas pollen, Stichwort Timeout einbauen

Kannst du "bleibt hängen" näher spezifierenz?

von Ingo Less (Gast)


Lesenswert?

Hier mal ein Beispiel, wie man ein Timeout einbaut:
1
static uint16_t WaitForFallingEdge ( void )
2
{
3
  uint16_t Temp = 0;
4
  while ( (TEMP_IO_PORT & (1<<TEMP_IO_PIN)) && Temp < TIMEOUT ) Temp++;
5
  if ( Temp == TIMEOUT ) return TIMEOUT_ACCOURED;
6
  return Temp;
7
}

von Old P. (Firma: nix) (old-papa)


Lesenswert?

Arduino Fanboy D. schrieb:
> In Zeile 42 schreibst du über Arraygrenzen hinweg.

YMMD ;-)

Old-Papa

von 100Ω Widerstand (tr0ll) (Gast)


Lesenswert?

Meine Glaskugel ist mir gestern explodiert und ist bei der Reparatur. 
deswegen veröffentliche hier bitte den Code der auf dem Controller 
läuft.

von Dunkelseher (Gast)


Lesenswert?

Manchmal ist es wirklich eine Strafe einen Eröffnungs-Beitrag
hier lesen zu müssen.

Leider merkt man das erst wenn man ihn gelesen hat sonst könnte
man die Situation ja sogar vermeiden.

von Tim B. (tim_b84)


Lesenswert?

Vielen Dank.

Also es ist so, dass ich nur sehr begrenzt progrtammieren kann, weshalb 
ich sowohl beim Arduino-Sketch sehr viel Hilfe hatte und an der 
PC-Software gar nicht beteiligt war. Den Arduino-Sketch werde ich mir 
wegen der Arraygrenzen gleich mal zur Brust nehmen aber soweit ich mich 
erinnere hat die PC-Software alle "Rechen- und Merkaufgaben" übernommen. 
Außerdem müsste die Software dann ja zeitlich immer nach einer 
bestimmten Anzahl von Schreibvorgängen - also auch nach einer bestimmten 
Zeit abstürzen. Die läuft aber mal über Nacht problemlos und stürzt dann 
wieder nach ein paar Minuten ab.

Bemerkbar macht sich der Absturz dadurch, dass der uC nichts mehr 
schaltet und die PC-Software einfriert. Sobald der uC neu gestartet wird 
läufts wieder.

Bevor ich jetzt lange suche: Ist vielleicht das Aktivieren des Watchdogs 
über die Fuses eine Lösung (Watchdog timer always on; [WDTON=0])? Wird 
der uC dann automatisch neu gestartet wenn er abstürtzt?

Eigentlich würde ich erst mal checken, ob der uC auch dann abstützt, 
wenn er nicht mit dem PC verbunden ist um herauszufinden ob vielleicht 
etwas mit der Kommunikation nicht stimmt. Das ist aber natürlich 
schwierig, wenn sich der Fehler nicht reproduzieren lässt...

von Framulestigo (Gast)


Lesenswert?

Dunkelseher schrieb:
> Manchmal ist es wirklich eine Strafe einen Eröffnungs-Beitrag
> hier lesen zu müssen.

Wieso? Der TO hat doch nur nach einer allgemeinen Vorgehensweise 
gefragt.
Also allgemein:
- Den Fehler eingrenzen!

Beitrag #6386452 wurde von einem Moderator gelöscht.
von Ingo Less (Gast)


Lesenswert?

Tim B. schrieb:
> Ist vielleicht das Aktivieren des Watchdogs
> über die Fuses eine Lösung (Watchdog timer always on; [WDTON=0])? Wird
> der uC dann automatisch neu gestartet wenn er abstürtzt?
Nein, der Watchdog ist das allerletzte Mittel, den µC wieder zu holen, 
wenn man selber keinen Einfluss mehr nehmen kann. Ein Programm, dass auf 
einen WDT angewiesen ist, damit es läuft ist ein schlechtes Programm.

von Tim B. (tim_b84)


Lesenswert?

Das ist der Arduino-Sketch:
1
#include <EEPROM.h> /// zum speichern im EEPROM des Arduino
2
#include <OneWire.h>
3
#include "WS2812.h"
4
5
////////////////////////////////////////////////
6
/// Ab hier kann wieder angepasst werden !!! ///
7
////////////////////////////////////////////////
8
9
/* Konstanten
10
*/
11
#define UPDATE_TIME_CHECK 500 /// ms zwischen Signal + Avg + Schutz
12
13
#define NUM_READ_A 125 /// Anzahl der Messungen Haupt-Stromsensor
14
#define UPDATE_TIME_A 4 /// ms zwischen den Messungen vom Haupt-Stromsensor
15
16
#define NUM_READ_U 20 /// Anzahl der Messungen Nutzer-Stromsensoren
17
#define UPDATE_TIME_U 25 /// ms zwischen den Messungen vom Spannung(s-Teiler)
18
19
#define NUM_READ_V 20 /// Anzahl der Messungen Spannung(s-Teiler)
20
#define UPDATE_TIME_V 25 /// ms zwischen den Messungen von Nutzer-Stromsensoren
21
22
#define OVP_MF_OFF_ID 767 /// ADC-Wert bei 15zu20V
23
#define OVP_MF_ON_ID 716 /// ADC-Wert bei 14zu20V
24
#define OVP_MF_TIME 10000 /// 10s nach aus darf ein
25
26
#define UVP_WR_OFF_ID 563 /// ADC-Wert bei 11zu20V
27
#define UVP_WR_ON_ID 588 /// ADC-Wert bei 11,5zu20V
28
#define UVP_WR_TIME 10000 /// 10s nach aus darf ein
29
30
#define OCP_MF_OFF_ID 2046 /// 2x 50A = 2x map(MAX_ADC_USER) = 2x 1023
31
#define OCP_MF_ON_ID 1637 /// 80A
32
#define OCP_MF_TIME 10000 /// 10s nach aus darf ein
33
34
#define OTP_MF_OFF 80.0 /// °C
35
#define OTP_MF_ON 70.0 /// °C
36
37
#define ADC_NUM 12 /// Anzahl analoge Eingänge
38
39
#define PORT_A A0 /// (?) Stromsensor zwischen WR und Bat
40
#define PORT_LED 13 /// 1x WS2812
41
#define PORT_MF 11 /// Port um Mosfets zu schalten
42
#define PORT_TEMP 7 /// Port vom Tempsensor DS18B20Z
43
#define PORT_U0 A9 /// Stromsensor User 0
44
#define PORT_U1 A8 /// Stromsensor User 1
45
#define PORT_U2 A7 /// Stromsensor User 2
46
#define PORT_U3 A11 /// Stromsensor User 3
47
#define PORT_U4 A5 /// Stromsensor User 4
48
#define PORT_U5 A4 /// Stromsensor User 5
49
#define PORT_U6 A3 /// Stromsensor User 6
50
#define PORT_U7 A2 /// Stromsensor User 7
51
#define PORT_U8 A6 /// (?) Stromsensor User 8
52
#define PORT_U9 A1 /// (?) Stromsensor User 9
53
#define PORT_V A10 /// Spannungsteiler
54
#define PORT_WR 5 /// Wechselrichter-Port fürs ein- und ausschalten
55
#define TIME_MF_OFF_TO_ON 10000 /// ms → nach min. wieviel Zeit wieder ON
56
#define TIME_WR_OFF_TO_ON 10000 /// ms → nach min. wieviel Zeit wieder ON
57
58
#define ALERT_USER_HIGH_W 100.0
59
#define ALERT_USER_LOW_W 40.0
60
#define BITBREITE 10 
61
#define BPS 115200 /// 115200 Bits_Per_Second (Serielle Kommunikation)
62
#define COUNT_USER 8 /// Nutzeranzahl
63
#define GAUGE_USER 100.00 /// W für Vollausschlag der Bargraphanzeige
64
#define KWH_AUSSCHLAG 0.10 /// kWh für Vollausschlag nach jeder Seite der Bargraphanzeige Verbrauch bzw. Erzeugt
65
#define MAX_ADC_A 921 /// bei +MAX_A_BATT
66
#define MAX_ADC_V 1023 /// ADC_Wert bei MAX_V
67
#define MAX_ADC_USER 614 /// (runtergerechneter) ADC_Wert inkl. Offset bei MAX_A_USER
68
#define MAX_V 20.00 /// Maximale Sensorbereich (Hardware)
69
#define MAX_A_USER 50.00 /// Maximale theoretische Sensorbereich (Hardware)
70
#define MAX_A_BATT 100.00 /// Maximale theoretische Sensorbereich (Hardware)
71
#define MIN_ADC_A 102 /// bei -MAX_A_BATT
72
#define MIN_ADC_V 0 /// ADC_Wert bei 0 V
73
#define MIN_ADC_USER 0 /// (runtergerechneter) ADC_Wert inkl. Offset
74
#define NUTZER_ID "" /// Das ist die Lizenz
75
#define OFFSET_A 0
76
#define OFFSET_V 0
77
#define OFFSET_USER 102 /// 102 rechnerisch (=0,5V)
78
#define VERSION "2019.10.03" /// vom µC
79
#define WR_DELAY 1000 /// Zeit jeweis zwischen Ausschalten, Kalibrieren, Einschalten des WR
80
81
/* Aufzählungen
82
 */
83
enum OPT /// Option für Serial-Event
84
{
85
  Mf_On     = 15,
86
  Mf_Off    = 14,
87
  Wr_On     = 13,
88
  Wr_Off    = 12,
89
  Send_Conf = 11,
90
  Kali      = 10,
91
  Send_Data =  9
92
};
93
94
/* RGB-Code für diverse States
95
 */
96
cRGB ALERT_PROTECT = {255, 255, 0 }; /// gelb → OCP || OTP || OVP || UVP ist 1
97
cRGB NO_COLOR = {0, 0, 0 }; /// aus bzw. schwarz bzw. keine Farbe
98
cRGB NO_PROTECT = {0, 255, 0 }; /// grün → OCP && OTP && OVP && UVP ist >= 2
99
cRGB OCP_OTP_OVP_UVP = {255, 0, 0 }; /// rot → OCP || OTP || OVP || UVP ist 0
100
cRGB TIME_ALERT_PROTECT = {255, 0, 0 }; /// lila → Abklingzeit + ALERT_PROTECT
101
cRGB TIME_NO_PROTECT = {255, 0, 0 }; /// türkis → Abklingzeit + NO_PROTECT
102
103
////////////////////////////////////////
104
/// Ab hier nichts mehr anpassen !!! ///
105
////////////////////////////////////////
106
107
struct Configuration{ /// Das was als Konfiguration über USB gesendet wird
108
  //short Alert_High_V_Id = OVP_MF_ALERT_ID;
109
  //short Alert_Low_V_Id = UVP_WR_ALERT_ID;
110
  float Alert_User_High_W = ALERT_USER_HIGH_W;
111
  float Alert_User_Low_W = ALERT_USER_LOW_W;
112
  float Gauge_User = GAUGE_USER;
113
  float KWh_Ausschlag = KWH_AUSSCHLAG;
114
  float Max_A_Batt = MAX_A_BATT;
115
  float Max_A_User = MAX_A_USER;
116
  float Max_V = MAX_V;
117
  short Mosfet_High_Id = OVP_MF_OFF_ID;
118
  short Mosfet_Low_Id = OVP_MF_ON_ID;
119
  uint8_t ADC_Bitbreite = BITBREITE;
120
  uint8_t Count_User = COUNT_USER;
121
  char Kinobox_Version[11] = VERSION;
122
  char Nutzer_ID[150] = NUTZER_ID;
123
  uint8_t dummy[17] = {0};
124
};
125
126
struct Daten{ /// Alle analoge Ports
127
  short adc[ADC_NUM]; /// Port A 0 bis A 11
128
};
129
130
/* Variablen
131
 */
132
byte Read_Index_A = 0;
133
byte Read_Index_V = 0;
134
byte Read_Index_U = 0;
135
short Reading_A[NUM_READ_A] = {0};
136
short Reading_V[NUM_READ_V] = {0};
137
short Reading_U[ADC_NUM-2][NUM_READ_U] = {0};
138
long Total_A = 0;
139
long Total_V = 0;
140
long Total_U[ADC_NUM-2] = {0};
141
unsigned long Last_Time_Check = 0;
142
unsigned long Last_Time_Read_A = 0;
143
unsigned long Last_Time_Read_V = 0;
144
unsigned long Last_Time_Read_U = 0;
145
unsigned long Last_Time_MF_Off = 0;
146
unsigned long Last_Time_WR_Off = 0;
147
unsigned long now = 0;
148
149
OneWire ds(PORT_TEMP); /// an welchen Port ist der Temperatursensor
150
byte Temp_Addr[8]; /// Adresse des Temperatursensors
151
byte Temp_Data[12]; /// Daten des Temperatursensors
152
int16_t Temp_Raw = 0;
153
float Temperatur = 0.0;
154
short adc = 0; /// temporär für Berechnungen usw.
155
short tempAall = 0; /// gesamt für alle Nutzer für OCP-Schutz
156
int Analog_Port_Array[ADC_NUM] = {PORT_A, PORT_V, PORT_U0, PORT_U1, PORT_U2, PORT_U3, PORT_U4, PORT_U5, PORT_U6, PORT_U7, PORT_U8, PORT_U9};
157
Daten Max_ADC = {MAX_ADC_A, MAX_ADC_V, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER, MAX_ADC_USER};
158
Daten Min_ADC = {MIN_ADC_A, MIN_ADC_V, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER, MIN_ADC_USER};
159
Daten Offset = {OFFSET_A, OFFSET_V, OFFSET_USER, OFFSET_USER, OFFSET_USER, OFFSET_USER, OFFSET_USER, OFFSET_USER, OFFSET_USER, OFFSET_USER, OFFSET_USER, OFFSET_USER};
160
Daten Data = {0}; /// Das was über USB gesendet wird
161
Configuration Conf;
162
WS2812 LED(1);
163
cRGB LED_rgb = {0};
164
byte OVP_State = 0; /// Überspannungsschutz
165
byte UVP_State = 0; /// Unterspannungsschutz
166
byte OCP_State = 0; /// Überstromstärkeschutz
167
byte OTP_State = 0; /// Temperaturschutz
168
169
////////////////////////////////////////
170
/// Ab hier nichts mehr anpassen !!! ///
171
////////////////////////////////////////
172
173
/* Programmstart
174
 */
175
void setup()
176
{
177
  init_default_led();
178
  init_default_mosfet();
179
  init_default_temp();
180
  init_default_wr();
181
  zero_reading_data();
182
  zero_total_data();
183
  zero_usb_data();
184
  Verbinden();
185
  //EEPROM_auslesen(); /// Ggf. in späteren Version aktivieren und erweitern
186
}
187
188
/* Dauerschleife für regelmäßige Aktionen
189
 */
190
void loop()
191
{
192
  now = millis();
193
  if( (now - Last_Time_Read_A) >= UPDATE_TIME_A ) /// Haupt-Stromsensor
194
  {
195
    Last_Time_Read_A = now;
196
    Total_A -= Reading_A[Read_Index_A];
197
    Reading_A[Read_Index_A] = (short)analogRead(Analog_Port_Array[0]);
198
    Total_A += Reading_A[Read_Index_A];
199
    Read_Index_A++;
200
    if( Read_Index_A >= NUM_READ_A ) { Read_Index_A = 0; }
201
  }
202
  if( (now - Last_Time_Read_V) >= UPDATE_TIME_V ) /// Spannung(s-Teiler)
203
  {
204
    Last_Time_Read_V = now;
205
    Total_V -= Reading_V[Read_Index_V];
206
    Reading_V[Read_Index_V] = (short)analogRead(Analog_Port_Array[1]);
207
    Total_V += Reading_V[Read_Index_V];
208
    Read_Index_V++;
209
    if( Read_Index_V >= NUM_READ_V ) { Read_Index_V = 0; }
210
  }
211
  if( (now - Last_Time_Read_U) >= UPDATE_TIME_U ) /// Nutzer_Stromsensoren
212
  {
213
    Last_Time_Read_U = now;
214
    for( byte i = 0 ; i < (ADC_NUM-2) ; i++ )
215
    {
216
      Total_U[i] -= Reading_U[i][Read_Index_U];
217
      Reading_U[i][Read_Index_U] = (short)analogRead(Analog_Port_Array[i+2]);
218
      Total_U[i] += Reading_U[i][Read_Index_U];
219
    }
220
    Read_Index_U++;
221
    if( Read_Index_U >= NUM_READ_U ) { Read_Index_U = 0; }
222
  }
223
  if( (now - Last_Time_Check) >= UPDATE_TIME_CHECK ) /// Signal+Avg+Schutz
224
  {
225
    Last_Time_Check = now;
226
    /// Falls keine Verbindung, soll auch OHNE Befehl der
227
    /// Mittelwert in der USB-Struktur gespeichert werden,
228
    /// damit die LED weiterhin einen Status geben kann.
229
    if(!Serial)
230
    {
231
      calc_save_avg();
232
    }
233
    temperaturschutz();
234
    ueberstromschutz();
235
    ueberspannungsschutz();
236
    unterspannungsschutz();
237
    update_states(); /// LED, WR und/oder MF beeinflussen
238
  }
239
}
240
241
/* USB-Data-Struktur mit den Mittelwert aus der 
242
 * Gesamt_pro_Port-Data-Struktur speichern
243
 */
244
inline void calc_save_avg()
245
{
246
/// Stromstärke-Batterie-ADC-Wert
247
  adc = Total_A / NUM_READ_A; /// Mittelwert bilden
248
  Data.adc[0] = (short)map(adc, Min_ADC.adc[0], Max_ADC.adc[0], -1023, 1023); /// Umwandeln per Verhältnis + speichern
249
/// Spannung-ADC-Wert
250
  adc = Total_V / NUM_READ_V; /// Mittelwert bilden
251
  Data.adc[1] = (short)map(adc, Min_ADC.adc[1], Max_ADC.adc[1], 0, 1023); /// Umwandeln per Verhältnis + speichern
252
/// Stromstärke-Nutzer-ADC-Wert
253
  for( int i = 0 ; i < (ADC_NUM-2) ; i++ )
254
  {
255
    adc = Total_U[i] / NUM_READ_U; /// Mittelwert bilden
256
    if(adc >= Offset.adc[i+2]) /// gemessenes größergleich Offset
257
    {
258
      adc -= Offset.adc[i+2]; /// adc um offset erleichtern
259
      Data.adc[i+2] = (short)map(adc, Min_ADC.adc[i+2], Max_ADC.adc[i+2], 0, 1023); /// Umwandeln per Verhältnis + speichern
260
    }
261
    else /// gemessenes kleiner als Offset
262
    {
263
      Data.adc[i+2] = (short)0; /// abspeichern → Strom/Spannung = 0
264
    }
265
  }
266
}
267
268
/* Daten übertragen
269
*/
270
inline void daten_senden()
271
{
272
    senden( (char*)&Data , (uint8_t)sizeof(Daten) );
273
}
274
275
/* Grundeinstellung vom LED laden
276
 */
277
inline void init_default_led()
278
{
279
  pinMode( PORT_LED , OUTPUT );
280
  set_port( PORT_LED , false );
281
  LED.setOutput(PORT_LED);
282
  set_led(NO_COLOR);
283
  LED.set_crgb_at(0, LED_rgb); /// Wert festlegen
284
  LED.sync(); /// Werte an LEDs übertragen
285
}
286
287
/* Grundeinstellung vom Mosfet laden
288
 */
289
inline void init_default_mosfet()
290
{
291
  pinMode( PORT_MF , OUTPUT );
292
  set_port( PORT_MF , true );
293
}
294
295
/* Grundeinstellung vom LED laden
296
 */
297
inline void init_default_temp()
298
{
299
/// Suchen
300
  if ( ds.search(Temp_Addr) )
301
  {
302
    ds.skip();
303
  }
304
  else
305
  {
306
    ds.reset_search();
307
  }
308
}
309
310
/* Grundeinstellung vom Wechselrichter laden
311
 */
312
inline void init_default_wr()
313
{
314
  pinMode( PORT_WR , OUTPUT );
315
  set_port( PORT_WR, true );
316
}
317
318
/* Konfiguration übertragen
319
 */
320
inline void konfig_senden()
321
{
322
/// die Konfiguration dem PC mitteilen
323
  senden( (char*)&Conf , (uint8_t)sizeof(Configuration) );
324
}
325
326
/* Daten über USB senden und dabei den
327
 * Eingangspuffer leeren,
328
 * Daten byte-weise übertragen und
329
 * Ausgangspuffer leeren
330
 */
331
inline void senden(char *structPointer, byte structLength)
332
{
333
  while( Serial.available() )
334
  {
335
    Serial.read();
336
  }
337
  for( int i = 0 ; i < structLength ; i++ )
338
  {
339
    Serial.write( structPointer[i] );
340
  }
341
  Serial.flush();
342
}
343
344
/* Daten über USB empfangen und
345
 * dabei das Kommando auswerten und
346
 * passende Aktion ausführen
347
 */
348
void serialEventRun()
349
{
350
  if (Serial.available())
351
  {
352
    switch(Serial.read())
353
    {
354
      case OPT::Mf_On : set_port( PORT_MF , true ); break;
355
      case OPT::Mf_Off : set_port( PORT_MF , false ); break;
356
      //case OPT::Wr_On : waiting(WR_DELAY); set_port( PORT_WR , true );  break;
357
      //case OPT::Wr_Off : waiting(WR_DELAY); set_port( PORT_WR , false );  break;
358
      case OPT::Send_Conf : konfig_senden();
359
      //case OPT::Kali : waiting(WR_DELAY); Strom_Kalibri_All();  break;
360
      case OPT::Send_Data : calc_save_avg(); daten_senden();  break;
361
    }
362
  }
363
}
364
365
/* Einen bestimmten digitalen Port einen Wert zuweisen
366
 */
367
inline void set_port(int port , bool value)
368
{
369
  if( digitalRead( port ) != value ) {
370
    digitalWrite( port , value ? HIGH : LOW );
371
  }
372
}
373
374
/* Einer LED einen Farbwert zuweisen
375
 */
376
inline void set_led(cRGB value)
377
{
378
  if( ( LED_rgb.r != value.r ) || ( LED_rgb.g != value.g ) || ( LED_rgb.b != value.b ) )
379
  {
380
    LED_rgb.r = value.r;
381
    LED_rgb.g = value.g;
382
    LED_rgb.b = value.b;
383
    LED.set_crgb_at(0, LED_rgb); /// Wert festlegen
384
    LED.sync(); /// Werte an LEDs übertragen
385
  }
386
}
387
388
/* Schutz: Mosfet und Wechselrichter sollen funktionieren, auch ohne PC
389
 */
390
inline void temperaturschutz()
391
{
392
/// ??????????
393
  ds.reset(); // RICHTIGE TEMP AKTUALISIERT NICHT
394
  ds.select(Temp_Addr); // RICHTIGE TEMP AKTUALISIERT NICHT
395
/// start conversion (, with parasite power on at the end = ds.write(0x44, 1) )
396
  ds.write(0x44); // RICHTIGE TEMP AKTUALISIERT NICHT
397
  ds.reset(); // FALSCHE TEMP AKTUALISIERT NICHT
398
  ds.select(Temp_Addr); // FALSCHE TEMP AKTUALISIERT NICHT
399
/// Read Scratchpad
400
  ds.write(0xBE); // FALSCHE TEMP AKTUALISIERT NICHT
401
/// Lesen 
402
  for (byte i = 0; i < 9; i++){
403
    Temp_Data[i] = ds.read();}
404
  Temp_Raw = (Temp_Data[1] << 8) | Temp_Data[0];
405
/// Sensortemperatur
406
  Temperatur = (float)Temp_Raw / 16.0;
407
/// Temp-Pegel prüfen
408
  if( Temperatur < OTP_MF_ON ) {
409
    OTP_State = 2; } /// an + grün
410
  else if( Temperatur > OTP_MF_OFF ) {
411
    OTP_State = 0; } /// aus + rot
412
  else {
413
    OTP_State = 1; } /// gelb
414
}
415
416
/* Schutz: Mosfet soll funktionieren, auch ohne PC
417
 */
418
inline void ueberspannungsschutz()
419
{
420
  if( Data.adc[1] < OVP_MF_ON_ID ) {
421
    OVP_State = 2; } /// an + grün
422
  else if( Data.adc[1] > OVP_MF_OFF_ID ) {
423
    OVP_State = 0; } /// aus + rot
424
  else {
425
    OVP_State = 1; } /// gelb
426
}
427
428
/* Schutz: Mosfet soll funktionieren, auch ohne PC
429
 */
430
inline void ueberstromschutz()
431
{
432
  tempAall = 0;
433
  for(int i=2 ; i<ADC_NUM ; i++)
434
  {
435
    tempAall += Data.adc[i];
436
  }
437
  if( tempAall < OCP_MF_ON_ID ) {
438
    OCP_State = 2; } /// an + grün
439
  else if( tempAall > OCP_MF_OFF_ID ) {
440
    OCP_State = 0; } /// aus + rot
441
  else {
442
    OCP_State = 1; } /// gelb
443
}
444
445
/* Schutz: Wechselrichter soll funktionieren, auch ohne PC
446
 */
447
inline void unterspannungsschutz()
448
{
449
  if( Data.adc[1] > UVP_WR_ON_ID ) {
450
    UVP_State = 2; } /// an + grün
451
  else if( Data.adc[1] < UVP_WR_OFF_ID ) {
452
    UVP_State = 0; }  /// aus + rot
453
  else {
454
    UVP_State = 1; } /// gelb
455
}
456
457
/* USB-Verbindung herstellen
458
 */
459
inline void Verbinden()
460
{
461
  Serial.begin(BPS);
462
}
463
464
/* Eine bestimmte Dauer abwarten
465
 */
466
inline void waiting(unsigned long dauer)
467
{
468
  unsigned long jetzt = millis();
469
  while( ( millis() - jetzt ) < WR_DELAY ){}
470
}
471
472
/* Mittelwert-Data-Struktur auf 0 setzen
473
 */
474
inline void zero_reading_data()
475
{
476
  for( int i = 0 ; i < NUM_READ_A ; i++ ) { Reading_A[i] = 0; }
477
  for( int i = 0 ; i < NUM_READ_V ; i++ ) { Reading_V[i] = 0; }
478
  for( int i = 0 ; i < NUM_READ_U ; i++ ){ 
479
    for( int j = 0 ; j < (ADC_NUM-2) ; j++ ) { Reading_U[j+2][i] = 0; }
480
  }
481
}
482
483
/* Gesamt_pro_Port-Data-Struktur auf 0 setzen
484
 */
485
inline void zero_total_data()
486
{
487
  Total_A = 0;
488
  Total_V = 0;
489
  for( int i = 0 ; i < (ADC_NUM-2) ; i++ ) { Total_U[i] = 0; }
490
}
491
492
/* USB-Data-Struktur auf 0 setzen
493
 */
494
inline void zero_usb_data()
495
{
496
  for( int i = 0 ; i < ADC_NUM ; i++ )
497
  {
498
    Data.adc[i] = 0;
499
  }
500
}
501
502
/* Anhand der Protect_States die LED farblich gestalten und
503
 * Mosfet bzw. Wechselrichter schalten
504
*/
505
void update_states()
506
{
507
/// Mindest 1 der States ist 0 → Rot → WR bzw MF ausschalten
508
  if( !OCP_State || !OTP_State || !OVP_State || !UVP_State ){
509
    set_led(OCP_OTP_OVP_UVP); /// Rot festlegen
510
////// Einer der WR-Relevanten States sind 0
511
    if( !UVP_State ) {
512
      set_port( PORT_WR , false ); /// Wechselrichter ausschalten
513
      Last_Time_WR_Off = now;} /// Zeit notieren für Einschaltverzögerung
514
////// Einer der MF-Relevanten States sind 0
515
    else{
516
      set_port( PORT_MF , false ); /// Mosfet ausschalten
517
      Last_Time_MF_Off = now;} } /// Zeit notieren für Einschaltverzögerung
518
/// Keins der States ist 0
519
  else{
520
////// Alle States sind mindest 2 → Grün üder Türkis
521
    if( ( OCP_State == 2 ) && ( OTP_State == 2 ) &&
522
        ( OVP_State == 2 ) && ( UVP_State == 2 ) ){
523
      if( ( ( now - Last_Time_WR_Off ) >= TIME_WR_OFF_TO_ON ) &&
524
          ( ( now - Last_Time_MF_Off ) >= TIME_MF_OFF_TO_ON ) ){
525
///////// Alle WR-Relevanten Stetes sind 2
526
        set_port( PORT_WR , true ); /// Wechselrichter ausschalten
527
///////// Alle MF-Relevanten States sind 2
528
        set_port( PORT_MF , true ); /// Mosfet einschalten
529
///////// Wartezeit für wieder einschalten abgelaufen
530
        set_led(NO_PROTECT); } /// Grün festlegen
531
      else{
532
///////// Wartezeit für wieder einschalten noch nicht abgelaufen
533
        set_led(TIME_NO_PROTECT); } } /// Türkis festlegen
534
////// Mindest 1 der States ist 1 → Gelb oder Lila → für Alarmanzeige
535
    else{
536
      if( ( ( now - Last_Time_WR_Off ) >= TIME_WR_OFF_TO_ON ) &&
537
          ( ( now - Last_Time_MF_Off ) >= TIME_MF_OFF_TO_ON ) ){
538
///////// Wartezeit für wieder einschalten abgelaufen
539
        set_led(ALERT_PROTECT); } /// Gelb festlegen
540
      else{
541
///////// Wartezeit für wieder einschalten noch nicht abgelaufen
542
        set_led(TIME_ALERT_PROTECT); } } } /// Lila festlegen
543
}
544
545
/*
546
 * Funktionen für später
547
 */
548
 
549
/*
550
void EEPROM_auslesen()
551
{
552
  for(byte i=0; i<(ADC_NUM); i++)
553
    EEPROM.get(EEPROM_Kalibrierung+(2*i), ADC_Offset[i]);
554
}
555
*/
556
557
/*
558
void Strom_Kalibri_All(){}
559
*/

: Bearbeitet durch Admin
Beitrag #6386472 wurde von einem Moderator gelöscht.
von Ingo Less (Gast)


Lesenswert?

Macht das Programm zufällig nach ~50 Tagen Probleme?

von jo mei (Gast)


Lesenswert?

Funkdeppjäger schrieb im Beitrag #6386472:
> Sag mal glaubst du wirklich, dass sich einer deinen Schrott ansieht und
> deine Hausaufgaben macht?

Ausserdem gehört der Text in einen Anhang und nicht in den
Beitrags-Textkörper!

Siehe:

Wichtige Regeln - erst lesen, dann posten!
....
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Tim B. schrieb:
> Nun bleibt der uC bei einem Kunden immer wieder hängen.
Softwarefehler.
Oder andersrum: die Software kommt nicht damit klar, dass da ein 
kleiner, fies kurzer Störimpuls kommt, wenn jemand das Licht 
ausschaltet.

Tim B. schrieb:
> Das ist der Arduino-Sketch:
Sowas bitte als Anhang (wie in der Anleitung über jeder Texteditbox 
geschrieben]! Oder pack den C-Code wenigstens in [C] Tags. Dann gibts 
Syntax-Highlighting gratis.

> short adc = 0; /// temporär für Berechnungen usw.
Wenn du in einer Funktion eine temporäre Variable brauchst, warum 
deklarierst du die dann nicht dort, wo sie hingehört?

> /// Das ist die Lizenz
Netter Ansatz...  ;-)

: Bearbeitet durch Moderator
von Chregu (Gast)


Lesenswert?

Tim B. schrieb:
> Also es ist so, dass ich nur sehr begrenzt progrtammieren kann

Tim B. schrieb:
> bei einem Kunden

Aha.

von Tim B. (tim_b84)


Lesenswert?

Ingo Less schrieb:
> Macht das Programm zufällig nach ~50 Tagen Probleme?

Leider schon wesentlich früher. Beim Kunden tritt das Problem anscheinen 
schon nach ein bis zwei Stunden auf.

von Dietrich L. (dietrichl)


Lesenswert?

Tim B. schrieb:
> Außerdem müsste die Software dann ja zeitlich immer nach einer
> bestimmten Anzahl von Schreibvorgängen - also auch nach einer bestimmten
> Zeit abstürzen.

Eben nicht unbedingt nach einer bestimmten Zeit: Es könnte z.B. sein, 
dass ein Interrupt, wenn er an einer bestimmten Stelle des 
Hauptprogramms auftritt, den Fehler produziert.
Dann ist das ein Zufallsgenerator: Zeitpunkt des Interrupts und Laufzeit 
der Hauptschleife.
Solche Fehler sind nur schwer zu finden. Da hilft oft nur Durcharbeiten 
aller kritischen Stellen im Programm. Und um zu wissen, welche Stellen 
kritisch sind, braucht dann schon Erfahrung.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Tim B. schrieb:
> Die Schaltung
Lass doch mal sehen. Und das Layout. Und den Aufbau. Nicht, dass da doch 
auch noch ein Problem drin ist...  ;-)

von Ingo Less (Gast)


Lesenswert?

Kommt evtl. so viel Noise über die serielle Schnittstelle, dass diese 
sich gestört fühlt und hier
1
while( Serial.available() )
2
  {
3
    Serial.read();
4
  }
hängen bleibt?

von Tim B. (tim_b84)


Angehängte Dateien:

Lesenswert?

Lothar M. schrieb:
> Tim B. schrieb:
>> Die Schaltung
> Lass doch mal sehen. Und das Layout. Und den Aufbau. Nicht, dass da doch
> auch noch ein Problem drin ist...  ;-)

Das ist das Layout. Das ist aber vermutlich so erst mal schwer zu 
verstehen...

von Tim B. (tim_b84)


Lesenswert?

Ingo Less schrieb:
> Kommt evtl. so viel Noise über die serielle Schnittstelle, dass diese
> sich gestört fühlt und hier
1
> while( Serial.available() )
2
>   {
3
>     Serial.read();
4
>   }
5
>
> hängen bleibt?

Das würde erklären warum das Ding beim Kunden abstürzt und bei mir 
nicht. Aber we kann man dem begegnen? Kabel besser schirmen?

von Tim B. (tim_b84)


Lesenswert?

Ingo Less schrieb:
> Tim B. schrieb:
>> Ist vielleicht das Aktivieren des Watchdogs
>> über die Fuses eine Lösung (Watchdog timer always on; [WDTON=0])? Wird
>> der uC dann automatisch neu gestartet wenn er abstürtzt?
> Nein, der Watchdog ist das allerletzte Mittel, den µC wieder zu holen,
> wenn man selber keinen Einfluss mehr nehmen kann. Ein Programm, dass auf
> einen WDT angewiesen ist, damit es läuft ist ein schlechtes Programm.

Irgendwie habe ich die Tendenz das trotzdem so zu lösen. Zumindest dann, 
wenn der Fehler durch Störimpuse hervorgerufen wird. Dazu müsste ich 
aber die Ursache kennen...

von Einer K. (Gast)


Lesenswert?

Serial ist virtuell.
Da reicht dann auch ein virtueller Schirm.
;-)

Im Ernst:
Ich kann das Programm kaum lesen und noch viel weniger verstehen.

Das ist C++.
Damit lässt sich viel schöner modularisieren, als es hier zu sehen ist.
Auch behagen mit die Defines nicht so, die meisten lassen sich 
sicherlich ersetzen.

von Anselm (Gast)


Lesenswert?

Ich vermute einfach mal dass ein EMV-Problem vorliegt.
Die Schaltung in ein Gehäuse welches auch geerdet ist (Schukostecker)
und eine gründlich entstörte Spannungsversorgung helfen dort fast immer.

bzw. hast du die USB-Versorgung so wie in den Application Notes 
geschrieben, entstört?
Den Plan haben wir ja nicht.

Der Watchdog hilft den Gerät wieder auf die Beine, aber das ist eine 
sehr "dirty" Lösung, die man nur macht wenn wirklich nichts mehr geht.

o/
Anselm

von Thomas W. (goaty)


Lesenswert?

Sieht so aus als ob über die fetten Tracks richtig Strom fließt und die 
winzigen Leitungen quer dazu gehen dann vom/zum µC. Hm, ob das nicht 
Probleme macht ?
Was sind das für dicke 10-polige Teile ? Shunts ?

Gehört das zum oekotrainer.de ?

: Bearbeitet durch User
von Tim B. (tim_b84)


Lesenswert?

Thomas W. schrieb:
> Sieht so aus als ob über die fetten Tracks richtig Strom fließt
> und die
> winzigen Leitungen quer dazu gehen dann vom/zum µC. Hm, ob das nicht
> Probleme macht ?
> Was sind das für dicke 10-polige Teile ? Shunts ?

An die Leisterplatte ist ein 40 Ah Akku und ein 1000 W Wechselrichter 
angeschlossen. Es fließt also tatsächlich ein sehr großer Strom. Der 
Akku wird über 10 Eingänge geladen. Die 4 MosFETs können die Eingänge im 
Fehlerfall trennen. Der Strom der 10 Eingänge wird jeweils über einen 
Hallsensor gemessen - ebenso der Strom zwischen Akku und Wechselrichter. 
Die Spannung für den uC wird mit einem LM317 erzeugt. Ich bin davon 
ausgegangen - dass der Akku mit dem niedrigen Innenwiederstand hier für 
stabilie Verhältnisse sorgt. Außerdem gibt es ja auch diverse 
Kondensatoren parallel zur Spannungsversorgung direkt am uC. Wenn es 
hier Schwierigkeiten gäbe würde der uC ja auch im Testlauf ständig 
abstützen. Das Problem tritt aber nur beim Kunden auf...

von Andreas M. (amesser)


Lesenswert?

Ich würde die Reset Leitung des Micros (ISP Verbinder) ja nicht 
unbedingt durch die Hälfte der Strompfade mitten durchrouten. Für mich 
sieht das so aus. als ob da schön viele Antennen sind die Dir alle 
möglichen Signale einfangen...:

- Ich würde die Filter für die HAL Sensoren direkt am Mikrocontroller 
plazieren

- Die Eingänge groundseitig abzutrennen ist auch sehr mutig. Was 
passiert im Fehlerfall? Ist die Eingangsspannung irgendwie begrenzt? 
Denn nach dem Abtrennen fehlt ja die Last durch den Akku.

- Bei solchen Strömen sollte man Leistungsteil und Steuerteil 
separieren.

- In die HAL Sensoren koppeln die Magnetfelder der Nachbarleitungen und 
auch der eigenen Leitungen zusätzlich ein. Im Datenblatt steht wie man 
es richtig macht

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Tim B. schrieb:
> Das ist das Layout. Das ist aber vermutlich so erst mal schwer zu
> verstehen...
Es ist schon mal schwer zu erkennen. Poste das mal als PNG und möglichst 
großformatig. Da gibts auch eine Checkbox, dass das Bild nicht 
verkleinert werden soll.

Zum Verständnis trägt dann der Schaltplan bei... ;-)

Tim B. schrieb:
> Aber we kann man dem begegnen? Kabel besser schirmen?
Die Software fehlertolerant machen.
Und die Hardware mal im Labor ein wenig mit EMV belasten.

Du schreibst da auch was von USB. Das ist beim EMV-Test bei mir immer 
der erste Bus, der abkotzt. Ich habe für die Schaltungsinbetriebnahme 
für begleitende "EMV-Vortests" einfach einen Viehtreiber wie 
https://www.ebay.de/itm/Viehtreiber-HandyShock-Rind-Tier-Treiber-11215/381541741059 
gekauft. Dazu brauche ich dann noch eine Metallplatte und eine 
Kunststoffplatte. Jetzt kommt das Metallblech auf den Labortisch, die 
Kunstoffplatte als Isolator drauf und auf diese Kunststoffplatte gut von 
der Metallplatte isoliert meine neue Schaltung. Die lasse ich laufen und 
zünde mit dem Viehtreiber auf die Metallplatte (einfach rein und gleich 
wieder raus, nicht in die Schaltung, die wäre sofort kaputt). Wenn meine 
Schaltung und die Software das überstehen, dann kann ich mich ins Feld 
trauen.
Dieser Aufbau ist der "Burst-Test des kleinen Mannes"... ;-)

: Bearbeitet durch Moderator
von Toby P. (Gast)


Lesenswert?

Tim B. schrieb:
> Das ist das Layout. Das ist aber vermutlich so erst mal schwer zu
> verstehen...

So auf den ersten Blick wird das nie funzen. Du hast einfach zu hohe 
Schaltströme zu dicht an empfindlicher Elektronik. Besser auf zwei 
Leiterplatten verteilen.

Softwarefehler kann man mit einem Zähler eingrenzen den man entweder 
nach dem Reset ausgibt oder bei Aufruf oder zwischen der Routinen.

von Ursain (Gast)


Lesenswert?

Na wenn schon die schwindelige PC Software einfriert, weil sie 
durcheinanderkommt, dann wird der Arduino Profi sich wohl eher gar nicht 
um Fehlersituationen, deren Erkennung und Behandlung Gedanken gemacht 
haben.

Das ist alles mit der heißen Nadel gestrickt, ausnahmslos....

von Joachim B. (jar)


Lesenswert?

Tim B. schrieb:
> Das würde erklären warum das Ding beim Kunden abstürzt und bei mir
> nicht. Aber we kann man dem begegnen? Kabel besser schirmen?

besser wäre doch die empfangenen Daten auf Plausibilität zu prüfen
kommen da Zeichen die man erwartet?

isprint
isnum
isalpha

wären mögliche Tests

wenn unplausible Zeichen kommen, wird der Buffer geleert?
werden unplausible Zeichen weiter eingelesen?
Droht Bufferüberlauf?

von Paul (Gast)


Lesenswert?

Tim B. schrieb:
> Also es ist so, dass ich nur sehr begrenzt progrtammieren kann, weshalb
> ich sowohl beim Arduino-Sketch sehr viel Hilfe hatte und an der
> PC-Software gar nicht beteiligt war.

Tim B. schrieb:
> Das Problem tritt aber nur beim Kunden auf...

Klingt nach Volkswagen ;).
Tu dir selbst einen gefallen und nimm das Produkt schnell vom Markt, 
bevor sich jemand die Bude damit abfackelt.

Ich vermute mal deine Bastelei hat keine EMV Tests gesehen. Genausowenig 
Vertrauen erweckt dein Layout. Sprint Layout ist einfach mal nicht das 
Programm der Wahl wenn man kundenfähige Produkte entwicklen möchte. Wie 
hälst du Schaltplan und Layout syncron? Oder gibt es gar keinen 
Schaltplan und es wurde direkt drauf loslayoutet?

Wenn ich lese, dass du 4 Mosfets schaltest im Fehlerfall...
Wie wurde der Fehlerfall in der FMEA bewertet?
Welches Performance Level soll deine Sicherheitsschaltung erfüllen?
Wie hast du den Fall simuliert?
Wie hast du den Fall getestet?

Solche Sachen wie du habe ich vor 10 Jahren auch gebaut, ich hatte die 
gleichen Probleme und wäre nicht im Traum darauf gekommen das zu 
verkaufen, da ich wusste das es zwar halbwegs funktioniert, aber nicht 
die Zuverlässigkeit an den Tag legt, die ich von so einem Produkt 
erwarten würde.

Aber zurück zum Problem. Schaltet dein Kunde während des Betriebs 
Leuchtstoffröhren?
Wie sicher bist du dir, dass es der µC ist? Hängt sich evenutell die 
Schnittstelle am PC auf? (Hatte ich bei mir privat, da war das PC 
Netzteil billiger Kernschrott und die Spannungen waren sehr instabil)

Es soll kein Bashing deines Produkts werden, bitte bleib unbedingt dran 
an der Elektronik. Aber das was du hier präsentiert hast ist weder 
tauglich noch sicher. Im Interesse deiner Kunden und deiner Freiheit: 
Nimm das Produkt vom Markt, entwickel es neu, teste und validiere es und 
dann vermarkte es.

Nutze KICAD für das Layout (Open Source), lasse Prototypen fertigen und 
dann teste sie systematisch oder gib sie zu einem Softwaretester 
(ISTQB).
Falls das finaziell nicht drin ist, dann teste du die Funktionen. Was 
passiert wenn deine serielle Schnittstelle Werte von 0 bis 10 erwartet, 
du aber ein "ü" sendest? Was passiert mit Funktionen die ein uint8_t 
erwarten, wenn stattdessen ein "-3" übergeben wird.
Stichwort: Error Handling.

VG Paul

von Ingo L. (corrtexx)


Lesenswert?

Ich hatte auch mal ne Schaltung, ein Step-Down, bei dem bei zu viel 
Power die serielle Schnittstelle am PC abgestürzt ist... Also zu viel EM 
können die nicht vertragen. Bei meinem ST-Link verliere ich regelmäßig 
die Verbindung zum uC wenn ich ne Schaltung habe, die zu sehr sendet 
bzw. größere Ströme im Spiel sind!

von GuckOchNur (Gast)


Lesenswert?

Joachim B. schrieb:

> besser wäre doch die empfangenen Daten auf Plausibilität zu prüfen
> kommen da Zeichen die man erwartet?
>
> isprint
> isnum
> isalpha
>
> wären mögliche Tests
>
> wenn unplausible Zeichen kommen, wird der Buffer geleert?

Falls die Zeichen nicht palausibel sind, kommt noch "ISNICHWAHR!" in 
Frage.

von Gerald K. (geku)


Lesenswert?

Ingo Less schrieb:
> Nein, der Watchdog ist das allerletzte Mittel, den µC wieder zu holen,
> wenn man selber keinen Einfluss mehr nehmen kann. Ein Programm, dass auf
> einen WDT angewiesen ist, damit es läuft ist ein schlechtes Programm.

Die große Frage ist das Betriebssystem. preemtiv oder kooperativ?

Der Watchdog sollte nicht nur einen Wiederanlauf ermöglichen, sondern 
auch Debuginforationen sichern.
Zu diesen Informationen zählt ein Schnappschuß der Register insbesondere 
des SP und PC. Der PC läßt auf die Stelle des Hängers schließen. Auch 
andere "Exceptions", z.B. Division durch Null, sollten so behandelt 
werden.

Für die Implementierung macht preemtiv oder kooperativ einen großen 
Unterschied aus. Bei kooperativen BS löst jede Dauerschleife eine 
WD-Restart aus. Bei preemtiven BS, wie Linux, können einzelne Prozesse 
oder Threads hängen. Hier ist es sinnvoll Überwachungsprozesse zu 
implementieren, die die zu überwachenden Prozesse auf Plausibiltät bzw. 
korrekten Ablauf prüfen.

: Bearbeitet durch User
von sid (Gast)


Lesenswert?

ich persönlioch bin ja schon kein Fan davon eine schon grün leuchtende 
LED
im nächsten "Arbeitsschritt" auf Grün zu schalten,
ich finde "schalter" egal welche, ob LEDS der sonstige outputs sollte 
NUR geschaltet werden wenn sich der Zustand ändert.

und sowas:
1
void setup()
2
{
3
...
4
   Verbinden();
5
}
6
inline void Verbinden()
7
{
8
  Serial.begin(BPS);
9
}
finde ich auch fürchterlich nutzlos
wenn eine funktion ausschliesslich einmalig im setup() aufgerufen wird,
ist sie mMn zu entfernen und ihr code ins setup zu schreiben;
insbesondere wenn es nur ein stumpfer Einzeler ist.

Egal ich behaupte der Fehler taucht in der ds auf,
die konvertierung via ds.write(0x44) kann ne Sekunde dauern,
millis laufen weiter,
schlimmer noch das Konversionsergebniss wird von Dir vollständig 
verworfen
1
  ds.reset(); // RICHTIGE TEMP AKTUALISIERT NICHT
2
  ds.select(Temp_Addr); // RICHTIGE TEMP AKTUALISIERT NICHT
3
  ds.write(0x44); // RICHTIGE TEMP AKTUALISIERT NICHT
4
  ds.reset(); // FALSCHE TEMP AKTUALISIERT NICHT
5
  ds.select(Temp_Addr); // FALSCHE TEMP AKTUALISIERT NICHT
ist also mindestens 'übereilt'
1
  ds.reset(); // RICHTIGE TEMP AKTUALISIERT NICHT
2
  ds.select(Temp_Addr); // RICHTIGE TEMP AKTUALISIERT NICHT
3
  ds.write(0x44); // RICHTIGE TEMP AKTUALISIERT NICHT
4
  delay(1000);
5
  ds.reset(); // FALSCHE TEMP AKTUALISIERT NICHT
6
  ds.select(Temp_Addr); // FALSCHE TEMP AKTUALISIERT NICHT
wäre der sicherere weg.

heisst aber dass alle "timer" die Du has immer auslösen MÜSSEN
(alle kleiner einer Sekunde)
deswegen solltest Du sie entsprechend anpassen.
Apropos...
1
#define UPDATE_TIME_A 4 /// ms zwischen den Messungen vom Haupt-Stromsensor
ist natürlich auch eher unsinnig
Im Grunde kannst Du UPDATE_TIME_A fast genausogut komplett weglassen und 
den Code bei jedem Schleifendurchlauf ausführen,
der braucht selbst in etwa 2.5-3ms würd ich schätzen.

spielt aber keine Rolle, denn ab dem ersten triggern von 
temperaturschutz()
ist jede folgende loop() eh komplett auf "max"
und alle vergleiche triggern darunterliegenden Code

Mach mal den Test wie folgt:
1
void loop()
2
{
3
  now = millis();
4
  if(now > 1000 && now < 10000)
5
    Serial.writeln(now);
6
...
(sollte in den ersten zehn sekunden die Zweit zwischen zwei
Loop durchläufen veranschaulichen)
und achte mal darauf wie gross der Abstand zwischen den letzten paar 
durchläufen ist,
ich möchte wetten, dass Du überhaupt nur 10 zeitangaben über den serial 
monitor bekommst,
(alles andere würde mich bei dem oneWire protokoll echt wundern)

'sid

von Tim B. (tim_b84)


Lesenswert?

Leute, vielen lieben Dank für die vielen Beiträge und Tipps. Ich werde 
am Montag weiter machen. Jetzt raucht der Kopf.

Eines konnte ich allerdings noch feststellen:
Ich habe den Watchdog aktiviert und der uC ist trotzdem hängen 
geblieben. Ich habe darum nun die Kommunikation mit dem PC im Verdacht. 
Eure Tipps werde ich mir natürlich trotzdem anschauen - vieles davon 
betrifft ja auch diesen Punkt.

Das doofe an dieser ganzen Sache ist, dass ich den Fehler nicht auslösen 
kann und darum immer Stunden lang warten muss bis der Fehler auftritt. 
EMV-Quälen habe ich mangels Weidezaungerät jetzt mal versucht wie hier 
beschrieben. Dabei habe ich mit dem Relais, der Leuchtstofflampe und 
einer alten Bohrmaschine direkt über dem uC rumhantiert. Das hat ihm 
alles nix ausgemacht :-)

von Stefan F. (Gast)


Lesenswert?

Sowohl die Schaltung als auch das Programm sind komplex. Ich würde drei 
Dinge versuchen:

a) Kläre, ob das Ding ohne große Lastströme zuverlässig funktioniert.

b) Gebe jede Menge Logmeldungen auf einem zweiten seriellen Port aus und 
zeichne diese in eine Datei auf. Diese Meldungen sollten einen Hinweis 
darauf geben, an welcher Stelle das Programm hängen bleibt und was kurz 
vorher passierte.

c) Reduziere das Programm auf weniger, um den Fehler einzukreisen. Man 
könnte sich da mal ganz dumm stellen und einfach mal jede Sekunde 
"Hallo" ausgeben. Dann mal schauen, ob das wenigstens stabil läuft. 
Danach könnte man Schaltvorgänge im Lastkreis manuell auslösen, um zu 
sehen, ob diese sich negativ auswirken.

Was manchmal auch Wunder wirkt: Zur Stromversorgung eine Batterie 
verwenden. Muss ja nicht für immer so bleiben, sondern nur, um Probleme 
mit dem Netzteil oder Masseschleifen auszuschließen.

von Stefan F. (Gast)


Lesenswert?

Hier wird die Variable "dauer" gar nicht benutzt:
1
/* Eine bestimmte Dauer abwarten
2
 */
3
inline void waiting(unsigned long dauer)
4
{
5
  unsigned long jetzt = millis();
6
  while( ( millis() - jetzt ) < WR_DELAY ){}
7
}

Ich wollte das gerne zum Test compilieren, aber dazu fehlt die WS2812.h.

von Gerald K. (geku)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich wollte das gerne zum Test compilieren, aber dazu fehlt die WS2812.h.

Vielleicht sollte später WR_DELAY durch dauer ersetzt werden.

von Gerald K. (geku)


Lesenswert?

Stefan ⛄ F. schrieb:
> while( ( millis() - jetzt ) < WR_DELAY ){}

Ich nehme an, mills() liefert den Wert des Systemtickers zurück und 
dieser ist auch vom Typ unsigned long.

Was passiert nach einem Überlauf von 0xffffffff auf 0 ?

Dann gibt es sehr lange Wartezeiten, oder?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Gerald K. schrieb:
> Was passiert nach einem Überlauf von 0xffffffff auf 0 ?
> Dann gibt es sehr lange Wartezeiten, oder?

Nein, die zeit stimmt nach einem Überlauf immer noch. Voraussetzung 
ist, dass man wie hier subtrahiert.

von Einer K. (Gast)


Lesenswert?

Gerald K. schrieb:
> Was passiert nach einem Überlauf von 0xffffffff auf 0 ?
>
> Dann gibt es sehr lange Wartezeiten, oder?

Da passiert gar nix (überraschendes).

Das Prinzip heißt in der Arduinowelt "Blink without Delay".
Zumindest wird in dem Beispiel das Prinzip implementiert.

Und ja:
Keine Problem beim Überlauf, wenn das Intervall kleiner als 49,x Tage 
ist

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

Vielleicht gibt es in der Nähe von oekotrainer.de einen Dienstleister, 
der sich das ganze mal anschauen möchte?

Lothar M. schrieb:
...
> Ich habe für die Schaltungsinbetriebnahme
> für begleitende "EMV-Vortests" einfach einen Viehtreiber wie
> 
https://www.ebay.de/itm/Viehtreiber-HandyShock-Rind-Tier-Treiber-11215/381541741059
> gekauft. Dazu brauche ich dann noch eine Metallplatte und eine
> Kunststoffplatte. Jetzt kommt das Metallblech auf den Labortisch, die
> Kunstoffplatte als Isolator drauf und auf diese Kunststoffplatte gut von
> der Metallplatte isoliert meine neue Schaltung. Die lasse ich laufen und
> zünde mit dem Viehtreiber auf die Metallplatte (einfach rein und gleich
> wieder raus, nicht in die Schaltung, die wäre sofort kaputt). Wenn meine
> Schaltung und die Software das überstehen, dann kann ich mich ins Feld
> trauen.
> Dieser Aufbau ist der "Burst-Test des kleinen Mannes"... ;-)

Lothar, Du begeisterst mich. Damit wird die 61000-4-2 (ESD) ein 
Kinderspiel. Und auch die für die anderen Störempfindlichkeiten bekommt 
man ein besseres Gefühl.
Ich halte gerne mal ein klingelndes Handy an Baugruppen. Gerade bei 
Analogschaltungen sieht man da schnell die Störempfindlichkeit. Und wenn 
die MCU abstürzt, bietet das Design noch viel Verbesserungspotential.

Frage: weißt Du, was der Viehtreiber rausreicht? Ladespannung (1..15kV), 
Ladekapazität (150pF) und Ausgangsimpedanz (330R)?
(Zum Vergleich, Werte aus der EN61000-4-2).

Beitrag #6387042 wurde vom Autor gelöscht.
von Ursain (Gast)


Lesenswert?

Bananensoftware :

Reift beim Kunden😂😂😂👍👍

von Tim B. (tim_b84)


Lesenswert?

Ich habe inzwischen versucht die Schaltung nochmal mit allen möglichen 
EMV-Störungen zu malträtieren (auch mit der Viehschockermethode mit 
echtem Viehschocker :-)) aber was ich auch mache, es hat keinen Einfluss 
auf die Schaltung. Außerdem habe ich den Code für den uC so geändert, 
dass er nur kuriose Zeichenketten an den PC sendet. Das hat nur dazu 
geführt, dass die PC-Software kurioses anzeigt (was hier nicht weiter 
schlimm ist) aber kein Absturz und kein Hänger.
Ich habe das while (serial.available()aus dem Code entfernt und einen 
einfachen Watchdog eingebaut. Vielleicht hat ersteres das Problem ja 
auch tatsächlich schon behoben. Sicher weiß ich das nicht, weil ich den 
Fehler ja doofer weise ja durch nichts auslösen konnte.
Als nächstes werde ich versuchen vom PC zum uC kuriose Zeichenketten zu 
senden. Anschließend werde ich mich nochmal mit der ds.write(0x44)-Sache 
beschäftigen. Ein delay einzubauen ist hier aber keine Lösung, weil das 
Programm weiterlaufen muss. Da würde ich dem Temp-Sensor eher komplett 
deaktivieren.

von Tim B. (tim_b84)


Angehängte Dateien:

Lesenswert?

Wahrscheinlich liest ja keiner mehr aber vielleicht ja auch doch:
Inzwischen hat sich herrausgestellt, dass ein defekter Wechselrichter 
die Störquelle war, der zwischen Eingang GND und PE eine Spannung von 
mehreren hundert Volt produziert hat.

Eine Messelektronik wird über den Akku, an den auch der Wechselrichter 
angeschlossen ist, gespeist. Ein PC nimmt die Signale der Messelektronik 
über eine USB-Verbindung ab. Dadurch ist  der PC über die USB-Verbindung 
mit dem Minus-Pol eines Akkus verbunden. Der Wechselrichter ist defekt 
und liefert darum (unter Last) gemessen zwischen Minus-Pol des Eingangs 
und Schutzleiter des Ausgangs, impulsweise eine sehr hohe Spannung von 
>500V. An den Wechselrichter ist ein Beamer angeschlossen und verbindet, 
sobald er eingeschaltet wird den Schutzleiter mit dem Gehäuse des 
HDMI-Steckers. Wenn nun der HDMI-Stecker am PC  eingesteckt wird, liegt 
die hohe Spannung zwischen Minus USB und Gehäuse HDMI Stecker an und 
sorgt offensichtlich dafür, dass die Schutzschaltung des PCs den 
USB-Port lahmgelegt. Mir ist das aufgefallen, weil der USB-Port, schon 
nicht mehr funktioniert hat bevor ich den HDMI-Stecker ganz eingesteckt 
habe. Als ich das dann näher beobachtet habe, habe ich bemerkt, dass 
beim Kontakt des HDMI-Steckers mit der Buchse Funken zu sehen sind.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.