mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik attiny adc macht nicht was er soll


Autor: Philipp Karbach (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich lese gerade einen Beschleunigungssensor aus. Mit einem mega16 
klappt das wie gewünscht. Die Werte im Ruhezustand der drei Achsen 
liegen bei etwa 400.

Nun muss ich die ganze Anwendung aber auf einem attiny84 laufen lassen.
Dieser soll per software UART die achsenwerte rausschicken. Die Software 
UART (dannegger code) funktioniert. Der ADC macht aber zicken:

ich initialisiere den PORTA folgendermaßen:

DDRA = 0x0;
PORTA = 0x0;

den ADC lese ich mit meiner Standardfunktion die beim mega16 klappt:

int ReadChannel(int channel)
{
  int i;
  int result = 0;
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
  ADMUX = channel;
  ADMUX |= (1<<REFS1) | (1<<REFS0);
  ADCSRA |= (1<<ADSC);
  while (ADCSRA&(1<<ADSC));
  for(i=0;i<4;i++)
  {
    ADCSRA |= (1<<ADSC);
    while (ADCSRA&(1<<ADSC));
    result += ADCW;
  }
  ADCSRA &= ~(1<<ADEN);
  result /= 4;
  return result;
}

Lese ich nun den ADC stürzt der tiny scheinbar ab, es wird nichts mehr 
an die UART gegeben. Ich sehe im Datenblatt keinen großen unterschied 
zwischen mega16 und tiny in bezug auf den adc... Was mache ich 
möglicherweise falsch?

Autor: Hubert G. (hubertg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In meinem Datenblatt steht bei ADMUX |= (1<<REFS1) | (1<<REFS0);
reserved.

Autor: Philipp Karbach (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh du hast recht! kann es gerade nicht testen aber vielleicht ist das 
genau mein problem!

Autor: Dimon11/09 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits,

Hab mich gerade mit selben Problem beschäftigt - Attiny24 ADC.

Nun Buch nachgelesen, Datenblat durchgewühlt und diesen Forum auch. Das 
obige Beispiel, sehr identisch mit meinen außer Filterung vielleich. Die 
Registereinstellungen 1:1. Hab einfach keinen Plan wie ich das zum 
laufem Bringe.

Bin sehr dankbar für jede Art der Anregung.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Hab einfach keinen Plan wie ich das zum laufem Bringe.

Was soll passieren? Was passiert?
Lass mich raten: Alle LEDs leuchten?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dimon11/09 schrieb:

> obige Beispiel, sehr identisch mit meinen außer Filterung vielleich. Die
> Registereinstellungen 1:1.

Das kann jeder sagen.
Ich hab aber jetzt absolut keine Lust, die Bits der Hex-Zahlen 
auseinanderzupfriemeln und nachzusehen, was du da eigentlich alles 
gesetzt hast. Nimm dir ein Beispiel am Code weiter oben, wie man sowas 
lesbar macht

>  // ADC Enable, ADC Clock = F_CPU/2

4Mhz ADC Takt?
Kann das der Tiny überhaupt?

Autor: Dimon11/09 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, ging flott!

Ich lege den PA7 zu Testzwecken mal auf die Masse mal auf Vcc. Es sollte 
sich was mit LED's was tun (mal alle mal keine bzw. nur eine an). Egal 
was ich mit der Spannung mache leuchten alle Leds ^^ (gut geraten :-). 
Obwohl ich die Funktion vergleich(); getestet hab.

Ja so ist der Stand.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>  // Interne SpannungsReferenz von 1,1V und PA7 Analog-Eingang
>>  ADMUX = 0x83;

Nicht PA7, sondern PA3 ist damit der Eingang.

>>  // Ergebniss Links In dem DATA REGISTER ausgerichtet ADCH = ADC9
>> ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2
>>  //                           ADCL = ADC1 ADC0
>>  ADCSRB = 0x00;

Hier stimmt der Kommentar (left adjust) nicht zum Register (right 
adjust)

Würdest Du nicht Hexwerte hinschreiben, würdest Du selber besser 
durchblicken.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Egal was ich mit der Spannung mache leuchten alle Leds ^^ (gut geraten :-).

Das war nicht wirklich geraten ;)

Probier doch mal sowas:

    if(Data>100){SET_LED_A(1);}
    else {CLEAR_LED_A(1);}


    if(Data>200){SET_LED_A(2);}
    else {CLEAR_LED_A(2);}

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> 4Mhz ADC Takt?
>> Kann das der Tiny überhaupt?

Wenn nicht die CKDIV8 Fuse umprogrammiert wurde, läuft der ATiny24 
frisch aus der Schachtel mit 1MHz, / 2 = 500kHz kann der ADC schon 
packen.

Autor: Dimon11/09 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@MWS
HAb während der Experimente vergessen die Komentare zu ändern.

Und haupsache MANN Vielen Dank hab vor lauter Binär unh Hex den 
Überblick verloren. Natürlich falscher Eingang jeztz funzt auch wie es 
soll!!!

ADC3 (PA3) 10000011 = 0x83

ADC7 (PA7) 10000111 = 0x87


Danke euch allen!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MWS schrieb:
>>> 4Mhz ADC Takt?
>>> Kann das der Tiny überhaupt?
>
> Wenn nicht die CKDIV8 Fuse umprogrammiert wurde, läuft der ATiny24
> frisch aus der Schachtel mit 1MHz,

:-)
Der F_CPU Wert behauptet aber was anderes
:-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dimon11/09 schrieb:
> @MWS
> HAb während der Experimente vergessen die Komentare zu ändern.
>
> Und haupsache MANN Vielen Dank hab vor lauter Binär unh Hex den
> Überblick verloren. Natürlich falscher Eingang jeztz funzt auch wie es
> soll!!!
>
> ADC3 (PA3) 10000011 = 0x83
>
> ADC7 (PA7) 10000111 = 0x87

Und nochmal:
Schreib das alles nicht als HEX-Zahl, dann hast du diese Probleme erst 
gar nicht. Schreib deinen Code, so, dass der Code sein eigener Kommentar 
ist, dann pasiiert dir auch nicht, dass der Kommentar falsch ist.

Was ist so schlimm an

   ADMUX = ( 1 << REFS1 ) |        // 1.1V Referenz
           PA7;

ausser, das man es lesen könnte und weniger Fehler macht?

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> :-)
>> Der F_CPU Wert behauptet aber was anderes
>> :-)

Yep, da hatte der Poster wohl Glück, daß das auch nicht gestimmt hat, 
denn mit 4 MHz Clcok würde der ADC jetzt ganz bestimmt nicht laufen :D

Da keine Delays vorkommen, ist die F_CPU Angabe zumindest in diesem Code 
nicht von Belang.

Autor: Thomas O. (kosmos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn alle LEDs leuchten deutet das darauf hin das die Pullups noch nicht 
deaktiviert wurden, so liegt an jedem Pin über den internen Pullup die 
Versorgungsspannung an. Such mal nach PUD im Datenblatt oder unter I/Os 
steht auch was dazu

Autor: Dimon11/09 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl heinz Buchegger

Ich mag diese Schreibweise auch, genau aus dem Grund, dass der Code sein 
eigener Kommentar ist. Hab mich aber mal böse auf die Schnauze damit 
gelegt.

Hab versucht so die Pins zu setzen, es ging um WGM02-Bit. AVR-Studio hat 
es einfach nicht gesetzt in TCCR0A und in TCCR0B (wo es sich normaler 
weise befindet) hat es gemeckert, dass es dort nicht vorhanden ist. Mit 
TCCR0B = 0x08 hat prima funktioniert.

Gruß.

Autor: Dimon11/09 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal andere Frage:

Hab die Zeile    data = ADCW;   auf   data = ADCW/1024;

und              ADMUX = (1<<REFS1)|(0<<REFS0);  // 1,1V Ref   auf

                 ADMUX = (0<<REFS1)|(0<<REFS0);  // Vcc  Ref

ersetzt.

Mann könnte meinen dass bei Vcc = 5V und 5V an PA7    data ~5 ist. 
Allerdings ist das bei mir nur bei:

                                     data = ADCW/176;

Was habe ich übersehen bzw. wo könnte der Denkfehler sein?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Überleg mal wie groß dein maximaler Wert für
ADCW werden kann! Tip: 10Bit

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dimon11/09 schrieb:
> @Karl heinz Buchegger
>
> Ich mag diese Schreibweise auch, genau aus dem Grund, dass der Code sein
> eigener Kommentar ist. Hab mich aber mal böse auf die Schnauze damit
> gelegt.
>
> Hab versucht so die Pins zu setzen, es ging um WGM02-Bit. AVR-Studio hat
> es einfach nicht gesetzt in TCCR0A und in TCCR0B (wo es sich normaler
> weise befindet) hat es gemeckert, dass es dort nicht vorhanden ist. Mit
> TCCR0B = 0x08 hat prima funktioniert.

Die Schreibweise

    TCCR0B = ( 1 << WGM02 );

ist nur eine andere Schreibweise für

    TCCR0B = 0x08;

Wenn WGM02 als
#define WGM02   3
definiert ist, dann gibt es aus C-Sicht keinen Unterschied zwischen den 
beiden Schreibweisen. Beides produziert identischen Code!

Das ist ungefähr so, wie wenn du schreiben würdest
   seconds_per_day = 86200;

und
#define SEC_PER_MIN  60
#define MIN_PER_HOUR 60
#define HOUR_PER_DAY 24

   seconds_per_day = (long)SEC_PER_MIN * (long)MIN_PER_HOUR * (long)HOUR_PER_DAY;

wären fundamental unterschiedlich.
In der zweiten Version sieht man viel besser, wie sich der Zahlenwert 
zusammensetzt (BTW: Hast du bemerkt, dass ich mich mit den 86200 
verrechnet habe :-)


Wenn also dein AVR-Studio-Simulator angezeigt hat, dass das Bit nicht 
gestezt wurde, dann war irgendetwas anderes faul.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.