TIME funktioniert nicht beim ATtiny44, wie kann ich das Problem lösen?
Hi,
habe mit einem 4 Zeilen Display und einem ATtiny44 einen einfachen Lichtschranken Rundenzähler für Schlitzrennbahnen gebastelt, hat alles gut funktioniert bis ich einen Zeitzähler brauchte der die Durchfahrt eines Slotcar korrekt erkennt und nur eine Runde zählt. Na ja, es funktioniert ( do : waitms 50 : until Spur_1 = 0 ) mit dem Nachteil das während den 50 ms die Spur 2 nicht erfasst wird wenn die Slotcars gleichzeitig durch die Lichtschranke fahren. Am PC war das kein Problem da bei Gambas man einfach mit ( Signal = Time : If Signal + 100 < time then : durchfahrt = 1 : endif ), und so etwas schaffe ich nicht mit Bascom.
Das ganze Programm:
Code:
' Compiler: Bascom-Demo 2.0.7.5
' Dateiname: Formel X.avr
' Funktion: ein Rundenzähler für Schlitzautos mit einem ATtiny44 auf einem 20x4 Display
' Datum: Start 01.02.2025, Stand 12.02.2025
' Von: Naubaddi foto-schubser@arcor.de
'
' ATtiny44 (B.3 RESET)
'
' +----v----+
' VCC | 1 14| GND
' PCINT8/XTAL1 B.0 | 2 13| A.0 ADC0/AREF/PCINT0
' PCINT9/XTAL2 B.1 | 3 12| A.1 ADC1/AIN0/PCINT1
' PCINT11/RESET/dW B.3 | 4 11| A.2 ADC2/AIN1/PCINT2
' PCINT10/INT0/OC0A/CKOUT B.2 | 5 10| A.3 ADC3/T0/PCINT3
' PCINT7/ICP/OC0B/ADC7 A.7 | 6 9| A.4 ADC4/USCK/SCL/T1/PCINT4
' PCINT6/OC1A/SDA/MOSI/ADC6 A.6 | 7 8| A.5 ADC5/DO/MISO/OC1B/PCINT5
' +---------+
'
' --- Mikrocontroler Daten... ----------------------------------------------------------------------------------
$regfile = "attiny44.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 40
$framesize = 40
' --- Deklarationen... -----------------------------------------------------------------------------------------
enable interrupts
config timer0 = timer , prescale = 256
on timer0 Timer_0
disable timer0
config porta = output
config portb = input
config lcdpin = pin , Db4 = porta.2 , Db5 = porta.3 , Db6 = porta.4 , Db7 = porta.5 , E = porta.0 , Rs = porta.1
config lcd = 20 * 4
cursor off : cls
Ampel_1 alias porta.6 : Ampel_1 = 0 ' Spannung für die Ampel Spur 1
Ampel_2 alias porta.7 : Ampel_2 = 0 ' Spannung für die Ampel Spur 2
Spur_1 alias pinb.1 ' Spur 1 und Auswahl -
Spur_2 alias pinb.2 ' Spur 2 und Auswahl +
Start_Stopp alias pinb.0 ' das Rennen starten/stoppen
' --- Variablen... ---------------------------------------------------------------------------------------------
dim Soll as byte : Soll = 122 ' 122,07 ist ca. eine Sekunde
dim Ist as byte : Ist = 1 ' Zeit-Zähler bis Ist > Soll erreicht wurde
dim blinken as byte : blinken = 0 ' blinken für die Runden, die Ampel, den Fehlstart...
dim Runden as byte : Runden = 20 ' die Anzahl der Runden für ein Rennen
dim Runde_Spur_1 as byte : Runde_Spur_1 = 0 ' die gefahrenen Runden auf Spur 1
dim Runde_Spur_2 as byte : Runde_Spur_2 = 0 ' die gefahrenen Runden auf Spur 2
dim Ampel as byte : Ampel = 0 ' die Startampel für Spur 1 und/oder Spur 2
dim Ampel_Z as byte : Ampel_Z = 0 ' ein Zähler für das Blinken der Ampel
dim Fehlstart as byte : Fehlstart = 0 ' ein Fahrer ist vor dem Startsignal losgefahren
dim rennen as byte : rennen = 0 ' läuft das Rennen? 0 = nein, 1 = ja
dim Z_formatiert as string * 2 : Z_formatiert = "" ' Zahlen rechtsbündige formatieren
' --- Programm Anfang ------------------------------------------------------------------------------------------
Z_formatiert = str(Runden)
locate 1,1 : lcd "Formel X " ; format(Z_formatiert , " ") ; " Runden"
locate 2,1 : lcd "--------------------"
locate 3,1 : lcd "Spur 1 ---- Runde 0"
locate 4,1 : lcd "Spur 2 ---- Runde 0"
do
gosub Runden_einstellen
if rennen = 1 then
Z_formatiert = str(Runden)
locate 1,12 : lcd ; format(Z_formatiert , " ") ; " Runden"
locate 2,1 : lcd "--------------------"
locate 3,1 : lcd "Spur 1 ---- Runde 0"
locate 4,1 : lcd "Spur 2 ---- Runde 0"
Runde_Spur_1 = 0 : Runde_Spur_2 = 0
Ampel = 0 : Ampel_1 = 0 : Ampel_2 = 0
gosub Ampelphase
if rennen = 1 then
do
if Spur_1 = 1 then
incr Runde_Spur_1
Z_formatiert = str(Runde_Spur_1)
locate 3,19 : lcd ; format(Z_formatiert , " ")
do : waitms 55 : loop until Spur_1 = 0
end if
if Spur_2 = 1 then
incr Runde_Spur_2
Z_formatiert = str(Runde_Spur_2)
locate 4,19 : lcd ; format(Z_formatiert , " ")
do : waitms 55 : loop until Spur_2 = 0
end if
if Runde_Spur_1 > Runden then
rennen = 0 : Ampel_1 = 1
locate 2,1 : lcd "- * ----------------"
locate 3,1 : lcd "Spur 1 hat gewonnen "
end if
if Runde_Spur_2 > Runden then
rennen = 0 : Ampel_2 = 1
locate 2,1 : lcd "---------------- * -"
locate 4,1 : lcd "Spur 2 hat gewonnen "
end if
if rennen = 0 then
do : waitms 55 : loop until Start_Stopp = 1
do : waitms 55 : loop until Start_Stopp = 0
locate 2,1 : lcd "--------------------"
else
gosub Abbruch
endif
loop until rennen = 0
end if
end if
loop
' --- Prozeduren, Funktionen... --------------------------------------------------------------------------------
Runden_einstellen:
Ampel_Z = 0 : blinken = 0
Ist = 1 : Soll = 122
enable timer0
do
if blinken = 1 then
locate 1,15 : lcd " "
else
locate 1,15 : lcd "Runden"
end if
if Spur_1 = 1 then
decr Runden
if Runden < 2 then : Runden = 99 : end if
Z_formatiert = str(Runden)
locate 1,12 : lcd ; format(Z_formatiert , " ") ; " Runden"
waitms 222
end if
if Spur_2 = 1 then
incr Runden
if Runden > 99 then : Runden = 2 : end if
Z_formatiert = str(Runden)
locate 1,12 : lcd ; format(Z_formatiert , " ") ; " Runden"
waitms 222
end if
loop until Start_Stopp = 1
rennen = 1
do : waitms 55 : loop until Start_Stopp = 0
disable timer0
return
' --------------------------------------------------------------------------------------------------------------
Ampelphase:
Ampel_Z = 0 : blinken = 0
Ist = 1 : Soll = 122 ' 122 = normal blinken, 33 = Fehlstart blinken
enable timer0
do
if Ampel_Z < 6 or Soll = 33 then
if Soll = 33 then : Ampel_Z = 0 : end if
if blinken = 1 then
Select case Ampel
case 0 : locate 2,1 : lcd "- * ------------ * -" : Ampel_1 = 1 : Ampel_2 = 1
case 1 : locate 2,1 : lcd "- * ------------ -" : Ampel_1 = 1 : Ampel_2 = 0
case 2 : locate 2,1 : lcd "- ------------ * -" : Ampel_1 = 0 : Ampel_2 = 1
end select
else
locate 2,1 : lcd "- ------------ -" : Ampel_1 = 0 : Ampel_2 = 0
end if
end if
if Soll <> 33 then
if Spur_1 = 1 then
Fehlstart = 3 : Ampel = 1
end if
if Spur_2 = 1 then
Fehlstart = 4 : Ampel = 2
end if
end if
if Fehlstart > 0 then
locate Fehlstart,8 : lcd " Fehlstart "
Fehlstart = 0
Ist = 1 : Soll = 33
end if
gosub Abbruch
loop until Ampel_Z > 9 or rennen = 0
locate 2,1 : lcd "--------------------" : Ampel_1 = 0 : Ampel_2 = 0
disable timer0
return
' --------------------------------------------------------------------------------------------------------------
Abbruch:
If Start_Stopp = 1 then
locate 2,1 : lcd "--------------------"
locate 3,8 : lcd " Abbruch "
locate 4,8 : lcd " --------- "
rennen = 0
do : waitms 55 : loop until Start_Stopp = 0
end if
return
' --------------------------------------------------------------------------------------------------------------
Timer_0:
if Ist > Soll then
Ist = 1
if blinken = 0 then
blinken = 1
else
blinken = 0
end if
incr Ampel_Z
else
incr Ist
end if
return
' --- Programm Ende --------------------------------------------------------------------------------------------
end
' --------------------------------------------------------------------------------------------------------------
und die Zeilen mit dem Problem:
Code:
if Spur_1 = 1 then
incr Runde_Spur_1
Z_formatiert = str(Runde_Spur_1)
locate 3,19 : lcd ; format(Z_formatiert , " ")
do : waitms 55 : loop until Spur_1 = 0
end if
if Spur_2 = 1 then
incr Runde_Spur_2
Z_formatiert = str(Runde_Spur_2)
locate 4,19 : lcd ; format(Z_formatiert , " ")
do : waitms 55 : loop until Spur_2 = 0
end if
Was ich brauche ist so etwas:
Code:
if Spur_1 = 1 then
if einfahrt = 0 then
einfahrt = time + 100
end if
if einfahrt < time then
incr Runde_Spur_1
Z_formatiert = str(Runde_Spur_1)
locate 3,19 : lcd ; format(Z_formatiert , " ")
einfahrt = 0
end if
end if
Hat Jemand eine Idee zu diesem Problem?
Grüßle, Naubaddi
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
habe mal ein Foto von dem fertigen Rundenzähler gemacht, so kann man besser erkennen worum es geht.
Anhang 36046
Grüßle, Naubaddi
Liste der Anhänge anzeigen (Anzahl: 1)
Hi Hannes,
Danke für die Anregungen und die Beispiele wie man es machen kann.
Zitat:
Zitat von
021aet04
...Ich weiß nicht ob Bascom Interrupts unterstützt...
Ja, BASCOM hat Interrupts welche ich auch benutze: timer0 für Spur 1 und timer1 für Spur 2, es sind die 2 Prozeduren am Ende des Programms. Das Programm funktioniert mittlerweile ja auch sehr zuverlässig, ein paar Verbesserungen und gut ist.
Zitat:
Zitat von
021aet04
...Was mir noch aufgefallen ist, ist die Variable "Blinken..."...
Die "if Blinken_1 = 0 then..." Schleife wurde auf Dein Anregen durch ein einfaches "toggle Blinken_1" ersetzt.
Zitat:
Zitat von
021aet04
...Wenn du die Eingänge per Sorftware entprellen willst, dann würde ich eine kurze Zeit wählen (z.B. 1ms) ...
Die Prellzeit muß lang sein weil z.B. das GoKart sehr viele Lücken hat und bei der Durchfahrt ca. 8 Runden zählt :-( , da reicht 1ms nicht aus.
Anhang 36048
So sieht es jetzt aus:
Code:
' Compiler: Bascom-Demo 2.0.7.5
' Dateiname: Formel X.avr
' Funktion: ein Rundenzähler für Schlitzautos mit einem ATtiny44 auf einem 20x4 Display
' Datum: Start 01.02.2025, Stand 17.02.2025
' Von: Naubaddi foto-schubser@arcor.de
'
' ATtiny44 (B.3 RESET)
'
' +----v----+
' VCC | 1 14| GND
' PCINT8/XTAL1 B.0 | 2 13| A.0 ADC0/AREF/PCINT0
' PCINT9/XTAL2 B.1 | 3 12| A.1 ADC1/AIN0/PCINT1
' PCINT11/RESET/dW B.3 | 4 11| A.2 ADC2/AIN1/PCINT2
' PCINT10/INT0/OC0A/CKOUT B.2 | 5 10| A.3 ADC3/T0/PCINT3
' PCINT7/ICP/OC0B/ADC7 A.7 | 6 9| A.4 ADC4/USCK/SCL/T1/PCINT4
' PCINT6/OC1A/SDA/MOSI/ADC6 A.6 | 7 8| A.5 ADC5/DO/MISO/OC1B/PCINT5
' +---------+
'
' --- Mikrocontroler Daten... ----------------------------------------------------------------------------------
$regfile = "attiny44.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 40
$framesize = 40
' --- Deklarationen... -----------------------------------------------------------------------------------------
enable interrupts
config timer0 = timer , prescale = 256 ' bei 8 Bit 256 für ca. eine Sekunde
on timer0 Timer_0
disable timer0
config timer1 = timer , prescale = 1 ' bei 16 Bit 1 für ca. eine Sekunde
on timer1 Timer_1
disable timer1
config porta = output
config portb = input
config lcdpin = pin , Db4 = porta.2 , Db5 = porta.3 , Db6 = porta.4 , Db7 = porta.5 , E = porta.0 , Rs = porta.1
config lcd = 20 * 4
cursor off : cls
Ampel_1 alias porta.6 : Ampel_1 = 0 ' Spannung für die Ampel Spur 1
Ampel_2 alias porta.7 : Ampel_2 = 0 ' Spannung für die Ampel Spur 2
Spur_1 alias pinb.1 ' Spur 1 und Auswahl -
Spur_2 alias pinb.2 ' Spur 2 und Auswahl +
Start_Stopp alias pinb.0 ' das Rennen starten/stoppen
' --- Variablen... ---------------------------------------------------------------------------------------------
dim Soll_1 as byte : Soll_1 = 122 ' 122,07 ist ca. eine Sekunde
dim Ist_1 as byte : Ist_1 = 1 ' Zeit-Zähler bis Ist_1 > Soll_1 erreicht wurde
dim blinken_1 as bit : blinken_1 = 0 ' blinken für die Runden, die Ampel, den Fehlstart...
dim Ampel_Z_1 as byte : Ampel_Z_1 = 0 ' ein Zähler für das blinken der Ampel
dim Soll_2 as byte : Soll_2 = 122 ' 122,07 ist ca. eine Sekunde
dim Ist_2 as byte : Ist_2 = 1 ' Zeit-Zähler bis Ist_2 > Soll_2 erreicht wurde
dim blinken_2 as bit : blinken_2 = 0 ' blinken für die Runden, die Ampel, den Fehlstart...
dim Ampel_Z_2 as byte : Ampel_Z_2 = 0 ' ein Zähler für das blinken der Ampel
dim Runden as byte : Runden = 20 ' die Anzahl der Runden für ein Rennen
dim Runde_Spur_1 as byte : Runde_Spur_1 = 0 ' die gefahrenen Runden auf Spur 1
dim Spur_1PZ as byte : Spur_1PZ = 0 ' die Prellzeit für Spur 1
dim Runde_Spur_2 as byte : Runde_Spur_2 = 0 ' die gefahrenen Runden auf Spur 2
dim Spur_2PZ as byte : Spur_2PZ = 0 ' die Prellzeit für Spur 2
dim Ampel as byte : Ampel = 0 ' die Startampel für Spur 1 und/oder Spur 2
dim Fehlstart as byte : Fehlstart = 0 ' ein Fahrer ist vor dem Startsignal losgefahren
dim rennen as byte : rennen = 0 ' läuft das Rennen? 0 = nein, 1 = ja
dim Z_formatiert as string * 2 : Z_formatiert = "" ' Zahlen rechtsbündige formatieren
' --- Programm Anfang ------------------------------------------------------------------------------------------
Z_formatiert = str(Runden)
locate 1,1 : lcd "Formel X " ; format(Z_formatiert , " ") ; " Runden"
locate 2,1 : lcd "--------------------"
locate 3,1 : lcd "Spur 1 ---- Runde 0"
locate 4,1 : lcd "Spur 2 ---- Runde 0"
do
gosub Runden_einstellen
if rennen = 1 then
Z_formatiert = str(Runden)
locate 1,12 : lcd ; format(Z_formatiert , " ") ; " Runden"
locate 2,1 : lcd "--------------------"
locate 3,1 : lcd "Spur 1 ---- Runde 0"
locate 4,1 : lcd "Spur 2 ---- Runde 0"
gosub Ampelphase
if rennen = 1 then
Runde_Spur_1 = 0 : Runde_Spur_2 = 0
Spur_1PZ = 0 : Spur_2PZ = 0
do
if Spur_1 = 1 or Spur_1PZ <> 0 then
if Spur_1PZ = 0 then
Ampel_1 = 1 : locate 2,1 : lcd "- * -"
incr Runde_Spur_1 : Z_formatiert = str(Runde_Spur_1)
locate 3,19 : lcd ; format(Z_formatiert , " ")
Ist_1 = 0 : Soll_1 = 222 : Spur_1PZ = 1
enable timer0
Ampel_1 = 0 : locate 2,1 : lcd "-----"
else
if Spur_1PZ > 120 then
disable timer0
Spur_1PZ = 0
end if
end if
end if
if Spur_2 = 1 or Spur_2PZ <> 0 then
if Spur_2PZ = 0 then
Ampel_2 = 1 : locate 2,16 : lcd "- * -"
incr Runde_Spur_2 : Z_formatiert = str(Runde_Spur_2)
locate 4,19 : lcd ; format(Z_formatiert , " ")
Ist_2 = 0 : Soll_2 = 222 : Spur_2PZ = 1
enable timer1
Ampel_2 = 0 : locate 2,16 : lcd "-----"
else
if Spur_2PZ > 120 then
disable timer1
Spur_2PZ = 0
end if
end if
end if
if Runde_Spur_1 > Runden then
rennen = 0 : Ampel_1 = 1
locate 2,1 : lcd "- * -"
locate 3,1 : lcd "Spur 1 hat gewonnen "
end if
if Runde_Spur_2 > Runden then
rennen = 0 : Ampel_2 = 1
locate 2,16 : lcd "- * -"
locate 4,1 : lcd "Spur 2 hat gewonnen "
end if
if rennen = 0 then
do : waitms 55 : loop until Start_Stopp = 1
do : waitms 55 : loop until Start_Stopp = 0
locate 2,1 : lcd "--------------------"
Ampel_1 = 0 : Ampel_2 = 0
else
gosub Abbruch
endif
loop until rennen = 0
end if
end if
loop
' --- Prozeduren, Funktionen... --------------------------------------------------------------------------------
Runden_einstellen:
Ist_1 = 1 : Soll_1 = 122 : blinken_1 = 0
enable timer0
do
if blinken_1 = 1 then
locate 1,15 : lcd " "
else
locate 1,15 : lcd "Runden"
end if
if Spur_1 = 1 then
decr Runden
if Runden < 2 then : Runden = 99 : end if
Z_formatiert = str(Runden)
locate 1,12 : lcd ; format(Z_formatiert , " ") ; " Runden"
waitms 222
end if
if Spur_2 = 1 then
incr Runden
if Runden > 99 then : Runden = 2 : end if
Z_formatiert = str(Runden)
locate 1,12 : lcd ; format(Z_formatiert , " ") ; " Runden"
waitms 222
end if
loop until Start_Stopp = 1
disable timer0
rennen = 1
do : waitms 55 : loop until Start_Stopp = 0
return
' --------------------------------------------------------------------------------------------------------------
Ampelphase:
Ist_1 = 1 : Soll_1 = 122 : blinken_1 = 0 ' 122 = normal blinken, 33 = Fehlstart blinken
Ampel_Z_1 = 0 : Ampel = 0
enable timer0
do
if Ampel_Z_1 < 6 or Soll_1 = 33 then
if Soll_1 = 33 then : Ampel_Z_1 = 0 : end if
if blinken_1 = 1 then
Select case Ampel
case 0 : locate 2,1 : lcd "- * ------------ * -" : Ampel_1 = 1 : Ampel_2 = 1
case 1 : locate 2,1 : lcd "- * ------------ -" : Ampel_1 = 1 : Ampel_2 = 0
case 2 : locate 2,1 : lcd "- ------------ * -" : Ampel_1 = 0 : Ampel_2 = 1
end select
else
locate 2,1 : lcd "- ------------ -"
Ampel_1 = 0 : Ampel_2 = 0
end if
end if
if Soll_1 <> 33 then
if Spur_1 = 1 then
Fehlstart = 3 : Ampel = 1
end if
if Spur_2 = 1 then
Fehlstart = 4 : Ampel = 2
end if
end if
if Fehlstart > 0 then
locate Fehlstart,8 : lcd " Fehlstart "
Fehlstart = 0
Ist_1 = 1 : Soll_1 = 33
end if
gosub Abbruch
loop until Ampel_Z_1 > 9 or rennen = 0
disable timer0
locate 2,1 : lcd "--------------------"
Ampel_1 = 0 : Ampel_2 = 0 : Ampel = 0
return
' --------------------------------------------------------------------------------------------------------------
Abbruch:
If Start_Stopp = 1 then
locate 2,1 : lcd "--------------------"
locate 3,8 : lcd " Abbruch "
locate 4,8 : lcd " --------- "
rennen = 0
do : waitms 55 : loop until Start_Stopp = 0
end if
return
' --------------------------------------------------------------------------------------------------------------
Timer_0:
if Ist_1 > Soll_1 then
Ist_1 = 1
toggle blinken_1
incr Ampel_Z_1
else
incr Ist_1
incr Spur_1PZ
end if
return
Timer_1:
if Ist_2 > Soll_2 then
Ist_2 = 1
toggle blinken_2
incr Ampel_Z_2
else
incr Ist_2
incr Spur_2PZ
end if
return
' --- Programm Ende --------------------------------------------------------------------------------------------
end
' --------------------------------------------------------------------------------------------------------------
Grüßle, Hermann