mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Spannungen vergleichen


Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ien C Programm geschrieben, welches 2 Spannungen mittel sdes 
internen Komperator vergleicht.
Kompilieren klappt, aber könntet Ihr trotzdem mal drüberschauen?
Habe es mit der Hilfe von dem Tutorila erstellt.
#include <avr/io.h>
#include <stdint.h>

int main (void)
{
ACSR &= ~(1<<ACD) | (1<<ACBG);  //ACE einschalten und externe Ref Spannung
DDRB |= (1<<DDB0);       //DDRB als Ausgang


while (1)
  {
  if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
    PORTB |= (1<<PB0);    //PORT B auf einschalten
  }
 


}


Danke

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und wann soll Port B wieder ausgehen?

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

gute Frage :-).
Wenn ACO also IST > SOLL.
Würde es gerne so machen, das wenn ACO = 1 (IST < SOLL) dann PB0 
einschalten (grüne LED brennt), und wenn ACO = 0, dann PB1 einschalten 
(rote LED).

Habe das mal programmiert:
#include <avr/io.h>
#include <stdint.h>

int main (void)
{
ACSR &= ~(1<<ACD) | (1<<ACBG);  //ACE einschalten und externe Ref Spannung
DDRB |= (1<<DDB0) | (1<<DDB1);       //DDRB als Ausgang


while (1)
  {
  if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
    PORTB |= (1<<PB0);    //PORT B0 auf einschalten
    PORTB &=~(1<<PB1);    //und B1 auf 0
  else                   //wenn IST > SOLL
    PORTB |= (1<<PB1);  //B1 einschalten
    PORTB &=~(1<<PB0);  //B0 ausschalten( auf 0)
  
  
  
  }
 


}


LG

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:

>
>   if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
>

Da gibt es 2 Fallen:
  Operatorenreihenfolge
  Der linke Teilausdruck muss nicht notwendigerweise 1 ergeben
  (nach der Syntaxkorrektur)

Der C-Compiler sieht diesen Ausdruck als
    ACSR & ( (1 << AC0) == 1 )
und das ist nicht ganz das was du haben willst. Du willst
    ( ACSR & (1 << AC0) ) == 1



Generell: Lass diese Vergleiche mit == 1 oder != 1 überhaupt weg. Die 
funktionieren nämlich meistens sowieso nicht, es sei denn AC0 ist 
zufällig genau 1
   if( ACSR & (1<<AC0) )
macht das Gewünschst und du laufst nicht Gefahr, dass dir da die 
Operatorenreihenfolge reinpfuscht. Die Umkehrung allerdings erfordert 
eine Klammer mehr
   if( !(ACSR & (1<<AC0) ) )
allenfalls, wenn du explizit sein möchtest, kannst du noch schreiben
    if( ( ACSR & (1<<AC0) ) == 0 )    // Bit nicht gesetzt
    if( ( ACSR & (1<<AC0) ) != 0 )    // Bit gesetzt
aber hüte dich davor, anzunehmen dass bei gesetztem Bit der ganze linke 
Ausdruck dann zu 1 wird! Das wird er nämlich nicht.

Nicht umsonst ist die C Definition für logisch wahr: alles was nicht 0 
ist. Daher: derartige Auswertungen immer so formulieren, dass auf 0 
Bezug genommen wird.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
>
>   if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
>     PORTB |= (1<<PB0);    //PORT B0 auf einschalten
>     PORTB &=~(1<<PB1);    //und B1 auf 0
>   else                   //wenn IST > SOLL
>     PORTB |= (1<<PB1);  //B1 einschalten
>     PORTB &=~(1<<PB0);  //B0 ausschalten( auf 0)

Einrückungen zu machen reicht nicht aus, um dem Compiler zu sagen, dass 
die ersten 2 Zeilen zum "if" gehören und die anderen zum "else".

Richtig wäre Klammerung mit "{" und "}'":
  if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
  {
    PORTB |= (1<<PB0);    //PORT B0 auf einschalten
    PORTB &=~(1<<PB1);    //und B1 auf 0
  }
  else                   //wenn IST > SOLL
  {
    PORTB |= (1<<PB1);  //B1 einschalten
    PORTB &=~(1<<PB0);  //B0 ausschalten( auf 0)
  }

> Habe das mal programmiert:

Was verstehst Du unter "programmieren"? Zumindest ein compilieren sollte 
schon dazugehören, um festzustellen, ob wenigstens syntaktisch alles in 
Ordnung ist. Deine Version kann eigentlich kein Compiler schlucken, weil 
dieser das "if" zum "else" ohne Klammern gar nicht finden kann...

Gruß,

Frank

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe in einem C-Buch nachgeschaut.
Wenn ich nach dem if nur einen Befehl habe, dann brauche ich keine 
Klammern, da ich aber zwei Zeilen habe, brauche ich bei if und auch bei 
else klammern, oder nicht?
Wenn ich es bei AVR Studio durchlaufen lasse, dann bekomme ich weder 
Fehler noch Warnungen, dann müsste es doch laut Compiler syntaktisch 
richtig sein, oder?
Aber es geht ja auch um die Funktion. Würde es so wie ich es geschrieben 
haben funktionieren, oder habe ich wasa grundlegendes falsch gemacht 
oder vergessen?

LG

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
> Hallo,
>
> habe in einem C-Buch nachgeschaut.
> Wenn ich nach dem if nur einen Befehl habe, dann brauche ich keine
> Klammern, da ich aber zwei Zeilen habe, brauche ich bei if und auch bei
> else klammern, oder nicht?


Ja
Und zwar deshalb, weil das hier

   {
      Anweisung
      Anweisung
      Anweisung
      ...
   }

(also eine Abfolge von Anweisungen eingeshlossen in { }, ein sog. Block) 
selbst wieder als eine Anweisung gilt.

Die Syntax vom if ist ganz einfach

   if( Ausdruck )
     Anweisung

Es kann also nur eine einzige Anweisung innerhalb des auszuführenden 
Teils geben. Aber man kann ja einen Block benutzen um eine Abfolge von 
Anweisungen als nur eine einzige Anweisung zu verkaufen.

> Wenn ich es bei AVR Studio durchlaufen lasse, dann bekomme ich weder
> Fehler noch Warnungen, dann müsste es doch laut Compiler syntaktisch
> richtig sein, oder?

Im letzten Fall nicht. Und zwar deshalb, weil die vollständige if-Syntax 
lautet

   if( Ausdruck )
     Anweisung
   else
     Anweisung

(wobei der else Teil auch entfallen kann)

Bei dem was du geschrieben hast, hängt das else aber in der Luft.
Das wird der Compiler monieren.

> Aber es geht ja auch um die Funktion. Würde es so wie ich es geschrieben
> haben funktionieren, oder habe ich wasa grundlegendes falsch gemacht
> oder vergessen?

Siehe weiter oben

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

verstehe ich nicht so ganz.
Durch meine Klammern, bei if und bei else, sage ich Ihm, dass es ein 
Block von Anweisungen ist, die werden doch dann beide abgearbeitet, 
oder?
Warum hängt else in der Luft?
Wenn die if Bedingung nicht zutrifft, dann wechselt er doch in den else 
Teil.
also wenn die Spannungen so sind, dann mache das ansonsten mach das.

Oder soll ich zwei If - Schleifen untereinander machen?


LG

Autor: Sven aus D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ein beispiel:

if(D)
 B=1;
 C=1;

wenn du das so machst meckert kein compiler. nur mach der daraus das 
hier:

if(D)
{
 B=1;
}

C=1;

das heißt das C=1 nicht mehr in der if ist und immer(!) nach der if 
abfrage ausgeführt wird.
der nimmt nur die erste zeile, die weiteren sind dann eigene befehle...
also bei einem oder mehr immer klammern setzen!

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
> Hallo,
>
> verstehe ich nicht so ganz.
> Durch meine Klammern, bei if und bei else, sage ich Ihm, dass es ein
> Block von Anweisungen ist, die werden doch dann beide abgearbeitet,
> oder?

Du hast aber keine Klammern gemacht.

Zitat
   if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
     PORTB |= (1<<PB0);    //PORT B0 auf einschalten
     PORTB &=~(1<<PB1);    //und B1 auf 0
   else                   //wenn IST > SOLL
     PORTB |= (1<<PB1);  //B1 einschalten
     PORTB &=~(1<<PB0);  //B0 ausschalten( auf 0)

Für den COmpiler ist das

   if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
     PORTB |= (1<<PB0);    //PORT B0 auf einschalten

   PORTB &=~(1<<PB1);    //und B1 auf 0

   else                   //wenn IST > SOLL
     PORTB |= (1<<PB1);  //B1 einschalten

   PORTB &=~(1<<PB0);  //B0 ausschalten( auf 0)

Das ist ist daher mit dem
     PORTB |= (1<<PB0);    //PORT B0 auf einschalten
zu Ende. Das
   PORTB &=~(1<<PB1);    //und B1 auf 0
gehört schon nicht mehr dazu.

Aber: Zu welchem if gehört denn jetzt das else. Da ist kein if mehr zu 
dem es gehören könnte. Denn das if war ja schon nach dem
     PORTB |= (1<<PB0);    //PORT B0 auf einschalten
zu Ende.

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist mir klar, aber ich habe doch Klammern gesetzt, sowohl bei if und 
auch bei else, oder?

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
> Das ist mir klar, aber ich habe doch Klammern gesetzt, sowohl bei if und
> auch bei else, oder?

Wo?

Schau dir doch noch einmal deinen Code an!
while (1)
  {
  if (ACSR & (1<<ACO)==1)    //wenn IST < SOLL
    PORTB |= (1<<PB0);    //PORT B0 auf einschalten
    PORTB &=~(1<<PB1);    //und B1 auf 0
  else                   //wenn IST > SOLL
    PORTB |= (1<<PB1);  //B1 einschalten
    PORTB &=~(1<<PB0);  //B0 ausschalten( auf 0)
  }

Wo sind da die beiden Anweisungen die vom if abhängen sollen mit einer { 
} geblockt worden?

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>
#include <stdint.h>

int main (void)
{
ACSR &= ~(1<<ACD) | (1<<ACBG);  //ACE einschalten und externe Ref Spannung
DDRB |= (1<<DDB0) | (1<<DDB1);       //DDRB als Ausgang


while (1)
  {
  if ((ACSR & (1<<ACO))==1)   //wenn IST < SOLL
    {
    PORTB |= (1<<PB0);    //PORT B auf einschalten
    PORTB &=~(1<<PB1);
    }
  else
    {
    PORTB |= (1<<PB1);
    PORTB &=~(1<<PB0);
    }
  }
}


Also so?

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:

> Also so?

Ja.

Aber wenn ich dir einen Formatiertip geben darf.
Lass die { } auf derselben Einrückungstiefe, wie die Anweisung 
deretwegen du sie gemacht hast und rücke nach der { um 2 Zeichen ein und 
beim } wieder um 2 Zeichen aus.
int main (void)
{
  ACSR &= ~(1<<ACD) | (1<<ACBG);  //ACE einschalten und externe Ref Spannung
  DDRB |= (1<<DDB0) | (1<<DDB1);       //DDRB als Ausgang


  while (1)
  {
    if ((ACSR & (1<<ACO))==1)   //wenn IST < SOLL
    {
      PORTB |= (1<<PB0);    //PORT B auf einschalten
      PORTB &=~(1<<PB1);
    }
    else
    {
      PORTB |= (1<<PB1);
      PORTB &=~(1<<PB0);
    }
  }
}

So ist es optisch einfacher, die zu einem } gehörende öffnende { zu 
finden. Die { und  } gehen dann nicht so leicht unter.

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

Bewertung
0 lesenswert
nicht lesenswert
Und lies dir das hier
Beitrag "Re: Spannungen vergleichen"
noch einmal durch!

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe jetzt alles mal auf meinem Breadboard aufgebaut und zwei 
verschiedene Spannungen drangelegt.
Die Spannung an AIN0 (SOLL) hat ca. 2,4V und die Spannung an AIN1 hat 
1,8V.
Das heißt Soll>IST und somit soll er doch laut meinem Code den Ausgang 
PB0 schalten, aber er setzt PB1 auf eins, es brennt die andere LED.
Wo ist der Denkfehler?

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

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht dein Code jetzt aus?

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

so:
#include <avr/io.h>
#include <stdint.h>

int main (void)
{
ACSR &= ~(1<<ACD) | (1<<ACBG);  //ACE einschalten und externe Ref Spannung
DDRB |= (1<<DDB0) | (1<<DDB1);       //DDRB als Ausgang


while (1)
  {
  if (ACSR & (1<<ACO))   //wenn IST < SOLL   (1)
    {
    PORTB |= (1<<PB0);    //PORT B auf einschalten
    PORTB &=~(1<<PB1);
    }
  else
    {
    PORTB |= (1<<PB1);
    PORTB &=~(1<<PB0);
    }
  }
}

Bemerkung: Habe bei (1) die Null bzw. 1 weggemacht, jetzt macht er es 
richtig.

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe da noch was, ich würde gerne den AD Wandler benutzen.
Also erstmal testen. Ich habe da an eine Schaltung gedacht, wo ich 8 
LED´s ansteuere.
Die erste hat die Wertigkeit 2^0, 2^1 usw.
damit möchte ich dann die Zahl 256 darstellen, also 8 Bit.
Hat das jemand schon gemacht, oder habt Ihr eine andere Idee, wie ich 
einen Einstieg in den AD Wandler bekomme (Tutorial habe ich schon 
gelesen), ich hätte gerne ein Bsp. Programm, an dem ich noch testen 
kann.

LG

Wollte dafür keinen neuen Beitrag schreiben, hoffe es ist O.K..

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

Bewertung
0 lesenswert
nicht lesenswert
Das hier

ACSR &= ~(1<<ACD) | (1<<ACBG);  //ACE einschalten und externe Ref 
Spannung

macht nicht das was du denkst.

Ironischerweise ist der ADC von Haus schon so konfiguriert, dass er 
genau das macht, was du eigentlich erreichen willst:
  Er ist eingeschaltet   und
  er vergleicht die Pins AIN0 und AIN1 miteinander

Wenn du ihn also einfach nur in Ruhe gelassen hättest, hättest du das 
gewünschte Ergebnis.


Mit obigen schaltest du den ADC so, dass die Referenzspannung die 
interne Referenz ist.

  ~(1<<ACD) | (1<<ACBG)

wird vom Compiler geparst als

  (~(1<<ACD)) | (1<<ACBG)

du bräuchtest aber:

   ~( (1<<ACD) | (1<<ACBG) )

Daher noch einmal der Aufruf: Wenn du dir über Opertorenreihenfolge 
nicht sicher bist, dann verwende Klammern!

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:

> einen Einstieg in den AD Wandler bekomme (Tutorial habe ich schon
> gelesen)

und, wo ist dann das Problem.
Im Tutorial gibt es eine schöne Routine, die dir den Wert vom AD Wandler 
holt. Was du dann mit dem Wert machst bleibt deiner Phantasie 
überlassen.

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, aber es fängt ja schon beim Schaltungsaufbau an.
Verbessert mich bitte.
Also ich würde ein Poti an PA0 z.B. anschliessen.
5V auf das Poti und die Spannung die an PA0 ankommt über den AD Wandler 
wandeln, mit 8 Bit aber, damit die Zahl nicht so riesig wird (wie ich 
mit 8 Bit anstatt 10 wandle, ist mir aber auch noch nicht klar).
Dann kann ich ja sagen, 5V / 256 = 19,53 mV. Das sind ja dann meine 
Schritte, denen ich Zahlenwerte zuweisen kann, das wird im Tutorial 
genauso gemacht.
0-19,53mV = 0
19,53mV - 39,06mV = 1
usw.

Dann würde ich gerne aber diese Zahlen irgendwie da ich kein Display 
habe über LED´s ausgeben. 2^0, 2^1, 2^2 usw.
Da hängt es aber auch schon. (Schaltungs und Programmiertechnisch)


LG

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:

> Also ich würde ein Poti an PA0 z.B. anschliessen.
> 5V auf das Poti

Für den Anfang:
ARef an das Poti.
Und das andere Ende des Potis kommt an GND

> und die Spannung die an PA0 ankommt über den AD Wandler

Der MIttenabgriff des Potis kommt an PA0

> wandeln, mit 8 Bit aber, damit die Zahl nicht so riesig wird (wie ich
> mit 8 Bit anstatt 10 wandle, ist mir aber auch noch nicht klar).

Wandle mit 10 Bit. Was du hast, hast du. Die Zahl kleiner machen (zb 
indem man durch 4 dividiert) kann man immer noch.

> Dann kann ich ja sagen, 5V / 256 = 19,53 mV. Das sind ja dann meine
> Schritte, denen ich Zahlenwerte zuweisen kann, das wird im Tutorial
> genauso gemacht.
> 0-19,53mV = 0
> 19,53mV - 39,06mV = 1
> usw.

Gib für den Anfang einfach nur den Wert vom ADC (geteilt durch 4) an 
deine 8 Leds aus. Ohne Umrechnung, ohne irgendwas. Einfach nur
   PORTB = adc_wert / 4;

(adc_wert ist das Ergbnis welches dir die ADC-routine aus dem Tutorial 
gegeben hat)

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar,

dannist ja PA0 mein Eingang (AD-Wanlder Eingang) und die Ausgänge, die 
sind ja egal, ob ich B oder C nehmen, oder?

LG

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
> Alles klar,
>
> dannist ja PA0 mein Eingang (AD-Wanlder Eingang) und die Ausgänge, die
> sind ja egal, ob ich B oder C nehmen, oder?

Dort wo du LEDs drann hast

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

O.K., ist klar.
Habe jetzt mal aus dem Tutorial die ersten Zeieln übernommen und 
abgeändert.
Komme aber trotzdem nicht so richig weiter.
Hier mal der Quelltext:
#include <avr/io.h>
#include <stdint.h>

int main(void)
{
uint8_t i;
uint16_t adc_wert;



DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4)| (1 << DDB5) | (1 << DDB6) | (1 << DDB7); //Datenrichtung Ausgang

  ADMUX &= ~(1<<REFS1);//auf Null setzen
  ADMUX |= (1<<REFS0); // auf eins setzen wegen der exteren Ref Spannung
 
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
                               // setzen auf 8 (1) und ADC aktivieren (1)
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 

while ( ADCSRA & (1<<ADSC) ) {
     ;     // auf Abschluss der Konvertierung warten 
  }
  adc_wert = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.
adc_wert = 0; 
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
    adc_wert += ADCW;        // Wandlungsergebnisse aufaddieren
  }
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
 
  PORTB=adc_wert/4;                    // Summe durch vier teilen = arithm. Mittelwert
 
  
}

Habe halt ziemlich viel aus dem Tutorial genommen, weis aber nicht, ob 
es passt.
Jetzt muss ich doch irgendwie noch mehrere If abfragen reiinmachen, 
damit ich bei bestimmten Werten, die verschiedenen Ausgänge ansteuern 
kann, oder?
Gibt es da noch eine andere Lösung, wie ich das machen kann?
Ist ja ganz schöne Schreibarbeit.
Verstehe es auch nicht so ganz, warum ich den Mittelwert bilden soll, 
wegen der Genauigkeit oder warum?
Ich habe mir jetzt hier auf einem Blatt mal angefangen die Werte 
aufzuschreiben, 0V-...V = 0 usw.
Das sind ja ziemlich viele Werte, muss ich jetzt für jeden Wert den ich 
ausgeben will, eine Zeile schreiben?


LG

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
> Hallo,
>
> O.K., ist klar.
> Habe jetzt mal aus dem Tutorial die ersten Zeieln übernommen und
> abgeändert.

Warum tust du das?
Im Tutorial ist eine fix und fertige Funktion. Die musst du für deine 
ersten Schritte nur aus dem Tutorial per Cut&Paste in deinen Code 
einsetzen und in main() einen Aufruf der Funktion in die Hauptschleife 
einbauen.

Machst du dir selbst absichtlich das Leben schwer?

Zuerst nimmt man was man kriegen kann. Dann bringt man es zum Laufen. 
Und erst dann fängt man an, die Funktionen zu modifizieren.

> Ist ja ganz schöne Schreibarbeit.

Was ist an ...
#include <avr/io.h>

.... Hier die ReadChannel Funktion aus dem Tut per Cut&Paste

int main()
{
  DDRB = 0xFF;

  while( 1 )
  {
    PORTB = ReadChannel( 0 ) / 4;
  }
}

... viel Schreibarbeit?

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh man, das ist ja ienfach als ich gedacht habe.
Hier jetzt der Code mit der Funktion aus dem Tutorial und dem Aufruf in 
der main
#include <avr/io.h>
#include <stdint.h>

uint8_t i;
uint16_t adc_wert;


uint16_t ReadChannel(uint8_t mux)

{
  uint8_t i;
  uint16_t result;
 
  ADMUX = mux;                      // Kanal waehlen
  ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
 
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
                               // setzen auf 8 (1) und ADC aktivieren (1)
 
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, 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;
}

int main()
{
  DDRB = 0xFF;

  while( 1 )
  {
    PORTB = ReadChannel( 0 ) / 4;
  }
}

Mit Schreibarbeit habe ich das auswerten von dem Messwert gemeint.
Ich muss doch jetzt sagen, welchen Ausgang von PORTB ich ansteuern will, 
oder?

Ich glaube ich denke in eine falsche Richtung oder zu umständlich.

Sorry

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:

> Mit Schreibarbeit habe ich das auswerten von dem Messwert gemeint.
> Ich muss doch jetzt sagen, welchen Ausgang von PORTB ich ansteuern will,
> oder?

Für deine ersten Tests reicht es völlig dem PORTB als Ganzes ein neues 
Bitmuster zu verpassen.
Genau das macht diese Zuweisung :-)

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wollte noch mal fragen, mit dem anschliessen.
Ich gehe von der Spannungsquelle an das Poti und an den AREF.
Mit dem Poti GND gehe ich zum Pin 31, also der GND unter AREF.
Dann gehe ich mit den 5V an Pin 10 Vcc und Pin 11 GND.
Muss ich it dem GND vom POTI auch noch auf den GND von der 
Spannungsquelle gehen, oder sind die GND von Pin31 mit dem Pin 11 intern 
gebrückt?


MfG

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
> Hallo,
>
> wollte noch mal fragen, mit dem anschliessen.
> Ich gehe von der Spannungsquelle an das Poti und an den AREF.

Nein.
Du gehst nicht an den ARef.

Du schaltest den Mega per Software so (das macht die ReadChanel), dass 
der Mega seine Versorgungsspannung als Referenzspannung hernimmt. Diese 
Referenzspannung stellt dir der Mega freundlicherweise am Pin ARef zur 
Verfügung.

Du schaltest also ganz einfach nur das Poti an den ARef und der Mega 
beaufschlagt das Poti mir der Spannung.

> Mit dem Poti GND gehe ich zum Pin 31, also der GND unter AREF.
> Dann gehe ich mit den 5V an Pin 10 Vcc und Pin 11 GND.
> Muss ich it dem GND vom POTI auch noch auf den GND von der
> Spannungsquelle gehen, oder sind die GND von Pin31 mit dem Pin 11 intern
> gebrückt?


Du machst dir das jetzt kompliziert (und ich hab jetzt keine Lust das 
auseinanderzudröseln)
Stinknormale Prozessorbeschaltung, so dass er läuft: Alle GND mit GND 
der Spannungsquelle verbunden. Alle Vcc, AVcc mit Vcc der 
Spannungsquelle verbunden. BLockkondensatoren wie gehabt.

Also -> ganz normale Arbeitskonfiguration des Prozessors.

Dann nimmst du dein Poti.
Das eine Ende (der 3 Anschlüsse) kommt an GND, das andere Ende an ARef 
und der mittlere Potianschluss an PA0.

Achte noch darauf, dass an ARef ein 100n Kondensator zur Abblockung der 
vom Mega zur Verfügung gestellten Spannung ist, und schon kanns 
losgehen.

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe es angeschlossen, und es leuchtet nix.
Ich kann das Poti drehen wie ich will, da tut sich nix.
Verschaltung:
Poti:
Plus vom Poti über 100n an AREF
Mittelabgriff an PA0
GND an GND vom mC (Pin 31)

ATmega
Vcc von der Sapnnungsquelle
GND mit GND der Spannungsquelle verbunden (PIN 11)
PB0 bis PB7 über Widerstände an LEDs,

LED´s
Anode mC
Kathode GND von Spannungsquelle.


LG

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
>
> ATmega
> Vcc von der Sapnnungsquelle

Was ist mit AVcc?
AVcc versorgt den Port A (also den Port an dem die ADC sind) mit Saft

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da habe ich nix dran.
Wird Port A nicht durch den Mittelabgriff des Potis versorgt.
Ich habe mal angeschlossen und gemessen, am Ausgang von Port B habe ich 
eine Spannung anliegen. Vom Ausgnag PB0 bis zum Widerstand auch noch, 
aber auf der anderen Seite des Widerstandes ist 0 V.
Hat das was mit den internen Pull up Widerständen zu tun?
Kann das sein?

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Peter schrieb:
> Da habe ich nix dran.

Dann mal schnell.

> Wird Port A nicht durch den Mittelabgriff des Potis versorgt.

Nein.
AVcc liefert die Energie, damit der ADC überhaupt arbeiten kann. 
Arbeiten bedeutet dann, dass der ADC die Spannung misst, die an einem 
bestimmten Pin anliegt.

Das wäre wohl ein wenig fatal, wenn das Messgerät die zu messende Größe 
dadurch beeinflusst, indem die Messgröße auch noch das Messgerät 
versorgen muss.

> Hat das was mit den internen Pull up Widerständen zu tun?
> Kann das sein?

Nein.
SChliess endlich Avcc an.
Und dann liest du das Assembler Tutorial von Anfang an durch. Auch wenn 
du nicht Assembler programmierst, so finden sich darin viele Hinweise, 
die auch für dich als C-Programmierer wichtig sind.

Und ich klinke mich jetzt aus.

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

AVCC ist angeschlossen, habe auch noch einen Fehler im Prog gehabt, habe 
die interne Ref Spannung verwendet, was ja falsch ist, ich lege ja eine 
externe an.
Ich habe bis zu 5V an PCB0 aber einen Strom von 20mA. Die LED macht nix, 
nicht mal aufleuchten.


LG

Autor: Hans Peter (gableguy2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar,
es funktioniert, war mein Fehler.


Danke

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Und ich klinke mich jetzt aus.
Respekt für deine Engelsgeduld.

@Hans Peter:
Is nicht böse gemeint, aber n bisschen mehr Eigeninitiative wär schon 
angebracht gewesen.

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.