ADC schwierigkeiten Mega8

OP #1202799
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
#1202807
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.
OP #1202839
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 ?
Gast #1202870
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.
#1202873
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
OP #1202924
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 !!!
#1202955
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.
OP #1202971
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 ?
Gast #1202977
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...

...
#1203000
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.
Gast #1203055
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
(Firma: Wolftec GmbH) #1213105
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
Gast #1213157
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.

...
(Firma: Wolftec GmbH) #1214324
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 :-)
#1214343
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren