Source Code Problem (Attiny2313 BASCOM)

Gast #682090
Lesenswert?

Guten Morgen alle. ! Ich bin es mal wieder :).

Habe jetzt meine Platine erweitert, indem ich einen Taster dran 
geschlossen habe der auch funktioniert. Pullup-Widerstände sind intern 
aktiviert.

Was ich möchte:

Wenn man einmal (Modus=1) auf die Taste drückt, soll die LED ständig 
leuchten.
Wenn man nochmal drückt (Modus=2), soll die LED in 1'er sek. Takt 
leuchten.
Wenn man nochmal drückt (Modus=3), wird sowas wie ein "reset" realisiert 
und die LED leuchtet wieder ständig.

Aber irgendwie klappt das nicht so, wie ich es möchte und kann meinen 
Fehler auch nicht finden.

Hier ist der Code:
1
$regfile = "2313def.dat"
2
$crystal = 12000000
3
$lib "mcsbyte.lbx"
4

5

6

7

8
Config Pinb.2 = Output
9
Portd = &B0100000
10

11
Dim Modus As Integer
12

13
Do
14

15
   If Pind.5 = 0 Then
16
         Modus = Modus + 1
17
   Else
18

19
   End If
20

21

22
   If Modus = 1 Then
23
      Portb.2 = 1
24
   End If
25

26
   If Modus = 2 Then
27

28
      Toggle Portb.2
29
      Wait 1
30
      Toggle Portb.2
31
      Wait 1
32
   End If
33

34
   If Modus = 3 Then
35
      Modus = 0
36
      Portb.2 = 1
37
   End If
38
                                                '//Weiße LED
39

40
Loop

Danke
#682101
Lesenswert?

Hallo,

was mir auffällt:
Du arbeitest mit dem Wait-Befehl, der hält dir das Programm an, wird in 
dieser Zeit ne Taste gedrückt bekommt das Programm das nicht mit. 
Verwende Statt des Wait-Befehls lieber nen Timer den du durchlaufen 
lässt, das hält dein Programm nicht an.
Du verwendest keine Tastenentprellung, solltest du aber nehmen das 
Programm wird sonst unzuverlässig und "springt". Verwende am besten den 
"Debounce" Befehl, in der Bascom-Hilfe steht ein Beispiel.
Wie ist der Pin des Tasters genau beschaltet? Nimmst du einen externen 
Pull-Up und der Taster zieht den Pin nach GND oder nimmst du den 
Internen R? Schreibe die Definitionen im Programm am Anfang lieber mal 
aus, das erleichtert die Fehlersuche ungemein.

Beschreibe mal genau was genau nicht funktioniert dann kann ich dir 
sicherlich helfen.

Roland :)
Gast #682128
Lesenswert?

Hallo Roland :)

Mein Schalter benutzt den internen PullUp Widerstand und ist so 
angeschlossen:
PD5------Taster----->GND


Also wenn ich auf den Taster einmal drücke, leuchtet diese ganz schnell 
und schwach und geht dann über zu den Blink Modus...


Kannst du meinen Source Code etwas bearbeiten ? Habe bis jetzt noch nie 
mit Timer'n gearbeitet.

Danke dir
#682132
Lesenswert?

Dein Programm wird (mit Ausnahme des Falles, wenn Modus den
Wert 2 hat) die do - Loop ein paar 10-tausend mal pro
Sekunde durchlaufen. Wenn also der Taster aus dem Grundzustand
heraus gedrückt ist, erhöhst du Modus um 1. Die darauffolgende
Abfrage erkennt dies auch und schaltet die LED ein. Aber:
Nach ein paar weiteren µSekunden beginnt die Schleife schon
wieder von vorne, die Taste ist immer noch gedrückt und dein
Programm erkennt schon wieder einen Tastendruck und schaltet
weiter in den Modus 2.

Du musst dir darüber im klaren sein, dass dein µC viel zu schnell
arbeitet, als dass du mit einem simplen

   If Pind.5 = 0 Then

einen einzelnen Tastendruck erkennen kannst. Selbst wenn du
ultraschnelle Finger hast, wird dein Programm diese Abfrage
viele tausend male in der Sekunde abarbeiten und demenstprechend
erkennt dein Programm viele tausend 'Tastendrücke'.
#682144
Lesenswert?

Hallo Peter,

ich werde dein Programm etwas bearbeiten und hier wieder Posten. Kann 
aber etwas dauern da ich heute erst in der Mittagspause dazu komme.

Was Karl Heinz Buchegger schreibt ist ein weiterer Punkt auf der Liste, 
der uC ist so schnell daß er die Taste mehrere Tausend mal pro Sekunde 
als gedrückt erkennt und rasend schnell die Modus-Variable 
weiterschaltet (ok, zugegeben die Wait befehle bremsen das etwas du 
bleibst immer bei denen hängen)
Der Debounce-Befehl verhindert die dann auch da der nur auf die Flanke 
und nicht auf den Zustand reagiert.
Was für eine Taktquelle verwendest du? Ext. Quarz?

Roland
#682544
Lesenswert?

So,

hier der Programmcode. Es ist zwar kein schönheitswettbewerb da nur 
schnell zusammengetippt aber er sollte laufen. Leider habe ich grade 
keinen Tiny2313 mit Testplatine da zum testen, könnte ich aber sonst 
morgen in der firma schnell auf dem Breadboard zusammenstöpseln.
Wenn jemand einen Fehler findet (auch ich bin nicht perfekt :) immer her 
damit.
Die "Blinkfrequenz" kann durch ändern des Vorteilers des Timer1 geändert 
werden oder wenns genau sein soll durch vorladen des Timers mit einem 
Wert.
Wenn was unklar ist Frag, dafür sind Foren ja nun mal da :D

Roland
1
$regfile = "attiny2313.dat"
2
$crystal = 12000000
3
$lib "mcsbyte.lbx"
4
$hwstack = 32
5
$swstack = 10
6
$framesize = 40
7

8
Config Portb.2 = Output                                     ' LED Ausgang
9
Config Portd.5 = Input                                      ' Taster Eingang
10
Portd.5 = 1                                                 ' Eingangs Pull-Up Widerstand Einschalten
11

12
Led Alias Portb.2                                           ' Alias-Namen zuweisen (besser wenn du Ports naher aendern willst)
13
Taster Alias Portd.5                                        ' wie oben :)
14

15

16
Config Timer1 = Timer , Prescale = 256                      ' Timer einrichten mit Vorteiler des Taktes, Blinkfrequenz kann hier geaendert werden
17
Start Timer1                                                ' Timer1 starten
18
On Timer1 Interrupt1                                        ' Interrupt Einrichten wenn Timer1 ueberläuft wird
19
Enable Interrupts                                           ' zum angegebenen Programmteil gesprungen
20

21
Config Debounce = 30                                        ' Entprellzeit in ms fuer das Debounce
22

23
Dim Modus As Byte                                           ' Statusvariable
24
Dim Blinken As Bit                                          ' Blink-Variable bedient von Timer1 :)
25

26
' Mainloop
27

28
Do
29
Debounce Pind.5 , 0 , Taster1 , Sub                         ' Bei Tastendruck wird jeweils EINMAL in die Subroutine gesprungen
30
If Modus = 0 Then Led = 1                                   ' LED einschalten wenn Modus = 0
31
If Modus = 1 Then Led = Blinken                             ' LED blinkt wenn Modus = 1
32
If Modus = 3 Then Modus = 0                                 ' Ruecksetzen wenn ueberlauf
33
Loop
34

35

36

37
' Subroutinen
38

39
Taster1:                                                    ' wird angesprungen wenn der Taster gedrueckt wird
40
Modus = Modus + 1                                           ' Tastervariable inkrementieren
41
Return                                                      ' Ruecksprung ins Hauptprogramm
42

43
' Interrupt-Routine von Timer1
44

45
Interrupt1:                                                 ' hier wird immmer hingesprungen wenn der Timer1 ueberlaeuft
46
Toggle Blinken                                              ' Blink-Variable wird mit jedem Aufruf getoggelt (=Umgeschaltet)
47
Return                                                      ' Ruecksprung ins hauptprogramm
48

49

50
End
Angehängte Dateien:
Gast #682869
Lesenswert?

Wow hört sich cool an.

Ich habe jetzt den Source Code drauf gebrannt und ihn getestet und habe 
folgendes festgestellt:

Wenn das Programm "startet" leuchtet die LED.  Das ist richtig.
Wenn man einmal klick ist die LED aus und blinkt auch nicht...das mit 
dem Reset funktioniert. Könnte das Problem an dem Prescaler liegen ? 
Kann man das ausrechnen wie groß dieser Wert sein muss, wenn man mit 12 
MHZ 1 sek erreichen möchte ?

Danke
Gast #682949
Lesenswert?

aso danke gut zu wissen... ich versuche gerade mein Gerät in das Gehäuse 
rein zu bekommen... naja wenn es dich interessiert.. hab ich mir eine 
Front-Fahrradbeleuchtung gebaut... die alte war kaputt und nicht so hell 
genug und hab mir das Gehäuse genommen, bischen rumgebastelt. Ich 
benutze eine superhelle weiße LED die sehr schönes Licht macht und 
jeweils links und rechts zwei blaue LEDs.. sieht vom weiten cool aus. 
Damit man mich besser sieht, soll das ganze blinken, wenn ich möchte 
(Taster=Modus) und darum hab ich das mit dem Attiny2313 realisiert und 
wenn ich was anderes will, einfach das Verhalten der LEDs 
umprogrammieren ;).

Danke
#683404
Lesenswert?

Hallo Peter,

sorry ich bin eben erst an das Proggie drangehockt, bin vorher wegen 
leichter Arbeitsüberlastung nicht dazu gekommen. :)

Hmm Interessante sache das, ich hätte aber noch ein paar 
Anmerkungen/Fragen dazu:

Wie wird die schaltung versorgt? Akkus, Batterien oder aus dem 
Fahrraddynamo.
Was für LEDs verwendest du, was für einen Strom wollen die haben? Wenn 
du mehr als 20mA aus einem Portpin des uC rausziehst machst du den auf 
Dauer kaputt. Lieber nen Transistor als "Verstärker" hintendran hängen. 
Falls du nur 20mA ziehst (pro LED) beachte das Maximum der VCC und 
GND-Pins, der ATtiny2313 kann soweit ich weiß max. 100mA. Genaueres 
steht im Datenblatt unter "Electrical Caracteristics".

Wenn ich das Proggie fertig habe poste ich das wieder hier :)

Roland
#683419
Lesenswert?

Hallo hier der Programmcode, habe diesen nochmals probiert und muß zu 
meiner Schande gestehen daß ein kleiner Fehler von mir drin war. Es ist 
alles korrekt eingestellt, aber ich habe vergessen dem Timer1 zu 
erlauben interrupts auszulösen :)
Sorry kann mal in der Hektik vorkommen :D
1
$regfile = "attiny2313.dat"
2
$crystal = 12000000
3
$hwstack = 32
4
$swstack = 10
5
$framesize = 40
6

7
Config Portb.2 = Output                                     ' LED Ausgang
8
Config Portd.5 = Input                                      ' Taster Eingang
9
Portd.5 = 1                                                 ' Eingangs Pull-Up Widerstand Einschalten
10

11
Led Alias Portb.2                                           ' Alias-Namen zuweisen (besser wenn du Ports naher aendern willst)
12
Taster Alias Portd.5                                        ' wie oben :)
13

14

15
Config Timer1 = Timer , Prescale = 256                      ' Timer einrichten mit Vorteiler des Taktes, Blinkfrequenz kann hier geaendert werden
16
Start Timer1                                                ' Timer1 starten
17
On Timer1 Isr                                               ' Interrupt Einrichten wenn Timer1 ueberläuft wird
18
Enable Timer1                                               ' interrupt Fuer Timer1 Freigeben
19
Enable Interrupts                                           ' zum angegebenen Programmteil gesprungen
20

21
Config Debounce = 30                                        ' Entprellzeit in ms fuer das Debounce
22

23
Dim Modus As Byte                                           ' Statusvariable
24
Dim Blinken As Byte                                         ' Blink-Variable bedient von Timer1 :)
25
Dim Test As Byte
26

27
' Mainloop
28

29
Do
30
Debounce Pind.5 , 0 , Taster1 , Sub                         ' Bei Tastendruck wird jeweils EINMAL in die Subroutine gesprungen
31
If Modus = 0 Then Led = 1                                   ' LED einschalten wenn Modus = 0
32
If Modus = 1 Then Led = Blinken                             ' LED blinkt wenn Modus = 1
33
If Modus = 2 Then Modus = 0                                 ' Ruecksetzen wenn ueberlauf
34
Print Blinken
35
Print Timer1
36
Waitms 200
37
Loop
38

39

40

41

42
' Subroutinen
43

44
Taster1:                                                    ' wird angesprungen wenn der Taster gedrueckt wird
45
Modus = Modus + 1                                           ' Tastervariable inkrementieren
46
Return                                                      ' Ruecksprung ins Hauptprogramm
47

48
' Interrupt-Routine von Timer1
49

50
Isr:                                                        ' hier wird immmer hingesprungen wenn der Timer1 ueberlaeuft
51
Blinken = Blinken + 1                                       ' Variable hin und her schalten
52
Return                                                      ' Ruecksprung ins hauptprogramm
53

54

55
End


Poste mal was für eine Spannungsquelle du verwendest. Je nach 
Stromversorgung solltest du in den Fusebits den Brown-Out einschalten 
damit der uC nicht "hängenbleibt" wenn die Versorgungsspannung 
zusammenbricht. Den Watchdog würde ich im Programmcode auch noch 
einschalten und konfigurieren der "fängt" den uC nach einem eventuellen 
Absturz wieder und startet den neu... :D

Je nach Schaltungsbelegung kannst du dir den Ein/Aus Schalter sparen 
wenn du den uC in den Power-Down Mode schickst (Der uC geht quasi pennen 
und klemmt vorher allen angeschlossenen Verbrauchern an den Portpins den 
Saft ab) der Strom verbrauch ist dann im uA-Bereich. :) "Aufwecken" 
kannst du diesen dann mittels eines "Level-Change" interrupt, d.h. wenn 
sich an dem besagten Pin was Tut wacht der uC wieder auf.

Roland
Angehängte Dateien:
Gast #683580
Lesenswert?

Hallo Roland !

Danke für dein Source Code, diesen werde ich es morgen testen können.

Ich benutze 3 mal 1.5V Batterien und habe bereits einen Ein/Aus Schalter 
dran geschlossen :P. Und natürlich habe ich diese super hellen LED's, 
welche bis zu 30mA nehmen, nicht direkt an den µC angeschlossen sondern 
habe dafür den ULN 2003AC (7 Darlington Transistor Array) benutzt ;)

Also:

µC Output---------Input ULN 2003AC | Output ULN 2003AC------>LED

Der ULN 2003 AC wird dann direkt mit der Batterie betrieben, wie der 
Attiny2313...

Das dürfte den Attiny2313 nich schaden.

peter
Gast #683843
Lesenswert?

Hi Roland !

Ok habs getestet, es funktioniert einwandfrei !

Danke.

Wenn ich den Prescaler Wert verkleine, blinkt die LED zwar schneller, 
aber nicht so schön regelmäßig, sondern sehr variierend.... könnte man 
das verhinden, wenn ja, wie ?

schönen tag noch.

peter
#684346
Lesenswert?

Hallo Peter,

schön das das Proggie geht :D Auf was hast du den Prescaler verändert, 
Poste bitte mal beispiele. Normalerweise rennt der Timer immer durch und 
es sollte keine unregelmäßigkeiten geben.
Bitte poste den Programmcode (nur der ausschnitt wo du was geändert hast 
reicht) und eine genaue beschreibung.

Wenn du die Zeit ganz genau einstellen willst (als sehr genau) dann 
solltest du den CTC-Mode des Timers verwenden. Damit sind auch "krumme" 
zwischenwerte der Timerzeiten möglich.

Roland :D

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