Forum: Mikrocontroller und Digitale Elektronik Programm Problem mit ADC ergebniss Attiny13


von Fritz B. (kleinfritzchen)


Lesenswert?

Hallo, ich möchte mir nach und nach ein Programm stricken mit dem ich 
einen Laminator auf ca. 200 Grad einregeln kann.
Ich bin grad am versuchen ein Poti auszulesen und über den ermittelten 
Wert eine Diode in der Blink-geschwindigkeit zu regeln.
Das Problem ist hier das ich als Rückgabewert des ADC kein Zahlenformat 
finde das ich in _delay_ms(xxx) eintragen kann ohne eine Fehlermeldung 
zu kriegen.
kann mir da vielleicht mal jemand einen Tip geben?

hier mal der Code:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
//#define F_CPU = 1200000UL
4
uint16_t leseKanal(uint8_t mux);
5
uint16_t verz=0;
6
int main (void){
7
  DDRB=0x01;
8
  
9
  
10
  while (1){
11
    PORTB ^= 0x01;
12
    verz =  leseKanal(0x21);
13
    verz =verz*3;
14
    _delay_ms(verz);
15
  } return 0;
16
  
17
}
18
19
//Routine zum einlesen eines Kanales
20
uint16_t leseKanal(uint8_t mux)
21
{
22
  uint8_t i;
23
  uint8_t ergebniss;
24
  uint16_t foo;
25
  ADCSRA |= (1<<ADEN) | (1<<ADPS0) | (1<<ADPS1);
26
    //ADC einschalten, Teiler auf 8
27
  ADMUX =mux;
28
  //lerlauf zum syncronisoeren
29
  ADCSRA |= (1<<ADSC);
30
  while (ADCSRA & (1<<ADSC)){
31
    ;
32
  }
33
  foo = ADCW;
34
    
35
  foo = 0;
36
  //eigentlicher Abfragezyklus
37
  for(i=0;i<4;i++){
38
    
39
    ADCSRA |= (1<<ADSC);
40
    while (ADCSRA & (1<<ADSC)){
41
      ;
42
    }
43
    foo +=ADCW;
44
  }
45
  foo = foo/4;
46
  foo += (foo>>2);
47
  ergebniss = (uint8_t)foo;
48
  return ergebniss;
49
  
50
}

von Karl H. (kbuchegg)


Lesenswert?

Fritz Bie schrieb:
> Hallo, ich möchte mir nach und nach ein Programm stricken mit dem ich
> einen Laminator auf ca. 200 Grad einregeln kann.
> Ich bin grad am versuchen ein Poti auszulesen und über den ermittelten
> Wert eine Diode in der Blink-geschwindigkeit zu regeln.
> Das Problem ist hier das ich als Rückgabewert des ADC kein Zahlenformat
> finde das ich in _delay_ms(xxx) eintragen kann ohne eine Fehlermeldung
> zu kriegen.

das Problem ist nicht das Zahlenformat. Das Problem ist, dass du bei 
_delay_ms einen konstanten Wert angeben musst.
Du kannst also schreiben
1
  _delay_ms( 50 );
oder auch
1
  _delay_ms( 200 );
da sowohl 50 als auch 200 konstante Werte seind.
Du kannst aber nicht schreiben
1
  int zeit;
2
3
  ...
4
  _delay_ms( zeit );
weil zeit eine Variable ist und keine Konstante.
Hintergrund: _delay_ms erfordert vom Compiler einiges an Aufwand. Er 
ermittelt aus der Zahl ein Schleifenkonstrukt, dass so oft durchlaufen 
wird, dass die angegebene Zeit ziemlich genau erreicht wird.
Das geht aber nur dann gut, wenn der Compiler die angestrebte Zeit als 
Zahlenwert auch tatsächlich kennt! Denn nur dann kann der Compiler all 
die Zwischenberechnungen rausoptimieren, so dass im Endeffekt nur das 
Schleifenkonstrukt mit genau diesem Zeitverhalten entsteht.

Daher die Einschränkung.

Aber:
Wenn man 50 Zeiteinheiten warten will, dann kann man auch 50 mal 1 
Zeiteinheit warten. Das ist im Endergebnis fast das selbe. Will man x 
Zeiteinheiten warten, dann kann man auch x mal 1 Zeiteinheit warten.

Anstatt einem nicht korrekten
1
  _delay_ms( zeit );
kann man zb ein
1
   for( i = 0; i < zeit; i++ )
2
     _delay_ms( 1 );
machen und ist damit auch (fast) dort, dass man eine vorher nicht näher 
bestimmte Zeit abwarten kann. Die Zeiten werden nicht ganz genau 
stimmen, weil ja das for-Konstrukt auch seine Zeit braucht, aber 
meistens ist das nicht so schlimm. Wir reden da über ein paar 
Zehntel-Prozent, die die Zeit deswegen abweichen wird.

: Bearbeitet durch User
von Fritz B. (kleinfritzchen)


Lesenswert?

Hallo,
ja hast recht,
als ich im mBett lag ist mir  diese Möglichkeit auch eingefallen.
danke erst mal so funktioniert es.

von Fritz B. (kleinfritzchen)


Lesenswert?

Das Blinken funktioniert jetz! Aber ich kann den Blinkrütmus im Bereich 
von 0V bis Vcc 4 mal über den Bereich verändern. das heist das der 
Zyklus bei Vcc langsam ist und er sich bis zu einem Spannungsabfall von 
ca 1.2V immer Scneller wird um danach beim weiteren drehen am Poti 
wieder schlagartig langsam und dann beim weiterdrehen wieder schneller 
zu werden. Dieser  Zyklus Wiedrholt sich 4 mal bis ich bei Null V bin.
kann mir mal jemand erklären woran das liegt? hab ich was falsch 
programmiert?
Code:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
//#define F_CPU = 1200000UL
4
uint16_t leseKanal(uint8_t mux);
5
uint16_t verz=0, i;
6
int main (void){
7
  DDRB=0x01;
8
  
9
  
10
  while (1){
11
    PORTB ^= 0x01;
12
    verz =  leseKanal(0x03);
13
    for ( i=0;i<=verz;i++){
14
      _delay_ms(2);
15
    }
16
  } return 0;
17
  
18
}
19
20
//Routine zum einlesen eines Kanales
21
uint16_t leseKanal(uint8_t mux)
22
{
23
  uint8_t i;
24
  uint8_t ergebniss;
25
  uint16_t foo;
26
  ADCSRA |= (1<<ADEN) | (1<<ADPS0) | (1<<ADPS1);
27
    //ADC einschalten, Teiler auf 8
28
  ADMUX =mux;
29
  //lerlauf zum syncronisoeren
30
  ADCSRA |= (1<<ADSC);
31
  while (ADCSRA & (1<<ADSC)){
32
    ;
33
  }
34
  foo = ADCW;
35
    
36
  foo = 0;
37
  //eigentlicher Abfragezyklus
38
  for(i=0;i<4;i++){
39
    
40
    ADCSRA |= (1<<ADSC);
41
    while (ADCSRA & (1<<ADSC)){
42
      ;
43
    }
44
    foo +=ADCW;
45
  }
46
  ergebniss = foo/4;
47
  ergebniss = (ergebniss>>2);
48
  return ergebniss;
49
  
50
}

von Karl H. (kbuchegg)


Lesenswert?

Fritz Bie schrieb:

> uint16_t leseKanal(uint8_t mux)
> {
>   uint8_t i;
>   uint8_t ergebniss;
    *******

>   ergebniss = foo/4;

foo/4 kann Werte zwischen 0 und 1023 ergeben.
ergebniss kann als uint8_t aber nur Werte zwischen 0 und 255 speichern.

: Bearbeitet durch User
von Fritz B. (kleinfritzchen)


Lesenswert?

Besten dank!
hab ich glatt übersehen!
MfG Fritz

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.