LED Würfel ATTINY13

Gast #3831954
Lesenswert?

Hallo,

ich habe diesen Schaltplan nachgebaut: 
http://www.avr-asm-tutorial.net/avr_de/wuerfel/wuerfel3.gif
Jedoch mit einem Unterschied, ich habe den GND der LEDs nicht auf den 
AVR gelegt, sondern die positive Seite auf den AVR, ein Test-Programm 
zeigt auch, dass alle LEDs leuchten (... wenn ich alle outputs auf on 
setze).

Ich bin neu in der AVR Programmierung, mein Ziel sollte es sein, dass 
der AVR wenn ich den Taster auf PB4 betätige eine random Zahl zwischen 1 
und 6 generiert, diese dann mittels der LEDs ausgibt.

Meinen Code habe ich angehängt. Wenn ich diesen Code so verwende, dann 
blinkt die mittlere LED herum, in unregelmäßigen Abständen, alle anderen 
LEDs leuchten durchgehend.

Wo liegt mein Fehler? Ich habe verschiedenste Varianten probiert, keine 
davon hat je ordentlich funktioniert.

Danke!

Gruß
Angehängte Dateien:
#3831975
Lesenswert?

>
1
   if ( PINB ^ ( 1<<PINB4 ) );

Du fragst den Taster mit XOR ab.

Taster gedrückt: 1 XOR 1 = 0
Taster nicht gedrückt= 0 XOR 1 = 1

Verwende also ein & statt ^.

eventuell solltest du in Erwägung ziehen, den Taster zu entprellen. Du 
hast zwar ein delay von 100 ms drin, da kann aber bei etwas längerem 
Tastendruck auch mehrmals auslösen.
#3832060
Lesenswert?

Marc Vesely schrieb:
> Gib's zu, du hast ins .lss gekiekt ?

Nein, warum?

Da steht:
   PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3);

PORTB &= 0xFE | 0x02 | 0x04 | 0x08

0xFE | 0x02 | 0x04 | 0x08 = 0xFE

Und dann ist nur noch ein Bit zu löschen.

genau genommen wird es nicht wegoptimert, sondern das ist eine 
Konstante, die errechnet und eingesetzt wird. Da der Compiler schlau 
ist, nimmt er für das eine Bit auch den passenden Befehl, anstatt 
Read-Modify-Write. Das ist allerdings eine Optimierung.

Geht also schön schnell, funktioniert aber nicht wie vom TO erwartet.

mfg.
Gast #3832221
Lesenswert?

Hallo,

danke erstmal für die Antworten.

Marc Vesely schrieb:
> So wie ich das sehe, wird nur PB0 gelöscht und dann mit PB1-PB3 OR-ed.

Du hast recht, ja. Wie bekomme ich es in einer Zeile zusammen, alle zu 
löschen?
>PORTB &= ~ (1<<PB0) ~ (1<<PB1) ~ (1<<PB2) ~(1<<PB3);
funktioniert ja nicht. Oder muss ich da für jeden Port eine eigene Zeile 
machen?

M. S. schrieb:
> Du fragst den Taster mit XOR ab.
>
> Taster gedrückt: 1 XOR 1 = 0
> Taster nicht gedrückt= 0 XOR 1 = 1
>
> Verwende also ein & statt ^.

Danke, werde ich versuchen. Was ich nicht ganz verstehe, der Taster ist 
in dem Schaltplan auf GND, somit sollte er den Eingang des AVRs auf 0 
setzen, lieg ich damit richtig?

M. S. schrieb:
> eventuell solltest du in Erwägung ziehen, den Taster zu entprellen. Du
> hast zwar ein delay von 100 ms drin, da kann aber bei etwas längerem
> Tastendruck auch mehrmals auslösen.

Stimmt, danke, werde ich machen.


Danke!

Gruß
Gast #3832252
Lesenswert?

erfusta schrieb:
> Du hast recht, ja. Wie bekomme ich es in einer Zeile zusammen, alle zu
> löschen?
>>PORTB &= ~ (1<<PB0) ~ (1<<PB1) ~ (1<<PB2) ~(1<<PB3);
> funktioniert ja nicht. Oder muss ich da für jeden Port eine eigene Zeile
> machen?

Ich habe es nun so geschafft:
> PORTB &= ~ (1<<PB0) & ~ (1<<PB1) & ~ (1<<PB2) & ~ (1<<PB3);

Damit hätte ich schon mal den Lampen-Test vor der eigenen 
Würfel-Anwendung funktionierend bekommen. :)
#3832255
Lesenswert?

erfusta schrieb

> Wie bekomme ich es in einer Zeile zusammen, alle zu
> löschen?
>>PORTB &= ~ (1<<PB0) ~ (1<<PB1) ~ (1<<PB2) ~(1<<PB3);
> funktioniert ja nicht. Oder muss ich da für jeden Port eine eigene Zeile
> machen?
1
PORTB &= ~( (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3) );
im Klartext:
1
PORTB &= ~(0b00000001|0b00000010|0b00000100|0b00001000);
2
= PORTB &= ~(0b00001111);
3
= PORTB &= 0b11110000;


> Was ich nicht ganz verstehe, der Taster ist
> in dem Schaltplan auf GND, somit sollte er den Eingang des AVRs auf 0
> setzen, lieg ich damit richtig?

Sorry, habe ich nicht bemerkt. Dann funktioniert dein XOR, Standardmäßig 
würde man es dann so machen:
1
if( ! (PINB & (1<<PINB4)) )
2
{
3
...
4
}

Siehe auch:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Digitale_Signale
Gast #3832265
Lesenswert?

M. S. schrieb:
> im Klartext:

Danke, deine Version ist kürzer, als die die ich im Post davor durch 
probieren herausgefunden habe. Ich habe diese nun übernommen.

M. S. schrieb:
> Sorry, habe ich nicht bemerkt. Dann funktioniert dein XOR, Standardmäßig
> würde man es dann so machen:

Hab ich probiert. Ich hab die Anwendung umgeschrieben, ich will einfach 
mal testweise bei einem Tastendruck alle LEDs zum leuchten bringen. 
Siehe Anhang. Funktioniert allerdings kein bisschen, und ich hab auch 
keine Ahnung wieso. Sämtliches herumspielen mit Operatoren hat nichts 
gebracht.

Hast du noch eine Idee?

Danke!

Gruß
Angehängte Dateien:
(Firma: Vescomp) #3832266
Lesenswert?

erfusta schrieb:
> Du hast recht, ja. Wie bekomme ich es in einer Zeile zusammen, alle zu
> löschen?

erfusta schrieb:
> Ich habe es nun so geschafft:
>> PORTB &= ~ (1<<PB0) & ~ (1<<PB1) & ~ (1<<PB2) & ~ (1<<PB3);

Thomas Eckmann schrieb:
> Auf den ersten Blick sollte "PORT =" statt "PORT |=" reichen.

 Auf den zweiten Blick auch.
 Lass die bitfummelei, du setzst PortB eh auf Null.
#3832276
Lesenswert?

Hast du genau wie im Schaltplan nur den Taster zwischen den Pin und GND? 
Dann solltest du einen Pull-Up Widerstand (z.B. 10 kOhm) zwischen VDD 
und ebendiesen Pin hängen, oder direkt den Pin mit VDD verbinden und den 
internen Pull-Up aktivieren. Das hat den Hintergrund, dass der Pin sonst 
bei geöffnetem Schalter "in der Luft" hängt, durch den PullUp wird er 
auf ein definiertes Potential (VDD, also "1") gezogen.
Gast #3832302
Lesenswert?

M. S. schrieb:
> Hast du genau wie im Schaltplan nur den Taster zwischen den Pin
> und GND?
> Dann solltest du einen Pull-Up Widerstand (z.B. 10 kOhm) zwischen VDD
> und ebendiesen Pin hängen, oder direkt den Pin mit VDD verbinden und den
> internen Pull-Up aktivieren. Das hat den Hintergrund, dass der Pin sonst
> bei geöffnetem Schalter "in der Luft" hängt, durch den PullUp wird er
> auf ein definiertes Potential (VDD, also "1") gezogen.

Ja, das habe ich. Hm. Also mit taster auf GND habe ich aktuell keine 
Chance?

Dann werde ich das morgen auf VDD umlöten.
#3832309
Lesenswert?

Doch, natürlich hast du eine Chance mit Taster auf GND. Ist eben die 
Frage, ob Active High, oder Active Low. Nur in beiden Fällen muss der 
Taster im geöffneten Zustand über einen Widerstand auf das jeweils 
andere Potential verbunden sein, da er sonst ja nirgends angeschlossen 
wäre und der Pin einfach "irgendwas" liest.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Eing.C3.A4nge_.28Wie_kommen_Signale_in_den_.C2.B5C.29 
-> Taster und Schalter
(Firma: Vescomp) #3832375
Lesenswert?

erfusta schrieb:
> Danach funktioniert der Code aus dem letzten Anhang. Mal schauen, ob ich
> das Ding nun fertig bekomme. Danke! :)

 Vorschlag:
 Mach mal eine function z.B. RollDice.
 Da machst du dann deine rand(), Abfrage usw.
 Und lass mal die Wurfel langsam ausrollen, etwa so:
1
   uint16_t dly = 200;
2
   uint8_t count;
3

4
   for (count=1; count < 6; count++) {
5
      num = rand()%6+1;
6
      PORTB = 0x10;
7

8
      if ( num == 1 )
9
      {
10
        PORTB |= (1<<PB0);
11
        ...
12
        ...
13
      }
14

15
      _delay_ms(dly);
16
      dly += 100;
17
   }
Gast #3832508
Lesenswert?

Marc Vesely schrieb:
> Vorschlag:
>  Mach mal eine function z.B. RollDice.
>  Da machst du dann deine rand(), Abfrage usw.
>  Und lass mal die Wurfel langsam ausrollen, etwa so:

Danke, werde ich probieren.

Ich habe es gestern im Übrigen noch geschafft das Ganze zum laufen zu 
bekommen.
Interessantwerweise Würfelt der Würfel immer die gleichen Zahlen, sprich 
die random Funktion ist bei mir nicht wirklich random ...
Nach dem Einschalten: 2-6-4-1, jedes mal gleich.

Jemand eine Idee wieso? Wird das evtl im RAM gespeichert?

Gruß
#3832535
Lesenswert?

erfusta schrieb:
> Jemand eine Idee wieso?

Die Startbedingung ist immer gleich. Da du nicht Uhrzeit und Datum 
dazurechnen kannst, um immer eine andere Startbedingung zu haben, musst 
du dem Zufall anders auf die Sprünge helfen.

Eine einfache Möglichkeit wäre, die Random-Funktion nach dem 
Programmstart einfach in einer Schleife laufen zu lassen, die mit 
Tastendruck beendet wird. Die Zeit vom Einschalten bis zum Tastendruck 
ist immer unterschiedlich. Dann bekommst du auch immer unterschiedliche 
Zahlen.

mfg.
Gast #3832556
Lesenswert?

@Thomas Eckmann:

>>Marc Vesely schrieb:
>> Gib's zu, du hast ins .lss gekiekt ?

>>Nein, warum?
_________________________________________________________
>Da steht:
>   PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3);

leuchtet mir ein, was es tut

>PORTB &= 0xFE | 0x02 | 0x04 | 0x08
>
>0xFE | 0x02 | 0x04 | 0x08 = 0xFE

Thomas, könntest Du bitte nochmal gena uerklären, was die beiden 
Anweisungen tun? und warum ist bei der unteren das "=" auf der rechten 
Position?


>Und dann ist nur noch ein Bit zu löschen.




>genau genommen wird es nicht wegoptimert, sondern das ist eine
>Konstante, die errechnet und eingesetzt wird. Da der Compiler schlau
>ist, nimmt er für das eine Bit auch den passenden Befehl, anstatt
>Read-Modify-Write. Das ist allerdings eine Optimierung.
>
>Geht also schön schnell, funktioniert aber nicht wie vom TO erwartet.
>
>mfg.
#3832570
Lesenswert?

tommyProg schrieb:
> @Thomas Eckmann:
>
>>>Marc Vesely schrieb:
>>> Gib's zu, du hast ins .lss gekiekt ?
>
>>>Nein, warum?
> ___________________________________________________________
>>Da steht:
>>   PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3);
>
> leuchtet mir ein, was es tut
>
>>PORTB &= 0xFE | 0x02 | 0x04 | 0x08
>>
>>0xFE | 0x02 | 0x04 | 0x08 = 0xFE
>
> Thomas, könntest Du bitte nochmal gena uerklären, was die beiden
> Anweisungen tun?

Welche beiden?

> und warum ist bei der unteren das "=" auf der rechten
> Position?

Das ist keine C Anweisung.
Das ist einfach nur der Rechengang.
1
   1           ist einfach nur binär 00000001
2
   1 <<        diese binäre 1 wird nach links geschoben. Um wieviel?
3
   1 << PB0    Aha! Um PB0 Stellen. PB0, das ist einfach nur ein anderes
4
               Wort für 0. Also schieb mal 00000001 um 0 Stellen nach links
5
               Das Ergebnis ist binär 00000001. Das'binär' deute ich in
6
               weiterer Folge mit dem Präfix 0b an. Also 0b00000001
7

8
   ~( 1<<PB0)  die 0b00000001 werden also invertiert.
9
               Neues Zwischenergebnis ist also 0b11111110
10

11
               Und da mir binäre Schreibweise auf Dauer zu blöd ist,
12
               schreib ich dieselbe Zahl Hexadezimal auf. Jede 8 Bit
13
               Binärzahl lässt sich ach als 2 stellige Hex-Zahl darstellen
14
               ohne dass man gross rechnen muss. Einfach die 8 Bit in der
15
               Mitte in2 4-Bit Einheiten teilen und getreu
16

17
               0000    0             1000    8
18
               0001    1             1001    9
19
               0010    2             1010    A
20
               0011    3             1011    B
21
               0100    4             1100    C
22
               0101    5             1101    D
23
               0110    6             1110    E
24
               0111    7             1111    F
25

26
               neu anschreiben.
27
               Aus 0b11111110 wird also 1111 1110 und das wird Hexadezimal
28
               als 0xFE geschrieben.

dasselbe für die anderen Teilausdrücke.
Aus (1<<PB1) wird 0x02
Aus (1<<PB2) wird 0x04
Aus (1<<PB3) wird 0x08

und dann oderst du die Einzelteile zusammen
1
   Hex        Binär
2

3
    0xFE      0b11111110
4
 |  0x02      0b00000010
5
-------------------------
6
 ergibt       0b11111110
7
 |  0x04      0b00000100
8
-------------------------
9
 ergibt       0b11111110
10
 | 0x08       0b00001000
11
-------------------------
12
  ergibt      0b11111110

0b11111110, das ist aber nichts anders als Hexadezimal 0xFE

Das Ergebnis von
1
    ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3);
isr also ausgerechnet die Zahl 0xFE.

Und mit der wird dann das PORT Register verundet.
#3832581
Lesenswert?

Und nimm den Kommentar am Anfang raus
1
/*
2
 * main.c
3
 * 
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
...

sowas ist lächerlich.
Du kannst kaum programmieren, tust aber so, als ob du bei den Grossen 
mitspielst. Das ist genauso lächerlich, wie die Skifahrer, die sich kaum 
auf den Bretteln halten können aber die tollste und teuerste Ausrüstung 
haben und auf der Hütte angeben, wie schnell sie nicht die Streif runter 
gefahren wären.
#3832596
Lesenswert?

tommyProg schrieb:
> Thomas, könntest Du bitte nochmal gena uerklären, was die beiden
> Anweisungen tun? und warum ist bei der unteren das "=" auf der rechten
> Position?

Wenn man noch am überlegen ist, wie man es schreiben soll, hat 
Karl-Heinz, sofern er online ist, schon die perfekte Erklärung fertig:

Karl Heinz schrieb:
> Das ist keine C Anweisung.
> Das ist einfach nur der Rechengang.

mfg.
Gast #3832943
Lesenswert?

Hallo,

Karl Heinz schrieb:
> sowas ist lächerlich.
> Du kannst kaum programmieren, tust aber so, als ob du bei den Grossen
> mitspielst. Das ist genauso lächerlich, wie die Skifahrer, die sich kaum
> auf den Bretteln halten können aber die tollste und teuerste Ausrüstung
> haben und auf der Hütte angeben, wie schnell sie nicht die Streif runter
> gefahren wären.

Zunächst einmal, vielen Dank für deine guten Erklärungen bzlg den Bits, 
ich werde mich weiter damit beschäftigen.
Danke auch an alle anderen, mein Würfel funktioniert nun erstmal, ich 
werde nun eure Kommentare Stück für Stück einarbeiten, und mich 
versuchen zu verbessern.

Zu deinem letzten Kommentar: Ich bin doch sehr erstaunt darüber.
Ich habe im Startpost sowie im weiteren Verlauf deutlich klar gemacht, 
dass ich Anfangs absolut keine Ahnung hatte was ich tat, und das ich ein 
absoluter Anfänger bin.
Als Anfänger nutzt man auch IDEs, mit vordefinierten Templates. Nicht 
jeder konnte mit vim und avr-gcc auf der Konsole bei seinem ersten 
Projekt herumjonglieren.
Meine IDE, in dem fall Geany, fügt diesen Text automatisiert ein, ich 
habe ihn nicht weiter beachtet, und mich nicht darum kümmern.

Ich werde aber in Zukunft darauf achten, dass meine IDEs nichts, was 
meinem "Skill-Level" nicht entsprechen könnte, einfügt, ok? :)

Nein, mal im Ernst: Wie gesagt, deine Erklärungen haben mir viel 
geholfen, wirklich Danke dafür. Das letzte war aber meiner Meinung nach 
sinnloses herumgebashe, da ich oft erwähnt habe, dass ich Anfänger bin 
...

Gruß

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