Hallo zusammen !
Ich habe C Code geschrieben, der eigenlich in AVR Studio macht was er
soll nur Praktisch klappts halt nicht. Da ist irgendwo ein Wurm drin und
ich such ihn schon seit 2 Tagen.
Ich benutze Atmega16 @ 16Mhz, Timer0 der ständig bei Overflow
Einzelwandlung auf ADC anstösst dann wirds bisschen gerechnet und
ausgegeben.
Bitte schaut mal drüber vielleicht fällt euch ja was auf, was ich nicht
sehe.
Dnake !
L0rd wrote:
> Praktisch klappts halt nicht. Da ist irgendwo ein Wurm drin
Das ist ja mal ne super konkrete Fehlerbeschreibung, damit kann jeder
was anfangen ?????
Du willst wohl keine Antworten ?
Ohne Fehlerbeschreibung gibts auch keine Hilfe.
Also, was wird erwartet und was passiert statt dessen ?
Peter
Danke für den Tip !
aber, nö :(,
mit
SIGNAL (TIMER0_OVF_vect)
SIGNAL(SIG_OVERFLOW0)
ISR(TIMER0_OVF_vect)
getestet - kein Unterschied.
Ich weiss nicht in wieweit man AVR Studio trauen kann, aber dort springt
er (wenn Timer0 zähler von FF -> 0 geht ) in ISR und dann ruft
rechnung(); auf und startet AD-Wandlung.... halt alles wie es sein soll.
Ich vermute dass mit AD-Wandler was nicht stimmt, weil ich kann/weiss
nicht wie man mit AVR Studio am ADC eingang ein Wert simulliert und
nach dem Auslesen x = ADCH; wird ADIF nicht zurück auf 0 gesetzt. Ist
aber net schlimm weil bei nächsten AD Start wird er automatisch
zurückgesetzt.
@ Peter Dannegger
sorry, am PortC sollte was rauskommen, kommt aber nicht - bleibt seit
Anschalten auf 0.
In Avr Studio kommt erste 2 Overflows am PortC was raus, eine Grosse
Zahl ich schätze über 128 und dann bei 2tem durchlauf ne 4 oder so und
bei nächsten durchläufen bleibt auf 0 stehen.
Sieht so aus als AD-Wandler keine Werte liefert, und die Formeln rechnen
mit "0"-Werten seit Initialisierung und gehen dann irgendwann gegen "0".
Tach.
Das Problem liegt mit Sicherheit an deiner Reglerberechnung. Ist glaub
ich ein I Regler. Nun verhält der sich so, dass er die Abweichung auf
null versucht zu ziehen. Da du aber in der digitalen welt lebst fallen
die Nachkommastellen unter den Tisch. Und so passierts, das bei großen
Regelabweichungen dein Algo was berechnet, nach der dritten ist schluss
da der Wert <1 wird.
Versuch den Regler so umzustricken dass er Ganzzahlen in ausreichender
Größe erhält, oder benutze Float, wenn das Dynamik und Speicher
zulasssen.
> #include <avr/iom16.h>
Mach das nicht. Die Device-spezifische Headerdatei wird nie direkt
eingebunden! Immer nur die io.h und dann im Makefile oder im AVRStudio,
je nachdem, womit Du arbeitest, den Controllertyp angeben.
@johnny.m
JTAG, wäre schön, aber son Spielzeug hab ich nicht. Ich öffne .elf-Datei
(was von Make All "übrig bleibt")in AVR Studio und sehe dann mein C-Code
den ich durchklicken kann. Und links sehe ich dann I/O Pins und die
ganzen Register und wie die gesetzt werden je nach dem wo ich im Code
bin.
#include <avr/iom16.h> habe ich irgendwo abgeschaut und vorsichtshalber
rein genommen. In Makefile gebe ich sowieso Atmega16 an und alles was
ich weiss angegeben, denn ich bin kein Linux freak um das alles zu
wiessen, man denkt automatisch wenn was anzugegeben ist, dann ist das
vielleicht wichtig. In AVR Studio gebe ich natürlich Simulator und
Atmega16 an, kommst nicht drum herum.
Jetzt ist es bisi spät,ich werde dann morgen mich sammeln und nen rar
mit Makefile und sonstigen Dateien und noch paar Bilder und Schaltplan
vielleicht hier hochladen. Damit alle sehen können was ich hier gebaut
habe :)
> JTAG, wäre schön, aber son Spielzeug hab ich nicht.
Eben deswegen musst Du es deaktivieren (Fuse JTAGEN). Diese Fuse ist im
Auslieferungszustand des ATMega16 gesetzt und das JTAG-Interface
blockiert die 4 mittleren Pins von PORTC (Pins 5...2). Du musst diese
Fuse unbedingt löschen, um PORTC benutzen zu können!
JTAGEN ist deaktiviert,
PortC habe ich schon mit Rampen (einfach ne schleife die hochzählt und
dann wieder von 0 anfängt) getestet, um Linearität des DAC zu testetn.
War alles OK.
Moin,
vielleicht steh ich mal wieder auf dem Schlauch? oder mein Freund Jim
Beam ist noch nicht aussem Kopf, aber so wie ich das sehe, "erzeugt" die
Berechnung den Ausgabewert für PortC (8-Bit Wert). Dann würde ich
zunächst verifizieren ob fest einprogrammierte Werte (ohne Wandler) den
von dir per Hand Berechneten Ausgabewert erzeugen.
Feste Eingabewerte erzeugen korrekten ausgabewert?
Ja --> Berechnung OK
Nein --> Berechnung überprüfen
Als Debughilfe vielleicht die RS232 anschmeißen!
Nochn Tip: Bei Regelungsalgos immer auf Überlauf kontrollieren, sonst
undefiniertes Verhalten.
@Tommy:
Die DDRx- und PORTx-Register haben einen Reset-Wert von 0, also Eingang
ohne Pull-Up. Sollte kein Problem sein.
BTW: Der ATMega16 hat die sehr komfortable Möglichkeit, den ADC
automatisch zu starten, wenn ein bestimmtes Ereignis auftritt (ADC Auto
Trigger). Das geht z.B. auch mit dem Overflow von Timer 0. Schau Dir mal
die ADTS-Bits im SFIOR an. Die Auswertung würde man dann über den
ADC-Conversion-Complete-Interrupt machen. Musst nur dran denken, das
Flag vom Timer0-Overflow jeweils entweder von Hand zu löschen oder einen
leeren Interrupt-Handler einzubauen, weil das ganze sonst nur einmal
funktioniert.
Ansonsten: Ich bin die Berechnung jetzt nicht komplett durchgegangen,
aber die Variable y, die an PORTC ausgegeben werden soll, ist ein int
(16 Bit). Bist Du sicher, dass da was Sinnvolles rauskommt?
Noch was: Du löschst das ADIF nie. D.h., so wie es da steht,
funktioniert das Ganze nach dem Reset genau einmal. Das ADIF muss, wenn
Du den Interrupt nicht aktiviert hast, von Hand gelöscht werden! Wenn Du
den ADC unbedingt per Polling abfragen willst (also ohne Interrupt),
dann am besten nicht das ADIF abfragen, sondern das ADSC-Bit. Das wird
nämlich nach Abschluss der Wandlung automatisch zurückgesetzt. Ich
vermute, das ist der eigentliche Fehler und die Ursache, warum Müll
rauskommt. Also anstatt
Ja, an SFIOR habe ich schon gedacht, aber ich bin nicht so mächtig in C,
wird auf jedenfall ne Zeit brauchen.
y sollte warscheinlich in char konvertiert werden, bevor der ausgegeben
wird. Bei x=0 kommt y=3,496 raus und das wird bestimmt nicht als 0b11
dargestellt, wie ich anfangs gehofft habe. Wir schauen auf AD-Wandler,
doch
es könnte gut mölich sein, dass es an diesen Nachkommastellen liegt.
Hm, laut dieser Seite
http://www.math.uni-bayreuth.de/~rbaier/lectures/java_multimedia_ws2004_05/html/node25.html
nen int in char umzuwandeln ist nicht möglich :(
Kennt jemand nen Trick um Nachkommastellen abzuschneiden und vielleicht
sogar noch zu runden ?
ADIF hatte ich schon mal von Hand gelöscht, hat auch keine änderung
gebracht. Ich habe hier oben glaube ich schon mal geschrieben, dass ADIF
wird im letzten Augenblick automatisch gelöscht, wenn Wandlung startet.
while((ADCSRA & (1 << ADSC))); habe ich eben ausprobiert - bleibt dunkel
:)
ich hänge hier noch nen .zip mit Bildern, Skizzzen und Schaltplännen vom
Projekt.
wenn du nen int nach einen char castest, fallen automatisch die oberen
8bit weg. Um sicher zu gehen kanns ja mal im disassembly nachschaun.
Nicht nur das Endergebnis ist nicht mit Nachkommastellen gesegnet,
sondern auch alle zwischenergebnisse werden beschnitten.
(10/3)*3 == 9 !! als beispiel
Hab mir mal die Zip reingezogen. Cooles Projekt um Regelungen zu
erlernen.
Ein PID Regler für die Aufgabe anzuwerfen scheint mir etwas
hochgegriffen (zumindest für den Anfang) Versuchs mit nem einfachen
P-Regler, der die LED einfach um die Differenz der zwischen 230 und
tatsächlichem Eingang hochregelt.
Die nachkommastellen sind eigentlich kein problem, einfach die Werte
erhöhen (Grenzen beachten) und am ende runterteilen. So wird dann zb aus
3,496 3496.
Wenn du änderungen um 3,irgendwas brauchst, musst du dir grundsätzliche
Gedanken über die Auflösung deiner Hardware machen.
Abend !
@Tommy ja ich wollte nun mal von Anfang bis Ende ne Regelung aufbauen.
Berechnet habe ich schon ein paar, doch nie eine Aufgebaut.
Und ich finde es kommisch, dass es zum Thema "wie realisiere ich nen
digitalen Regler" fast gar nichts im Netz zu finden gibt. Nur das hier
http://www.roboternetz.de/wissen/index.php/Regelungstechnik
Ich habe Strecke "1.Ordnung mit kleiner Totzeit" eigentlich wegen
RC-Glied, und auf dieser Seite steht, wieso ich kein P-Regler genommen
habe.
habe mich mit AD-Wandler beschäftigt (getestet) und rausgefunden dass
das hier geht:
ADCSRA|=(0<<ADIF);// geht auch ohne, aber sicher ist sicher.
23
24
}
hab einfach mit Poti Werte simulier und am PortC kammen dieselben raus.
Wenn ich auch noch Formel rein nehme da kann ich so viel an dem Poti
drehen wie ich will, PortC bleibt immer auf 11111111
Also es ist dann Kommazahlen und vielleicht auch die Rechnung(Formel).
Es muss nen Trick geben wie man aus Komma- Ganzzahlen macht. Auch wenn
es genau so viel wie die Formel dauert.
Es steht ne Gesamtzeit ca 120us zur Verfügung, wobei Rechnung dauert ca.
27us die meiste Zeit warten wir sowieso auf Overflow.
> PortC bleibt immer auf 11111111
Das wundert mich aber.
Eine Excel Simulation zeigt, das deine reglergleichung
spätestens nach der 3. Iteration immer 0 erreicht hat.
3 Iterationen hat der µC in Windeseile durch.
Komma oder Fix Point haben damit nichts zu tun.
Deine 'Reglergleichung' ist einfach Mist.
@ Karl heinz Buchegger
das kann man nur mit Mathlab/Simulink oder anderen Regelungstechnischen
Programm testen. Denn das ist nur der Regler und der kriegt nicht immer
"0" drauf, dahinten kommt ja noch die Strecke (LEDs und
Fototransistoren) die das ganze noch verändern. Wenn übertragung z.B.
1:1 ist dann sollte bei zweitem schrit x=2 sein und nicht "0" und das
sollte ganz andere werte ergeben, als Iteration gegen "0".
Kannst du bitte vielleicht random werte zwischen 0 und 255 mal
draufgeben und dann kucken was an max und min rauskommt in deiner Excel
Tab. ?
würde mich interessieren.
> das kann man nur mit Mathlab/Simulink oder anderen Regelungstechnischen> Programm testen.
Quatsch.
Ich kann deine Gleichung nehmen und sie in Excel
einsetzen und druchrechnen lassen. Nichts anderes
macht auch der µC. Und da sehe ich, dass egal mit
welchem Wert für x ich anfange, y spätestens nach der
3. Iteration den Wert 0 erreicht hat. Das heist nach
dem 3. Overflow ist dein y Wert auf jeden Fall 0.
Egal welchen Wert ich für x annehme.
> Denn das ist nur der Regler
Denk mal drüber nach.
Ein Regler soll ja eine Stellgröße einer Istgröße
nachführen. Deine Istgröße kommt vom ADC. Aber woher
kommt eigentlich der 2. Wert, die Stellgröße?
In deiner Gleichung ist davon nichts zu sehen. Die
berechnet immer nur aus dem ADC Wert und dem vorhergehenden
ADC Wert und dem davor einen Wert.
Danke für Excel ! Werde mir später anschauen.
Ich habe jetzt nen anderen Problemchen den PortC in meiner Schaltung
gibt immer 11111111 aus wenn ich ADC Wert direckt Ausgeben will.
Gleiche schaltung gleiches Programm nur an PortD Ausgeben geht.
Stecke ich Atmega16 ins STK500 alles geht.
Stecke wieder in meine Schaltung geht auf 11111111.
Ein fester Wert wie
1
PORTC=200;
oder
1
PORTC=10;
geht.
Nur direkt
1
PORTC=x;
da springt er auf 11111111. Auch wenn ich Fotodiode abdecke und
einschalte,
wocher nimmt er sollche Werte ?
Hexerei :(
> x = ADCW;// 10-bit Wert nach x laden> x = ~x>>2; // nur 8-bit davon Verwenden
Der Atmega16 hat doch einen 10bit-AD-Wandler. Das heißt doch nur, dass
er den Analogwert mit 10 bit Auflösung abfragt. Aber das Ergebnis,
welches nachher im Ergebnisregister steht hat doch trotzdem nur 8bit
Datenbreite?!?!?! Oder irre ich mich da?!
Gruß
der Praktikant
@Philip:
Und warum sollte er dann mit 10 Bit wandeln, wenn nur 8 Bit rauskommen?
Ich hab doch in meinem Auto auch keinen Motor mit 200 PS drin, obwohl
ich nur 100 PS davon benutze... Natürlich sind die vollen 10 Bit als
Ergebnis verfügbar, nur eben aufgeteilt auf zwei 8-Bit-Register, weils
nun mal nur 8-Bit-Register gibt. In C sind diese Doppelregister aber als
ein 16-Bit-Wert verarbeitbar, weil der Compiler dem Programmierer den
Doppelzugriff abnehmen kann.
Ach ja, es steht dem Programmierer natürlich frei, von den verfügbaren
10 Bit nur 8 oder so zu verwenden für die Weiterverarbeitung (Bei
höheren Samplingraten als den im Datenblatt für max. Auflösung
angegebenen sind die LSB sowieso nicht mehr sinnvoll brauchbar).
"...meiner Schaltung gibt immer 11111111 aus "
Woher weisst du das? Gemessen? LED's? Wie angeschlossen?
Oliver
P.S. Die Regelungsrechung ist wirklich Unsinn.
johnny.m wrote:
> @Philip:> Und warum sollte er dann mit 10 Bit wandeln, wenn nur 8 Bit rauskommen?> Ich hab doch in meinem Auto auch keinen Motor mit 200 PS drin, obwohl> ich nur 100 PS davon benutze... Natürlich sind die vollen 10 Bit als> Ergebnis verfügbar, nur eben aufgeteilt auf zwei 8-Bit-Register, weils> nun mal nur 8-Bit-Register gibt. In C sind diese Doppelregister aber als> ein 16-Bit-Wert verarbeitbar, weil der Compiler dem Programmierer den> Doppelzugriff abnehmen kann.
Dachte, das ist nur für die Auflösung nötig. Je höher der Wert, desto
genauere Ergebnisse im Ergebnisregister.... Ist das nicht so, dass er
dadurch einfach z.B. eine Differenz von 3V mit 2^10 Schritten auflösen
kann, aber trotzdem das gewandelte Ergebnis in einem 8bit-Register
ausgibt?!
Da hab ich aber grade eniges dazugelernt....
Gruß
der Praktikant
Ich habs mal in vmlab laufen lassen. Der meckert erst mal:
"[PC = $006D, Time = 0.27 ms, {ADC}]: ADC: Clock is recommended to be
in the 50KHz-200KHz range"
Da du nur ADPS2 (Faktor 16) gesetzt hast, ergibt das 1MHz, und das ist
deutlich mehr als die empfohlenen 200kHz.
Oliver