Forum: Mikrocontroller und Digitale Elektronik Atmega 328p Referenzspannung und Kanal wählen


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 Torsten W. (toto1975)


Bewertung
0 lesenswert
nicht lesenswert
Hallo in die Runde,

ich bin mir nicht sicher ob ich das richtig verstanden habe was ich bis 
jetzt über den ADC gelesen/gelernt habe. Ich möchte gerne bei dem Atmega 
328p die Spannung an einem Akku messen. Als Referenz möchte ich die 
interne 1,1 Volt nehmen ADC Eingang ist ADC3 (siehe Datenblatt Seite 
317. Nun habe ich dazu folgenden Code geschrieben:
1
#define ADC_MUX_MASK ((1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0))
2
3
void setup() {
4
ADMUX = (1 << REFS1) | (1 << REFS0);    //Interne 1.1 Volt
5
ADCSRA |= (1 << ADPS2) | (1 << ADPS1);          // Frequenzvorteiler
6
}
7
8
void loop() {
9
adcval = ADC_Read(3);
10
//mach was mit adcval
11
}
12
13
int ADC_Read(int kanal) {
14
  int a;
15
  ADMUX = (ADMUX & ~ADC_MUX_MASK) | (kanal & ADC_MUX_MASK);
16
  ADCSRA |= (1 << ADEN);      //ADC starten
17
  delay(250);
18
  ADCSRA |= (1 << ADSC);      //DUMMY erste Messung 
19
  while (bitRead(ADCSRA, ADSC));  //warten bis Messung beendet ist
20
  a = ADC;            //ADC auslesen
21
  a = 0;
22
23
  for (int i = 0; i < 5; i++) {             //Mehrfachmessung starten
24
    ADCSRA |= (1 << ADSC);      //Erste Messungen
25
    while (bitRead(ADCSRA, ADSC));  //warten bis Messung beendet ist
26
    a += ADC;
27
  }
28
  a = a / 5;
29
30
  return a;
31
}

Ich bin mir ein wenig unsicher ob der Code stimmt, da Anfänger und das 
Ergebnis sobald ich eine LED an PB5 mit HIGH einschalte der ADC Wert um 
20 sinkt (475 ohne LED 455 mit eingeschalteter LED). Am AREF sitzt wie 
unter 
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe 
beschrieben ein Kondensator.

Ich bin für jeden Tipp Dankbar

Viele Grüße
Torsten

von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Der Prescaler für den ADC-Takt muß noch eingestellt werden.

Die durchgehende Verwendung von int als Variablentyp ist nicht gut. Nimm 
unsigned char und erst wenn der Wertebereich 255 überschreitet int, 
besser noch unsigned int.

Dividieren durch 5 ist eine schlechte Idee. Da muß der Controller 
richtig rechnen. Nimm 4 oder 8 Werte. Dann wird die Division mit einer 
einfachen Schiebeoperation erledigt.

Wenn der Akku die Versorgungsspannungsquelle des Controllers ist, kann 
man die Spannung auch intern und ohne externe Beschaltung mit Bandgap 
gegen Vcc messen.

von Torsten W. (toto1975)


Bewertung
0 lesenswert
nicht lesenswert
Thomas E. schrieb:
> Der Prescaler für den ADC-Takt muß noch eingestellt werden.

Ich dachte das hätte ich mit
1
ADCSRA |= (1 << ADPS2) | (1 << ADPS1);          // Frequenzvorteiler
erledigt oder habe ich da was falsch verstanden?

Thomas E. schrieb:
> Die durchgehende Verwendung von int als Variablentyp ist nicht gut. Nimm
> unsigned char und erst wenn der Wertebereich 255 überschreitet int,
> besser noch unsigned int.

Werde ich umsetzen

Thomas E. schrieb:
> Dividieren durch 5 ist eine schlechte Idee. Da muß der Controller
> richtig rechnen. Nimm 4 oder 8 Werte. Dann wird die Division mit einer
> einfachen Schiebeoperation erledigt.

Das ist eine gute Idee.

Viele Grüße
Torsten

: Bearbeitet durch User
von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Torsten W. schrieb:
> Ich dachte das hätte ich mitADCSRA |= (1 << ADPS2) | (1 << ADPS1);
> // Frequenzvorteiler
> erledigt oder habe ich da was falsch verstanden?

Ne, das hab ich übersehen.

Das
>  ADCSRA |= (1 << ADEN);      //ADC starten

kannst du auch damit kombinieren

Also:

ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);

und startest auch gleich:
1
void Setup(void)
2
{
3
  ADCSRA |= (1 << ADEN) | (1 << ADSC)| (1 << ADPS2) | (1 << ADPS1);
4
  ADMUX = (1 << REFS1) | (1 << REFS0);
5
  while (bitRead(ADCSRA, ADSC));
6
  (void)ADCH;   //Dummy Read
7
}

Den Dummy Read kann man nach dem Enable des ADC machen, muß aber nicht 
sein. Nach einer Kanalumschaltung ist es vollkommen unnötig.

von Karl M. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

im meinen Augen ist es sinnfrei den ADC immer wieder von neuem 
einzuschalten.
1
ADCSRA |= (1 << ADEN);

Überlege bitte was Setup ist und was man für eine Wandlung machen muss.

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
Mit dem Dummy Read hat es folgendes auf sich: Man kann den ADC ja 
automatisch fortlaufend messen lassen. Wenn du dann den Kanal 
(zwangsläufig während der Messung) umschaltest, bekommst du danach ein 
Ergebnis, bei dem unklar ist, zu welchem Kanal es gehört. Denn je nach 
Zeitpunkt des Befehls findet die tatsächliche Kanal-Umschaltung 
verzögert statt. Diese unklare Messung wird dann gerne als Dummy 
verworfen.

In deinem Fall finden aber Einzel-Messungen statt, da ist das nicht 
nötig.

von Manfred (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Stefan U. schrieb:
> Mit dem Dummy Read hat es folgendes auf sich: Man kann den ADC ja
> automatisch fortlaufend messen lassen. Wenn du dann den Kanal
> (zwangsläufig während der Messung) umschaltest, bekommst du danach ein
> Ergebnis, bei dem unklar ist, zu welchem Kanal es gehört.
Ich betreibe den AT328 als Arduino. Da hat es sich ergeben, dass ich den 
Meßwert hole, wegwerfe und einen Zweiten hole.

Meist stimmt schon der erste Wert, aber oft genug leider nicht.

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
> Meist stimmt schon der erste Wert, aber oft genug leider nicht.

Möglicherweise hat deine Signalquelle einen (zu) hohen 
Ausgangswiderstand, so dass sie den S&H Kondensator im ADC nicht schnell 
genug umladen kann. Dann muss man halt ein bisschen warten, ich auch 
kein Problem.

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.