Forum: Mikrocontroller und Digitale Elektronik Überlastung Atmega64


von Marcel D. (dmarcel21)


Lesenswert?

Hallo,

ich entwickle momentan einen FlightController für meinen Quadrocopter.
Ich verwende für die Winkelbrechnung einen itg3205 und einen adxl345.
Der ATmega64 liest diese zwei Bausteine aus und berechnet daraus den 
aktuellen Winkel.
Zusätzlich liest er 4 PWM - Signale vom Empfänger mittels den externen 
Interrupt's aus.
Und schlussendlich erzeugt er 4 PWM - Signale für die 4 ESC's.

Ich habe alles einzeln geschrieben und getestet. Dort hat es immer 
funktioniert, jedoch wenn ich alles gleichzeitig ausführe stimmt der 
berechnete Winkel nicht mehr.
Meine Theorie dazu ist, dass der Interrupt (der von einem TimerOVF 
ausgelöst wird), durch die zusätzlichen Interrupt's, nicht mehr im 
gleichen Zeitabstand aufgerufen wird und das verfälscht den berechneten 
Winkel (den Winkel des Gyro's) sehr.

Stimmt diese Theorie bzw. wie kann ich dieses Problem lösen?
Würde es reichen, wenn ich die PWM Signale mittels einem externen 
Baustein's erzeuge, welcher mit I2C angesprochen wird?

Danke für eure Hilfe

von MaWin (Gast)


Lesenswert?

Marcel D. V. schrieb:
> Stimmt diese Theorie

Das wissen wir nicht, aber es kann schon sein.

> mittels einem externen Baustein's

Eher durch besser formulierte Software.

von Marcel D. (dmarcel21)


Lesenswert?

okay danne für deine Hilfe.
Ich werde mal versuchen ob ich was aus der Sodtware rausholen kann.

von Ulrich (Gast)


Lesenswert?

Die PWM Signale sollten die Timer rein in HW erzeugen können. Das sollte 
also nicht das Problem sein.

von H.Joachim S. (crazyhorse)


Lesenswert?

Steig beizeiten um auf was mit mehr Rechenleistung.
Könnte sein, dass du es rechenzeitmässig noch reingequetscht bekommst, 
bist aber von Anfang an am oberen Limit - nicht gut. Es kommen ständig 
neue Sachen hinzu :-)
Ich habe sowas mal gemacht, allerdings für einen echten Helikopter 
(könnte mir vorstellen, dass ein Quadrokopter etwas einfacher zu steuern 
ist), die erste Version Mit ATMega ging in die Hose...
STM32 war prima.

von Marcel D. (dmarcel21)


Lesenswert?

ja es ist aber so:
der Winkel stimmt solange die PWM - Signale einen HighPegel von 1.0 ms 
haben. (19 ms low)
erhöhe ich diese Zeit (gebe gas) stimmt er bei weiten nicht mehr.
darum dachte ich, dass das irgendwie zusammenhängt.

ich habe viele FlightController mit einen Atmega daraug gesehen, daher 
denke ich, dass es möglich ist.
aber sobald ich mehr Funktionen einbauen will, muss ich ziehmlich sicher 
alles anders aufbauen.

von Uwe S. (de0508)


Lesenswert?

Hallo Marcel,

und mit was kodierst Du?

Zeige uns bitte deine Hauptprogrammschleife. THX

von Marcel D. (dmarcel21)


Lesenswert?

ich kodiere mit AVR Studio.

meine Code besteht aus vielen Teilen.
ich kann morgen einiges davon mal posten.

von Dominic S. (Firma: Privat) (dominics)


Lesenswert?

Versuch deinen Code um alles was geht zu optimieren. Das reine benutzen 
von Hardware sollte da keine Probleme machen. Wenn du dem Timer sagst 
welchen Wert du haben willst, sollte es alles weitere ohne dein Zutun 
erledigen.

Versuche den Code so zu schreiben, dass du nicht überwachen musst ob du 
Fehler dinn hast. Solche Überwachungen machen meist sehr viel aus. Ich 
hab früher auch in jeder Software ebene überwacht ob ich einen falschen 
Wert habe, wenn es jedoch wirklich darauf ankommt, mache ich das nur 
noch soweit oben wie möglich. Wieso sollte ich einen Wert der nicht 
falsch sein kann überprüfen?

Zeigt doch mal bitte deine Hauptschleife, vielleicht finden wir da noch 
n paar Sachen.

von Marcel D. (dmarcel21)


Lesenswert?

Okay ich werde das Mal beachten.

Ich werde meine Hauptschleife morgen posten.

von X. A. (wilhem)


Lesenswert?

Marcel,
ich hatte ein sehr ähnliches Problem. Ich würde an deiner Stelle eine 
extra Platine kaufen, durch serial oder I2C angeschlossen, mit der Du 
die Motoren ansteuern kannst. Der CPU wird somit entlastet und die PWM 
Signale der Steurungsplatine delegiert.
Durch diese Entkopplung solltest Du das Problem beseitigen können.

Gruß

von Marcel D. (dmarcel21)


Lesenswert?

Das habe ich auch zusätzlich dazu geplant zu machen.
ich werde aber auch versuchen den Code zu optimieren.

von Falk B. (falk)


Lesenswert?

@ Marcel D. V. (dmarcel21)

>Das habe ich auch zusätzlich dazu geplant zu machen.
>ich werde aber auch versuchen den Code zu optimieren.

Das kommt später. Erstmal musst du MESSEN, um deine Vermutung zu 
untermauern oder zu widerlegen. Das kann man im ersen Schritt im 
Simulator machen. Aber das könnte schwierig werden, wenn man I2C 
Zugriffe simulieren will. Einfacher und schneller ist eine Messung am 
echten System mit einem Testpin, welcher immer dann auf HIGH geht, wenn 
der Controller aktiv was macht und wieder auf LOW, wenn eine Funktion 
etc. beendet ist. Damit kann man in Echtzeit die Rechenzeit der 
einzelnen Funktionen messen. Am Ende deiner Hauptschleife, wenn alle 
zyklischen Aufgaben erledigt sind, muss immer noch etwas Zeit übrig 
bleiben. Wenn nicht, ist dein Controller überlastet.

Man sollte aber nicht vergessen, dass es auch andere Fehlermöglichkeiten 
gibt. Z.B. dass deine Motortreiber deine Sensoren stören. Ein Oszi hilft 
hier auch ungemein.

von Marcel D. (dmarcel21)


Lesenswert?

Das Problem ist das mein ganzer Code in Interrupts ist.
Aber ich habe schon eine Idee wie ich das lösen kann.

Danke mal für die Hilfe

von Falk B. (falk)


Lesenswert?

@ Marcel D. V. (dmarcel21)

>Das Problem ist das mein ganzer Code in Interrupts ist.

Kann sinnvoll sein. Aber umso einfacher kann man das messen bzw. Prüfen.

http://www.mikrocontroller.net/articles/Multitasking#Ein_einfaches_Beispiel_f.C3.BCr_den_AVR

3.Beispiel mit Timer.

"Es kann leicht im realen System geprüft werden, ob die Laufzeit der 
Tasks klein genug ist, um den Anforderungen des Timers zu genügen. "

von stefanus (Gast)


Lesenswert?

> Das Problem ist das mein ganzer Code in Interrupts ist.
Schön, dass Du es erkannt hast. Das war der wichtigste Schritt. Nun mach 
es besser.

Lies Dich in das Thema "Zustandsautomat" ein und nutze Interrupts 
lediglich dazu, Ereignisse zu erfassen und in irgendwelche Variablen 
abzulegen, damit sie später in der (einzigen) Programmschleife 
abgearbeitet werden.

Sobald Deine Interrupt-Routine aus mehr als 10 Zeilen C besteht, 
solltest Du nachdenklich werden. Folgende Dinge haben in 
Interrupt-Routinen grundsätzlich nichts zu suchen:

- Display Ausgaben
- Divisionen mit Divisor ungleich 2, 4, 8, 16, ....
- Fließkommazahlen
- Wiederholschleifen
- Sleep Befehle

Lass mich raten: Du hast aon allem was dabei, oder?

von Marcel D. (dmarcel21)


Lesenswert?

Nein ganz so dumm bin jetzt auch wieder nicht.
Ich habe keine Displayausgaben und Sleepbefehle in meinen Interrupts.
Jedoch habe ich die Berechnungen vom Gyro in einem.
Aber wie soll ich eine Berechnung, welche nur benötigt wird, wenn er den 
Gyro ausliest ausliest dann einbinden?

von Karl H. (kbuchegg)


Lesenswert?

Marcel D. V. schrieb:
> Nein ganz so dumm bin jetzt auch wieder nicht.
> Ich habe keine Displayausgaben und Sleepbefehle in meinen Interrupts.
> Jedoch habe ich die Berechnungen vom Gyro in einem.
> Aber wie soll ich eine Berechnung, welche nur benötigt wird, wenn er den
> Gyro ausliest ausliest dann einbinden?

So wie immer
1
volatile uint8_t gyroReady;
2
3
IRS( ... )
4
{
5
  gyroReady = 1;
6
}
7
8
int main()
9
{
10
  ...
11
12
  while( 1 ) {
13
14
    ...
15
    if( gyroReady ) {
16
      gyroReady = 0;
17
18
      ..... mach was mit den Gyro Daten
19
    }
20
21
    ....
22
  }
23
}


und so machst du das mit allem was ein wenig länger dauert.
Die ISR kann kleinere Dinge berechnen, solange sie schnell gehen. 
Ansonsten stösst die nur an, indem sie das Flag setzt. In der 
Hauptschleife werden nacheinander die einzelnen 'Jobs' überprüft, ob sie 
wieder mal anstehen und werden abgearbeitet, wenn es wieder mal soweit 
ist.

von jonas biensack (Gast)


Lesenswert?

>Aber wie soll ich eine Berechnung, welche nur benötigt wird, wenn er den
>Gyro ausliest ausliest dann einbinden?

Diese Berechnungen da sicher mit Fließkomma dauern ewig aufm Atmega da 
kein Hardwaremultiplizierer für floats oder doubles exestiert. Eventuell 
lässt sich da was optimieren, aber wahrscheinlich brauchst du mehr 
rechen power bzw. andere architektur (32bit).

GRuß Jonas

von Marcel D. (dmarcel21)


Lesenswert?

Okay ich werde es Mal mit Flags versuchen.

von Karl H. (kbuchegg)


Lesenswert?

Man kann im übrigen Berechnungen, wenn sie wirklich extrem lang sind 
(und sich das auch nicht verkürzen lässt) auch in mehrere Abschnitte 
unterteilen, die sie selbst auf genau die gleiche Art und Weise die 
Freigabe geben.
1
  while( 1 ) {
2
3
    .... YYYY
4
5
    if( performPart4 ) {
6
      performPart4 = 0;
7
8
      ... bearbeite Abschnitt 4
9
    }
10
11
    if( performPart3 ) {
12
      performPart3 = 0;
13
14
      .... bearbeite Abschnitt 3
15
16
      performPart4 = 1;
17
    }
18
19
    if( performPart2 ) {
20
      performPart2 = 0;
21
22
      .... bearbeite Abschnitt 2
23
24
      performPart3 = 1;
25
    }
26
27
    if( doTheJob ) {
28
      doTheJob = 0;
29
30
      .... bearbeite Abschnitt 1
31
32
      performPart2 = 1;
33
    }
34
35
    ... XXXX
36
37
  }

Ziel der Sache ist es, dass die Programmteile XXXX bzw. YYYY während der 
länger andauernden Berechnung auch eine Chance haben, ihr Ding zu 
machen.

Der Schlüssel zu einem Programm, welches mehrere Dinge 'gleichzeitig' 
macht besteht darin, dass alles in kleine Happen aufgeteilt wird und 
sich der Rechner die Happen reihum einzeln vornimmt. D.h. sofern die 
Rechenleistung grundsätzlich ausreicht.

Ein weiterer Schlüssel besteht in der korrekten Verwendung von 
Datentypen. Wer einfach wahllos mit int oder double um sich schmeisst, 
darf sich nicht wundern, wenn sein Mega nicht mehr mitkommt. 
Fleissaufgaben benötigen schliessllich auch Rechenzeit, selbst wenn sie 
unnütz sind.

von H.Joachim S. (crazyhorse)


Lesenswert?

Kalman-Filter (wirst du brauchen) schon drin?
Die oben gemachten Vorschläge sind alle gut und richtig - hilft aber 
alles nichts, wenn du es nicht schaffst, innerhalb deiner Zykluszeit 
alle Berechnungen auszuführen.
Dann bleibt dir nur 3 Wege:
-die Zykluszeit erhöhen (schlecht für die Qualität der Regelung)
-die Berechnungen zu vereinfachten (was bei einer 3D-Lageregelng Grenzen 
hat)
-die Berechnungen auf einer schnelleren Maschine ausführen

von Marcel D. (dmarcel21)


Lesenswert?

Die Winkelberechnung mache ich mittels einem digitalen Hoch- und 
Tiefpass. Das ist zwar nicht so genau, wie der Kalman Filter, jedoch ist 
er weniger aufwendig und benötigt nicht so viel rechenpower.
Und mit dieser kleinen Ungenauigkeit kann ich leben.

Ja ich versuche eben mal meine Codr zu optimieren und so wenig wie 
möglich in den Interrups zu machen.

von Ingo (Gast)


Lesenswert?

Also grundsätzlich kann man bei richtigem Programmierstil schon gut was 
ausm AVR rausholen. Aber irgendwann ist Schluss. Dann muss man sich halt 
mehr Rechenleistung gönnen, z.B. einen Cortex M3/M4.

So schlimm ist die Einarbeitung nicht. Ganz im Gegenteil, durch die 
CMSIS ist die Hardware schnell initialisiert und man kann sich dem 
eigentlichen Problem widmen.



Ingo

von Marcel D. (dmarcel21)


Lesenswert?

Ich bleibe vorerst beim AVR Studio, da andere FlightController ja auch 
mit ATmegas arbeiten, muss es so gehen.

Aber trotzdem danke für die super Vorschläge.

von Ulrich (Gast)


Lesenswert?

Der ggf. kritische Teil ist die PWM-erzeugung. Wenn man das in Software 
macht, verbraucht es sehr viel Rechenzeit. Auch bei der Erfassung der 
Pulse kann man mit einem nicht so guten Programm viel verschenken. Der 
Trick ist es halt vieles direkt von der Hardware machen zu lassen und 
nicht alles von Hand zu programmieren.

Die Datenerfassung von Gyro und Filterung sollte eher das kleinere 
Problem sein, und ist eher nicht so zeitkritisch. Wenn das Fehler 
auftreten wenn der Code länger wird, ist es eher ein Problem mit dem 
Stack oder nicht atomarem Datenzugriff.

von Marcel D. (dmarcel21)


Lesenswert?

Ich erzeuge die PWM im Fast-PWM Modus, also über die Hardware.

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.