mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega88PA mehrere ADC Kanäle auslesen


Autor: eTchz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag liebe Community,

Ich möchte 4 ADC Kanäle des ATmega88PA auslesen und die digitalisierten 
Werte via uart an meinen Rechner schicken.

Harware:

Ich habe 4 Potis, an einem Labornetzteil bei der Spannung 3,3V 
angeschlossen, den Abgriff je an einen ADC Pin des Mikrocontrollers.
Zur seriellen Übertragung verwende ich eine "Silicon Labs CP210x USB to 
UART Bridge".
Referenzspannung des ADC sind ebenfalls 3,3V.

Der Code:
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include "uart.h"


#define BOOT_UART_BAUD_RATE 9600


uint16_t readADC(uint8_t channel) {
  uint8_t i;
  uint16_t result = 0;
    
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);  
  ADMUX = channel | (1<<REFS1) | (1<<REFS0);  
  
  ADCSRA |= (1<<ADSC);
  while(ADCSRA & (1<<ADSC));  
  
  for(i=0; i<3; i++) {    
    ADCSRA |= (1<<ADSC);    
    while(ADCSRA & (1<<ADSC));    
    result += ADCW;
  }
  
  result /= 3;  
  return result;
}


int main(void)
{
  uart_init(UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU));
  sei();  
  
  uint16_t adc_ch1 = 0;
  uint16_t adc_ch2 = 0;
  uint16_t adc_ch3 = 0;
  uint16_t adc_ch4 = 0;

  char ch1_chr[] = "";
  char ch2_chr[] = "";
  char ch3_chr[] = "";
  char ch4_chr[] = "";

  while(1){
    
    adc_ch1 = readADC(0);
    adc_ch2 = readADC(1);
    adc_ch3 = readADC(2);
    adc_ch4 = readADC(3);  

    itoa(adc_ch1, ch1_chr, 10);
    itoa(adc_ch2, ch2_chr, 10);
    itoa(adc_ch3, ch3_chr, 10);
    itoa(adc_ch4, ch4_chr, 10);

    uart_puts(ch1_chr);
    uart_puts(",");
    uart_puts(ch2_chr);
    uart_puts(",");
    uart_puts(ch3_chr);
    uart_puts(",");
    uart_puts(ch4_chr);
    uart_puts(";");
  }
}

Problem:

Im Anhang ist ein Screenshot des Outputs der im Terminal Programm zu 
sehen ist.
Alle Potis befinden sich etwa in Mittelstellung und sollten daher einen 
Wert von ~500 ausgeben.
Ich habe die Software zur Fehleranalyse einmal soweit abgespeckt, dass 
ich nur einen Kanal auslese und das Ergebnis ausgebe, dies hat tadellos 
funktioniert.

Sobald ich allerdings auf zwei Kanäle erweitere tritt der im Screenshot 
zu sehende Fehlerfall ein.

Ich hoffe auf schnelle und konstruktive Antworten.

MfG

eTchz

Autor: Rainer U. (r-u)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
irgendwie meine ich mich zu erinnern, das es mir damals geholfen hat, 
nach dem Umschalten die erste Messung zu verwerfen oder zu warten / bin 
aber nicht mehr sicher - versuch mal.

Autor: Axel S. (a-za-z0-9)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eTchz schrieb:
...
>   uint16_t adc_ch1 = 0;
>   uint16_t adc_ch2 = 0;
>   uint16_t adc_ch3 = 0;
>   uint16_t adc_ch4 = 0;
> 
>   char ch1_chr[] = "";
>   char ch2_chr[] = "";
>   char ch3_chr[] = "";
>   char ch4_chr[] = "";
...
>     itoa(adc_ch1, ch1_chr, 10);
>     itoa(adc_ch2, ch2_chr, 10);
>     itoa(adc_ch3, ch3_chr, 10);
>     itoa(adc_ch4, ch4_chr, 10);

Aua. itoa() braucht einen Buffer, in den es den String schreibt. Mit
char ch1_chr[] = "";

legst du aber nur einen String der Länge 0 an. In den paßt dann auch 
nichts größeres als ein String der Länge 0. Was dein itoa() Aufruf dann 
macht, ist über das Ende des Buffers hinauszuschreiben und dabei andere 
Variablen zu überschreiben. Welche das sind, hängt davon ab wie der 
Compiler die Variablen im RAM plaziert hat.

Auf einem PC hättest du im Ergebnis wahrscheinlich einen schönen 
segmentation fault (vulgo: Crash) bekommen.

Einen Buffer legt man an, indem man ein char-Array mit einer bestimmten 
Länge definiert. Ein 16-Bit uint kann bis zu 5 Dezimalstellen ergeben. 
Dazu noch das \0 ans Endekennzeichen macht mindestens 6 Zeichen 
Buffer-Länge:
char ch1_chr[6];

Dito für die anderen Buffer.

: Bearbeitet durch User
Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eTchz schrieb:
> char ch1_chr[] = "";
>   char ch2_chr[] = "";
>   char ch3_chr[] = "";
>   char ch4_chr[] = "";

Hmm, was meinst du denn, wieviel Speicher du für die Buffer reservierst?
Icj zitiere mal kurz aus der avr-libc Hilfe zu itoa:
"Convert an integer to a string.

The function itoa() converts the integer value from val into an ASCII 
representation that will be stored under s. The caller is responsible 
for providing sufficient storage in s"

Edit: Zu spät, Axel war schneller.

: Bearbeitet durch User
Autor: eTchz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Liebe Poster,

Vielen Dank für die Ratschläge!
Ich konnte das Problem lösen, vielleicht nicht mit dem Höchstmaß an 
Eleganz aber mit voller Funktionalität.

Ich habe für jeden Kanal eine eigene Funktion zum Auslesen geschrieben.
Der Code ist zwar jetzt um einiges größer, aber wie gesagt, es 
funktioniert.

Ich werde mir eure Tipps trotzdem zu Gemüte führen und sie in die 
Optimierung einfließen lassen.

Nochmals vielen Dank und einen schönen Tag wünsche ich!

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.