'Gaak, das Entenprogramm - So fing es jedenfalls an, denn zu Beginn war nur 'ein Schaltmodul zum Ein/Ausschalten eines Soundmoduls einer schwimmenden 'RC-gesteuerten Ente gefragt. Inzwischen ist es zu einem 4-fach-Schaltmodul 'mutiert, das auf wiederholtes schnelles Umschalten des Steuerknüppels eines 'anderweitig genutzten Kanals (Antrieb, Ruder) reagiert. 'Die Funktion ist Folgendermaßen: 'Durch schnelles Schalten des Steuerknüppels von der Neutralstellung zu einer 'Endlage (kurzer oder langer Kanalimpuls) wird ein Zähler erhöht, wobei jede 'Endlage ihren eigenen Zähler hat. Bleiben weitere Zählvorgänge aus, so wird 'die dem Zählerstand zugehörige Schalthandlung durchgeführt. Im Beispielcode 'wird bei kurzem Impuls ausgeschaltet, bei langem Impuls eingeschaltet. 'Anschlussbelegung des Tiny13: 'Pin 1: Reset, Widerstand 4k7...10k nach Pin 8 (VCC) 'Pin 2: PB3, Ausgang 3 'Pin 3: PB4, Ausgang 4 'Pin 4: GND, Masse 'Pin 5: PB0, Ausgang 1 'Pin 6: PB1, Impulseingang vom RC-Empfänger (über Schutzwiderstand 1k) 'Pin 7: PB2, Ausgang 2 'Pin 8: VCC, Versorgungsspannung, Kerko 100n nach GND, Reset-Widerstand 'Das Programm wurde bewusst ohne Interrupts geschrieben, da in Bascom die 'Interrupts aufgrund der kompletten Registersicherung unnötig lange dauern. 'Die Fusebits des Tiny13 sind folgendermaßen einzustellen: 'High-Fuse: 0xFB, Low-Fuse: 0x6A 'Dabei ist eigentlich nur Brown-Out auf 2,7 Volt eingestellt. Alle anderen 'Fuses sind im Auslieferungszustand des Tiny13 belassen worden. Die 'Takteinstellung erfolgt nicht per Fusebits, sondern per Software. 'Dazu muss der interne RC-Oszillator mit 9,6 MHz aktiviert sein. Der Zustand 'der CKDIV8-Fuse ist egal, der Clock-Prescaler wird per Software überschrieben. 'einige vordefinierte Parameter: Const Sperrzeit = 50 'Anzahl der ignorierten Impulse bei Start Const Zeitlimit = 30 'Zeitlimit zum Umschalten (in 20 ms) Const Zaehlzeit = 50 'Zeitlimit für Zählimpulse (in 20 ms) Const Maxposi = 130 'Schwellwert langer Impuls (75 bis 150) Const Mitposu = 105 'untere Grenze Mittenposition Const Mitposo = 120 'obere Grenze Mittenposition Const Minposi = 95 'Schwellwert kurzer Impuls (75 bis 150) Const Maxlimit = 180 'maximal erlaubte Impulsbreite Const Minlimit = 50 'minimal erlaubte Impulsbreite 'Per Simulator wird ermittelt, wieviele Rechentakte die Hauptschleife 'mindestens braucht, wenn kein Impulsende detektiert wird. Das Ergebnis 'wird hier eingetragen und ist für den Senderausfall-Timeout zuständig: Const Leerlauf = 92 '92 CPU-Takte je leeren Schleifendurchlauf Const Txaus = 25 'Senderausfall-Reaktionszeit in ms Const Auszeit = 4800 * Txaus / Leerlauf 'Startwert Senderausfallzähler 'Bascom-spezifische Deklarationen: $regfile = "attiny13.dat" 'Portnamen vereinbaren $crystal = 4800000 'Takt vereinbaren $hwstack = 4 'keine Interrupts, keine Unterprogramme $swstack = 4 'keine ByVal-Übergabewerte nötig $framesize = 4 'kein Rechenbereich für Funktionen nötig 'Den Portpins erstmal sinnvolle/sinnlose Namen geben: Ausg1 Alias Portb.0 'Steuerausgang 1 für Soundmodul Impuls Alias Pinb.1 'Impulseingang Ausg2 Alias Portb.2 'Steuerausgang 2 für Soundmodul Ausg3 Alias Portb.3 'Testausgang Max-Wert Ausg4 Alias Portb.4 'Testausgang Min-Wert 'Variablen einrichten: Dim Zsalt As Byte 'Zeitszempel Impulsbeginn Dim Posi As Byte 'Positionswert Kanalimpuls Dim Zeit1 As Byte 'CountDown 1 (Zeitfenster Knüppelbewegung) Dim Zeit2 As Byte 'CountDown 2 (Zeitfenster Zählvorgang) Dim Kunum As Byte 'Zähler für Anzahl der Knüppelbewegungen k Dim Lanum As Byte 'Zähler für Anzahl der Knüppelbewegungen l Dim Wachhund As Word 'Zeitzähler für Senderausfall Dim Softstart As Byte 'Unterdrücken der ersten Kanalimpulse Dim Merker As Byte 'Pool für Bitvariablen Ida Alias Merker.0 'Merker, ein neuer gültiger Impuls ist da 'Programmstart, Reset-Routine: 'Tiny13 auf 4,8 MHz umschalten: Clkpr = 128 'Taktvorteiler Schreibschutz aufheben Clkpr = 1 'Taktvorteiler auf 1:2 Clkpr = 1 'einstellen 'PB1 (Pin 6) wird der Impulseingang, alles andere werden Ausgänge Portb = &B00010 'Ports erstmal auf L-Pegel, PullUp 1 ein Ddrb = &B11101 'PB2 als Eingang, Rest als Ausgeng 'Timer einschalten, es werden keine Pin-Sonderfunktionen und auch kein 'Interrupt verwendet. Der Timer wird von der Hauptschleife ausgelesen und 'gelöscht. Tccr0b = 3 'Timer mit Vorteiler 1:64 starten Softstart = Sperrzeit 'erste 50 Kanalimpulse ignorieren 'Hauptschleife des Programms Do 'Beginn der Endlos-Schleife If Impuls = 0 Then 'nur bei L-Pegel am Impuls-Eingang Posi = Timer0 'Zeitstempel holen, Posi = Posi - Zsalt 'Differenz zur vorherigen Runde ermitteln, Zsalt = Timer0 'und alten Zeitstempel nachziehen 'Die Abfrage erfolgt ja nur während des L-Pegels. Die Differenz zwischen 'neuem und altem Zeitstempel kann nur dann einen plausiblen Wert (50...180) 'erreichen, wenn zwischen beiden Scanns ein H-Pegel (0,67...2,4ms) auftrat. 'Dies wird jetzt überprüft: Set Ida 'erstmal einen gültigen Impuls vermuten, 'also von einer korrekten Impulsbreite ausgehen, dann die Grenzwerte der 'Impulsbreite überprüfen und bei Überschreitung für ungültig erklären: If Posi > Maxlimit Then Reset Ida 'Impuls zu lang, ungültig If Posi < Minlimit Then Reset Ida 'Impuls zu kurz, ungültig If Softstart > 0 Then 'Einschaltsperre nach Start und TX-Ausfall Decr Softstart 'Sperrzähler runterzählen Reset Ida 'Impuls entwerten (ignorieren) End If 'Der Merker "Ida" entscheidet nun darüber, ob ein gültiger Kanalimpuls 'empfangen wurde oder nicht: If Ida = 1 Then 'falls ein Impuls im erlaubten Bereich kam: 'Es wurde ein gültiger Impuls empfangen. Da dies im regelmäßigen Abstand 'von etwa 20ms (Telegrammabstand des Senders) der Fall ist, kann dieser '"Takt" gleich als Zeittakt zum Herunterzählen der Timeouts missbraucht 'werden. Nur aktive Timeouts (ungleich 0) werden heruntergezählt. If Zeit1 > 0 Then Decr Zeit1 'Countdown 1 herunterzählen, falls aktiv If Zeit2 > 0 Then Decr Zeit2 'Countdown 2 herunterzählen, falls aktiv 'Die Count-Down-Zähler sind nun fertig. Jetzt wird der Wachhund gefüttert 'und gestreichelt, damit er die Ausgänge nicht abschaltet, denn es wurde 'ja ein gültiger Impuls empfangen, der Sender lebt also noch: Wachhund = Auszeit 'Senderausfall-TimeOut auf Startwert setzen 'Jetzt wird geprüft, ob die Impulsbreite innerhalb der Neutralposition 'liegt: If Posi < Mitposo Then 'wenn Impuls kürzer als obere Mitte ist: If Posi > Mitposu Then 'wenn Impuls länger als untere Mitte ist: 'Set Ausg2 'Hier wird nur das Zeitfenster zum Schalten der Gegenrichtung geöffnet. Zeit1 = Zeitlimit 'Knüppel-CountDown auf Startwert 'Else 'Reset Ausg2 End If 'Ende (Impuls ist länger als obere Mitte) 'Else 'Reset Ausg2 End If 'Ende (Impuls ist kürzer als untere Mitte) 'Jetzt wird geprüft, ob die Impulsbreite den Schwellwert einer 'Schaltposition überschreitet: If Posi < Minposi Then 'wenn Impuls kürzer als Schwellwert ist: 'Hier wird nur innerhalb des noch nicht abgelaufenen Knüppel- 'Zeitfensters auf kurzen Kanalimpuls reagiert: If Zeit1 > 0 Then 'ist Knüppel-CountDown noch aktiv, dann Incr Kunum 'Job-Nummer (kurze Richtung) hochzählen, Zeit1 = 0 'CountDown entwerten und Zeit2 = Zaehlzeit 'Zähl-CountDown auf Startwert End If 'Ende (Knüppel-CountDown noch aktiv) End If 'Ende (Impuls ist kleiner als Schwellwert) If Posi > Maxposi Then 'wenn Impuls länger als Schwellwert ist: 'Hier wird nur innerhalb des noch nicht abgelaufenen Knüppel- 'Zeitfensters auf langen Kanalimpuls reagiert: If Zeit1 > 0 Then 'ist Knüppel-CountDown noch aktiv, dann Incr Lanum 'Job-Nummer (lange Richtung) hochzählen, Zeit1 = 0 'CountDown entwerten und Zeit2 = Zaehlzeit 'Zähl-CountDown auf Startwert End If 'Ende (Knüppel-CountDown noch aktiv) End If 'Ende (Impuls ist größer als Schwellwert) 'Hier werden die Schalthandlungen ausgeführt, dabei sind, Set, Reset, Toggle 'und direkte Portzuweisungen zulässig: If Zeit2 = 1 Then 'wenn das Zähl-Zeitfenster abläuft, dann 'Es wurde verpasst, rechtzeitig weiter zu zählen, somit ist der 'aktuelle Zählerstand gültig und kann ausgewertet werden: If Kunum = 7 Then Portb = &B00010 'alle Ausgänge ausschalten If Kunum = 2 Then Reset Ausg1 'Ausgang 1 ausschalten If Kunum = 3 Then Reset Ausg2 'Ausgang 2 ausschalten If Kunum = 4 Then Reset Ausg3 'Ausgang 3 ausschalten If Kunum = 5 Then Reset Ausg4 'Ausgang 4 ausschalten If Lanum = 7 Then Portb = &B11111 'alle Ausgänge einschalten If Lanum = 2 Then Set Ausg1 'Ausgang 1 einschalten If Lanum = 3 Then Set Ausg2 'Ausgang 2 einschalten If Lanum = 4 Then Set Ausg3 'Ausgang 3 einschalten If Lanum = 5 Then Set Ausg4 'Ausgang 4 einschalten Kunum = 0 'Job-Nummer entwerten Lanum = 0 'Job-Nummer entwerten 'Zeit2 wird vor der nächsten Abfrage bereits vermindert und erreicht 'somit auch ohne weiteres Zutun 0, was weitere Zählvorgänge blockiert. End If 'Ende (wenn das Zähl-Zeitfenster abläuft) End If 'Ende (gültiger Impuls) End If 'Ende (L-Pegel liegt an) Decr Wachhund 'Timeout Impulsausfall herunterzählen If Wachhund = 0 Then Portb = &B00010 'angelaufen? - Ports ausschalten Softstart = Sperrzeit 'die nächsten Kanalimpulse ignorieren End If Loop 'zurück zum Beginn der Endlos-Schleife