;Schaltmodul für AVR Tiny15 zum Einsatz im Modellbau. ;Es werden mit einem Kanalimpuls zwei Schaltausgänge gesteuert, ;die in vier verschiedenen Betriebsarten arbeiten können, ;welche mittels zweier analoger Steuerspannungen (Trimmpotis) ;eingestellt werden. ;Das Modul hat einen Impulseingang (1,0ms...2,0ms), ;ein Poti zum Trimmen des Schaltpunktes (Differenz zu Neutralpunkt) ;ein Poti zum Einstellen von Betriebsart und eines weiteren Parameters (Zeit), ;zwei Ausgänge zum Ansteuern von Schalttransistoren. ;Das Modul arbeitet mit Auto-Neutralscan, der 15. empfangenen Impuls ;(300ms nach dem Einschalten) wird als Neutralpunkt gewertet. ;Dies gibt der Anlage Zeit zum Einschwingen. ;Erst danach werden die Schaltausgänge unterstützt. ;Die empfangenen Impulsbreiten werden digitalisiert. Dazu wird der Wertebereich ;eines Bytes (0...255) bei einer Auflösung von 10µs je Ziffer genutzt. ;Gültige Impulsbreiten von 1,0ms bis 2,0ms entsprechen Zahlenwerten von 100 bis 200. ;Betriebsarten: ;Die Betriebsart wird mit dem Betriebsart-Trimmpoti eingestellt. ;Dazu ist der Stellbereich in 4 Sektoren aufgeteilt, die jeweils einer ;Betriebsart entsprechen. Durch feinfühliges Einstellen innerhalb des ;Sektors kann ein weiterer Parameter (Verzögerung, Blinkfrequenz, ;Untermode) eingestellt werden. ;1,2 Zeitschalter: (0% bis 49% des Stellbereiches des Betriebsart-Potis) ; (2 gleiche Modi mit verschiedenen Zeitbereichen, die direkt ; aneinander anschließen und daher als ein Bereich wirken) ; Treffen 8 Impulse mit der Impulsbreite des oberen oder unteren Schaltpunktes ein ; (also im Fangbereich), so wird der entsprechende Schaltausgang aktiviert. ; Danach läuft ein Timer ab, der den Schaltausgang wieder deaktiviert. ; Die Zeit ist durch feinfühliges Einstellen des Betriebsart-Potis ; innerhalb der Zeitschalter-Sektoren einzustellen. Beide Schaltausgänge arbeiten dabei ; unabhängig voneinander, nutzen aber die gleiche Verzögerungszeit. ; Nach Ablauf der Zeit wird abgeschaltet, auch wenn die Impulsbreite immer noch im ; Fangbereich liegen sollte. Dies erlaubt das das Erzeugen kurzer prellfreier Schaltimpulse. ; Die Basis-Zeit (1% vom Endwert) wird für Betriebsart 1 mittels der Konstante 'basz1' ; definiert. für Betriebsart 2 mittels der Konstante 'basz2'. ;3 Blinker: (50% bis 74% des Stellbereiches des Betriebsart-Potis) ; Das Modul ist mit dem Kanalimpuls für das Lenkservo anzusteuern. ; Mit dem Schaltpunkt-Poti ist die Ansprechschwelle einzustellen. Im Gegensatz zu den anderen ; Betriebsarten wirkt hier kein "Fangbereich", sondern das Überschreiten der Schwelle. ; Mit dem Betriebsart-Poti ist innerhalb des Betriebsart-Sektors die Blinkfrequenz ; einzustellen. Somit generiert das Modul beim Lenken die Blinklicht-Impulse. ;4a Schaltbetrieb: (75% bis 87% des Stellbereiches des Betriebsart-Potis) ; Treffen mehrere Impulse ein, die einem der Schaltpunkte entsprechen, ; so wird der jeweilige Schaltausgang eingeschaltet. Verlässt die Eingangsimpulsbreite ; den Fangbereich, so wird der Ausgang wieder deaktiviert. Beide Schaltausgänge können ; nicht gleichzeitig aktiviert werden. ;4b Toggle-Betrieb: (88% bis 100% des Stellbereiches des Betriebsart-Potis) ; Treffen mehrere Impulse ein, die einem der Schaltpunkte entsprechen, ; so wird der jeweilige Schaltausgang getoggelt. Somit kann durch wiederholtes Schalten ; zwischen "ein" und "aus" hin und her geschaltet werden. Beide Schaltausgänge arbeiten ; dabei unabhängig voneinander. ;Impulsbreitenerkennung... ;Entspricht die Eingangsimpulsbreite nicht dem beim Start gescannten Neutralpunkt, dann wird ;zuerst die Richtung der Abweichung (kürzer oder länger als Neutralpunkt) in 'Flags.ineg' gesichert. ;Dann wird der Betrag der Differenz zum Neutralpunkt ermittelt und als positive Zahl zum Vergleich ;mit dem Schaltpunkt (Wert aus Schaltpunkt-Poti) bereitgestellt. Die folgende Beschreibung der ;Impulsbreitenerkennung bezieht sich daher immer auf die absolute Differenz zum Neutralpunkt, ;das Vorzeichen (kurzer oder langer Impuls) ist ja schon bekannt und gesichert. Somit wirkt die ;Erkennung für kurze und lange Impulse gleichermaßen, obwohl es im Text so aussieht, als ob es ;nur "einen" Schaltpunkt gibt, denn dieser Schaltpunkt wirkt vom Neutralpunkt aus gesehen in beiden ;Richtungen der Impulsbreite. ;Schaltpunkt, Fangbereich... ;In den Betriebsarten Zeitschalter, Schalter und Togglen wird mit dem Schaltpunkt-Poti ein Schaltpunkt ;eingestellt, der nach oben und unten um die Konstante "fang" zu einem Fangbereich erweitert ;wird. Nur die Impulsbreiten, die im Fangbereich liegen, werden als gültige Schaltimpulse ;gewertet, alle anderen Impulsbreiten (darüber und darunter) gelten als Neutralwert. ;Um eine Schalthandlung auszulösen, müssen exakt 8 aufeinanderfolgende Impulse im ;Fangbereich liegen. Jeder weitere gültige Impuls (nach Auslösen des Schaltvorgangs) wird ignoriert. ;Jeder Impuls außerhalb des Fangbereiches (darunter und darüber) setzt den Zähler zurück. ;Damit ist es möglich, bei geeignetem Sender zwei (oder mehr?) Schaltmodule mit einem ;Fernsteuerkanal zu betreiben indem man z.B. ein Modul auf 0,2ms Schaltpunkt einstellt ;(es reagiert dann bei 1,3ms und 1,7ms), das andere auf 0,4ms (Reaktion auf 1,1ms und 1,9ms). ;Beispiel (gilt nicht für Blinker): Schaltpunkt=20, Neutralpunkt=150, fang=5 erkennt: ; 125-135 (1,25ms bis 1,35ms) als Schaltsignal "a" und ; 165-175 (1,65ms bis 1,75ms) als Schaltsignal "b" und ;alle Impulsbreiten außerhalb dieser beiden Fenster als Neutralwert, egal ob drüber oder drunter. ;Schaltpunkt, Schaltschwelle... ;In der Betriebsart Blinker wird mit dem Schaltpunkt-Poti die Schaltschwelle eingestellt. ;Damit werden alle Impulsbreiten, die vom Neutralpunkt aus gesehen jenseits der Schaltschwelle ;liegen, als Einschalten gewertet (Kurvenfahrt). Nur der Bereich von Neutralpunkt-Schaltpunkt bis ;Neutralpunkt+Schaltpunkt wird als Ausschalten gewertet (Geradeausfahrt). ;Beispiel (gilt nur für Blinker) ;Schaltpunkt=10, Neutralpunkt=150, blihy=3 erkennt: ; 70-140 (0,70ms bis 1,40ms) als Schaltsignal "a" zum Einschalten und ; 160-230 (1,60ms bis 2,30ms) als Schaltsignal "b" zum Einschalten und ; 143-157 (1,43ms bis 1,57ms) als Neutralwert zum Ausschalten, aber (wegen Hysterese 'blihy') ; 141-159 (1,41ms bis 1,59ms) als Neutralwert, wenn Blinker noch aus ist. ; (c) 08/2004 by ...HanneS... ;Anschlussbelegung des Tiny15: ;Pin 1: Reset (über R an +5V) ;Pin 2: Steuereingang für Betriebsarten (Analogeingang) ;Pin 3: Trimmeingang für Schaltpunkt (Analogeingang) ;Pin 4: GND ;Pin 5: Ausgang für Schalttransistor ;Pin 6: Ausgang für Schalttransistor ;Pin 7: Impulseingang ;Pin 8: +5V ;Die Trimmpotis sind zwischen GND und Betriebsspannung zu schalten, ;mit Schleifer am Trimmeingang (C gegen Masse)... ;Damit die Kalibration des internen RC-Oszillators auf 1,6MHz funktionieren kann, ;muss das "Calibrationsbyte" mittels eines ISP-Programms aus dem Signature-Bereich ;des Tiny15 gelesen werden und in die letzten beiden Bytes des Flash-Speicherbereiches ;eingetragen werden. (eigentlich nur in das L-Byte der letzten Word-Zelle) ;Wird das versäumt, stimmt das Timing nicht!!! ;Funktionsbeschreibung (grob): ;- Analog-Digitalwandler (Vorteiler 128, Messdauer etwa 1,05ms) ; * erste Schaltpunkt-Messung wird durch Reset-Routine aktiviert, ; * jede weitere Schaltpunkt-Messung wird durch das Ende des Kanalimpulses aktiviert, denn ; * da ist genug Zeit für zwei Messungen während der MC schläft, und es kann kein Impuls- ; Interrupt blockiert (verzögert) werden, was die Genauigkeit der Impulsmessung erhöht. ; ADC-Interrupt: wechselweise entweder: ; * liest Schaltpunkt-Poti ein, ; * errechnet daraus den Schaltpunkt (0...63), ; * schaltet Quelle auf Betriebsart-Poti um. ; * aktiviert nächste Messung... ; oder: ; * liest Betriebsart-Poti ein, ; * errechnet daraus Betriebsart (0...3) und Zeitwert (1...127), ; * schaltet Quelle auf Schaltpunkt-Poti um, ; * nächste Messung wird erst nach Impulsende von Impuls-ISR aktiviert ;- Steigende Flanke am Impulseingang (Eingangsimpulsanfang) ; * setzt Timer1 auf 0 und startet ihn mit 100kHz, ; * zählt im Zeitschalterbetrieb die Verzögerung und schaltet die Ausgänge nach Zeitablauf aus ;- Fallende Flanke am Impulseingang (Eingangsimpulsende) ; * liest Timer1 aus (Eingangsimpulsbreite), ; * sorgt dafür, dass die ersten 14 empfangenen Impulse verworfen werden und ; der 15. Impuls als Neutralpunkt des Senders interpretiert wird, und ; erst ab 16.Impuls nach dem Einschalten Schalthandlungen ausgelöst werden. ; * stoppt Timer1, ; * prüft Impulsbreite auf Gültigkeit (imin, imax), ; * prüft Impulsabstand auf Minimalwert (mittels Timer0), ; * schaltet nach mehreren ungültigen Impulsen (Anzahl in Konstante "errors") Ausgänge ab, ; * setzt Timer0 auf Startwert (25,6ms vor Timeout für Impulsabstand), ; * prüft, ob Eingangsimpuls Schwellwert überschritten hat und schaltet Blinker ein (nur Blinker-Mode), ; * prüft, ob Eingangsimpuls Schwellwert unterschritten hat und schaltet Blinker aus (nur Blinker-Mode), ; * prüft, ob Eingangsimpuls im Fangbereich ist zählt 8 gültige Impulse ab (außer Blinker-Mode), ; * errechnet im Zeitschalter-Mode die Verzögerung, ; * aktiviert die nächsten zwei ADC-Messungen, da jetzt >18ms Zeit ist... ;- Timer1-Überlauf (Sende-Impulsende, Überlauf bei Impulsmessung wegen zu langem Impuls) ; * deaktiviert Timer1, (gemessener Impulswert ist dann 0, also illegal), ;- Timer0-Überlauf (Timeout vermisster Eingangsimpuls) ; * setzt Timer0 auf Startwert (25,6ms vor Timeout), ; * schaltet nach mehreren vermissten oder ungültigen Impulsen (Anzahl in Konstante "errors") Ausgänge ab, ;- Reset-Routine ; * kalibriert den internen RC-Oszillator aif 1,6MHz, ; * initialisiert beim Einschalten alle benötigten Ressourcen, ; * aktiviert die ersten beiden ADC-Messungen ;- Hauptprogramm ; * schickt den AVR in den Schlafmodus, von dem er von einem der auftretenden Interrupts ; geweckt wird. Dies erhöht die Genauigkeit der Timer, was aber hier keine große Rolle spielt. ;Timing: ;- Alle Programmteile (außer 'Schlafen') laufen in Interrupts. ;- Zwischen den Auslösen des Impulsflanken-IRQ vergeht 1...20ms, genug Zeit zur Abarbeitung ;- ADC wird immer nach Impulsende aktiviert, da sind min. 18ms Zeit, er braucht 2,1ms für beide Messungen ;- Timer0-Int tritt nur im Fehlerfall auf (Impulsausfall), kann daher den Ablauf nicht stören ;- Timer1-Int tritt nur im Fehlerfall auf (Impulsbreite zu lang), kann daher den Ablauf nicht stören ;Somit ist bei Empfang gültiger Fernsteuerimpulse sichergestellt, dass kein Interrupt aufgerufen wird, ;während noch eine andere ISR abgearbeitet wird. ;------------------------------------------------------------------------------ ;AVR-interne Hardware-Ressourcen: ;Timer0: Impulsabstandmessung für Error ;Timer0-Überlauf: Impulsausfall-Timeout ;Timer1: Impulsbreitenmessung Eingangsimpuls ;Timer1-Überlauf: Impulsbreitenfehlerbehandlung ;Ext.Interrupt, steigende Flanke: Beginn Impulsmessung, Zeitmessung/Abschaltung bei Zeitschalter ;Ext.Interrupt, fallende Flanke: Ende Impulsmessung, Auswertung, Gesamtsteuerung, ADC-Start ;ADC: periodisch laufend mit Interrupt, Start durch Reset und Impulsende, Auslesen wenn fertig .include"tn15def.inc" ;Konstanten / Parameter (Anpassung in sinnvollen Grenzen erlaubt): .equ tsw=96 ;Timer0-Startwert für 25,6ms Timeout-Error (Impulsausfall) (Def. 96) .equ tmin=tsw+90 ;Timer0-Vergleichswert für minimalen Impulsabstand (14,4ms) (Def. +90) .equ imin=70 ;Minimale Impulsbreite für Error (Def. 70, 0,7ms) .equ imax=231 ;Maximale Impulsbreite für Error (Def. 231, 2,3ms) .equ errors=10 ;Anzahl der erlaubten Impulsfehler (Def. 10) .equ blihy=3 ;Hysterese für Schaltpunkt im Blinker-Mode (Def. 3) .equ basb=2 ;Basiszeit Blinker (Def. 2) .equ basz1=1 ;Basiszeit (%-Raster) für Zeitschalter1 (in 20ms-Schritten) (Def. 1) .equ basz2=128 ;Basiszeit (%-Raster) für Zeitschalter2 (in 20ms-Schritten) (Def. 128) .equ fang=5 ;Fangbereich Impulserkennung, +/- wirkend in 10µs (Def. 5) ;Konstanten, fix (nicht ändern!) .equ bamux=3 ;Betriebsart-Muxwert ADC-Quelle = Pin 2, rechtsbündige Ausgabe .equ trmux=(1<$ff)? out osccal,r0 ;ja, kalibrieren ldi tmp,1<