Forum: Mikrocontroller und Digitale Elektronik Attiny44 ADC-Wandler Software-Problem


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Jenny E. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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;



    }


}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
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
von Jenny E. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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...

von Jenny E. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
...aber ich schau mir mal schnell maskieren an, dass kenn ich noch nicht 
so richtig...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

von Jenny E. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
...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...

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Und an PA0 liegt welche Referenzspannung?

von Jenny E. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> 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...

von S. Landolt (Gast)


Bewertung
1 lesenswert
nicht lesenswert
ADLAR steht doch in ADCSRB, nicht in ADMUX?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
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
von Jenny E. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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!

von Kirk (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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.

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> ...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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.