Hallo,
ich habe seit längerem ein Problem mit meinem ATmega1284P. Ich hatte
dieses Problem schonmal erklärt
TitelBeitrag "ATmega1284P 6tes Bit wird gelöscht"]],
jedoch nicht den Ursprung des Problems gefunden und möchte einen neuen
Anlauf starten.
Kurze Erklärung, für diejenigen die sich den alten Thread nicht
durchlesen wollen.
Ich habe eine Flowregelung für ein Proportionalventil programmiert, die
unregelmäßig springt. Ich habe ein Tool, um mir 4 Variablen in Echtzeit
auf dem PC ausgeben zu lassen. Dort erkenne ich, dass aus irgendeinem
Grund das 6. Bit in Variablen gelöscht und auch wieder gesetzt wird.
Anhand eines bildlichen Beispiels möchte ich dies erklären:
Das Bild im Anhang zeigt die springende Variable, die in der Funktion an
3 verschiedenen Stellen an den PC gesendet wird. Die x-Achse ist in
Millisekunden dargestellt. In diesem Takt läuft auch mein Interrupt
(1kHz), der die Funktion aufruft.
1 | u8_SendTX0[1] = (Tu8) ((u16_PWMAir10bit64fach) & 0xFF); //low Byte
|
2 | u8_SendTX0[2] = (Tu8)(((u16_PWMAir10bit64fach) & 0xFF00) >> 8); //high Byte
|
3 |
|
4 | if (u16_ADD_ & 0x8000) // PWM - verkleinern
|
5 | {
|
6 | if (u16_PWMAir10bit64fach > (IFLOW_PWMIN - u16_ADD_))
|
7 | u16_PWMAir10bit64fach = u16_PWMAir10bit64fach + u16_ADD_;
|
8 | else
|
9 | u16_PWMAir10bit64fach = IFLOW_PWMIN;
|
10 | }
|
11 | else // PWM - vergroessern
|
12 | {
|
13 | if (u16_PWMAir10bit64fach < (IFLOW_PWMAX - u16_ADD_))
|
14 | u16_PWMAir10bit64fach = u16_PWMAir10bit64fach + u16_ADD_;
|
15 | else
|
16 | u16_PWMAir10bit64fach = IFLOW_PWMAX;
|
17 | }
|
18 |
|
19 | u8_SendTX0[3] = (Tu8) ((u16_PWMAir10bit64fach+1) & 0xFF); //low Byte
|
20 | u8_SendTX0[4] = (Tu8)(((u16_PWMAir10bit64fach+1) & 0xFF00) >> 8); //high Byte
|
21 |
|
22 | u16_DummyFlowAir = PWM_MAX - (u16_PWMAir10bit64fach / 64);
|
23 |
|
24 | if (u8_AIRVersorgungOK == 1)
|
25 | OCR1A = u16_DummyFlowAir; //Anpassung des AIR-PWM-Signals, OCR1A = 1023 bedeutet PWM aus
|
26 | else
|
27 | OCR1A = PWM_MAX; //Prop-Ventil schließen, damit kein Gas zurück in ZGV
|
28 |
|
29 | u8_SendTX0[5] = (Tu8) ((u16_PWMAir10bit64fach+2) & 0xFF); //low Byte
|
30 | u8_SendTX0[6] = (Tu8)(((u16_PWMAir10bit64fach+2) & 0xFF00) >> 8); //high Byte
|
Das Array u8_SendTX0 sende ich an den PC. Im Bild im Anhang seht ihr nun
die Variable "PWMAir10bit64fach" 3 mal abgebildet:
in grün, dort wo sie in u8_SendTX0[1+2] geschrieben wird
in blau, dort wo sie in u8_SendTX0[3+4] geschrieben wird
in rot, dort wo sie in u8_SendTX0[5+6] geschrieben wird
Der oben gepostete Code zeigt alle Stellen, in denen die lokale Variable
"PWMAir10bit64fach" vorkommt. Die Funktion wird aus einem Interrupt
aufgerufen, kann also nicht durch einen Interrupt-Aufruf gestört werden.
Im Bild sieht man nun, dass die Variable an den beiden später
aufgenommenen Stellen deutlich fällt und wieder steigt, und zwar von ca.
27300 auf 19100 und zurück. Dies entspricht genau dem Löschen und wieder
Setzen des 6. Bits im höherwertigen Byte der Variable.
Dieses Phänomen kommt unregelmäßig bis gar nicht vor und ist daher
schwer zu reproduzieren. Da mein Kollege und ich keinen Fehler in der
Software finden konnten, haben wir uns mal die 5V-Spannungen am uC mit
einem scope angeschaut, siehe Bild2 im Anhang.
Dort sind Spannungsspitzen zu erkennen, die mit dem PWM-Signal des
Proportionalventils wandern. Das PWM-Signal hat eine Frequenz von ca.
20kHz. Wie stark die Spannungsspitzen sind, möchte ich noch nicht ganz
beurteilen, da ich mir mit dem jetztigen Messaufbau evtl. HF-Störungen
eingefangen haben könnte.
Die Schaltung, mit der das Ventil angesteuert wird, seht ihr in Bild3.
Das RC-Glied am Portpin haben wir hinzugefügt, um steilere Flanken am
PWM-Signal zu erzeugen. Kann es aber sein, dass bei leerem C der Strom
auf ca. 200mA ansteigt (knapp. 4V zwischen Portpin und Transitor) und
dadurch den uC so sehr belastet, was den Spannungseinbruch erzeugt. Wie
gesagt, die Spannungsspitzen wandern mit dem PWM-Signal. Ich habe zwar
die Fuse Brown-out-detection = 4,3V gesetzt und der uC wird nicht
geresettet, allerdings sehe ich im Datenblatt unter 26.2, dass der uC
bei 20Mhz mindestens 4.5V brauch, um sicher zu arbeiten.
Dazu kommt noch, dass der Portpin für die Ventilansteuerung PD5 ist,
also der 6. Pin an Port D.
Nun meine Frage, kann eine zu hohe Strombelastung an einem Portpin dazu
führen, dass intern ein einzelnes Bit gelöscht wird?
Leider bekomme ich den Fehler nicht reproduziert, sonst würde ich das
gleiche ohne den C nochmals ausprobieren.