Forum: Mikrocontroller und Digitale Elektronik CodeVision AVR und Interrupt


von Heiß Michael (Gast)


Lesenswert?

Hallo

Ich will mit CodeVision ein Proramm schreiben welches immer Daten von
der Seriellen Schnittstelle einliest und dabei den Programmablauf nicht
beeinflusst.
getchar() lässt das Programm warten und is daher unbrauchbar.

Kann mir jemand den Umgang mit Interupts erklären.
Den Quellcode den CodeVision erzeugt kappier ich nicht.
Gibt es keine Einfachere Lösung nur zum Empfangen per Interrupt?

Mfg DarkMarine

von Heiß Michael (Gast)


Lesenswert?

Sorry ganz vergessen ich verwende das STK 500 und den ATMEG163

von crazy horse (Gast)


Lesenswert?

verwende doch den CodeWizard, bei Uart Receiver und Rx interrupt
anmarkern, dazu noch eine Rx-Buffergrösse wählen, je nach Bedarf.
Ankommende Zeichen werden in den Buffer geschrieben, davon merkst du
nicht viel.
Im Programm dann kannst du prüfen, ob rx_counter>0, wenn ja, einfach
mit getchar Byte aus dem Buffer abholen.

von Heiß Michael (Gast)


Lesenswert?

Super danke für deinen Tipp! Funktioniert bestens

Mfg

von crazy horse (Gast)


Lesenswert?

na ja, manchmal lohnt es sich schon, die gesamte Hilfe durchzulesen,
damit man mal weiß, welche Möglichkeiten man hat :-)

von Heiß Michael (Gast)


Lesenswert?

Ok das mit dem Interupt funktioniert aber ganz das wahre ist es nicht.
Folgendes Problem:

Ich schreibe ein Regelungsprogramm das nicht unterbrochen werden darf.
Wenn jetzt ein Interupt kommt wird mein Programm unterbrochen und die
Zeit des Regelungsprogrammes verändert sich was sich negativ auswirkt.

Hat das Stk500/ATMega163 einen "Zwischenspeicher" der Daten, die ich
nicht sofort abfragen kann, speichert sodass sie nicht verloren gehen?

von Heiß Michael (Gast)


Lesenswert?

schieb
Es ist wirklich wichtig weiß wirklich keiner wie ich das lösen kann?

von Stefan May (Gast)


Lesenswert?

Hi,

Also wenn Du einen Regler mit genauen Abtastmomenten benötigst, dann
solltest Du das über einen Timer-Interrupt machen. Das ist in meinen
Augen die sicherste Lösung.

Eine andere Idee ist die Verarbeitung des UART in der Hauptschleife.
Wenn ein Zeichen da ist, dann verarbeite das. Wenn keins da ist, dann
mache solange NOPs, wie Deine Verarbeitungsroutine lang ist.

Was ist eigentlich dieses Codevision?

mfg, Stefan.

von crazy horse (Gast)


Lesenswert?

glaub ich im Leben nicht, dass dein Programm so  zeitintensiv ist, dass
es nicht unterbrochen werden darf - und wenn doch, also 100% Auslastung
(und nur das wäre ein Grund "welches nicht unterbrochen werden
darf"), hast du im Entwurf was falsch gemacht, also falschen Prozessor
oder zumindest zu niedrigen Takt.
Der STK500 macht/hat überhaupt nichts, ist eine dumme Platine, die
verschiedene AVRs mit Takt und Strom versorgen kann, ein paar Taster,
ein paar Leds, und als wichtigstes, den eingesetzten Prozessor
programmieren kann. Damit erschöpfen sich die Möglichkeiten auch schon
fast.
Prinzipiell ist kein AVR in der Lage, mehrere Prozesse wirklich
parallel zu verarbeiten, das funktioniert nur durch timesharing,
verschiedenen Prozessen wird Prozessorzeit zugeteilt, entweder feste
Zeitscheiben oder Ereignisgesteuert. Gehts an die Grenze der
Prozessorleistung, ist diese Verteilung durchaus nicht mehr trivial,
aber wie gesagt, meiner Meinung nach bist du meilenweit davon entfernt.
Und ich verstehe dein Problem auch nicht wirklich, vielleicht wäre mal
das Programm mit ein paar Anmerkungen, wo deiner Meinung nach Probleme
auftauchen, sehr sinnvoll. Ich jedenfalls habe keine Lust, weiter im
Dunkeln zu tauchen.

von Stefan May (Gast)


Lesenswert?

Ich glaube da verstehst Du was falsch. Für eine zeitdiskrete Regelung
(bei digitalen Regelungen immer der Fall) ist es wichtig, daß die
Abtastzeit konstant ist. Das sind sie nicht, wenn der Regler an
zufälligen Zeitpunkten von einem Interrupt unterbrochen wird.

Deshalb mein Vorschlag, die Regelung in einen Timer-Interrupt zu
verlagern. Damit hast du eine konstante Abtastzeit und kannst im
Hauptprogramm noch andere Sachen machen.

Wenn ich es richtig verstehe, sollen Reglerparameter über UART gesetzt
werden. Das sollte sogar ohne Hauptprogramm auskommen. Den Regler also
in den Timer-Interrupt, das Verarbeiten und setzen der Parameter in den
UART Rx Interrupt. Ist fast wie mehrere Prozesse. :-)

mfg, Stefan.

von Heiß Michael (Gast)


Angehängte Dateien:

Lesenswert?

@May stimmt alles was du geschrieben hast!

Die Abtastung muss immer konstant sein und darf deshalb nicht
unterbrochen werden.
Das Regelungsprogramm steht in der Timer0 Overflow routine.
Und die Regelparamter sollen über die RS232 übertragen werden.


Nur zu meinem Verständniss:
Kann der Timer0 Overflow interupt eigentlich durch einen anderen
Interupt unterbrochen werden?.

Ich füge mal den Aktuellen Quellcode ein.

Zum Quellcode:

Das was zur Zeit im Main Programm steht soll nicht mehr durch Taster
auswählbar sein sondern eben per PC-Steuerbar. Diesen Teil möchte ich
ersetzen.
Dafür habe nehme ich die (vorgeferitgte) Interupt Routine von
CodeVision zum Empfangen von Daten.(noch nicht integriert)
Wenn der Timer0 Overflow ausgelöst wird sprich das Regelungsprogramm
läuft darf es eben nicht mehr durch einen anderen Interupt gestört
werden.
-->Genau da liegt mein Problem: Wenn ich während dessen Daten sende
unterbricht der RX-Interupt mein Programm und der Regler funktioniert
nicht mehr einwandfrei.

Zum Regler:
Ich bin gerade beschäftigt ein Inverses Pendel zu bauen. Der uP soll
einen Motor ansteuern der das Pendel dann ausbalciert sodass es nach
oben steht.

Hoffe das waren genug Infos um mein Progblem zu verstehen.

CodeVision ist ein C-Compiler.

Mfg und danke für eure bisherige Hilfe DarkMarine

von Heiß Michael (Gast)


Angehängte Dateien:

Lesenswert?

Ein Bild um vielleicht das verständniss zu erleichtern.

von Stefan May (Gast)


Lesenswert?

Timer0 Overflow kann durch einen externen Interrupt, Reset und Watchdog
unterbrochen werden. Den externen Interrupt kann man unterdrücken,
ebenso den Watchdog. Reset ist aber unmöglich abzuschalten. :-)

Aber jetzt wird das Problem klar. Die Lösung habe ich schon weiter oben
skizziert. Die Regelung kommt in den Timer0 Interrupt rein, im UART Rx
Interrupt werden die Reglerparameter gesetzt. Main besteht dann nur aus
einer Endlosschleife, die einen Sleep enthalten kann. Achtung: Keinen
Powerdown! Dann wacht der Controller nicht mehr auf.

Du mußt folgendes beachten: Der Rx Interrupt sollte jederzeit durch
Deinen Regler unterbrochen werden können. Wichtig ist dann, daß Du das
überschreiben der Parameter dann lockst. Also so:

   cli();
   parameter = neuerparameter;
   sei();

Ich bin mir jetzt nicht sicher, ob mit Eintritt der Interrupt-Routine
alle Interrupts ausgeschaltet werden. Wenn ja, dann solltest Du den in
Rx wieder einschalten, da Timer0 sonst nicht aktiv wird.

Viel Spaß mit dem inversen Pendel. Ich habe das auch mal gemacht,
allerdings mit Matlab und einem PC.

Was Dir noch fehlt, ist die Normierung des Reglers. Du benutzt im
Moment float, was Du unbedingt auf integer (am besten 8 Bit) umstellen
solltest. Du kannst die Abtastzeit dann verringern, was die
Ungenauigkeit der 8 Bit wieder ausgleicht.

Für mehr Kommentare ist es jetzt schon zu spät. :-) Schreib mal, wie es
weitergeht.

mfg, Stefan.

von Heiß Michael (Gast)


Lesenswert?

Für mehr Kommentare ist es nie zu spät ich bin gerade erst am Anfang!

Ich muss das Programm nämlich verbessern.

Zur Zeit ist geplant die AD-Wandlung nicht mehr vom uP erledigen zu
lassen sondern über einen Externen AD-Wandler.

Mal schauen was ich noch verändern muss/kann.

Thx für deine bisherige Hilfe!

Mfg DarkMarine

von Stefan May (Gast)


Lesenswert?

Ich meinte mit spät eher die Zeit. Den Beitrag habe ich um 2:30 Uhr
geschrieben.:-)

Warum willst Du die Wandlung extern machen? Ist der interne A/D-Wandler
nicht genau genug? Ich sehe einen externen Wandler eher als Nachteil.

An Deiner Stelle würde ich den Regleralgorithmus noch verbessern. Die
Berechnung der Stellgröße als float ist unnötig und belastet den
Prozessor zu stark. Wie gesagt: Normiere Deine Reglerparameter und Du
kannst mit 8 bit Integer (signed char) weiterrechnen.

Ein bisschen Kritik noch am Schluß: Du solltest Deinen Regler VORHER!
sorgfältig planen. Also wie man es in der Schule lernt:

1.) Modell bilden
2.) Das ganze normieren
3.) Reglerparameter berechnen

Danach kommt erst die Implementation. Das ist eigentlich der einfachste
Teil. Wenn es dann nicht funktioniert, dann ist was an Deinem Modell
oder Deinen Reglerparametern faul. Es ist auch nicht verkehrt, das
ganze vorher zu simulieren.

Machst Du das ganze just for fun oder als Studienarbeit? Uni? Schule?

mfg, Stefan.

P.S. Eventuelle Unterstellungen bitte nicht persönlich nehmen. Ich
spreche nur aus eigener Erfahrung, und da setzt man sich gerne erst mal
an den Rechner und programmiert drauf los.

von Stefan May (Gast)


Lesenswert?

Und noch ein Link:

http://www.cis.tugraz.at/regis/Welcome.html

Dort wird ein inverses Pendel beschrieben, inkl. Java-Applet, ein paar
Beispielfilmen und ein bisschen Systemtheorie. Könnte vielleicht ganz
brauchbar sein.

mfg, Stefan.

von Heiß Michael (Gast)


Lesenswert?

g aso verstehe.

Zur Zeit wird das Winkelsignal über eine längere Strecke übertragen
(~2m). Das Signal wird also durch Störungen (Motor,...) beeinflusst.
Deshalb wird das Signal vorher Umgewandelt und anschliesend als
digitales Signal übertragen.

Die Stellgröße ist als Int definert. Ich verstehe auch nicht ganz was
du mit Normierung meinst.
Das gesammte Timing der Regelung wird als nächstes überarbeitet.

Das ganze mache ich im Ramen einer Diplomarbeit an der HTL.
(Weiterentwicklung)

Wieso kenns du dich so gut in der Regelungstechnik aus?
Eigeninteresse oder?

Thx

Mfg Michael

von Stefan May (Gast)


Lesenswert?

Hallo Michael,

Ich habe Technische Informatik studiert. Da war Regelungstechnik eines
der Hauptfächer.

Folgendes zur Normierung:


/* --- Positionswerte in Meter --- */
poswert[3] = pos()*(0.11/2000.0);  // 11cm bei 2000 Pulsen

Am Kommentar kannst Du schon erkennen, daß Du in der Einheit Meter
rechnest. Wozu? Mein Regleungstechniksckript sagt dazu:

"Um die folgenden Berechnungen nicht unnötig zu belasten, werden die
Variablen, z.B. Druck, Füllstand, Weg, normiert, d.h. dimensionsfrei
gemacht. Hierzu werden die Variablen auf ihre Nennwerte bzw.
Maxmimalwerte bezogen. Beispiel Füllstandsregelung: Die Variable h
kennzeichnet den Füllstand, der im Bereich 0<=h<=5m schwanken kann. Der
maximale Füllstand hmax beträgt somit 5m. Die normierte Variable h*
errechnet sich aus: h*(t) = h(t) / hmax."

Auf Deine Anwendung bezogen: Du willst 2 Sachen Regeln. Zum einen die
Position des Pendels. Diese Größe hast Du schon "normiert", indem Du
mit der Anzahl der Pulse rechnest. Die andere Größe ist der Winkel.
Diesen hast Du ebenfalls schon "normiert", indem Du einfach den
ADC-Wert nimmst.

Was ist eigentlich schon fertig und worauf baust Du Deine Diplomarbeit
auf? Was ist denn Deine genaue Aufgabe?

mfg, Stefan.

von Heiß Michael (Gast)


Lesenswert?

Hallo,

Das Pendel ist schon fertig und funktioniert, ich noch jemand sollen es
verbesserb.

Meine Aufgabe:

Steuerung über PC ermöglichen
AD-Wandlung des Winkelsignals
Verbesserung des Regelalgorithmus
Programmieren eines Beobachters: Falls durch Störungen falsche Werte
ausgegeben werden soll der Beobachter diese korrigieren.
Das wären die Hauptaufgaben.

Mit dem Regelaungsalgorithmus habe ich mich (wie du wahrscheinlich
schon bemerkt hast ) noch fast gar nicht auseinandergesetzt.
Bis jetzt habe ich an einem C++ Programm für Windows gearbeitet mit dem
ich das Pendel steurn kann.

Jetzt muss ich mich einmal in den Regelungs Code einarbeiten den ich
vom Vorjahr übernommen habe. Bin für jede Hilfe sehr dankbar.

Mfg Michael

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.