Forum: Mikrocontroller und Digitale Elektronik Ersten A/D Wandlerwerte Murcks?


von Stefan G. (Gast)


Lesenswert?

Hallo,
ich habe offenbar ein Problem mit meinem A/D Wandler (ATmega323). Ich
wollte eine Regelung realisieren. Dabei hatte ich immer innerhalb der
ISR einen Ist-wert mit dem A/D Wandler eingelesen. Nun hatte ich das
Problem daß meine eingelesenen Werte ständig durch nichtpassende werte
gestört wurden. Alle par Werte bekam ich eine 1023 (10 bit ADC -> max.
wert), obwohl der Wert dort nichts zu suchen hatte.

Nun habe ich nochmal einen Test gemacht, indem ich die Pulsbreite
vorgebe mit der ich mein ventil ansteuere und dann einfach den Output
des Flusssensors auslese. Da stellte ich fest, daß oft die ersten 4-5
Werte meiner A/D Wandlung Murcks waren. Ich bekam also auch für die
ersten werte 1023 und danach pendelte der Wandler sich auf z.B. ~ 800
ein.

Ist euch ein derartiges Problem bekannt bzw. wißt ihr Abhilfe?
Gruß,
Stefan

von Matthias (Gast)


Lesenswert?

Hi

Block-C an Aref?`

Matthias

von Max (Gast)


Lesenswert?

Das steht soviel ich weiß sogar im Manual der Controller?! Man sollte
erst nach einigen Auslesungen (nachdem er gestartet wurde) den Wert
verwenden. Ich lasse den ADC meist durchlaufen dann kann ich sofort
drauf zugreifen, ansonsten lieferte er mir auch nur Blödsinn.

von Stefan G. (Gast)


Lesenswert?

Hallo,
danke erstmal für eure Antworten. Mit Block-C an Aref kann ich leider
nichts anfangen. Was bedeutet das?

@ Max: den ADC durchlaufen zu lassen habe ich auch schon überlegt. Aber
wie machst du das bzw. wie fragst du dann beispielsweise in einer
Interrupt Service Routine den aktuellen wert ab?

Gruß,
Stefan

von Matthias (Gast)


Lesenswert?

Hi

Also das man die ersten Messungen wegwerfen soll hör ich zum ersten
Mal. Kann auch nicht sein da ich in einer Anwendung hier den ADC nach
einem bestimmten Ereignis anwerfe und die Werte durchaus sinnvoll
sind.

Mit Block-C an Aref meinte ich einen Kondensator (etwa 10n) am Pin Aref
des Mega.

Matthias

von thkais (Gast)


Lesenswert?

wartest Du auch wirklich, bis der A/D-Wandler fertig ist? Nach einem
Start dauerts a bisserl, bis er die Wandlung durch hat. Da könnte es
sein, daß Dein Programm den Wandler überholt und dadurch Mist einliest.
Ich hatte bislang keinerlei Probleme mit den Wandlern, wenn man mal von
den typischen EMV-Geschichten absieht.
Ich habe meistens eine Interrupt-Routine laufen, die mir bei Ende der
Wandlung das Ergebnis ins SRAM reinwirft und dann den nächsten Kanal
wandelt. So hat man immer (fast) aktuelle Werte von allen Kanälen
(sofern man mehrere braucht). Das Hauptprogramm greift dann nicht mehr
auf den A/D-Wandler direkt zu (und muß auch nicht auf ihn warten),
sondern liest die Werte aus dem SRAM.

von Stefan G. (Gast)


Lesenswert?

@ thkais: Die Methode den ADC nicht direkt auszulesen sondern die
Ergebnisse so wie du beschrieben hast ins SRAM zu packen scheint mir
plausibel. Nur wie machst du das genau (zum einen das mit der ISR, zum
anderen das Speichern ins SRAM)? Ich bin leider noch ziemlicher
Anfänger auf dem Gebiet, darum fehlen mir oft die Basics....
Gruß,
Stefan

von Stefan G. (Gast)


Lesenswert?

@ thkais: Könntest du mir mal ein Programmbeispiel zukommen lassen, daß
sowohl das mit der ISR als auch mit dem SRAM macht? (wenn dunicht
gerade in Assembler programmierst). Ich benutze Codevision AVR.
Gruß,
Stefan

von thkais (Gast)


Lesenswert?

Die Programme sind in Assembler geschrieben, lassen sich aber einfach
auf andere Sprachen umsetzen. Ich werde sie mal rauskramen, wenns
zeitlich klappt, male ich ein Flußdiagramm. Ist in der Code-Sammlung
echt noch nichts zu diesem Thema?

von Stefan G. (Gast)


Lesenswert?

@ thkais: Wenn du das hinbekommen würdest wäre´s super. In der
Codesammlung bin ich nicht so wirklich fündig geworden (dann schon mal
ne Frage: malst du Flussdiagramme einfach mit word?)
Stefan

von thkais (Gast)


Lesenswert?

@Stefan G.
Sorry, hat ein wenig länger gedauert, und zu einem Flußdiagramm hat die
Zeit auch nicht gereicht. Ich denke aber, das Prinzip wird aus dem
Programm ersichtlich, auch wenn man kein Assembler-Champ ist.
In dieser speziellen Version brauchte ich nur 8-Bit Werte, werden alle
10 Bit benötigt, werden natürlich 2 Bytes/Wert gebraucht. Falls noch
Fragen sind, einfach Posten.
Grundprinzip: Der Wandler wird gestartet, wenn er fertig ist, wird ein
Interrupt ausgelöst. In diesem Interrupt wird der Wert gelesen und im
SRAM gespeichert, anschließend der nächste Kanal ausgewählt und die
nächste Wandlung gestartet. So stehen so ganz nebenbei die Werte aller
6 Kanäle in Reih und Glied im SRAM, und man kann mit dem Hauptprogramm
ohne irgendwelche Verzögerungen darauf zugreifen.


---------------------------------------------
.include "c:\avrtools\appnotes\4433def.inc"

.cseg
.org 0
  rjmp reset    ;Reset handler
  reti      ;External interrupt 0 - Not used
  reti      ;External interrupt 1
  reti      ;Counter1 capture event
  reti      ;Counter1 compare match
  reti      ;Counter1 overflow
  reti      ;Counter0 overflow
  reti      ;Serial Transfer complete
  reti      ;UART RX complete
  reti      ;UART Data register empty
  reti      ;UART TX complete
  rjmp adc_int    ;ADC Conversion Complete
  reti      ;EEPROM Ready
  reti      ;Analog comparator

.equ  impuls  =  0
.equ  adc_puffer=  $60  ;$60...$65 ist der A/D-Wandler Puffer

.def  temp  =  r16
.def  temp2  =  r17
.def  analog  =  r0  ;aktueller 8-Bit Analog-Wert
.def  flag  =  r25
.def  xl  =  r26
reset:
  ldi temp,ramend
  out SPL,temp

  ldi temp,$FF
  out DDRD,temp
  ldi temp,$03
  out DDRB,temp

  ldi temp,$05
  out ADMUX,temp

  ldi temp,(1<<ADEN)+(1<<ADIE)+(1<<ADPS2)+(1<<ADPS1)
  out ADCSR,temp

  sei

  sbi ADCSR,ADSC  ;Start Conversion

main:
  rjmp main       ;Das Hauptprogramm macht nix.


adc_int:    ;A/D-Wandler-Interrupt, wird aufgerufen, wenn eine Wandlung
fertig ist

  push temp    ;benutzte Register und SREG auf Stack sichern
  in temp,SREG
  push temp
  push xl
  push temp2

  in temp,ADMUX    ;welcher Kanal wurde gerade gewandelt?
  andi temp,$07    ;nur Bit 0..2 verwenden
  ldi xl,adc_puffer  ;Basis-Adresse des SRAM für die Analog-Werte
  add xl,temp    ;Kanal-Nummer addieren
  in temp,ADCL    ;Den aktuell gewandelten Wert in temp1 und temp2 laden
  in temp2,ADCH

  ror temp2
  ror temp
  ror temp2
  ror temp    ;10 Bit nach 8 Bit konvertieren

  st x,temp    ;in Puffer schreiben

  in temp,ADMUX    ;aktuellen Kanal nochmals in temp laden
  andi temp,$07    ;nur Bit 0..2 verwenden
  dec temp    ;den nächsten Kanal anwählen
  brpl adc_int_1
  ldi temp,$05    ;Kanal 5 anwählen

adc_int_1:
  out ADMUX,temp    ;Das MUX-Register mit dem neuen Wert laden
  sbi ADCSR,ADSC          ;nächste Wandlung starten

  pop temp2    ;die gesicherten Register wiederherstellen
  pop xl
  pop temp
  out SREG,temp
  pop temp
  reti

von Stefan G. (Gast)


Lesenswert?

@ thkais: Danke für den Code. Fürs erste habe ichzwar mein Problem
gelöst, aber vielleicht kann ich dein Beispiel später immer noch
gebrauchen.
Vielen Dank und Gruß,
Stefan

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
Noch kein Account? Hier anmelden.