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
Lesezeichen