Forum: Mikrocontroller und Digitale Elektronik avr - adc problem


von Chris :. (fr34k)


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?
1
int adc_main(int adc_wert)
2
{
3
   ADCSRA = 0x68;  // 1000 0110
4
  ADMUX = 0x41;  // 0100 0001
5
6
  ADCSRA |= (1<<ADSC);
7
  while(ADCSRA & (1<<ADSC));
8
  
9
  // Jetzt 3x die analoge Spannung and Kanal channel auslesen
10
  // und dann Durchschnittswert ausrechnen.
11
  for(int i=0; i<10; i++) {
12
    // Eine Wandlung
13
    ADCSRA |= (1<<ADSC);
14
    // Auf Ergebnis warten...
15
    while(ADCSRA & (1<<ADSC));
16
    
17
18
    adc_wert += ADC;
19
  }
20
  
21
  // ADC wieder deaktivieren
22
  ADCSRA &= ~(1<<ADEN);
23
  
24
  adc_wert /= 3;
25
  
26
  return adc_wert;
27
}

lg

von 2920 (Gast)


Lesenswert?

Lass dir doch mal einen einzelnen ADC wert ausgeben.

von Johannes M. (johnny-m)


Lesenswert?

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

von Chris :. (fr34k)


Lesenswert?

hab ich eben auch schon versucht, trotzdem immer die 2131 am display...

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

von Chris :. (fr34k)


Lesenswert?

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

von Johannes M. (johnny-m)


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)

von Chris :. (fr34k)


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.)
1
    lcd_init(LCD_DISP_ON);
2
3
    while(1)
4
  {                           /* loop forever */
5
      
6
  //  unsigned char ReadChannel();
7
      /* 
8
         * Test 1:  write text to display
9
         */
10
11
        /* clear display and home cursor */
12
        lcd_clrscr();
13
        
14
        /* put string to display (line 1) with linefeed */
15
        lcd_puts("  Digi - Waage\n");
16
17
        /* cursor is now on second line, write second line */
18
        
19
    lcd_puts("Gewicht:");
20
21
// ******************************************************************** //
22
// ******************************************************************** //
23
// ******************************************************************** //
24
   ADCSRA = 0x86;  // 1000 0110
25
  ADMUX = 0xC1;  // 1100 0001
26
27
  while(1)
28
  {
29
  ADCSRA |= (1<<ADSC);
30
  while(ADCSRA & (1<<ADSC));
31
  
32
  // Jetzt 3x die analoge Spannung and Kanal channel auslesen
33
  // und dann Durchschnittswert ausrechnen.
34
    // Eine Wandlung
35
    ADCSRA |= (1<<ADSC);
36
    // Auf Ergebnis warten...
37
    while(ADCSRA & (1<<ADSC));
38
39
    adc_wert = ADCL;
40
    adc_wert += (ADCH >> 8);
41
  }
42
  
43
  // ADC wieder deaktivieren
44
  ADCSRA &= ~(1<<ADEN);
45
// ******************************************************************** //
46
// ******************************************************************** //
47
// ******************************************************************** //
48
49
        
50
        /* move cursor to position 9 on line 2 */
51
  
52
      itoa(adc_wert,buffer,10);
53
    lcd_gotoxy(9,1);  
54
        
55
        lcd_puts(buffer);

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

von Johannes M. (johnny-m)


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!

von Chris :. (fr34k)


Lesenswert?

1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/pgmspace.h>
4
#include "lcd.h"
5
6
/*
7
** constant definitions
8
*/
9
static const PROGMEM unsigned char copyRightChar[] =
10
{
11
  0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
12
  0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
13
};
14
15
16
/*
17
** function prototypes
18
*/ 
19
void wait_until_key_pressed(void);
20
21
22
void wait_until_key_pressed(void)
23
{
24
    unsigned char temp1, temp2;
25
    unsigned int i;
26
    
27
    do {
28
        temp1 = PIND;                  // read input
29
        for(i=0;i<65535;i++);
30
        temp2 = PIND;                  // read input
31
        temp1 = (temp1 & temp2);       // debounce input
32
    } while ( temp1 & _BV(PIND2) );
33
    
34
    loop_until_bit_is_set(PIND,PIND2);            /* wait until key is released */
35
  
36
}
37
38
39
int main(void)
40
{
41
42
  int adc_wert;
43
    char buffer[7];
44
    
45
    
46
    DDRD &=~ (1 << PD2);        /* Pin PD2 input              */
47
    PORTD |= (1 << PD2);        /* Pin PD2 pull-up enabled    */
48
49
50
    /* initialize display, cursor off */
51
    lcd_init(LCD_DISP_ON);
52
53
    while(1)
54
  {    
55
        /* clear display and home cursor */
56
        lcd_clrscr();
57
        
58
        /* put string to display (line 1) with linefeed */
59
        lcd_puts("  Digi - Waage\n");
60
61
        /* cursor is now on second line, write second line */
62
        
63
    lcd_puts("Gewicht:");
64
65
// ******************************************************************** //
66
// ****************************ADC************************************* //
67
// ******************************************************************** //
68
   ADCSRA = 0x86;  // 1000 0110
69
  ADMUX = 0x41;  // 0100 0001
70
71
  ADCSRA |= (1<<ADSC);
72
  while(ADCSRA & (1<<ADSC));
73
  
74
  for(int i=0;i<10;i++) {
75
    // Eine Wandlung
76
    ADCSRA |= (1<<ADSC);
77
    // Auf Ergebnis warten...
78
    while(ADCSRA & (1<<ADSC));
79
80
    adc_wert = ADCL;
81
    adc_wert += (ADCH >> 8);
82
  }
83
  
84
  // ADC wieder deaktivieren
85
  //ADCSRA &= ~(1<<ADEN);
86
// ******************************************************************** //
87
// ******************************************************************** //
88
// ******************************************************************** //
89
90
        
91
        /* move cursor to position 9 on line 2 */
92
  
93
      itoa(adc_wert,buffer,10);
94
    lcd_gotoxy(9,1);  
95
        
96
        lcd_puts(buffer);
97
98
    lcd_gotoxy(14,1);
99
    lcd_puts("g");
100
        
101
        /* wait until push button PD2 (INT0) is pressed */
102
        wait_until_key_pressed();
103
        
104
              
105
    }
106
}

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...

von Johannes M. (johnny-m)


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...

von Johannes M. (johnny-m)


Lesenswert?

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

von Chris :. (fr34k)


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 ...

von Karl H. (kbuchegg)


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.

von Chris :. (fr34k)


Lesenswert?

danke für die vielen tipps :)

jetzt funktionierts endLich .g.

lg

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.