mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik avr - adc problem


Autor: Chris :) (fr34k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,

probier jetzt schon ewig herum, doch ich bekomme am display immer 
denselben wert: 2131.

hab keine ahnung woher dieser wert kommt.

als adc hab ich "ADC1" also an PA1 verwendet.

kann mir vielleicht jemand sagen ob der programmcode falsch ist?
int adc_main(int adc_wert)
{
   ADCSRA = 0x68;  // 1000 0110
  ADMUX = 0x41;  // 0100 0001

  ADCSRA |= (1<<ADSC);
  while(ADCSRA & (1<<ADSC));
  
  // Jetzt 3x die analoge Spannung and Kanal channel auslesen
  // und dann Durchschnittswert ausrechnen.
  for(int i=0; i<10; i++) {
    // Eine Wandlung
    ADCSRA |= (1<<ADSC);
    // Auf Ergebnis warten...
    while(ADCSRA & (1<<ADSC));
    

    adc_wert += ADC;
  }
  
  // ADC wieder deaktivieren
  ADCSRA &= ~(1<<ADEN);
  
  adc_wert /= 3;
  
  return adc_wert;
}

lg

Autor: 2920 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass dir doch mal einen einzelnen ADC wert ausgeben.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ADCSRA = 0x68;  // 1000 0110
Das im Kommentar ist aber 0x86 und nicht 0x68...

Autor: Chris :) (fr34k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab ich eben auch schon versucht, trotzdem immer die 2131 am display...

meiner meinung nach stimmt aber auch mein programmcode....

Autor: Chris :) (fr34k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das mit dem 68 bzw. 86 muss irgendwie beim reinkopieren durcheinander 
gekommen sein, im programm steht auch 0x86 dort ....

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist immer sehr hilfreich, bei solchen Problemen
1. Zu erzählen, um welchen AVR es sich konkret handelt
2. Was an dem ADC-Eingang überhaupt dranhängt
3. Wie der Rest des Programms aussieht (v.a. wie der betreffende Port 
konfiguriert ist)

Autor: Chris :) (fr34k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1.) es handelt sich um einen ATmega32
2.) am ADC1 hängt eine brückenschaltung mit einem dehnmessstreifen => 
eine waage soll realisiert werden
3.)
    lcd_init(LCD_DISP_ON);

    while(1)
  {                           /* loop forever */
      
  //  unsigned char ReadChannel();
      /* 
         * Test 1:  write text to display
         */

        /* clear display and home cursor */
        lcd_clrscr();
        
        /* put string to display (line 1) with linefeed */
        lcd_puts("  Digi - Waage\n");

        /* cursor is now on second line, write second line */
        
    lcd_puts("Gewicht:");

// ******************************************************************** //
// ******************************************************************** //
// ******************************************************************** //
   ADCSRA = 0x86;  // 1000 0110
  ADMUX = 0xC1;  // 1100 0001

  while(1)
  {
  ADCSRA |= (1<<ADSC);
  while(ADCSRA & (1<<ADSC));
  
  // Jetzt 3x die analoge Spannung and Kanal channel auslesen
  // und dann Durchschnittswert ausrechnen.
    // Eine Wandlung
    ADCSRA |= (1<<ADSC);
    // Auf Ergebnis warten...
    while(ADCSRA & (1<<ADSC));

    adc_wert = ADCL;
    adc_wert += (ADCH >> 8);
  }
  
  // ADC wieder deaktivieren
  ADCSRA &= ~(1<<ADEN);
// ******************************************************************** //
// ******************************************************************** //
// ******************************************************************** //

        
        /* move cursor to position 9 on line 2 */
  
      itoa(adc_wert,buffer,10);
    lcd_gotoxy(9,1);  
        
        lcd_puts(buffer);

das ist im großen und ganzen der programmcode, diesmal die adc funktion 
direkt im main geschrieben...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könntest Du bitte EXAKT DEN CODE posten, den Du auch wirklich 
verwendest und mit dem es nicht funktioniert? Der Code hat mit dem von 
oben nichts zu tun und die Kommentare stimmen auch nicht mit dem Code 
überein.

> adc_wert = ADCL;
> adc_wert += (ADCH >> 8);
Und das ist schwachsinnig. Benutze ADC, wie Du es oben ja auch richtig 
gemacht hast! Dann passieren auch keine Sachen wie hier der Rechtsshift 
anstelle des (korrekten) *LINKS*shifts!

Autor: Chris :) (fr34k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "lcd.h"

/*
** constant definitions
*/
static const PROGMEM unsigned char copyRightChar[] =
{
  0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
  0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};


/*
** function prototypes
*/ 
void wait_until_key_pressed(void);


void wait_until_key_pressed(void)
{
    unsigned char temp1, temp2;
    unsigned int i;
    
    do {
        temp1 = PIND;                  // read input
        for(i=0;i<65535;i++);
        temp2 = PIND;                  // read input
        temp1 = (temp1 & temp2);       // debounce input
    } while ( temp1 & _BV(PIND2) );
    
    loop_until_bit_is_set(PIND,PIND2);            /* wait until key is released */
  
}


int main(void)
{

  int adc_wert;
    char buffer[7];
    
    
    DDRD &=~ (1 << PD2);        /* Pin PD2 input              */
    PORTD |= (1 << PD2);        /* Pin PD2 pull-up enabled    */


    /* initialize display, cursor off */
    lcd_init(LCD_DISP_ON);

    while(1)
  {    
        /* clear display and home cursor */
        lcd_clrscr();
        
        /* put string to display (line 1) with linefeed */
        lcd_puts("  Digi - Waage\n");

        /* cursor is now on second line, write second line */
        
    lcd_puts("Gewicht:");

// ******************************************************************** //
// ****************************ADC************************************* //
// ******************************************************************** //
   ADCSRA = 0x86;  // 1000 0110
  ADMUX = 0x41;  // 0100 0001

  ADCSRA |= (1<<ADSC);
  while(ADCSRA & (1<<ADSC));
  
  for(int i=0;i<10;i++) {
    // Eine Wandlung
    ADCSRA |= (1<<ADSC);
    // Auf Ergebnis warten...
    while(ADCSRA & (1<<ADSC));

    adc_wert = ADCL;
    adc_wert += (ADCH >> 8);
  }
  
  // ADC wieder deaktivieren
  //ADCSRA &= ~(1<<ADEN);
// ******************************************************************** //
// ******************************************************************** //
// ******************************************************************** //

        
        /* move cursor to position 9 on line 2 */
  
      itoa(adc_wert,buffer,10);
    lcd_gotoxy(9,1);  
        
        lcd_puts(buffer);

    lcd_gotoxy(14,1);
    lcd_puts("g");
        
        /* wait until push button PD2 (INT0) is pressed */
        wait_until_key_pressed();
        
              
    }
}

hier mein gesamtes main, wo auch alles fürn adc drinnen ist.

hab naürlich noch andere module fürs lcd, diese funktionieren ja. es 
geht rein um den adc...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> adc_wert = ADCL;
> adc_wert += (ADCH >> 8);
Das ist nach wie vor FALSCH! Überleg einfach mal, was passiert, wenn man 
einen 8-Bit-Wert um 8 Stellen nach rechts schiebt...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> for(i=0;i<65535;i++);
...und das ist ein sauberer Kandidat für einen Rausschmiss durch den 
Optimizer...

Autor: Chris :) (fr34k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die vielen tipps...

hab das jetzt soweit hinbekommen dass ich richtige werte bekommen.

nur ein letztes problem hab ich noch...

wenn ich die analoge eingangsspannung am adc ändere verändert sich der 
wert nur, wenn ich das programm wieder neu rüber lade, bzw. wenn ich den 
avr von der spannung trenne und wieder anschließe....

ich möchte aber dass sich der wert ständig ändert, also dass der adc 
ständig wandelt...

nur weiß ich leider nicht wie ich das programmtechnisch lösen soll ...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Chris :) wrote:

> ich möchte aber dass sich der wert ständig ändert, also dass der adc
> ständig wandelt...
>
> nur weiß ich leider nicht wie ich das programmtechnisch lösen soll ...

Hast du doch im Prinzip schon.
Du hast alles in eine while(1) Schleife gepackt.
Damit wird es ständig wiederholt.
Allerdings ist am Ende der Schleife ein Aufruf von
wait_until_key_pressed();
und diese Funktion ist reichlich kryptisch. Nur durch
schnelles Hinschauen kann ich in 30 Sekunden nicht sagen,
ob diese Funktion korrekt ist oder nicht.

Ich würde den Aufruf einfach mal rausschmeissen.

Autor: Chris :) (fr34k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die vielen tipps :)

jetzt funktionierts endLich .g.

lg

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.