www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC schwierigkeiten Mega8


Autor: Ayran Bahamas (habot)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hakan Nidya wrote:

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

??

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Ayran Bahamas (habot)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ayran Bahamas (habot)
Datum:

Bewertung
0 lesenswert
nicht 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 !!!

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>muss dann das so ausehen ?

Ja

>falls fehler drin sind bitte sagen !!!

void Funktionen koennen kein return 0 zurueckgeben

Autor: Ayran Bahamas (habot)
Datum:

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

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ayran Bahamas (habot)
Datum:

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

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum schreibst du nicht einfach beim Aufruf

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

Autor: Ayran Bahamas (habot)
Datum:

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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

;-)

...

Autor: Ayran Bahamas (habot)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

...

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: MWS (Gast)
Datum:

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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ayran Bahamas (habot)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ey ihr habt auch nix anderes zu tuhen ne ^^

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

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

Autor: Wolfgang Beppler (Firma: Wolftec GmbH) (wbeppler)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

...

Autor: twin_mbj (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
laut DAtenblatt kein ADC auf diesem uC!

Autor: Johannes M. (johnny-m)
Datum:

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

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

...

Autor: Wolfgang Beppler (Firma: Wolftec GmbH) (wbeppler)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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).

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.