Forum: Mikrocontroller und Digitale Elektronik Problem bei einfachen Lauflicht :-(


von R. S. (schmidtbot)


Lesenswert?

Hallo,

ich habe bis gestern gedacht, ich kann mal schnell nebenbei ein 
Lauflicht programmieren. Doch leider wurde mir nach längerer Fehlersuche 
eines besseren belehrt.

Das Licht sollte einfach nur nach rechts laufen. Das tut es auch mehr 
oder weniger, aber jeden LED blinkt nur kurz auf statt für 1sec zu 
leuchten. Das lustige an der Sach ist aber wenn ich über ledra oder 
ledla alle LEDs blinken lasse bzw. aktivieren Funktioniert es.
Kann mir bitte jemand helfen? Ich finden den Fehler leider nicht.

AVR Atmega8
Internen Quarz
AVR Studio 6
LEDS über BC639 an:
PB6
PB7
PD5
PD6
PD7
PB0

das wäre der Sourcecode:
------------------------------------------------------------------------ 
---
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000

unsigned char ledl1 = 0;
unsigned char ledl2 = 0;
unsigned char ledl3 = 0;
unsigned char ledr1 = 0;
unsigned char ledr2 = 0;
unsigned char ledr3 = 0;
unsigned char ledla = 0;
unsigned char ledra = 0;



void ausgabe(void)
{
  if (ledl1 == 1)
  {
    PORTB = PORTB | (1<<PD0);
  }
  else
  {
    PORTB = PORTB &~ (1<<PB0);
  }

  if (ledl2 == 1)
  {
    PORTD = PORTD | (1<<PD7);
  }
  else
  {
    PORTD = PORTD &~ (1<<PD7);
  }


  if (ledl3 == 1)
  {
    PORTD = PORTD | (1<<PD6);
  }
  else
  {
    PORTD = PORTD &~ (1<<PD6);
  }

  if (ledr1 == 1)
  {
    PORTD = PORTD | (1<<PD5);
  }
  else
  {
    PORTD= PORTD &~ (1<<PD5);
  }
  if (ledr2 == 1)
  {
    PORTB = PORTB | (1<<PB7);
  }
  else
  {
    PORTB = PORTB &~ (1<<PB7);
  }

  if (ledr3 == 1)
  {
    PORTB = PORTB | (1<<PB6);
  }
  else
  {
    PORTB = PORTB &~ (1<<PB6);
  }

  if (ledla == 1)
  {
    PORTB = PORTB | (1<<PB0);
    PORTD = PORTD | (1<<PD7);
    PORTD = PORTD | (1<<PD6);
  }
  else
  {
    PORTB = PORTB &~ (1<<PB0);
    PORTD = PORTD &~ (1<<PD7);
    PORTD = PORTD &~ (1<<PD6);
  }

  if (ledra == 1)
  {
    PORTD = PORTD | (1<<PD5);
    PORTB = PORTB | (1<<PB7);
    PORTB = PORTB | (1<<PB6);
  }
  else
  {
    PORTD = PORTD &~ (1<<PD5);
    PORTB = PORTB &~ (1<<PB7);
    PORTB = PORTB &~ (1<<PB6);
  }

}

int main(void)
{


DDRB = DDRB | (1<<PB0)| (1<<PB6)| (1<<PB7); // Ausgänge
DDRD = DDRD | (1<<PD5)| (1<<PD6)| (1<<PD7); // Ausgänge
PORTD = 0x1F; //Pullups für Eingänge aktiviren



    while(1 == 1)
 {
  ledl1=0;
  ledl2=0;
  ledl3=0;
  ledr1=0;
  ledr2=0;
  ledr3=0;
  ausgabe();
  _delay_ms(1000);

  ledl1=0;
  ledl2=1;
  ledl3=0;
  ledr1=0;
  ledr2=0;
  ledr3=0;
  ausgabe();
  _delay_ms(1000);

  ledl1=0;
  ledl2=0;
  ledl3=1;
  ledr1=0;
  ledr2=0;
  ledr3=0;
  ausgabe();
  _delay_ms(1000);

  ledl1=0;
  ledl2=0;
  ledl3=0;
  ledr1=1;
  ledr2=0;
  ledr3=0;
  ausgabe();
  _delay_ms(1000);


  ledl1=0;
  ledl2=0;
  ledl3=0;
  ledr1=0;
  ledr2=1;
  ledr3=0;
  ausgabe();
  _delay_ms(1000);

  ledl1=0;
  ledl2=0;
  ledl3=0;
  ledr1=0;
  ledr2=0;
  ledr3=1;
  ausgabe();
  _delay_ms(1000);
    }
}
------------------------------------------------------------------------ 
--
Besten Dank!

PS: Ich würde fast darauf wetten, dass es ein peinlicher Fehler ist :-)

von Blueberry (Gast)


Lesenswert?

Rolf Schmidt schrieb:
> PS: Ich würde fast darauf wetten, dass es ein peinlicher Fehler ist :-)

Das glaube ich auch, so macht doch kein Mensch ein Lauflicht!
Schau Dir mal die logischen Operationen wie Bitshift an.
Alternativ auch die Multiplikation/Division mit/durch 2.

von Ingo (Gast)


Lesenswert?

Wie ist deine Optimierung eingestellt?
Ich sehe keinen Fehler. Beschreib mal dein Blitzen!
Welche IDE?



Ingo

von hans (Gast)


Lesenswert?

Reihenfolge
1
#include <util/delay.h>
2
#define F_CPU 1000000
falsch ;(

hans

von Karl H. (kbuchegg)


Lesenswert?

Wow.
Das ist das komplizierteste Lauflicht, an das mich erinnern kann.
Und das will in diesem Forum was heißen.

: Wiederhergestellt durch User
von trollalala (Gast)


Lesenswert?

Schmeiß den Code weg und fang von vorne an. Vorher aber bitte in einem 
Buch über den shift-operator lesen...

Alle LEDs an einen PORT, dann ist das ein 3-Zeiler.

von trollalala (Gast)


Lesenswert?

OK, zu langsam...

von Ingo (Gast)


Lesenswert?

hans schrieb:
> Reihenfolge#include <util/delay.h>
> #define F_CPU 1000000
> falsch ;(
>
> hans

Richtig, hatte ich überlesen (Bei dem riesen Code).
Aber wenn der interne Oszillator läuft (8Mhz oder 1MHz), dann sollte die 
1s halt etwas länger sein.



Ingo

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wow.
> Das ist das komplizierteste Lauflicht, an das mich erinnern kann.
> Und das will in diesem Forum was heißen.

Aber ....
Ingo hat Recht.
Einen offensichtlichen Fehler gibt es nicht.

von John B. (johnbauer)


Lesenswert?

Wie sieht deine Schaltung aus (LEDs, Transistoren etc.)?

von debugger (Gast)


Lesenswert?

Dämlichster (Troll-)Fehler wo gibt!!!

Bei ausgabe() schaltest Du deine Wunsch-Led ein und unten bei der 
letzten if-clause setzt Du beide Ports wieder auf aus. Ausnahme: Es 
werden alle LEDs ein- oder ausgeschaltet.

Ab in die Ecke und schämen!!!

von Karl H. (kbuchegg)


Lesenswert?

debugger schrieb:
> Dämlichster (Troll-)Fehler wo gibt!!!
>
> Bei ausgabe() schaltest Du deine Wunsch-Led ein und unten bei der
> letzten if-clause setzt Du beide Ports wieder auf aus. Ausnahme: Es
> werden alle LEDs ein- oder ausgeschaltet.

<Hand an die Strin klatsch>

>
> Ab in die Ecke und schämen!!!

Richtig.
Nämlich: wir Helfer.

von R. S. (schmidtbot)


Lesenswert?

Klar kenn ich die shift-operatoren. Wenn man sich den Code an sieht, 
dann sieht man auch, dass ich ihn zum setzten der Ausgänge nehme :-)
Er ist aber wegen Zusatzfunktionen (nicht online) leider ungeeignet.
Und wenn die Hardware schon fertig ist, kann man nicht einfach 
irgendwelche Pins tauschen :-)

Aber ich hatte recht, es war ein sehr peinlicher und einfacher Fehler. 
X+2 Augen sind halt immer besser als nur zwei :-)

Danke für den Hinweis

von noonien (Gast)


Lesenswert?

Wirst du nach Codezeilen bezahlt? :)

von Stefan F. (sfrings)


Lesenswert?

Du könntest doch wenigstens die ganzen (unsigned char) durch eine 
einzige ersetzen, bei der jedes Bit für eine LED steht. Dann brauchst Du 
im Hauptprogramm auch nicht (gefühlte) 500 Schreibzugriffe, sondern nur:
1
unsigned char value;
2
while (1) {
3
  value=0b000001;
4
  do {
5
    ausgabe();
6
    _delay_ms(1000);
7
    value=value<<1;
8
  }
9
  while (value<=0b100000);
10
}

Nur so als Denkanstoß. Wie die ausgabe() Funktion umgeschrieben werden 
muss, kannst Du Dir sicher selbst denken.

von R. S. (schmidtbot)


Lesenswert?

das muss ich natürlich zugeben, diese Variante ist bedeutent schöner 
programmiert als meine "quick and dirty" Version.

von Bart (Gast)


Lesenswert?

Bei der langen Tipparbeit und Fehlersuche, ist das wohl kaum als "quick" 
zu bezeichnen...

von Karl H. (kbuchegg)


Lesenswert?

R. Schmidt schrieb:

> Und wenn die Hardware schon fertig ist, kann man nicht einfach
> irgendwelche Pins tauschen :-)

Das ist richtig.
Aber man kann sich zb in einem, nein 2, Arrays die jeweils an den ports 
auszugebenden Werte ablegen und dann ganz einfach in ausgabe() in die 
Arrays indizieren um den Wert zu erfahren, der ausgegeben werden soll.
Dann spart man sich einen Großteil dieser if - else kette

von Holger (Gast)


Lesenswert?

R. Schmidt schrieb:
> mal schnell nebenbei ein
> Lauflicht programmieren.

Gratuliere. Dein Code hat es in meine All-Time "so-macht-man-es-nicht" 
Sammlung geschafft...

von Karl H. (kbuchegg)


Lesenswert?

Bart schrieb:
> Bei der langen Tipparbeit und Fehlersuche, ist das wohl kaum als "quick"
> zu bezeichnen...

Dafür dirty!

von Checker Bunny (Gast)


Lesenswert?

Also ich finde den Code toll.
Den hebe ich mir auf und erschrecke damit kleine Kinder.

von RTFM (Gast)


Lesenswert?

Checker Bunny schrieb:
> Den hebe ich mir auf

Das wäre doch was zur Abschreckung neugieriger Kollegen? Das muss auch 
in die Schreibunterlage mit rein!

von Fred (Gast)


Lesenswert?

Ich bin zwar auch Anfänger, aber da musste auch ich schlucken. 
Kompliziert.
Wie es der Zufall so will, habe ich vor 2 Tagen auch ein Lauflicht 
gemacht.
Mein Code ist extrem simpel da er erstmal zum testen war, man kann noch 
etwas optimieren.
Das ganze läuft auf einem Attiny 44 mit internem Takt. Das einzigste was 
Du tun musste ist die Pinausgänge festlegen und Pinnamen entsprechend 
Deines Avr ändern.

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRA = (1 << PA0) | (1 << PA1) | (1 << PA2) | (1 << PA3) | (1 << PA5) 
| (1 << PA7);
  DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2);

    while(1)
    {
    PORTA |= (1 << PA0); _delay_ms(70);
  PORTA &= ~((1 << PA0));
  PORTA |= (1 << PA1); _delay_ms(70);
  PORTA &= ~((1 << PA1));
  PORTA |= (1 << PA2); _delay_ms(70);
  PORTA &= ~((1 << PA2));
  PORTA |= (1 << PA3); _delay_ms(70);
  PORTA &= ~((1 << PA3));
  PORTB |= (1 << PB0); _delay_ms(70);
  PORTB &= ~((1 << PB0));
  PORTB |= (1 << PB1); _delay_ms(70);
  PORTB &= ~((1 << PB1));
  PORTB |= (1 << PB2); _delay_ms(70);
  PORTB &= ~((1 << PB2));
  PORTA |= (1 << PA7); _delay_ms(70);
  PORTA &= ~((1 << PA7));
  PORTA |= (1 << PA5); _delay_ms(70);
  PORTA &= ~((1 << PA5));

  PORTA |= (1 << PA7); _delay_ms(70);
  PORTA &= ~((1 << PA7));
  PORTB |= (1 << PB2); _delay_ms(70);
  PORTB &= ~((1 << PB2));
  PORTB |= (1 << PB1); _delay_ms(70);
  PORTB &= ~((1 << PB1));
  PORTB |= (1 << PB0); _delay_ms(70);
  PORTB &= ~((1 << PB0));
  PORTA |= (1 << PA3); _delay_ms(70);
  PORTA &= ~((1 << PA3));
  PORTA |= (1 << PA2); _delay_ms(70);
  PORTA &= ~((1 << PA2));
  PORTA |= (1 << PA1); _delay_ms(70);
  PORTA &= ~((1 << PA1));

}
}

Also wie man sieht geht es auch extrem einfach.
Gruß
Fred

von Fred (Gast)


Angehängte Dateien:

Lesenswert?

Achja. Du kannst z.B. einfach einen Vorwiderstand vor die LED bauen. 
Plus kommt vom Chip und Minus an gemeinsame Masse.

von EGS_TI (Gast)


Lesenswert?

lol

von troll (Gast)


Lesenswert?

Fred schrieb:
> Also wie man sieht geht es auch extrem einfach.
Genau:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main(void)
5
{
6
  DDRA = 0xFF;
7
  uint16_t i;
8
  for(;;)
9
  {
10
    for(i=1;i!=(1<<8);i<<=1)
11
    {
12
      PORTA=(uint8_t)i;
13
      _delay_ms(70);
14
    }
15
  }
16
  return 0; //neaver reached
17
}

SCNR

Wie wäre es mit einem Wettbewerb: Wer schreibt das kürzeste Lauflicht?

von Fred (Gast)


Lesenswert?

Das ist mir klar, daß ich das ganze in einer schleife machen kann.
Ich wollte halt nur zeigen, daß seines schon extrem umständlich ist.
Auch wenn Deines schön klein ist, so finde ich es absolut 
unübersichtlich.
Zum lernen finde ich die Portnamen etc. besser.

von troll (Gast)


Lesenswert?

troll schrieb:
> Wie wäre es mit einem Wettbewerb: Wer schreibt das kürzeste Lauflicht?
Ich leg dann mal vor:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
main(){DDRA=~0;char i;for(;;)for(i=0,PORTA=1;i<8;i++,PORTA<<=1,_delay_ms(70));}
Kann sein dass man noch unsigned vor den char setzen muss, hab gerade 
keinen AVR-GCC zur Hand. Mal sehen, vielleicht schlage ich Karl-Heinz ja 
dieses Mal...

von troll (Gast)


Lesenswert?

troll schrieb:
> Kann sein dass man noch unsigned vor den char setzen muss
Nein Blödsinn, das war für eine andere Version. :-(

von Fred (Gast)


Lesenswert?

Ich sehe schon, wie in so manchen anderen Threads wird hier alles ins 
lächerliche gezogen.
Vielleicht sollte man mal über die Gastfunktion nachdenken.

von troll (Gast)


Lesenswert?

Fred schrieb:
> Ich sehe schon, wie in so manchen anderen Threads wird hier alles ins
> lächerliche gezogen.
> Vielleicht sollte man mal über die Gastfunktion nachdenken.

Ich ziehe überhaupt nichts ins Lächerliche... Sei nicht so humorlos, 
kurze (und unübersichtliche) Programme in C haben eine lange Tradition. 
Siehe auch IOCC. :-)

von troll (Gast)


Lesenswert?

Sorry for x-fach-Post. Ich bessere nochmal nach: Beispiel =~ s!#include 
<util/delay.h>!! Sollte funktionieren, Defaultwerte passen.

von Thorsten S. (whitejack)


Lesenswert?

...viel interessanter ist ein Lauflicht mit 10 Duo LED  an 5 Portpins 
mit 5 Widerständen. Mit integriertem weichem Farbwechsel von rot zu grün 
während das Lauflicht läuft....

TS

von Peter D. (peda)


Lesenswert?

Die Ausgabefunktion kann man auch drastisch vereinfachen.
Und Parameterübergabe macht man nicht in globalen Variablen, sondern 
direkt:
1
#include <avr/io.h>
2
#define F_CPU   1e6
3
#include <util/delay.h>
4
5
#define LEDL1B  (1<<PB0)
6
#define LEDL2D  (1<<PD7)
7
#define LEDL3D  (1<<PD0)
8
#define LEDR1D  (1<<PD5)
9
#define LEDR2B  (1<<PB7)
10
#define LEDR3B  (1<<PB6)
11
12
void ausgabe( uint8_t val )
13
{
14
  uint8_t vald = PORTD & ~(LEDL1B | LEDR2B | LEDR3B);
15
  uint8_t valb = PORTB & ~(LEDL2D | LEDL3D | LEDR1D);
16
  if( val & 1<<0 )
17
    valb |= LEDL1B;
18
  if( val & 1<<1 )
19
    vald |= LEDL2D;
20
  if( val & 1<<2 )
21
    vald |= LEDL3D;
22
  if( val & 1<<3 )
23
    vald |= LEDR1D;
24
  if( val & 1<<4 )
25
    valb |= LEDR2B;
26
  if( val & 1<<5 )
27
    valb |= LEDR3B;
28
  PORTD = vald;
29
  PORTB = valb;
30
}
31
32
int main()
33
{
34
  DDRB = LEDL1B | LEDR2B | LEDR3B;
35
  DDRD = LEDL2D | LEDL3D | LEDR1D;
36
  
37
  for(;;){
38
    uint8_t val = 1;
39
      ausgabe( 0 );
40
    do{
41
      _delay_ms(1000);
42
      ausgabe( val );
43
      val <<= 1;
44
    }while( val != 0b1000000 );
45
  }
46
}

Peter

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.