Forum: Mikrocontroller und Digitale Elektronik ADC Messung mit Attiny84


von Ingo (Gast)


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

von c-hater (Gast)


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.

von Georg M. (g_m)


Lesenswert?

Ingo schrieb:
> Die Einstellung der Spannung nehme ich mit einem Poti vor, das zwischen
> 0 und Vcc (5V) eingestellt werden kann.

Zeigt auch das Multimeter an, dass elektrisch alles in Ordnung ist?

von Mario M. (thelonging)


Lesenswert?

Ingo schrieb:
> ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler

Mit welchem Prozessor-Takt läuft der Tiny?

von Ingo (Gast)


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

von Mario M. (thelonging)


Lesenswert?

Ingo schrieb:
> adcval = ADC_Read(0);  // Kanal 0
> ...
>       PORTA |=(1<<PINA0);

Wo sind Poti und LED angeschlossen? ADC-Kanal 0 und PA0 sind der selbe 
Pin?

von c-hater (Gast)


Lesenswert?

Ingo schrieb:

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

Schaltungsfehler sehr wahrscheinlich. Zeichne mal die Schaltung auf. Und 
zwar die reale...

von Ingo (Gast)


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

von c-hater (Gast)


Lesenswert?

Ingo schrieb:

> Der Regler (22k) ist mit seinem Schleifer an PA3, die beiden anderen
> Anschlüsse sind an GND und Vcc

Das hast du tatsächlich überprüft oder ist nur das, was du wolltest?

von Mario M. (thelonging)


Lesenswert?

Im Programm wird weder PA0 auf Ausgang geschaltet noch findet eine 
ADC-Wandlung auf ADC3 statt.

von Ingo (Gast)


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.

von c-hater (Gast)


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

von Ingo (Gast)


Lesenswert?

Habe die Spannung am PA3 gemessen (direkt), lässt sich mit dem Regler 
von 0 bis 5V Vcc durch drehen.
Fehler im Programm, hatte angenommen das es funktioniert wenn es im AVR 
GCC steht

von c-hater (Gast)


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.

von Ingo (Gast)


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

von Hennes (Gast)


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

von Hermes (Gast)


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

von sid (Gast)


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.

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.