Hallo liebes Forum, ich arbeite mich gerade etwas in die Mikroprozessor-Programmierung ein und sitze schon den ganzen Nachmittag vor einem Problem und finde die Lösung nicht. Ziel: Ich möchte über einen Attiny44A mehrere Potis auslesen (klappt nicht) und die Ergebnisse an PWM-Kanäle ausgeben (klappt prinzipiell). Versuchsaufbau: Eine RGB-LED soll über drei Potentiometer gesteuert werden. Zu Versuchszwecken erstmal nur zwei Kanäle. Die PWM-Ausgabe funktioniert, also wenn ich einen Farbwechsel programmiere, dann läuft der auch über meinen Testaufbau. Allerdings funtkioniert irgendwie die Übergabe des Wertes an die PWM-Kanäle nicht richtig: Per Multimeter gemessen liefern die PWM-Kanäle einen Wert zwischen 4,95V und 5V. An den Eingängen hingegen kommen 0-5V an. Der Versuchsaufbau ist denkbar einfach, daran wirds nicht liegen. Ich vermute den Fehler im Auslesen des ADCH Registers, weil es scheint ja um drei Stellen verrückt zu klappen. Aber auch nach Stunden des Probierens und Recherchierens finde ich die Lösung nicht. Das ist mein erstes C-Projekt, ich komm nicht auf die Lösung. Anbei der Quellcode. Danke für jeden Tip und einen schönen Abend euch allen! J. #include <avr/io.h> #include <util/delay.h> //Eingänge definieren ADC4, ADC3, ADC2 #define Poti_eins ADMUX = (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (0 << MUX0) #define Poti_zwei ADMUX = (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0) #define Schalter ADMUX = (0 << MUX3) | (1 << MUX2) | (0 << MUX1) | (0 << MUX0) int main(void) { // Variablen deklarieren uint8_t x, Poti_eins_Wert, Poti_zwei_Wert; //ADC-Setup // left shift result | Sets ref. voltage to VCC, bit 1 | Sets ref. voltage to VCC, bit 0 ADMUX |= (1 << ADLAR) | (0 << REFS1) | (1 << REFS0); ADCSRA |= (1 << ADEN) | // Enable ADC (1 << ADPS2) | // set prescaler to 64, bit 2 (0 << ADPS1) | // set prescaler, bit 1 (0 << ADPS0); // set prescaler, bit 0 //****DUMMY READOUT***** ADCSRA |= (1<<ADSC); while (ADCSRA &(1<<ADSC)); x = ADCH; ///PWM-Setup / Prescaler einstellen TCCR1B |= (1<<CS10); //No Prescaling TCCR0B |= (1<<CS00); // Timer in den Fast PWM Mode, 8 Bit schalten TCCR1A |= (1<<WGM10); TCCR1B |= (1<<WGM12); TCCR0B |= (0<<WGM02); // Compare Output mode einstellen; Invertierte PWM weil CommonAnodeRGB_LED TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1 << COM1A0) | (1 << COM1B0); TCCR0A |= 3<<COM0A0 | 3<<COM0B0 | 3<<WGM00; // PWM-Register OCR1A = 0; OCR1B = 0; // Output-Pins definieren DDRA |= (1<<PA6) | (1<< PA5) | (1 << PA7); while(1) { //Kanal festlegen Poti_eins; //ADC Wandlung starten und Wert speichern ADCSRA |= (1<<ADSC); while (ADCSRA &(1<<ADSC)); Poti_eins_Wert = ADCH; //Kanal festlegen Poti_zwei; //ADC Wandlung starten und Wert speichern ADCSRA |= (1<<ADSC); while (ADCSRA &(1<<ADSC)); Poti_zwei_Wert = ADCH; //PWM ausgeben OCR1A = Poti_eins_Wert; OCR1B = Poti_zwei_Wert; OCR0B = 255; } }
Jenny E. schrieb: > ADMUX |= (1 << ADLAR) | (0 << REFS1) | (1 << REFS0); Mit dem ersten Aufruf von Jenny E. schrieb: > Poti_eins; killst du das schöne Setup von ADMUX, das eigentlich ja auch AREF und ADLAR auswählen sollte. Abhilfe kannst du schaffen, indem du entweder das ADLAR/AREF Setup mit in deine 'poti_Eins' und 'poti_Zwei' defines einbindest, oder die Kanalauswahl so maskierst, das du das ursprüngliche Setup von ADMUX nicht zermanschst. Da du nichts von der verwendeten Taktfrequenz schreibst, noch der Hinweis, das er ADC am besten mit einer Frequenz von unter 200kHz läuft, der Prescaler sollte entsprechend gesetzt werden.
:
Bearbeitet durch User
Danke für schnelle Antwort; ich dachte mir schon, dass dies ein Problem sein könnte und hatte das -glaube ich- schon ausprobiert. wenn ich es wie folgt ändere: #define Poti_eins ADMUX = (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (0 << MUX0) | (1 << ADLAR) | (0 << REFS1) | (1 << REFS0) #define Poti_zwei ADMUX = (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0) | (1 << ADLAR) | (0 << REFS1) | (1 << REFS0) und jede weitere ADMUX-Deklaration auskommentiere, passiert nichts mehr, nicht mal die Änderung um 0,05V... Wie gesagt, bin darüber am verzweifeln. Danke für die Hilfe...
...aber ich schau mir mal schnell maskieren an, dass kenn ich noch nicht so richtig...
Ich weiss nicht, obs hilft, aber ich hänge mal den Code für einen Dual LED Dimmer mit dem Tiny45 an, den ich vor einiger Zeit mal für ein Schiff programmiert habe. Die LEDs werden hier über eine Tabelle linearisiert, damit Drehen an den Potis auch gleichmässig die LEDs steuert. Der Tiny hat etwas andere Ports und ich benutze den ADC Interrupt zum Auslesen, vllt. hilfts trotzdem beim Lernen, es ist immerhin alles definierbar. Wundere dich nicht über die Konstrukte mit EMPTY_INTERRUPT usw. Das mache ich nur, damit das alles auf jeden Fall startet und einigermassen Failsafe ist.
...also auch mit der maskierung: #define Poti_eins ADMUX |= (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (0 << MUX0) #define Poti_zwei ADMUX |= (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0) (so sollten die anderen bits vonadmux ja gleich bleiben) verschlechtert sich alles nur, weil dann keine änderung mehr an den pwm-ausgängen ankommt... versteh ich nicht...
> Und an PA0 liegt welche Referenzspannung?
über 100n an ground. aber auch wenn ich es mit VCC (superstabile 5v) als
referenz probiere, will es nicht funktionieren...
@matthias s.
DANKE!!! arbeite mich da mal durch...
Jenny E. schrieb: > (so sollten die anderen bits vonadmux ja gleich bleiben) verschlechtert > sich alles nur, weil dann keine änderung mehr an den pwm-ausgängen > ankommt... versteh ich nicht... Nee, das klappt so nicht. Mit dem |= Operator kannst du nur Bits setzen und nicht löschen. Du hast also nach 2 Durchläufen MUX 0 und MUX1 für immer gesetzt. Helfen würde so ein Konstrukt:
1 | // Setze Poti 1
|
2 | ADMUX = (ADMUX & 0xF0) | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (0 << MUX0); |
3 | // Setze Poti 2
|
4 | ADMUX = (ADMUX & 0xF0) | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0); |
S. Landolt schrieb: > ADLAR steht doch in ADCSRB, nicht in ADMUX? Ach, siehste - hatte ich auch übersehen.
:
Bearbeitet durch User
S. Landolt schrieb: > ADLAR steht doch in ADCSRB, nicht in ADMUX? S. Landolt, du bist mein Held des Tages!!!! Das wars! Ich übe mit einem Lehrbuch für Atmega, bei dem scheint es anders zu sein!!!! DANKE!
Jenny E. schrieb: > S. Landolt schrieb: >> ADLAR steht doch in ADCSRB, nicht in ADMUX? > > > S. Landolt, du bist mein Held des Tages!!!! > Das wars! Ich übe mit einem Lehrbuch für Atmega, bei dem scheint es > anders zu sein!!!! DANKE! Das sollte der Weckruf sein, immer das passende Datenblatt zur Hand zu haben und zu nutzen. Beim zB ATmega8 scheint es nicht nur, sondern ADLAR IST im ADMUX.
> ...Weckruf sein, immer das passende Datenblatt...
Ach was!
Wer will mich da um das Vergnügen bringen, nach Großvätersitte jungen
Menschen etwas vorlesen zu dürfen und dafür auch noch Beifall zu
erhalten.
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.