ADC Messung mit Attiny84

Gast #6016285
Lesenswert?

Hallo
möchte meinen ATTINY84 eine Spannung messen. habe mir dazu das AVR GCC 
Tutorial Analoge Eingänge zur Hilfe genommen.
Das Programm und Anpassungen:
1
// Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
2
// unter Verwendung der internen Referenzspannung von nominell 1,1V.
3
// Zur Anpassung an andere AVR und/oder andere Referenzspannungen
4
// siehe Erläuterungen in diesem Tutorial und im Datenblatt
5

6
/* ADC initialisieren */
7
void ADC_Init(void)
8
{
9
  // die Versorgungsspannung AVcc als Referenz wählen:
10
  // ADMUX = (1<<REFS0);  // Ausgeschaltet da Ref Vcc ist  
11
  // oder interne Referenzspannung als Referenz für den ADC wählen:
12
  // ADMUX = (1<<REFS1) | (1<<REFS0);
13

14
  // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
15
  // schon auf 0, also single conversion
16
  ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
17
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
18

19
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
20
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
21

22
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
23
  while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
24
  }
25
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
26
     Wandlung nicht übernommen. */
27
  (void) ADCW;
28
}
29

30
/* ADC Einzelmessung */
31
uint16_t ADC_Read( uint8_t channel )
32
{
33
  // Kanal waehlen, ohne andere Bits zu beeinflußen
34
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
35
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
36
  while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
37
  }
38
  return ADCW;                    // ADC auslesen und zurückgeben
39
}
40

41
/* ADC Mehrfachmessung mit Mittelwertbbildung */
42
/* beachte: Wertebereich der Summenvariablen */
43
uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples )
44
{
45
  uint32_t sum = 0;
46

47
  for (uint8_t i = 0; i < nsamples; ++i ) {
48
    sum += ADC_Read( channel );
49
  }
50

51
  return (uint16_t)( sum / nsamples );
52
}
53

54
...
55

56
/* Beispielaufrufe: */
57

58
int main( void )
59
{
60
  uint16_t adcval;
61
  ADC_Init();
62

63
  while( 1 ) {
64
    adcval = ADC_Read(0);  // Kanal 0
65
    // mach was mit adcval
66
    if(adcval>628)
67
      {
68
       
69
      PORTA |=(1<<PINA0);  
70
      }
71
      else
72
      {
73
        
74
       PORTA &=~(1<<PINA0);
75
      }
76

77
    adcval = ADC_Read_Avg(2, 4);  // Kanal 2, Mittelwert aus 4 Messungen
78
    // mach was mit adcval
79
  }
80
}
Die Einstellung der Spannung nehme ich mit einem Poti vor, das zwischen 
0 und Vcc (5V) eingestellt werden kann.
Mit  if(adcval>628) kann ich die Schwelle (zwischen 0 und 1023) 
einstellen an dem die LED einschaltet.
Leider scheint nur ein Punkt zu reagieren. Egal an welchem Angabe ich 
mache, es schaltet immer am selben Punkt ein.
Habe ich da was falsch eingestellt?
LG Ingo
Gast #6016297
Lesenswert?

Ingo schrieb:

> Mit  if(adcval>628) kann ich die Schwelle (zwischen 0 und 1023)
> einstellen an dem die LED einschaltet.
> Leider scheint nur ein Punkt zu reagieren. Egal an welchem Angabe ich
> mache, es schaltet immer am selben Punkt ein.

Welche Angabe du wo genau machst?

Tipp: Dein Problem kann niemand verstehen. Du beschreibst das Erwartbare
und tust so, als wenn das Eintreten des Erwartbaren nicht korrekt wäre.
Gast #6016307
Lesenswert?

Mit dem Poti kann ich einen Wert von 0-5V einstellen, das entspricht bei 
einer Referenzspannung von 5V den Werten von 0 bis 1023.
Bei der Einzelmessung wird der ermittelte Wert mit
1
return ADCW;                    // ADC auslesen und zurückgeben
zurückgegeben und mit
1
adcval = ADC_Read(0);  // Kanal 0
2
    // mach was mit adcval
3
    if(adcval>628)
4
      {
5
       
6
      PORTA |=(1<<PINA0);  
7
      }
8
      else
9
      {
10
        
11
       PORTA &=~(1<<PINA0);
12
      }
ausgewertet. In der Variablen adcval ist der Wert des Potis gespeichert, 
kann den Wert von 0-1023 annehmen, und wird mit >628 vergliechen. Ist 
der Wert des Potis grösser oder kleiner schaltet die LED entweder ein 
oder aus.
Bei mir schaltet die LED ein/aus bereits bei ca. 5% des Drehweges und 
lässt sich die änderung von 628 auf 128 oder 828 nicht verändern. Egal 
welchen Wert (628) ich eingebe, es verändert sich nichts.
Hoffe das es klarer ist
LG Ingo
Gast #6016327
Lesenswert?

Der Regler (22k) ist mit seinem Schleifer an PA3, die beiden anderen 
Anschlüsse sind an GND und Vcc und die LED ist am PA0 über einen 
Vorwiederstand nach Vcc angeschlossen. Es befindet sich alles auf einem 
Brett zur Zeit. Eine Zeichnung müsste ich erst machen
Gast #6016335
Lesenswert?

Ja, ich habe es noch mal geprüft und dazu den Regler abgezogen. Von den 
3 Beinen ist der einzelne auf dem PA3 (ADC3) und die beiden anderen auf 
GND und Vcc.
Laut Datenblatt hat der PA3 den ADC3 und PA0 den ADC0.
Gast #6016342
Lesenswert?

Ingo schrieb:
> Ja, ich habe es noch mal geprüft und dazu den Regler abgezogen. Von den
> 3 Beinen ist der einzelne auf dem PA3 (ADC3) und die beiden anderen auf
> GND und Vcc.
> Laut Datenblatt hat der PA3 den ADC3 und PA0 den ADC0.

Schön, dass wir das geklärt haben. Der Fehler kann also nur in deinem 
Programm liegen...
Gast #6016352
Lesenswert?

Ingo schrieb:

> Fehler im Programm, hatte angenommen das es funktioniert wenn es im AVR
> GCC steht

???

Was auch immer du damit meinen magst...

Die Tatsache, dass ein Programm sich kompilieren läßt, heißt jedenfalls 
nichtmal annähernd, das es auch das tut, was man will...

Der Compiler kann nur ein syntaktische Prüfung leisten, keine logische. 
Wenn also der Compiler durchläuft, heißt das nur, das formal gültiger 
Quelltext übersetzt wurde.

Das Programm kann natürlich trotzdem kompletter Unsinn sein.
Gast #6016356
Lesenswert?

Scheinbar habe ich das Problem gefunden. Hatte beim testen ADLAR drin 
und danach wieder rausgenommen. Beim messen der Spannung hatte ich das 
Teil ausgeschaltet und wieder eingeschaltet. Wahrscheinlich ist ADLAR 
noch drin gewesen, wie auch immer. Ergebnis, es läuft jetzt korrekt.
Danke für eure Hilfe
Gast #6016362
Lesenswert?

Hallo

"Schön, dass wir das geklärt haben. Der Fehler kann also nur in deinem
Programm liegen..."

Ach nee - welch eine Feststellung...
Kombiniere doch mal was der TO wohl gerne damit sagen indem er hier sein 
Programm gepostet hat und erklärt hat wie er die Hardware nach den 
ersten sinnvoll Anschlussfragen und Empfehlungen überprüft hat...
Na kommt dir eine Idee was der TO wohl gebrauchen könnte?
Und nein um einige gerne hervor gezauberte "Hilfestellungen" gleich aus 
zu schließen:

Keine allgemeines Bla Bla zur Selbsthilfe
Kein allgemeines Bla Bla  und "Empfehlungen" erst mal weiter zu lernen

Sondern? - Na was wohl...?
Eventuell eine funktionierende  Lösung mit viel hilfreichen Kommentaren 
im Quellcode?

Aber nein das widerspricht ja den Bildungsauftrag swn sich so mancher 
selbst gegeben hat und den Moralwächtern die von Anspruchsdenken 
schwadronieren...

Hennes
Gast #6016522
Lesenswert?

Hennes schrieb:
> Na kommt dir eine Idee was der TO wohl gebrauchen könnte?
> Und nein um einige gerne hervor gezauberte "Hilfestellungen" gleich aus
> zu schließen:
>
> Keine allgemeines Bla Bla zur Selbsthilfe
> Kein allgemeines Bla Bla  und "Empfehlungen" erst mal weiter zu lernen
>
> Sondern? - Na was wohl...?
> Eventuell eine funktionierende  Lösung mit viel hilfreichen Kommentaren
> im Quellcode?

Und wenn Du das alles weißt - warum hast Du ihm nicht entsprechend 
geholfen? Dein Blabla ist auch nicht hilfreich
Gast #6017845
Lesenswert?

Hennes schrieb:
> Eventuell eine funktionierende  Lösung mit viel hilfreichen Kommentaren
> im Quellcode?
>
> Aber nein das widerspricht ja den Bildungsauftrag swn sich so mancher
> selbst gegeben hat und den Moralwächtern die von Anspruchsdenken
> schwadronieren...

Dir ist schon aufgefallen, dass die gefundenen Fehlerquelle,
NICHT Teil des zitierten Quelltextes ist, und deswegen dort nicht hätte 
gefunden werden können, oder?

(ADLAR ist im ATTiny84 auch bit5 im ADMUX wie beim 13er, oder?)

weswegen Hilfe zur Selbsthilfe in diesem speziellen Fall doch garkein 
schlechter Ansatz gewesen ist,
wenngleich leider nicht unmittelbar zielführend.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren