Forum: Mikrocontroller und Digitale Elektronik Spannung an Ausgangsports zu niedrig


von emit5 (Gast)


Lesenswert?

Hallo zusammen,

bin ein Anfänger und habe eine Frage.

Habe einen Atmega 644 und habe das Problem das ich mit dem ADC (Spannung 
messsen) LEDs ansteuern will. An den Ports habe ich aber immer 
Spannungen zwischen 0,6 V - 2,9 V als high Signal.

Habe einen ULN2804 dazwischen gesetzt inkl. Vorwiderstand für die LED.

Woran kann das liegen das die Spannung an den Ports so niedrig ist?

Bekomme keine vernünftige Leistung an die LEDs.

Laut Datenblatt müsste ein high Siganl mindestens 4,2 V haben.

von Simon D. (simon86)


Lesenswert?

emit5 schrieb:
> Habe einen Atmega 644 und habe das Problem das ich mit dem ADC (Spannung
> messsen) LEDs ansteuern will.

Benutzt du den Port (Pin) zum Einlesen einer Spannung oder möchtest du 
ein Signalpegel ausgeben, oder misst du mit einem Pin die Spannung und 
möchtest eine entsprechende Ausgabe über einen anderen Pin machen??

emit5 schrieb:
> Habe einen ULN2804 dazwischen gesetzt inkl. Vorwiderstand für die LED.

Wenn du "normale" LEDs nutzt kannst du sie mit Vorwiderstand direkt an 
den Pin schalten - entweder gegen Masse oder gegen Vcc.

Teile mal mit, welchen Pin / Port du nutzt und wie du ihn ansteuerst -> 
wahrscheinlich schreibst du die Register falsch. Hast du denn den 
Ausgangsport mal als einfache Blinkschaltung betreiben können??

von Tobi (Gast)


Lesenswert?

Du willst mit dem ADC eine LED ansteuern?
Sicher dass du den ATmega mit 5V betreibst und nich tnur mit 3,3V?
Beschaltung?

von Klaus W. (mfgkw)


Lesenswert?

ADC ist doch ein "AVR to Diode Converter"?

Im Ernst: das was dir fehlt, steht vermutlich auch großteils im 
Tutorial.

von emit5 (Gast)


Lesenswert?

Simon D. schrieb:
> Benutzt du den Port (Pin) zum Einlesen einer Spannung oder möchtest du
>
> ein Signalpegel ausgeben, oder misst du mit einem Pin die Spannung und
>
> möchtest eine entsprechende Ausgabe über einen anderen Pin machen??

Benutze PIN PA0 zum Einlesen der Spannung.

Zur Ausgabe des Ergebnisses benutze ich PD0- PD5.

Simon D. schrieb:
> Wenn du "normale" LEDs nutzt kannst du sie mit Vorwiderstand direkt an
>
> den Pin schalten - entweder gegen Masse oder gegen Vcc.

Habe ich probiert. Gab auch nur ein paar gedimmte LEDs.

Simon D. schrieb:
> Teile mal mit, welchen Pin / Port du nutzt und wie du ihn ansteuerst ->
>
> wahrscheinlich schreibst du die Register falsch. Hast du denn den
>
> Ausgangsport mal als einfache Blinkschaltung betreiben können??

Blinkschaltung hat geklappt (2 Leds). Die hatte ich auch direkt an die 
Ports angeschlossen. Aber sobald ich 4 oder 5 LEDs ansteuere dimmen die 
nur noch vor sich hin oder gehen gar nicht mehr an.

Register schreibe ich immer zuerst auf null mit :

PORTD: 0x00;

Dann setze ich Port D als Ausgang:

DDRD: 0xff;

Danach im Programm setze ich die Signale mit den üblichen Befehlen:

PORTD = (1<<PD0);
PORTD &=~(1<<PD1);

von ich (Gast)


Lesenswert?

>Aber sobald ich 4 oder 5 LEDs ansteuere dimmen die
nur noch vor sich hin oder gehen gar nicht mehr an.

Der AVR ist nur begrenzt belastbar, sthet im Datenblatt (ich meine 20mA 
oder so ähnlich). Bau Transistoren ein und gut ist.

von emit5 (Gast)


Lesenswert?

Tobi schrieb:
> Du willst mit dem ADC eine LED ansteuern?
>
> Sicher dass du den ATmega mit 5V betreibst und nich tnur mit 3,3V?
>
> Beschaltung?

Möchte mit dem ADC nur zu Versuchszwecken die LED ansteuern.

Habe den ATmega ganz sicher auf 5V.

Die Beschaltung? Ich habe mir ein Pollin ATMEL Evaluations Board 
gekauft.

von ich (Gast)


Lesenswert?

>Möchte mit dem ADC nur zu Versuchszwecken die LED ansteuern.

Herje... Mit einem ADC steuert man keine LEDs an, sondern misst eine 
analoge Größe.
Wenn du nicht richtig beschreiben kannst wie deine Schaltung aussieht, 
dann zeig wenigstens einen Schaltplan her...

von Felix (Gast)


Lesenswert?

emit5 schrieb:
> Danach im Programm setze ich die Signale mit den üblichen Befehlen:
>
> PORTD = (1<<PD0);
> PORTD &=~(1<<PD1);

Naja, das ist ja schonmal nicht ganz korrekt!
Das Löschen stimmt soweit, nur beim Setzen von Bits in einem Register 
muss das schon REG |= (1<<BIT_NUM); heißen. In deinem Fall überschreibst 
du ja das gesamte Register mit deinem neu zu setzenden Bit. Also egal 
was da vorher gesetzt war, hinterher ist es genau das eine Bit von der 
Zuweisung.

Mit dem |= verhinderst du das Problem. Du gibst ja damit die Anweisung, 
den momentanen Wert des Registers einzulesen, ihn mit dem zu setztenden 
Bit zu ver-odern und in das Register zurückzuschreiben.

Das falsche Setzen könnte auch deinen Fehler erklären. Bei einer 
Blinkschaltung kann es sein, dass das garnicht auffällt. Aber jetzt, wo 
es mehr Leds sind, schalten die Setz-Anweisungen sich gegenseitig aus.

Genauer kann man dir das sagen wenn du deinen Code mal hochladen 
würdest...

von XXX (Gast)


Lesenswert?

Kann es sein, das du wild an den LED-Pins umschaltest und es
dadurch aussieht, daß die LED gedimmt wird.

Zeig mal dein Programm.

Gruß
Joachim

von emit5 (Gast)


Lesenswert?

ich schrieb:
> Herje... Mit einem ADC steuert man keine LEDs an, sondern misst eine
>
> analoge Größe.
>
> Wenn du nicht richtig beschreiben kannst wie deine Schaltung aussieht,
>
> dann zeig wenigstens einen Schaltplan her...

Ich steuere mit dem ADC keine LEDs an sondern benutzte den ADC nur um 
die Ports zu steuern! Die auf den ULN2804 gehen, der dann LEDs 
ansteuert!

Entschuldigung das ich ein Anfänger bin und etwas lernen möchte!!

Ausserdem geht es mir mehr darum: Warum ist die Spannung an den 
Ausgangsports so niedrig?

von Michael R. (mexman) Benutzerseite


Lesenswert?

Hallo emit5:


>>Möchte mit dem ADC nur zu Versuchszwecken die LED ansteuern.
>
> Herje... Mit einem ADC steuert man keine LEDs an, sondern misst eine
> analoge Größe.
> Wenn du nicht richtig beschreiben kannst wie deine Schaltung aussieht,
> dann zeig wenigstens einen Schaltplan her...

Da siehst Du mal wohin das fuehrt...... Du hast es zwar schon oben 
erklaert, aber wenn man eine Frage KLAR stellt, kommt schneller eine 
sinnvolle Antwort heraus.

Gruss

Michael

von ich (Gast)


Lesenswert?

>Ausserdem geht es mir mehr darum: Warum ist die Spannung an den
>Ausgangsports so niedrig?

Weil du vermutlich mehr Strom aus dem AVR ziehst als du darfst.
Oder du im Programm schnell ein- und ausschaltest.
Hast du eine Möglichkeit mit einem Oszilloskop an deinen Ausgangspins zu 
messen?
Wie groß sind denn deine Vorwiderstände der LEDs?

von emit5 (Gast)


Lesenswert?

Hallo Felix,

Felix schrieb:
> Naja, das ist ja schonmal nicht ganz korrekt!
>
> Das Löschen stimmt soweit, nur beim Setzen von Bits in einem Register
>
> muss das schon REG |= (1<<BIT_NUM); heißen. In deinem Fall überschreibst
>
> du ja das gesamte Register mit deinem neu zu setzenden Bit. Also egal
>
> was da vorher gesetzt war, hinterher ist es genau das eine Bit von der
>
> Zuweisung.
>
>
>
> Mit dem |= verhinderst du das Problem. Du gibst ja damit die Anweisung,
>
> den momentanen Wert des Registers einzulesen, ihn mit dem zu setztenden
>
> Bit zu ver-odern und in das Register zurückzuschreiben.
>
> Das falsche Setzen könnte auch deinen Fehler erklären. Bei einer
>
> Blinkschaltung kann es sein, dass das garnicht auffällt. Aber jetzt, wo
>
> es mehr Leds sind, schalten die Setz-Anweisungen sich gegenseitig aus.

> Genauer kann man dir das sagen wenn du deinen Code mal hochladen
>
> würdest...

Danke!! Das ist schonmal ne super Erklärung! Werde mein Programm 
hochladen wenn ich zu Hause bin. Bin im Moment noch auf der Arbeit!!

von emit5 (Gast)


Lesenswert?

ich schrieb:
> Weil du vermutlich mehr Strom aus dem AVR ziehst als du darfst.
>
> Oder du im Programm schnell ein- und ausschaltest.
>
> Hast du eine Möglichkeit mit einem Oszilloskop an deinen Ausgangspins zu
>
> messen?
>
> Wie groß sind denn deine Vorwiderstände der LEDs?

Benutze 220 Ohm Widerstände.
Oszilloskop habe ich leider nicht!

von Felix (Gast)


Lesenswert?

emit5 schrieb:
> Ausserdem geht es mir mehr darum: Warum ist die Spannung an den
> Ausgangsports so niedrig?

Ich habe dir ein klein wenig weiter oben schon einen Hinweis gegeben. 
Gehe dem bitte mal nach und kontrolliere deinen Quellcode und/oder poste 
ihn auch gleich mal hier im Forum, vielleicht finden sich ja noch mehr 
Fehler.

Das mit der Spannung würde sich auch über durch den oben beschriebenen 
Fehler beim Bits setzen erklären. Ich nehme mal an du misst die Spannung 
mit einem normalen Multimeter. Dein Controller läuft aber nun wesentlich 
schneller als das Multimeter messen kann. Der Controller schaltet nun 
die Leds immer mal kurz an und wieder aus, weil du das wahrscheinlich so 
programmiert hast. Daher ist die mittlere Spannung eben wesentlich 
geringer als die 5V, die Multimeter messen ja nur rund drei bis fünf mal 
pro Sekunde und haben eine gewisse Integrationszeit. Auf einem 
hinreichend schnellen Ozilloskop würdest du dann sicher auch die kleinen 
Pulse sehen die dein Controller ausgibt.

-> Also: Schau nach dem Bit-Setz-Problem

von ich (Gast)


Lesenswert?

220 Ohm... Das entspricht dann etwa 15mA pro LED.
Das sollte vom Strom her noch kein Problem sein.
Pro Pin musst du unter 40mA, im gesammten unter 200mA bleiben!

von emit5 (Gast)


Lesenswert?

Felix schrieb:
> -> Also: Schau nach dem Bit-Setz-Problem

Hallo nochmal,

das mit dem Bit-Setz-Problem stimmte.

Aber da ich euch noch den Quellcode schuldig bin:

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>


int main (void)
{

  unsigned int low=0, high=0, ad=0, x=0, admax=0;


  DDRD = 0xFF;
  PORTD = 0x00;

  ADMUX = 0b01000000;
  ADCSRA = 0xE0;


  while(1)
  {

    low  = ADCL;
    high = ADCH;
    ad   = high * 256;
    x    = ad + low;


    if (x > admax)
    {
      x = admax;
    }


    if (x >= 206 || admax >=206)
    {
      (PORTD |= (1<<PD0));
    }

    else
    {
      (PORTD &=~ (1<<PD0));
    }

    if (x >= 412 || admax >=412)
    {
      (PORTD |= (1<<PD1));
    }

    else
    {
      (PORTD &=~ (1<<PD1));
    }

    if (x >= 618 || admax >=618)
    {
      (PORTD |= (1<<PD2));
    }

    else
    {
      (PORTD &=~ (1<<PD2));
    }

    if (x >= 824 || admax >=824)
    {
      (PORTD |= (1<<PD3));
    }

    else
    {
      (PORTD &=~ (1<<PD3));
    }

    if (x >= 950 || admax >=950)
    {
      (PORTD |= (1<<PD4));
    }

    else
    {
      (PORTD &=~ (1<<PD4));
    }
  }
}

Vielleicht findet ja noch einer einen Fehler?!?

Danke im voraus!!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Vielleicht findet ja noch einer einen Fehler?!?
Ist da noch einer versteckt, oder ist das nur einfach so pauschal 
dahingefragt?

Na gut. Du mußt du den AD-Wert nicht selber zusammenbasteln, das macht 
der Compiler für dich:
1
    x   = ADCW;

Ist hier bei der Zuweisung x und admax vertauscht?
1
    if (x > admax)  x = admax;
Was wäre, wenn admax=0 wäre und x=10?
Dann wären anschliessend beide 0...   :-o


Drehen wir das mal um:
1
    if (x > admax)  admax = x;
2
3
    if (x >= 206 || admax >=206)    PORTD |=  (1<<PD0);
4
    else                            PORTD &=~ (1<<PD0);
Überleg mal die Funktion deines Programms nochmal genau. (Lass dich mal 
nicht davon verwirren, dass ich das etwas lesbarer formatiert habe)
Ich würde sagen, du kannst die Abrage auf x ganz einfach ohne 
Funktionseinschränkung weglassen...

von emit5 (Gast)


Lesenswert?

Lothar Miller schrieb:
> Was wäre, wenn admax=0 wäre und x=10?
>
> Dann wären anschliessend beide 0...   :-o

Super Danke!!!

Habe die ganze Zeit versucht meinen Fehler zu finden!
Bin aber irgendwie nicht drauf gekommen!

Lothar Miller schrieb:
> Ich würde sagen, du kannst die Abrage auf x ganz einfach ohne
>
> Funktionseinschränkung weglassen...

Was meinst du damit?

von Karl H. (kbuchegg)


Lesenswert?

emit5 schrieb:

>> Ich würde sagen, du kannst die Abrage auf x ganz einfach ohne
>>
>> Funktionseinschränkung weglassen...
>
> Was meinst du damit?

Denk logisch

nach (korrigiert)
1
    if (x > admax)
2
      admax = x;

kann admax nicht mehr kleiner als x sein. Wenn es das wäre, wäre es 
durch diese Abfrage auf x angehoben worden.

Damit ist es hier zb
1
    if (x >= 950 || admax >=950)
nicht notwendig beide abzufragen. Wenn x größer/gleich 950 ist, dann 
muss es auch admax sein. admax kann niemals kleiner als x sein. Deine 
vorhergehende Abfrage x > admax mit Nachsetzen von admax hat das 
sichergestellt. Allerdings kann x kleiner als admax sein. Das spielt 
hier aber keine Rolle mehr, denn in dem Fall greift dann immer (auch bei 
den anderen Fällen) die Abfrage ob admax größer/gleich als irgendein 
Wert ist.

-> Die Abfrage ob x irgendetwas ist, ist sinnlos und ohne Auswirkungen. 
Probiers mit ein paar Zahlen in mehreren Schleifendurchgängen auf dem 
Papier durch. Das ist überhaupt empfehlenswert, denn dann hättest du 
deinen letzten Fehler auch ganz einfach selbst erkannt.

von emit5 (Gast)


Lesenswert?

Alles klar! Vielen Dank für die Hilfe!!

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.