Forum: Mikrocontroller und Digitale Elektronik ADC schwierigkeiten Mega8


von Ayran B. (habot)


Lesenswert?

Hallo,
ich habe mir schon viele Beiträge gelesen aber nicht eine lösung 
gefunden.
Das tutorial habe ich auch durch geackert und auch den teil wo es um ADC 
geht verstanden doch irgendwie weis ich nicht wie ich mein problem löse.
Möchte so gern einen LIPOLY saver machen, also der adc soll bei einer 3v 
niedrigen spannung (einer lipolyzelle) einen pin der auf 1 gestellt war 
auf 0 stellen.

z.info:
-Ich programmiere auf c
-Mein µc ist Mega8
-Pin PC5 wird alls adc eingang genommen

Quellcode:
     #include <avr/io.h>
     int main ()
     {
     uint16_t ReadChannel(uint8_t mux)
     {
       mux = 0x05;
       uint8_t i;
       uint16_t result;

       ADMUX = mux;          // Kanal waehlen
       ADMUX |=  (1<<REFS0); // AVCC als Referenz

       ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);

       /* Dummy-Readout um den ADC "warmlaufen zu lassen" */
       ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung
       while ( ADCSRA & (1<<ADSC) ) {
          ;     // auf Abschluss der Konvertierung warten
       }
       result = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.

       /* Eigentliche Messung-Mittelwert aus 4 aufeinanderfolgenden 
Wandlungen */
       result = 0;
       for( i=0; i<4; i++ )
       {
         ADCSRA |= (1<<ADSC);            // eine Wandlung "single 
conversion"
         while ( ADCSRA & (1<<ADSC) ) {
           ;   // auf Abschluss der Konvertierung warten
         }
         result += ADCW;        // Wandlungsergebnisse aufaddieren
       }
       ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)

       result /= 4;                     // Summe durch vier teilen = 
arithm. Mittelwert

       return result;
     }
     return 0;
     }

MFG
HaBot

von Johannes M. (johnny-m)


Lesenswert?

Erstens solltest Du die Codeformatierung und vernünftige Einrückungen 
benutzen, dann kann man den Code auch vernünftig lesen.

Zweitens solltest Du auch mal erzählen, was denn jetzt nicht so 
funktioniert, wie Du Dir das vorstellst. Ich sehe da nur einen 
(möglicherweise aus dem AVR-GCC-Tutorial kopierten) Code, aber keine 
konkrete Fragestellung, auf die man eine Antwort geben könnte.

von Justus S. (jussa)


Lesenswert?

Hakan Nidya wrote:

>      #include <avr/io.h>
>      int main ()
>      {
>      uint16_t ReadChannel(uint8_t mux)
>      {
>       ...
>        return result;
>      }
>      return 0;
>      }

??

von Johannes M. (johnny-m)


Lesenswert?

Au ja, ein Buch zum Thema C ist da auch unabdingbar! So genau hatte ich 
mir das aufgrund der tollen Formatierung noch gar nicht angesehen.

V.a. sollte er mal was zum Thema Funktionen lesen...

von Ayran B. (habot)


Lesenswert?

#include <avr/io.h>
int main ()
{
uint16_t ReadChannel(uint8_t mux)
{
 ...
  return result;
}
DDRB = 0x01;
PORTB = 0x01;

if(//adc messung wen 3 v ist)
PORTB = 0x00;

return 0;
}


es soll halt wen die messung der zelle auf 3v ist den pin PB0 auf 0 
sätzten.
Ich weis nicht wie ich das mit dem adc machen muss ?

von MWS (Gast)


Lesenswert?

Würd' sagen, Du hast von C Programmierung keinerlei Ahnung, an Deiner 
Stelle würde ich also erst mal den Aufbau und die Funktionsweise eines C 
Programms lernen.

ReadChannel ist eine Funktion, die aus der main aufgerufen wird, aber 
selbst drin nix zu suchen hat. Den Rückgabewert aus ReadChannel 
verarbeitet man dann in der main sinnvoll weiter.

Aber wie gesagt, lern erst mal C, nur mit zusammenkopieren wird das nix.

von Helmut L. (helmi1)


Lesenswert?

Du kannst es mal so versuchen.

x = dein ADC Channel

void main(void)
{
  DDRB = 0x01;
  while(1)
  {
    if(ReadChannel(x) > 614)
    {
      PORTB |= 0x01;
    } else
    {
      PORTB &= 0xfe;
    }
  }
}

Die 614 entsprechen deinen 3V.

Andere Werte kannst du so berechnen:

                 ADCBEREICH(1024)
Vergleichswert = ---------------- * Schaltschwelle (3V)
                  URef (5V =AVCC)

Gruss Helmi

von Ayran B. (habot)


Lesenswert?

#include <avr/io.h>

uint16_t ReadChannel(uint8_t mux)
{
  mux = 0x05;
  uint8_t i;
  uint16_t result;


  ADMUX = mux;
  ADMUX |=  (1<<REFS0);

  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);

  ADCSRA |= (1<<ADSC);
  while ( ADCSRA & (1<<ADSC) )
  {
     ;
  }
  result = ADCW;

  result = 0;
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);
    while ( ADCSRA & (1<<ADSC) )
    {
      ;
    }
    result += ADCW;
  }
  ADCSRA &= ~(1<<ADEN);
  result /= 4;
  return result;
}
void main(void)
{
  DDRB = 0x01;
  while(1)
  {
    if(ReadChannel(mux) > 614)
    {
      PORTB |= 0x01;
    } else
    {
      PORTB &= 0xfe;
    }
  }
return 0;
}

muss dann das so ausehen ?
falls fehler drin sind bitte sagen !!!

von Helmut L. (helmi1)


Lesenswert?

>muss dann das so ausehen ?

Ja

>falls fehler drin sind bitte sagen !!!

void Funktionen koennen kein return 0 zurueckgeben

von Ayran B. (habot)


Lesenswert?

aber das mit mus in if ist richtig ne.
ja dann muss ich das return wert auf 1 sätzen ne ?

von Helmut L. (helmi1)


Lesenswert?

>uint16_t ReadChannel(uint8_t mux)
>{
>  mux = 0x05;


Hiermit ueberschreibst du den Parameter mux

Und in deiner main Funktion gibt es die Variable mux nicht

von Helmut L. (helmi1)


Lesenswert?

>aber das mit mus in if ist richtig ne.

Aus diesem Satz werde ich nicht so richtig schlau

>ja dann muss ich das return wert auf 1 sätzen ne ?

Weder auf 1 oder sonst noch was. Lass das return ganz einfach weg.

von Ayran B. (habot)


Lesenswert?

also muss ich das mux = 0x05; global machen ne damit der damit was 
anfangen kann.

von Helmut L. (helmi1)


Lesenswert?

warum schreibst du nicht einfach beim Aufruf

if( ReadChannel(0x05) > 614)
....

von Ayran B. (habot)


Lesenswert?

aber die 0x05 sollen ADC5 sein also ist es so richtig ?

von Johannes M. (johnny-m)


Lesenswert?

main ist standardmäßig int und nicht void. Und eine Funktion vom Typ 
void kann nunmal keinen Wert zurückgeben.

Und wenn Du schon einen Funktionsaufruf zum Auslesen eines ADC-Kanals 
schreibst, dann übergib der Funktion doch einfach die Kanalnummer als 
Dezimalzahl, also nicht 0x05, sondern einfach 5. Macht das ganze besser 
lesbar.

von Hannes Lux (Gast)


Lesenswert?

> also nicht 0x05, sondern einfach 5. Macht das ganze besser lesbar.

In HEX sieht es aber intelligenter aus, daran erkennt man den 
Mais-Teer...

;-)

...

von Ayran B. (habot)


Lesenswert?

haha ^^

#include <avr/io.h>

uint16_t ReadChannel(uint8_t mux)
{
  mux = 5;
  uint8_t i;
  uint16_t result;


  ADMUX = mux;
  ADMUX |=  (1<<REFS0);

  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);

  ADCSRA |= (1<<ADSC);
  while ( ADCSRA & (1<<ADSC) )
  {
     ;
  }
  result = ADCW;

  result = 0;
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);
    while ( ADCSRA & (1<<ADSC) )
    {
      ;
    }
    result += ADCW;
  }
  ADCSRA &= ~(1<<ADEN);
  result /= 4;
  return result;
}
int main(void)
{
  DDRB = 0x01;
  while(1)
  {
    if(ReadChannel(5) > 614)
    {
      PORTB |= 0x01;
    }
  PORTB = 0x00;
  }

}
also so sollte es richtig sein ?

von Hannes Lux (Gast)


Lesenswert?

Achja, noch ein Tip für Hakan:

ADMUX enthält drei verschiedene Dinge:
- Auswahl der Referenzspannung
- Formatierung der Ausgabe
- Auswahl des Mess-Eingangs

Solange Du die Bits der drei Dinge nicht zu einem Byte zusammenfasst, 
ehe Du sie in einem Rutsch in das Register ADMUX schreibst, löscht Du 
bei jedem Schreiben die zuvor geschriebenen Bits.

Klar man kann es auch verodern und veranden, aber das vorherige 
Zusammenfassen halte ich für einfacher.

Einen Codefetzen bekommst Du von mir nicht, denn ich kann genausowenig C 
wie Du. Ich werkele daher in ASM...

...

von Helmut L. (helmi1)


Lesenswert?

@Hannes
>In HEX sieht es aber intelligenter aus, daran erkennt man den
>Mais-Teer...

Wenn schon dann in Oktal. Daran erkennt man den Programmieren alter 
Schule.

  while(1)
  {
    if(ReadChannel(5) > 614)
    {
      PORTB |= 0x01;
    }
  PORTB = 0x00;
  }

Du hast das else vergessen. So wird der Port zwar gesetzt aber ruckzuck 
wieder geloescht.

von Johannes M. (johnny-m)


Lesenswert?

Oh, der OP hat sich auf die Schnelle umtaufen lassen...

@Ayran-Hakan-wasauchimmer:
Du überschreibst in der Funktion immer noch den übergebenen Parameter 
mux!

von MWS (Gast)


Lesenswert?

Das ist die neue evolutionäre Programmiertechnik durch Raten, nach 2^16 
Iterationen kommt ein Programm raus.

von Johannes M. (johnny-m)


Lesenswert?

MWS wrote:
> Das ist die neue evolutionäre Programmiertechnik durch Raten, nach 2^16
> Iterationen kommt ein Programm raus.
Halte ich für ein Gerücht. Mit 2^16 kommste nicht hin...

von MWS (Gast)


Lesenswert?

Johannes,

darfst nicht den korrigierenden Einfluss der Forumsmitglieder vergessen, 
unter Berücksichtigung dessen halte ich 2^16 für möglich.

Leider stört dieser Einfluss gleichzeitig die natürliche Evolution und 
verhindert sehr wahrscheinlich, daß statt des ursprünglich gedachten 
Codes eine ganz wunderbare neue Schöpfung mit ungeahnten Möglichkeiten 
entsteht :D

von Ayran B. (habot)


Lesenswert?

ey ihr habt auch nix anderes zu tuhen ne ^^

von Helmut L. (helmi1)


Lesenswert?

>> Das ist die neue evolutionäre Programmiertechnik durch Raten, nach 2^16
>> Iterationen kommt ein Programm raus.
>Halte ich für ein Gerücht. Mit 2^16 kommste nicht hin...

Schliesslich sind wir im Zeitalter der 32 Bit Controller.

also dann 2^32

Gruss Helmi

von Johannes M. (johnny-m)


Lesenswert?

Helmut Lenzen wrote:
> Schliesslich sind wir im Zeitalter der 32 Bit Controller.
Das ist ja total ARM...

von Wolfgang B. (Firma: Wolftec GmbH) (wbeppler)


Lesenswert?

wow,

ich hab auch probleme mit analogwert auslesen, doch wie man in dem forum 
fertig gemacht wird wenn man was nicht weiss, da trau ich mich kaum.

dennoch

ich hab heute nach langem probieren mein SDK500 und studio 4 zum laufen 
gekriegt und krieg auch schon DI und DO mit den tastern und LED's hin.

nun versuche ich seit stunden nen analogen wert zu bekommen und der 
compiler meckert (zurecht) undeclared, undeclared, ... ADMUX ..., 
undeclared.

wo bitte finde ich was ich alles includen muss ? auf dem board steckt 
ein 8515L und was ich mal brauchen werde weiss ich noch nicht. doch nen 
analogwert holen weiss ich nicht mal richtig welchen pin.

ich bitte um hilfe, nicht um "lies mal ein buch ueber C", das hab ich 
schon bestellt (obwohl ich C etwas kann und gar nicht viel will)

wie krieg ich nen analogwert moeglichst einfach in ne variable ??????
welche includes, bitte einfach, ich weiss dass ich nicht viel weiss, 
danke !

gruss und dank

wolfgang :-)

PS: wenn ich es wueste, waehr ich nicht hier

von Hannes Lux (Gast)


Lesenswert?

Wie wäre es denn mit dem AVR-GCC-Tutorial hier auf dieser Seite?

Oder einfach mal in der Linksammlung nach Projekten anderer Leute suchen 
und mal in deren Quelltexte schaun, wie die das machen?

In ASM könnte ich Dir helfen, in C leider nicht. C ist mir zu komplex, 
obwohl ich DAS C-Buch (K&R) habe und auch gelegentlich reinschaue.

...

von twin_mbj (Gast)


Lesenswert?

laut DAtenblatt kein ADC auf diesem uC!

von Johannes M. (johnny-m)


Lesenswert?

twin_mbj wrote:
> laut DAtenblatt kein ADC auf diesem uC!
Richtig! Weder der AT90S8515 noch der ATMega8515 hat einen ADC.

von Hannes Lux (Gast)


Lesenswert?

Stimmt, hatte ich überlesen, sorry, ging vom Betreff aus, also vom 
Mega8. Und der hat ADC...

Ein Blick ins Datenblatt hätte vermutlich auch geholfen.

...

von Wolfgang B. (Firma: Wolftec GmbH) (wbeppler)


Lesenswert?

ihr habt ja recht,

im datenblatt steht es, ich habs nur nicht zu lesen gewusst weil im 
studio4 bei dem controller ja alnalogfunktionen gezeigt werden, das mit 
dem komperator (irgend eines der vielen tutorials die ich gelesen habe) 
dachte ich ist dann immer so bei den atmegas.

ich steig noch nicht recht durch, deshalb eine bitte:

taugt das buch "AVR hardware und C-programmierung in der praxis" vom 
elektor-verlag was ? kennt das jemand ? ist das mit stk500 und C und hat 
es vor allem analog-beispiele ??

bis dahin mach ich noch bissele weiter mit dem duemilenova denn in 
arduino krieg ich es auch in.

danke nochmal an alle antworten !

gruss

wolfgang :-)

von Johannes M. (johnny-m)


Lesenswert?

Wolfgang Beppler wrote:
> ihr habt ja recht,
>
> im datenblatt steht es, ich habs nur nicht zu lesen gewusst weil im
> studio4 bei dem controller ja alnalogfunktionen gezeigt werden, das mit
> dem komperator (irgend eines der vielen tutorials die ich gelesen habe)
> dachte ich ist dann immer so bei den atmegas.
Ist es auch. Aber der Analog- Komparator ist etwas ganz anderes als 
der Analog-Digital-Wandler! Ich wüsste keinen einzigen AVR, der keinen 
Analog-Komparator hat, aber einen ADC haben nicht alle (auch wenn es 
mittlerweile kaum noch welche ohne gibt).

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.