HAllo, ich habe vor mehrere ADC kanäle einzulesen, diese messen jeweils verschiedene spannungen. Damit der Prozessor nicht ständig arbeiten muss verwende ich gerne die ISR und würde gerne die ADC Werte über einen Timer jede Minute einlesen. Ich lese dabei im Single Conversion Modus ein. Jetzt versteh ich nicht ganz genau wie ich in der ISR die kanäle wechseln soll. Wechsel ich die Kanäle in den jeweiligen Timerblöcken? Oder setzte ich in der Timer_ISR ein Flag und werte diesen in der ADC_ISR aus?
Bei einem Messwert pro Minute kannst du das machen, wie immer dir das gefällt. Solange du kein delay_ms(60000) hinschreibst, ist alles erlaubt und richtig. Oliver
um gottes willen... _delay_ms kommt erst gar nicht in die software... man müsste einen code schreiben bei dem sobald eine delay funktion geschrieben wird... ein Totenkopf auf dem bildschirm auftauchen und teuflisch lachen... zumindest für mich :)
Die Syntax fehlt mir... Oder besser gesagt der Ablauf und welche Bits ich setzen muss oder abfragen bevor ich einen Kanalwechsel durchführe... und wie diese Prozedur speziell dann mit einer ISR aussieht... Im Tutorial hab ich auch schon gelesen wie man den ADC sequentiell wie auvch interruptgesteuert durchführt... hat auch alles wunderbar geklappt auf meinem Board... nur kriege ich diesen Wechsel der Kanäle nicht hin...
Rafi Dafi schrieb: > Jetzt versteh ich nicht ganz genau wie ich in der ISR die kanäle > wechseln soll. Die Kanäle wechselt man in der ADC-ISR nach der Werteinlesung. Man legt da eine Volatile-Variable an, die man im Interrupt immer um 1 weiter schaltet, zum nächsten Kanal.
Wilhelm Ferkes schrieb: > Man legt > da eine Volatile-Variable an, die man im Interrupt immer um 1 weiter > schaltet, zum nächsten Kanal. vorrausgesetzt die genutzten ADC Kanäle folgen aufeinander. Das heißt dann das die Kanäle ständig gelesen werden? Geht das nicht per Abfrage des ADIF, oder ähnliches? Das wäre nämlich sinnfrei wenn ich jede minute einen Wert einlesen möchte der Prozessor aber jedoch ständig ackert... Ich habe das mal über Flags in der Timer ISR versucht nur leider klappt es nicht... Nach Ablauf eines Timerblocks setze ich das 1. ADC Flag in der Timer_ISR... Die ADC_ISR wertet dieses Flag aus und setzt dementsprächend den Kanal und liest danach den ADC Wert ein... Beim ersten funktioniert es wunderbar, wenn ich jedoch in den zweiten Timerblock für die 2. ADC Messung wechsel und dort das 2. ADC Flag setze und dieses dann in der ADC_ISR auswerte... erhalte ich den Wert der ersten Messung... ISR(ADC_vect) { if (Timer1Flag == 1) { ADMUX = (ADMUX&~(0x1F)) | (ADC_Kanal_2 & 0x1F); ADCwert = ADC; Timer1Flag = 0; ADCSRA |= (1<<ADSC); } if (Timer2Flag == 1) { ADMUX = (ADMUX&~(0x1F)) | (ADC_Kanal_4 & 0x1F); ADCwert = ADC; Timer2Flag = 0; ADCSRA |= (1<<ADSC); } }
Rafi Dafi schrieb: > vorrausgesetzt die genutzten ADC Kanäle folgen aufeinander. Wenn sie nicht gerade aufeinander folgen, z.B. man verwendet nur Kanal 0, 1 und 4, dann zählt man die Variable 0, 1 und 2, dann wieder 0, und macht eine if-Abfrage, oder switch case, und schaltet dort den richtigen Kanal ein. Deinen µC kenne ich nicht, zu den Registern kann ich nichts sagen, aber das Prinzip ist oft ähnlich.
guugst du hier: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe Oliver
Rafi Dafi schrieb: > Timerblock für die 2. ADC Messung wechsel und dort das 2. ADC Flag setze Anderer Vorschlag: Schreib dir keine "Timerblöcke" in die ISR. Schreib dir eine einzige Funktion (außerhalb der ISR), z.B.
1 | uint16_t GETADC(uint8_t channel) |
Und in der ISR zählst du nur eine static-8bit-volatile-Variable hoch, wenn sie die Nummer des höchsten Kanals erreicht hat, setz sie auf Null. Und mit dieser Variablen rufst du in der Routine die Funktion GETADC auf. Bei jedem Aufruf einen Kanal höher. Dann hast du nur eine Funktion und eine Zähl-Variable und der Prozessor kann wieder eine Weile schlafen. Oder du zählst nur die Kanäle in der ISR hoch und setze ein Flag, daß eine Wandlung stattfinden darf. Außerhalb (in der main) schaust du nur das Flag an und wenn es gesetzt ist, rufst du GETADC(channel) auf. Hier kann der Prozessor nicht schlafen, weil er ja nach dem Flag gucken muß. Das wären zwei Varianten, die mir jetzt so einfallen.
Hi >Nach Ablauf eines Timerblocks setze ich das 1. ADC Flag in der >Timer_ISR... Die ADC_ISR wertet dieses Flag aus und setzt >dementsprächend den Kanal und liest danach den ADC Wert ein... Wozu? bei den neueren AVRs kann der ADC auch direkt von verschiedenen Timerereignissen getriggert werden. Welchen hast du denn? MfG Spess
> ISR(ADC_vect)
Würde ich gar nicht machen.
Starte den ADC für einen Kanal. Warte auf das Andlungsergebnis.
Danach: starte den ADC für den nächsten Kanal - warte auf das Ergebnis
Danach: starte den ADC für den nächsten Kanal - warte auf das Ergebnis
etc. etc.
bis alle Kanäle durch sind. Und danach legt sich der µC wieder schlafen,
bis er vom Timer nach 1 Minute erneut aufgeweckt wird und wieder reihum
alle ADC-Kanäle abfragt und auswertet.
KISS - Keep it simple, stupid.
Im Tutorial gibt es eine schöne Funktion, die man aufruft und der man
den zu wandelnden Kanal mitgibt. Dann steh halt in der main-Schleife
1 | ....
|
2 | |
3 | int main() |
4 | {
|
5 | ....
|
6 | |
7 | while( 1 ) { |
8 | |
9 | value0 = ADC_Read( 0 ); |
10 | value1 = ADC_Read( 1 ); |
11 | value2 = ADC_Read( 5 ); |
12 | |
13 | .... mach was mit den Werten |
14 | |
15 | ... und wieder schlafen legen |
16 | sleep(); |
17 | }
|
18 | }
|
und der Timer holt den µC regelmässig aus dem Sleep wieder raus.
>Das wäre nämlich sinnfrei wenn ich jede minute einen Wert einlesen >möchte der Prozessor aber jedoch ständig ackert... Schwierig wird's erst wenn Du den Betriebsmodi "idle" noch zu "ackern" zählst (über die Modi "active" und "power down" dürfte diesbezüglich Einigkeit herrschen). Frage für Experten: Was hat es für Folgen für Deinen µC, wenn Du ihn jede Sekunde z. B. zwanzigtausend mal in den idle-Modus schickst und wieder daraus zurückholst? Oder wenn Du den ADC hundertmal pro Sekunde einschaltest, eine AD-Wandlung durchführen lässt und ihn danach wieder ausschaltest? Beides ununterbrochen über Jahre.
Vuvuzelatus schrieb: > Frage für Experten: Was hat es für Folgen für Deinen µC, wenn Du ihn > jede Sekunde z. B. zwanzigtausend mal in den idle-Modus schickst und > wieder daraus zurückholst? Lässt du auch 50 mal in der Sekunde über einen Zeitraum von knapp 2.5 Jahren zu? Wenn ja: der Stromverbrauch sinkt. Und sonst? Nichts.
>Nichts.
Richtig. Was ich damit sagen wollte: Der bisweilen geäußerte Wunsch nach
langen Sleep-Phasen a la "mein µC soll nur jede Minute aufwachen, aber
nur jede Stunde wäre noch besser. Leider lassen sich solch lange
Intervalle mit einem Timer nicht erreichen. Was soll ich blos tun?" hat
selten eine rationale Grundlage. Dahinter steht oft der (Irr-)glaube, zu
häufiges Wechseln in den Sleep und das Wieder-Daraus-Aufwachen würde dem
µC irgendwie schaden.
Die Stromersparnis ist nur beim Betrieb mit Knopfzellen machen ernsthaft
relevant. Bei AA-Zellen ist es überhaupt kein Problem, einen µC z. B.
fortlaufend alle 10 bis 20 ms aus dem Sleep aufzuwecken, ein paar Taster
zu pollen (dann kann das Device jederzeit sofort reagieren) oder eine
AD-Wandlung zu triggern inklusive Warten auf das Ergebnis, und ihn
danach wieder in den Idle zu schicken. Man kann den Stromverbrauch
anhand des Datenblatts sogar einfach ausrechnen, und wird einen Wert
herausbekommen, der der Selbstentladung von Batterien entspricht
(Hausnummer: 30 µA).
Vuvuzelatus schrob: > Dahinter steht oft der (Irr-)glaube, zu >häufiges Wechseln in den Sleep und das Wieder-Daraus-Aufwachen würde dem >µC irgendwie schaden. Vielleicht ist der TO im 3-Schicht System beschäftigt und hat mit dieser Verfahrensweise am eigenen Leib schlechte Erfahrungen gemacht. Dann wäre es verständlich, wenn er dem Kontroller diese Erfahrung ersparen möchte. ;-) MfG Paul
Paul Baumann schrieb: > Vielleicht ist der TO im 3-Schicht System beschäftigt und hat mit dieser > Verfahrensweise am eigenen Leib schlechte Erfahrungen gemacht. Dann wäre > es verständlich, wenn er dem Kontroller diese Erfahrung ersparen möchte. Vielleicht aber auch nicht... ;) Und was bringt eigentlich so ein Post zur Problemlösung... naja ist ja deine zeit... Zurück zum Thema... Vom sleep_mode war von meiner Seite her keine Rede... naja Ackern ist auch eine Definitionssache... sorry wenn es falsch verstanden wurde Denn neben der minütlichen ADC Wandlung, sollen ständig LED's läuchten um die gemessenen Spannungen zu signalisieren... Bleiben im idlemode die von mir vorher gesetzten Pin's für die LED`s oder werden diese gelöscht? Das wäre natürlich super praktisch wenn er denn aktuellen Status beibehällt... und wie ich gelesen habe kann die ISR für den UART in dem mode auch daten empfangen/senden... bzw. weckt den µC wieder aus dem idle_mode, wenn Daten empfangen werden oder eben vom µC gesendet werden ich hab jetzt die sachen so programmiert das ich nicht über die ISR_ADC arbeite... sondern über get_ADC() und dann eben der warteschleife in dieser, die mir den Abschluss der Konvertierung signalisiert. Es funktioniert... Danke für alle hilfreichen Posts... :) und die weniger hilfreichen waren auch amüsant... **Paul-schiel**
Rafi Dafi schrieb: > Bleiben im idlemode die von mir vorher gesetzten Pin's für die LED`s > oder werden diese gelöscht? In dem Fall kannst du dir den ganzen Aufwand aber auch sparen. Denn deine leuchtenden Leds (wenn es ein paar sind) brauchen um einiges mehr Strom als der µC für sich braucht. Und dann kannst du dir auch den ganzen Aufwand mit minütlicher Wandlung sparen. Denn dem µC ist es egal ob er Däumchen dreht oder mal wieder eine AD Wandlung macht.
O.T. Rafidafi schrub: >naja ist ja deine zeit... Ja, man muß auch mal trotz aller Probleme, die zu lösen sind, zwischendurch einmal grinsen können. Die halbe Minute reißt es dann auch nicht mehr raus. >und die weniger hilfreichen waren auch amüsant... **Paul-schiel** Naja, so sollte das sein. MfG Paul
>Vom sleep_mode war von meiner Seite her keine Rede... Nur zur Klarstellung der Begrifflichkeiten: Mit Sleep meint man gemeinhin alle Modi außer "active", d. h. sleep fasst die Modi "idle" und "power-down" zusammen (von denen es wiederum die ein oder andere Variante gibt). >Denn neben der minütlichen ADC Wandlung, sollen ständig LED's läuchten >um die gemessenen Spannungen zu signalisieren... OK, damit fällt Stromsparen als Hintergrund Deiner Frage flach. >Bleiben im idlemode die von mir vorher gesetzten Pin's für die LED`s >oder werden diese gelöscht? Die Pinzustände bleiben erhalten, sogar im Modus power-down. >[...] kann die ISR für den UART in dem mode auch daten empfangen/senden... >bzw. weckt den µC wieder aus dem idle_mode, wenn Daten empfangen werden >oder eben vom µC gesendet werden Ja. Idle ist der Schlafmodus, in dem alles, was über Interrupts läuft, noch zur Verfügung steht. Ich frage mich immer noch, was für Vorteile Du Dir von der minütlichen AD-Wandlung erhoffst. Ich sehe keinen einzigen, aber dafür einen Nachteil, der Dir vielleicht nicht bewusst ist: Deine LED-Anzeige wird auf jede Änderung erst mit durchschnittlich halbminütiger (maximal minütlicher) Verzögerung reagieren. Sowas kann massiv nerven, beim Testen während der Entwicklung, aber auch später. Ein Beispiel: Du klemmst irgendwann probeweise einen niederohmigen Widerstand als Last an Deinen Akku (?) an, um herauszufinden, wie stark die Spannung einbricht. Dann wird der Lastwiderstand heißer und heißer während Du ewig auf das Umschalten Deiner LEDs wartest - Spaßfaktor Null. Tipp: Investiere keine Zeit in die Realisierung sehr langer, d. h. Sekunden oder noch länger dauernder Schlafphasen. Du würdest am Schluss höchstwahrscheinlich nur feststellen, dass Dich das Ergebnis nicht zufriedenstellt und dann war die Mühe umsonst. Lass die AD-Wandlung etwa 4 mal pro Sekunde stattfinden. Das ist für den ADC immer noch "selten" (er könnte auch problemlos 4000 mal pro Sekunde), aber oft genug, damit sich Dein fertiges Device so verhalten wird, wie es der Benutzer intuitiv erwartet, nämlich (annähernd) sofort auf Änderungen reagierend.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.