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.
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...
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:
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.