PWM-Messung mit ATTiny15 - INT0 TIMER0
Hallo Zusammen,
ich habe eine Frage zur Nutzung eines ATTiny15L zur "Messung" (eher Detektion von 2 Werten (an/aus = max/min) eines
PWM-Signals am Empfänger einer Modellfernsteuerung.
Zum grundsätzlichen Test habe ich zunächst ein Programm für einen AT MEGA 8 geschrieben, was auch ganz gut funktioniert.
Es liefert je nach Breite des H-Impulses (hab einen Servotester am INT-Eingang angeschlossen) entsp. valide Timerwerte.
Der Code für den MEGA8 sieht so aus:
Code:
' Testprogramm zur Auswertung eines Servosignals (PWM) und Anzeige
' der Wertes (Timer) auf dem LCD DIsplay (Typ: EA W204B-NLW (Reichelt)
'
' Zuordnung: LCD RW = Pin5 = GND
' LCD RS = Pin4 = PortC.5
' LCD E = Pin6 = PortC.4
' LCD DB4 = Pin11 = PortC.3
' LCD DB5 = Pin12 = PortC.2
' LCD DB6 = Pin13 = PortC.1
' LCD DB7 = Pin14 = PortD.2
' LCD GND = Pin1
' LCD Vdd = Pin2 (+5V)
' LCD Vee = Pin3 (Contrast)
' LCD LED+ = Pin15
' LCD LED- = Pin16
'
' Interrup-Eingang Mode: Change Pin: PD2 (4) = Servosignal (PWM H-Pgel: ~1.6 - 2.5ms)
$regfile = "m8def.dat" ' MC-Definitionen laden
$crystal = 16000000 ' Quarzfrequenz
Dim A As Byte ' Variable deklarieren
' der folgende Befehl ordnet die PORT-Pins den Signalen
' gemäß der obigen Verkabelung zu
Dim Timerwert As Byte ' Übergabevariable des Timers
Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
Config Lcd = 20 * 4 ' definiert das Display als 20 x 4
Config Lcdbus = 4 ' definiert 4Bit-Kommunikation
Config Timer0 = Timer , Prescale = 1024 ' Konfiguration Timer0 auf 64 Mikrosek.
Enable Timer0 ' pro Takt, überlauf bei ca. 16ms
' bei 16MHz: 1/(16.000.000/1024) = ein TimerIcement
' alle 64 Mikrosek
'
'
Config Int0 = Change ' Konfiguration Int0 auf wechselnde Flanke
Enable Interrupts ' einschalten der Interrupts
Enable Int0 ' einschalten von Interrupt Int0
On Int0 Servowert ' Definition Sprungmarke INT0
Cls ' Display löschen
Lcd "INT-TESTER" ' Text auf das Display schreiben
Do ' Hauptschleife
Locate 3 , 1 : Lcd "Servo: " : Lcd Timerwert ' Augabe der Wertes auf Diplayposition (Zeile, Spalte)
Loop
End
Servowert:
' Interrupt-Routine (INT0)
Timerwert = Timer0 ' Timer-Wert wegspeichern und
Timer0 = 0 ' zurücksetzen
Return
End
Jetzt habe ich das Programm für den ATTiny15 umgeschrieben - musste leider die Erfahrung machen, das dieser Chip
über kein SRAM verfügt, was man nutzen kann … aber für die Anforderung sollte es reichen.
Habe auch schon mitbekommen, das BASCOM nicht so gut geeignet ist um diese "kleinen" MC's zu programmieren ;-(
Zunächst habe ich 2 LED's an die Ports B.3 und B.4 und das PWM-Signal an den INT0 (Pin7) anschlossen.
Die LED an B.4 soll leuchten wenn der Min-Wert (Länge des H-Pegels ~1ms) des PWM-Signals anliegt und die LED an B.3 soll
leuchten, wenn der Max-Wert (Länge des H-Pegels ~2.5ms) des PWM-Signals anliegt
Leider funktioniert mein Programm nicht so richtig … egal wie lang der H-Impuls am INT-Eingang ist, es wird immer die LED
am Port B.3 eingeschaltet. Das würde bedeuten, dass der Wert des Timers immer größer ist, als mein Schwellwert von "9"
D.h. prizipiell muss also der INT ausgelöst werden … es scheint jedoch ein Problem mit dem Timer-Wert zu geben.
Ich habe auch schon mit div. Schwellwerten experimentiert - es wird aber immer die LED an B.3 aktiviert.
Habe ich bei der Berechnung etwas falsch gemacht ? Kann man die von mir verwendeten Operatoren und Befehle für
den ATTiny15 überhaupt verwenden?
Berechnung:
System-Takt= 1.6MHz
Prescaler 256 (Timer0)
1/(1.600.000/256) = ein TimerIncrement alle 160Mikrosekunden
Bei H-Impulslängen von ~1ms - 2.5ms müssten Timerwerte von 6(min) und 12(max) herauskommen - die Mitte (Schwellwert)
liegt bei 9
Hier der Code für den ATTiny15:
Code:
' Auswertung eines PWM-Servosignals (ein Kanal)
' PWM-Signal H-Pegel zwischen ~1ms und 2.5ms
' INT bei wechselnder Flanke
$regfile = "ATtiny15.DAT" ' MC-Definitionen laden
$crystal = 1600000 ' Quarzfrequenz (internal Clock 1.6 Mhz)
Config Portb.4 = Output ' Status-LED am Port B.4
Config Portb.3 = Output ' Status-LED am Port B.3
Config Timer0 = Timer , Prescale = 256 ' Config Timer0 auf 160 Mikrosekunden pro Takt,
Enable Timer0 ' Überlauf bei ca. 40ms
' bei 1.6MHz: 1/(1.600.000/256) = ein TimerIncrement
' alle 160 Mikrosek
' zu erwartender Zählerbereich von ~6 bei 1ms PWM
' und ~12 bei 2.5ms PWM
Config Int0 = Change ' Konfiguration Int0 wechselnde Flanke
Enable Interrupts ' Einschalten der Interrupts
Enable Int0 ' Einschalten Von Interrupt Int0
On Int0 Servowert ' Definition Sprungmarke INT0
Portb.4 = 0 ' beide Ports aus (LED aus)
Portb.3 = 0
Do ' Hauptschleife
Loop
End
Servowert: ' Interrupt-Routine (INT0)
If Timer0 < 9 Then ' Schwellwert des Zählers gemittelt zwischen
Portb.4 = 1 ' den maximalen Werten: 6 und 12 = 9
Portb.3 = 0
Else
Portb.4 = 0
Portb.3 = 1
End If
Timer0 = 0 ' Timer zurücksetzen
Return
End
Wäre super, wenn jemand von den Experten mir einen Tipp geben könnte, was ich hier falsch gemacht habe.
Vielen Dank,
Ulf
Problem eingegrenzt ... aber
Hallo,
ich habe nach einigen Tests das Problem eingegrenzt. Es scheint an dem Code in der ISr des INT0 zu liegen - anscheinend sind bereits die paar Zeilen Code zu viel für einen Tiny15 .. sogar für einen MEGA8. Ich habe die gleiche Auswertung (also z.B. IF TCNT0 < 25 Then ...) im MEGA8 nachprogrammiert.
Und siehe da ... selbst der MEGA8 ist dabei regelmäßig "abgestürzt".
Vermutlich erzeugt BASCOM beim compilieren soviel HEX-Code, dass es für die ISR zuviel wird (ich vermute mal "<" ">" wird recht komplexer Code beim Compilieren). Whatever ... ich breche an dieser Stelle zunächst ab und werde mir einen ATTiny25 besorgen und damit weitermachen ... der hat zumindest 128bytes SRAM (für Variablen) ;-)
PS die Definition mit "CONFIG PORTB.3 = Input" funktioniert sehr gut wobei CONFIG PINB.3 = INPUT zwar keine Fehlermeldung erzeugt hat, aber auch irgendwie nicht funktioniert hat - habe das aber auch nicht weiter analysiert. Trotzdem Danke für den Tipp!
Ich melde mich wieder wenn ich den ATTiny25 habe ;-)
VG
Ulf