Problem bei einfachen Lauflicht :-(

OP #2785028
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 :-)
Gast #2785034
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.
Gast #2785041
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.
Gast #2785048
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
Gast #2785096
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!!!
#2785113
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.
OP #2786274
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
#2786450
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.
#2787932
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
Gast #2791037
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
Gast #2791047
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?
Gast #2791054
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.
Gast #2791056
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...
Gast #2791061
Ich sehe schon, wie in so manchen anderen Threads wird hier alles ins 
lächerliche gezogen.
Vielleicht sollte man mal über die Gastfunktion nachdenken.
Gast #2791065
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. :-)
#2791141
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.