Forum: Mikrocontroller und Digitale Elektronik Attiny13 ADC mittels Poti


von Martin (Gast)


Lesenswert?

Hallo zusammen. Ich würde gerne ab einer bestimmten Spannung, durch ein 
Poti mittels Spannungsteiler erzeugt, eine LED anschalten und bei 
unterschreiten wieder abschalten.
Zu diesem Thema gibt es mehrere Forenbeiträge.
Ich habe mir ein Steckboard mit einem Attiny 13 aufgebaut. Der Poti ist 
an ADC0 (PB5) angeschlossen, die LED an PB4.
Die Spannung des Potis überwache ich parallel mit einem Multimeter.

Die Led geht bei Verstellen des Potentiometers ab einer Spannung von ca 
>2.2V an.
Leider ist es egal welchen Wert ich für ADCH eingebe, der Ausgang 
schaltet stets bei der Spannung 2,2V. Kann mir jemand helfen? Was mache 
ich falsch?

Ich habe folgenden Code benutzt, nachdem ich etwas hin und her probiert 
habe:
1
#include <avr/io.h>
2
3
int main (void)
4
{
5
  DDRB |= (1 << PINB4); // Set LED1 as output
6
7
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // // /128
8
9
  ADMUX |= (0 << REFS0); // Set ADC reference to AVCC
10
  ADMUX |= (0 << MUX1); // ADC0
11
  ADMUX |= (0 << MUX0);
12
  ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading
13
14
  ADCSRA |= (1 << ADATE);  // Set ADC to Free-Running Mode
15
  ADCSRA |= (1 << ADEN);  // Enable ADC
16
  ADCSRA |= (1 << ADSC);  // Start A2D Conversions
17
18
19
  for(;;)  // Loop Forever
20
  {
21
    if(ADCH <50)
22
    {
23
      PORTB |= (1 << PINB4); // Turn on LED1
24
    }
25
    else
26
    {
27
      PORTB &= ~(1 << PINB4); // Turn off LED1
28
    }
29
  }
30
}

von Florian (Gast)


Lesenswert?

Hallo Martin,

wie hast Du denn Dein Poti angeschlossen? Bitte poste mal den 
Schaltplan. Skizze reicht.

Gruß
Florian

von HildeK (Gast)


Lesenswert?

Bist du sicher, dass du den Reset-Pin (ADC0) als AD-Eingang nutzen 
willst?

von Florian (Gast)


Lesenswert?

Du shiftest für MUX0 und MUX1 eine 0 ins ADMUX ???

ADMUX |= (0 << MUX1); // ADC0
ADMUX |= (0 << MUX0);

ist das denn richtig?

von student (Gast)


Lesenswert?

war da nicht was das man ADCH und ADCL auslesen muss damit die 
Wandlung von vorn beginnt?

von Stefan F. (Gast)


Lesenswert?

PB5/ADC0 ist normalerweise der /Reset Eingang. Hast du das bedacht?

von Florian (Gast)


Lesenswert?

HildeK schrieb:
> Bist du sicher, dass du den Reset-Pin (ADC0) als AD-Eingang nutzen
> willst?

Das würde auf jeden Fall auch erklären warum sich der Wert nicht ändert, 
wenn der Reset korrekt an einem 10k Pullup hängt :-)

Ich denke aber der 2. Fehler ist die Zeile (0 << MUX0), wobei eine 0 
verodern auch nicht unbedingt sehr viel Sinn macht :-)

Besser so:

ADMUX |= (1 << MUX0);

Schau mal was ich gerade noch gegoogelt habe:

https://www.adnbr.co.uk/articles/adc-and-pwm-basics

von HildeK (Gast)


Lesenswert?

Florian schrieb:
> Du shiftest für MUX0 und MUX1 eine 0 ins ADMUX ???
>
> ADMUX |= (0 << MUX1); // ADC0
> ADMUX |= (0 << MUX0);
>
> ist das denn richtig?

Jein.
Es wird keine Null geschrieben, wenn eine Eins drin stünde. Dann geht 
das so nicht!
Per Default steht jedoch eine Null drin, aber wenn das Statement so mal 
im Code steht, ist es leicht, aus der Null eine Eins zu machen.
Machen manche, um den Zustand zu verdeutlichen.

von Axel S. (a-za-z0-9)


Lesenswert?

Martin schrieb:
1
> ADMUX |= (0 << REFS0); // Set ADC reference to AVCC
2
> ADMUX |= (0 << MUX1); // ADC0
3
> ADMUX |= (0 << MUX0);
4
> ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit 
5
> reading

Das hier ist großer Unfug. Die ersten 3 Befehle haben gar keinen Effekt. 
Initial solltest du einmal einen Wert direkt nach ADMUX schreiben und 
dabei alle Bits, die gesetzt sein müssen, entsprechend verodern. So wie 
du es darüber für ADCSRA gemacht hast.

von Mario M. (thelonging)


Lesenswert?

Ihr könnt aufhören zu raten. Stefan Us hat Recht. Ab 2,2V kommt RESET.
Hier hat das mal einer ausprobiert:
http://www.instructables.com/id/Using-pin-1-on-Attiny13-without-messing-with-fuse-/
"It turns out that the point of reset was at 9K Ohm (out of 25). Which 
is equal to 5 *(9/25)= 45/25=9/5=2.2 Volt."

von Stefan F. (Gast)


Lesenswert?

Atmel garantiert, daß der Pin 10% von VCC nach unten gehen darf, ohne 
einen Reset auszulösen. Alles darunter ist tabu, es sei denn du 
deaktivierst die Reset Funktion in den Fuses. Aber dann geht ISP auch 
nicht mehr.

Das ist zumindest der Wert, den ich im Kopf habe. Genaues kannst du dem 
DB entnehmen.

von Thomas E. (thomase)


Lesenswert?

Stefan U. schrieb:
> Das ist zumindest der Wert, den ich im Kopf habe.

Was du so alles im Kopf hast.


Laut Datenblatt ist Input High Voltage für den Reset 0,9V - Vcc+0,5V

Allerdings mit dem Zusatz "Not tested in production". Was immer das für 
den tatsächlichen Wert bedeuten mag. Aber mit Vcc-10% liegst du völlig 
daneben.

: Bearbeitet durch User
von Martin (Gast)


Lesenswert?

Hallo zusammen. Vielen Dank für die ganzen Antworten, wirklich sehr nett 
und vor allen Dingen hilfreich.
Habe noch einmal einen anderen Beispielcode gefunden welchen ich benutzt 
habe. Anfangs zeigte sich das gleiche Phänomen wie beim anderen Code. Es 
lag tatsächlich am ADC0 welcher auf dem RESET Pin liegt. Habe den Code 
auf ADC3 umgeschrieben und es hat sofort funktioniert.

Code sieht nun wie folgt aus:
1
#include  <avr\io.h>
2
#include <util/delay.h>
3
unsigned int xx=0;
4
5
6
/////////////////////
7
//Poti ADC
8
/////////////////////
9
10
uint16_t readADC(uint8_t channel)
11
{
12
  uint8_t i;
13
  uint16_t result = 0;
14
  // die Versorgungsspannung AVcc als Referenz wählen:
15
  ADMUX = (0<<REFS0);
16
  // Set the ADC input to PB2/ADC3
17
  ADMUX |= (1 << MUX0)|(1 << MUX1);
18
  // Set the prescaler to clock/128 & enable ADC
19
  ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
20
21
  ADCSRA |= (1<<ADSC);
22
  while(ADCSRA & (1<<ADSC));
23
24
  for(i=0; i<3; i++)
25
  {
26
    // Eine Wandlung
27
    ADCSRA |= (1<<ADSC);
28
    // Auf Ergebnis warten...
29
    while(ADCSRA & (1<<ADSC));
30
31
    result += ADCW;
32
33
    // ADC wieder deaktivieren
34
    ADCSRA &= ~(1<<ADEN);
35
36
    result /= 3;
37
38
    return result;
39
  }
40
}
41
42
main (void)
43
{
44
  DDRB |= (1 << PINB4); // Set LED1 as output
45
  while (1)
46
  {
47
48
    ADCSRA |= (1<<ADSC);
49
    uint16_t result = readADC(3);  //Auslesen der analogen Spannungen an Pin 2,
50
    xx=result;
51
    if (xx>305) //ungefähr 4,4 Volt
52
    {
53
      PORTB &= ~(1 << PINB4); // Turn on LED1
54
    }
55
    if (xx<300) //etwas unter 4,4 Volt
56
    PORTB |= (1 << PINB4); // Turn on LED1
57
  }
58
}

von Stefan F. (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Laut Datenblatt ist Input High Voltage für den Reset 0,9V - Vcc+0,5V
Dass heisst, alles ab 0,9V aufwärts ist garantiert High. Das bezieht 
sich auf die Nutzung des Pins als I/O Pin.

Aber schau mal nach "RESET Pin Threshold Voltage". Das ist 0.2*VCC bis 
0.9*VCC. Damit garantiert kein Reset ausgelöst wird, muss die Spannung 
demnach höher als 0,9*VCC sein. Das sind die von mir genannten 10% 
unterhalb VCC.

Siehe auch Kapitel 8.2.2 "External Reset" Figure 8.4 "External Reset 
During Operation". Das Diagramm zeigt unmissverständlich, dass der Reset 
ausgelöst wird, wenn die Spannung am Reset Pin unter VRST fällt. Und das 
ist die eben genannte "RESET Pin Threshold Voltage".

von M. K. (sylaina)


Lesenswert?

Martin schrieb:
> // die Versorgungsspannung AVcc als Referenz wählen:
>   ADMUX = (0<<REFS0);

Lass diesen Unsinn irgendwohin Nullen zu schieben wo eh schon Nullen 
drin stehen.

von Mario M. (thelonging)


Angehängte Dateien:

Lesenswert?

Stefan U. schrieb:
> Aber schau mal nach "RESET Pin Threshold Voltage". Das ist 0.2*VCC bis
> 0.9*VCC.

Threshold heißt Schwellwert, also der Punkt wo RESET intern zwischen H 
und L wechselt. Und der liegt irgendwo zwischen diesen Extremwerten. Der 
typische Wert bei 5V Betriebsspannung liegt allerdins bei ca. 2,2V. 
Siehe Diagramm.

Stefan U. schrieb:
> Damit garantiert kein Reset ausgelöst wird, muss die Spannung
> demnach höher als 0,9*VCC sein.

Genau. Deswegen sind die Schaltungen, die RESET als Analogeingang 
oberhalb 2,2V nutzen eigentlich Pfusch.

von Stefan F. (Gast)


Lesenswert?

> Deswegen sind die Schaltungen, die RESET als Analogeingang
> oberhalb 2,2V nutzen eigentlich Pfusch.

Du meinst "unterhalb".

von c-hater (Gast)


Lesenswert?

M. K. schrieb:

> Lass diesen Unsinn irgendwohin Nullen zu schieben wo eh schon Nullen
> drin stehen.

Das ist nur in fertigem Code Unsinn, nicht unbedingt aber in Code, der 
der Evaluierung dient.

Aber klar, wenn man sich mit der Peripherie schon sehr gut auskennt und 
es deshalb kaum noch was zu evalieren gibt, mutet es natürlich wie 
kompletter Unsinn an.

AAABER: sobald man mal wieder mit einer neuen, unbekannten Peripherie 
konfrontiert wird, fällt man doch sehr schnell wieder darauf zurück. 
Sicher nicht für jedes verschissene Bit, aber eben für die, deren genaue 
Wirkungsweise man nach Lektüre des DB doch lieber selber noch mal 
überprüft, weil das DB gewisse "Interpretationsspielräume" läßt...

Wem das noch niemals so gegangen ist, der ist kein Programmierer, 
sondern ein C&P-Idiot, der noch niemals selbst die Leistung vollbracht 
hat, irgendeine Hardware anzuknoten, sondern immer nur die Leistungen 
anderer genassauert hat...

von Mario M. (thelonging)


Lesenswert?


von Stefan F. (Gast)


Lesenswert?

Der Reset Pin ist Low Aktiv. Die Spannung soll also oberhalb der 
maximalen Schwelle sein, wenn man keinen Reset auslösen möchte.

von Thomas E. (thomase)


Lesenswert?

Stefan U. schrieb:
> Dass heisst, alles ab 0,9V aufwärts ist garantiert High. Das bezieht
> sich auf die Nutzung des Pins als I/O Pin.

Du solltest einfach mal ins Datenblatt gucken, anstatt hier irgendwas 
umherzuplappern, was du meinst, im Kopf zu haben.

Input High Voltage ist 0,6V/0,7V - Vcc+0,5V, je nach Vcc.

von M. K. (sylaina)


Lesenswert?

c-hater schrieb:
> Das ist nur in fertigem Code Unsinn, nicht unbedingt aber in Code, der
> der Evaluierung dient.

Nein, das ist hier an der Stelle schlicht Unsinn, auch in der 
Evaluierung.

c-hater schrieb:
> Aber klar, wenn man sich mit der Peripherie schon sehr gut auskennt und
> es deshalb kaum noch was zu evalieren gibt, mutet es natürlich wie
> kompletter Unsinn an.

Dafür muss man sich nicht gut mit der Peripherie auskennen sondern nur 
das Datenblatt lesen. Da hat man ja auch die Bezeichner her.

c-hater schrieb:
> AAABER: sobald man mal wieder mit einer neuen, unbekannten Peripherie
> konfrontiert wird, fällt man doch sehr schnell wieder darauf zurück.
> Sicher nicht für jedes verschissene Bit, aber eben für die, deren genaue
> Wirkungsweise man nach Lektüre des DB doch lieber selber noch mal
> überprüft, weil das DB gewisse "Interpretationsspielräume" läßt...

Nur läßt es hier absolut keine Interpretation zu sondern ist eindeutig.

c-hater schrieb:
> Wem das noch niemals so gegangen ist, der ist kein Programmierer,
> sondern ein C&P-Idiot, der noch niemals selbst die Leistung vollbracht
> hat, irgendeine Hardware anzuknoten, sondern immer nur die Leistungen
> anderer genassauert hat...

Genau so sieht das Verschieben der Null aus: Da weiß jemand nicht was er 
da tut, ist also völliger Unsinn. Und nur darauf hab ich hingewiesen.

von Thomas E. (thomase)


Lesenswert?

c-hater schrieb:
> Sicher nicht für jedes verschissene Bit

Wie kannst du so ein armes Bit, daß treu und brav seinen Dienst tut, als 
verschissen bezeichnen?

Das ist ein Bit-Mobbing!

von Axel S. (a-za-z0-9)


Lesenswert?

M. K. schrieb:
> Martin schrieb:
>> // die Versorgungsspannung AVcc als Referenz wählen:
>>   ADMUX = (0<<REFS0);
>
> Lass diesen Unsinn

Ja.

> irgendwohin Nullen zu schieben wo eh schon Nullen
> drin stehen.

Das auch, aber das ist nicht der Punkt.

Ich habe es oben schon einmal geschrieben, aber offensichtlich haben das 
einige nicht verstanden (insbesondere die nicht, die mir dafür -1 
gegeben haben).

1. Man kann sich hier nicht darauf verlassen, daß ADMUX auf 0x00 
steht. Selbst wenn das der Default nach Power-On Reset ist - wer 
garantiert uns denn, daß der µC frisch aus dem Reset kommt? Der kann ja 
genausogut vom BOD oder Watchdog resettet worden sein.

2. einzelne Bits zu setzen oder zu löschen ist genau dann richtig, wenn
a) die anderen Bits wirklich egal sind; z.B. weil es in dem Register nur 
das eine Bit gibt, oder
b) man weiß, daß die anderen Bits den gewünschten Wert haben; z.B. weil 
man den ADC vorher schon initialisiert hat und hier wirklich nur noch 
den MUX umschalten will, oder
c) man die anderen Bits unabhängig vom derzeitigen Zustand gezielt nicht 
anfassen will; z.B. um einen einzelnen Pin zu setzen.

keins davon ist hier gegeben. Darüber hinaus ist die derzeitige 
Codesequenz
1
ADMUX = (0<<REFS0);
2
// Set the ADC input to PB2/ADC3
3
ADMUX |= (1 << MUX0)|(1 << MUX1);

auch noch länger (Codegröße und Ausführungszeit) als das bessere
1
// internal reference
2
// ADC input to PB2/ADC3
3
ADMUX = (1 << MUX0)|(1 << MUX1);

hier könnte man auf der rechten Seite noch alle 0-Bits entsprechend 
aufzählen, wenn man es übersichtlicher findet (finde ich zwar nicht, 
aber über Geschmack soll man nicht streiten)

von Thomas E. (thomase)


Lesenswert?

Stefan U. schrieb:
> Aber schau mal nach "RESET Pin Threshold Voltage". Das ist 0.2*VCC bis
> 0.9*VCC. Damit garantiert kein Reset ausgelöst wird, muss die Spannung
> demnach höher als 0,9*VCC sein. Das sind die von mir genannten 10%
> unterhalb VCC.

Ja, jetzt sehe ich es auch, da bin ich schon öfter drüber gestolpert.

Betrachtet die Beträge von mir zu diesem Thema als nicht geschrieben.

von M. K. (sylaina)


Lesenswert?

Axel S. schrieb:
> 1. Man kann sich hier nicht darauf verlassen, daß ADMUX auf 0x00
> steht. Selbst wenn das der Default nach Power-On Reset ist - wer
> garantiert uns denn, daß der µC frisch aus dem Reset kommt? Der kann ja
> genausogut vom BOD oder Watchdog resettet worden sein.

Der Reset ist ja egal, nach einem Reset gelten die Initial/Values und 
auf das Datenblatt muss man sich nun schon verlassen können.

von Stefan F. (Gast)


Lesenswert?

> Ja, jetzt sehe ich es auch, da bin ich schon
> öfter drüber gestolpert.

Wie meinst du das? Wenn Dir diese Eigenart des Reset Pins bereits öfters 
Schwierigkeiten bereitet hat, warum hast du dann bis gerade eben 
mehrfach meiner Erklärung trotz Bezug zum Datenblatt widersprochen?

Ich meine, sowas tust du doch bestimmt nicht ohne Überzeugung. Und senil 
wirkst du auch keineswegs. Deswegen irritiert mich diese Satz sehr.

Wie kommt es zu dem plötzlichen Sinneswandel?

von Simpel (Gast)


Lesenswert?

ich hatte das mit dem Reset bislang so verstanden:

Wenn der Resetpin High war, muss er aufgrund seiner breiteren Hysterese 
auf < 0.2Vcc runtergezogen werden, um einen Reset auszulösen. War der 
Resetpin low, muss er bis mindestens 0.9Vcc hochgezogen werden, um die 
Hysterese nach oben zu überwinden und den Resetstatus zu beenden...
Das bedeutet nicht, dass der Bereich zwischen 0.2Vcc und 0.9Vcc instabil 
oder undefiniert wäre. Nur der spannungsmässige Störabstand wird mit 
zunehmender Nähe zur unteren Schaltschwelle eben kleiner.

von Stefan F. (Gast)


Lesenswert?

Ja, so habe ich das auch verstanden. Wenn ich den Eingang also auch 
analog nutze aud z.B. von 5V auf 3V runter ziehe, kann der Reset Impuls 
nicht beendet werden, weil 3V kleiner als 0.9*VCC ist.

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.