2-Kanal-Funkschaltinterface
Software
Der Bascom-Quellcode ist eigentlich gut dokumentiert, somit ist zur Software eigentlich nicht viel zu erläutern. Zuerst werden der Prozessortyp, dessen Taktfrequenz und die Stacks definiert:
'2-Kanal-Funk-Schaltinterface für Fernbedienung FS10, AM-Empfänger HFS301 433 MHz
$regfile = "attiny44.dat"
$hwstack = 32
$swstack = 10
$framesize = 40
$crystal = 8000000 ' 8 MHz interner Oszillator
|
Als nächstes werden 4 Portpins als Ausgänge deklariert und mit Aliasnamen versehen. Da Ausgänge beim Programmstart auf Low-Pegel sind und die Leuchtdioden nicht leuchten sollen, werden sie auf High-Pegel geschaltet (Set Ledx).
Config Porta.0 = Output
Led1 Alias Porta.0 ' LED 1
Set Led1 ' LED ausschalten
Config Porta.1 = Output
K1 Alias Porta.1 ' Relais 1
Config Porta.2 = Output
K2 Alias Porta.2 ' Relais 2
Config Porta.3 = Output
Led2 Alias Porta.3 ' LED 2
Set Led2 ' LED ausschalten
|
Danach definieren wir die Variablen, die wir benötigen. Die Einstellungen für die Tastaturebene und den Hauscode werden im EEPROM des AVR dauerhaft gespeichert (Eram)..
Dim Rxbit As Byte ' empfangenes Bit
Dim Rxready As Byte ' Interrupt fertig
Dim Rxcycle As Byte ' Wellenlänge
Dim Count As Byte ' Zähler
Count = 42 ' 42 Bits empfangen
Dim Praeambel(8) As Byte ' 8 Bit Präambel
Dim Typ(4) As Byte ' 4 Bit Typ
Dim Code(30) As Byte ' 30 Bits Daten
Dim Taste As Byte ' Taste
Dim Ebene_l As Byte ' Tastaturebene low
Dim Ebene_l_k1 As Byte ' eigene Tastaturebene Kanal 1 low
Dim Ebene_l_k1_eram As Eram Byte ' EEPROM eigene Tastaturebene Kanal 1 low
Dim Ebene_l_k2 As Byte ' eigene Tastaturebene Kanal 2 low
Dim Ebene_h As Byte ' Tastaturebene high
Dim Ebene_he As Byte ' eigene Tastaturebene high
Dim Ebene_he_eram As Eram Byte ' EEPROM eigene Tastaturebene high
Dim Hauscode As Byte ' Hauscode
Dim Hauscode_e As Byte ' eigener Hauscode
Dim Hauscode_e_eram As Eram Byte ' EEPROM eigener Hauscode
Dim Check As Byte ' Prüfsumme
Dim Rxpari As Byte ' Paritätsbit empfangen
Dim Erpari As Byte ' Paritätsbit errechnet
Dim Startbit As Byte ' Startbit für Umwandlung Empfangscode
Dim Sekunde As Byte ' Sekundentakt
Dim Setup As Byte ' Einstellung speichern
Dim Temp As Byte ' Code temporär
Dim Tmr1_pre As Word ' Timer Preload
Tmr1_pre = &HC2F7 ' 0,5 Sek Takt bei 8 MHz
Dim X As Byte ' temporär
|
Danach werden die im EEPROM gespeicherten Werte für die Tastaturebene und den Hauscode in den RAM übernommen:
Ebene_l_k1 = Ebene_l_k1_eram ' gespeicherte Tastaturebene Kanal 1 low auslesen
Ebene_l_k2 = Ebene_l_k1 + 1 ' Tastaturebene Kanal 2 low errechnen
Ebene_he = Ebene_he_eram ' gespeicherte Tastaturebene high auslesen
Hauscode_e = Hauscode_e_eram ' gespeicherten Hauscode auslesen
|
Es werden 2 Timer eingerichtet. Timer 0 ist ist ein 8-bit-Timer und wird verwendet für die Messung der Wellenlänge der Empfangsdaten des 433-MHz-Empfängers. Timer 1, ein 16-bit-Timer, wird verwendet, um die Dauer eines Tastendruckes zu ermitteln bzw. nach Ablauf einer Zeit die Setup-Routine wieder zu verlassen.
'8-bit Timer für Wellenlänge 800 µS (0), 1200 µS (1)
Config Timer0 = Timer , Prescale = 64 ' 8 µS, Overflow 2048.000 µSec
'16-bit Timer für Laufzeitmessungen
Config Timer1 = Timer , Capture Edge = Rising , Prescale = 256 ' 32 µS, Overflow 2097.152 mSec
Enable Timer1
On Timer1 Tmr1_ovfl
Stop Timer1
|
Pin A.7 wird als Eingang für den Anschluss eines Tasters konfiguriert. Verwendet wird er als Input Capture Pin und löst damit bei jedem Tastendruck einen Interrupt aus. Angesprungen wird dadurch das Label "Tast_icp1". Ein zweiter Eingang wird für den Anschluss des Empfängers verwendet. Hierfür ist unbedingt ein Interrupt notwendig, da sofort auf jedes empfangene Signal reagiert werden muss.
Config Pina.7 = Input ' Taster, normal low
On Capture1 Tast_icp1 ' Interruptaufruf ICP
Enable Capture1 ' Interrupt einschalten
Config Pinb.2 = Input ' RX Input FS10
Config Int0 = Rising ' Interrupt bei steigender Flanke
On Int0 Fs10_int0 ' Interruptaufruf
Enable Int0 ' Interrupt einschalten
|
Um ein wenig Strom zu sparen werden noch unbenötigte Teile des Prozessors abgeschaltet und vor Beginn des Hauptprogrammes die Interrupts global eingeschaltet.
Stop Ac ' Strom sparen
Stop Adc ' Strom sparen
Stop Watchdog ' Strom sparen
Enable Interrupts
|
Im Hauptprogramm erfolgt die Dekodierung der empfangenen Bits. Insgesamt werden 43 Bit pro Befehl übertragen. Der Bitzähler zählt abwärts. Deshalb beginnt die Dekodierung bei Bit 42. Zuerst werden werden 8 Bits mit Wert 0 übertragen. Sollte ein Bit davon 1 sein, wird die Dekodierung abgebrochen, der Bitcounter auf den Startwert 42 gesetzt und zum Start gesprungen. Als nächste 4 Bit folgt der Typ, im Falle der Fernbedienung auch alles Nullen. Auch in dieser Abfrage erfolgt wieder ein Abbruch bei Empfang einer 1. Die Bits 0 bis 30 werden in das Array "Code" übernommen. Nach jedem empfangenen Bit wird der Counter um 1 verringert.
'# # # # # # # # # # # # # # # # Hauptprogramm Endlosschleife # # # # # # # # # # # # # # # #
Do
Start: ' Beginn Übernahme empfangener Bits
Config Powermode = Idle ' Strom sparen
Bitwait Rxready , Set ' warten auf gesetztes Bit
Rxready = 0 ' Interrupt fertig zurück setzen
If Count >= 35 Then ' Bit 42-35 Präambel
If Rxbit = 1 Then ' Präambel muss 0 sein
Count = 42 ' Zaehler zurück setzen
Goto Start ' Abfrage neu starten
Else
X = Count - 34 ' Praeambel ermitteln
Praeambel(x) = Rxbit ' Bit in Praeambel übernehmen
End If
Elseif Count >= 31 Then ' Bit 34-31 Typ
If Rxbit = 1 Then ' Typ muss 0 sein
Count = 42 ' Zaehler zurück setzen
Goto Start ' Abfrage neu starten
Else
X = Count - 30 ' Typ ermitteln
Typ(x) = Rxbit ' Bit in Typ übernehmen
End If
Else
Code(count) = Rxbit ' Bit 30-1
End If ' Ende Übernahme empfangener Bits
Decr Count ' Zähler verringern
|
Wenn alle 43 Bits empfangen wurden, d.h. der Zähler auf 0 steht, erfolgt die Dekodierung der einzelnen Sequenzen. Jedes 5. Bit muss 1 sein. Sollte dies nicht der Fall sein, wird die Auswertung abgebrochen und wieder zum Start gesprungen. Danach erfolgt die Erfassung der Tastaturebene, des Hauscodes und einer Checksumme. Falls diese nicht mit der errechneten Prüfsumme übereinstimmt, wird auch hier wieder abgebrochen und zum Start gesprungen.
' Gültigkeit empfangener Bits prüfen
If Count = 0 Then ' 42 Bit empfangen
Count = 42 ' Zaehler zurück setzen
If Code(30) = 0 Or Code(25) = 0 Or Code(20) = 0 Or Code(15) = 0 Or Code(5) = 0 Then
Goto Start ' jedes 5. Bit muss 1 sein
End If
Startbit = 26 ' Bit 26-28 - Taste
Gosub Wandeln
Taste = Temp ' Taste übernehmen
Startbit = 21 ' Bit 21-23 - Ebene low
Gosub Wandeln
Ebene_l = Temp ' Ebene low übernehmen
Startbit = 16 ' Bit 16-18 - Ebene high
Gosub Wandeln
Ebene_h = Temp ' Ebene high übernehmen
Startbit = 6 ' Bit 6-8 - Hauscode
Gosub Wandeln
Hauscode = Temp ' Hauscode übernehmen
Startbit = 1 ' Bit 1-3 - Checksumme
Gosub Wandeln
Check = Temp ' Checksumme übernehmen
X = Taste ' Quersumme errechnen
X = X + Ebene_l ' Quersumme errechnen
X = X + Ebene_h ' Quersumme errechnen
X = X + Hauscode ' Quersumme errechnen
If X >= 11 Then
X = 18 - X ' Quersumme + Checksumme = 18
Else
X = 10 - X ' Quersumme + Checksumme = 10
End If
If X <> Check Then ' Checksumme prüfen
Goto Start
End If ' fertig Gültigkeit empfangener Bits prüfen
|
Falls sich das Programm im Setup-Modus befindet, werden die empfangenen Befehle übernommen, im EEPROM gespeichert, die Kontroll-LED abgeschaltet und die Timer zurück gesetzt.
' Einstellungen speichern
If Setup = 1 Then ' empfangene Codes speichern
If Ebene_l < 4 Then ' Ebene darf nicht 4 sein
Hauscode_e = Hauscode ' empfangenen Hauscode übernehmen
Ebene_l_k1 = Ebene_l ' empfangenen Ebene low Kanal 1 übernehmen
Ebene_l_k2 = Ebene_l + 1 ' empfangenen Ebene low Kanal 2 errechnen
Ebene_he = Ebene_h ' empfangenen Ebene high übernehmen
Hauscode_e_eram = Hauscode ' Hauscode im EEPROM speichern
Ebene_l_k1_eram = Ebene_l ' Ebene low im EEPROM speichern
Ebene_he_eram = Ebene_h ' Ebene high im EEPROM speichern
Setup = 0 ' Setup deaktivieren
Sekunde = 0 ' Sekundenzaehler auf 0
Stop Timer1 ' Sekunden-Timer anhalten
Set Led1 ' LED ausschalten
Tmr1_pre = &HC2F7 ' 0,5 Sek Takt bei 8 MHz
Else
Tmr1_pre = &HF0BE ' schnelles Blinken
End If
End If
|
Sollte der empfangene Hauscode und die Tastaturebene mit den gespeicherten Werten übereinstimmen, wird das dazu gehörige Relais und die LED ein- bzw. ausgeschaltet.
' empfangene Codes vergleichen und auswerten
If Hauscode = Hauscode_e Then ' Hauscode vergleichen
Hauscode = 255 ' nur einmal ausführen
If Ebene_h = Ebene_he Then ' Ebene high vergleichen
If Ebene_l = Ebene_l_k1 Then ' Ebene low Kanal 1 vergleichen
K1 = Taste.0 ' K1 Ausgang schalten
Led1 = Not K1 ' LED 1 schalten
End If
If Ebene_l = Ebene_l_k2 Then ' Ebene low Kanal 2 vergleichen
K2 = Taste.0 ' K2 Ausgang schalten
Led2 = Not K2 ' LED 2 schalten
End If
End If
End If
End If
Loop
End
|
Damit ist die Hauptschleife beendet und es folgt ein Unterprogramme zur Übernahme von jeweils 3 Bit in ein Byte. Das jeweilige 1. Bit ist ein Paritätsbit. Sollte das errechnete Paritätsbit nicht mit dem empfangenen übereinstimmen, wird die Dekodierung abgebrochen.
'############################## U N T E R P R O G R A M M E ##############################
Wandeln:
X = 0
Erpari = 1 ' Parität gerade
Do
Temp.x = Code(startbit) ' Code in temporäres Byte übernehmen
Erpari = Erpari + Temp.x ' Summe von Bit 0 bis 2 ermitteln
Incr X
Incr Startbit
Loop Until X = 3 ' 3 Bit übernehmen
Rxpari = Code(startbit) ' Bit 4 - Paritätsbit übernehmen
Erpari = Erpari And 1 ' Parität errechnen
If Rxpari <> Erpari Then ' Parität vergleichen
Goto Start ' abbrechen
End If
Return
|
Die erste Interruptroutine wird aufgerufen, wenn ein Tastendruck erkannt wurde. Es erfolgt nur der Start von Timer 1.
'############################## Interruptroutinen und Timer ##############################
Tast_icp1: ' Taste betätigt
Sekunde = 0 ' Sekunden zurück setzen
Start Timer1 ' Timer 1 starten
Timer1 = Tmr1_pre ' Timer laden
Return
|
Der zweite Interrupt wird ausgelöst durch einen Pegelwechsel von 0 auf 1 am Eingang, der mit dem Empfänger verbunden ist. Hier wird die Zeit zwischen zwei Interrupts mittels Timer 0 erfasst. Sollte diese kleiner 600 oder größer 1400 Mikrosekunden sein, so wird der Counter wieder auf seinen Startwert zurück gesetzt. Zeiten zwischen 600 bis 1000 Mikrosekunden bedeuten, das eine 0 empfangen wurde und eine 1 bei Zeiten von 1008 bis 1400 Mikrosekunden.
Fs10_int0: ' Funk-Empfang
Rxcycle = Timer0 ' Dauer übernehmen
Timer0 = 0 ' Timer zurück setzen
Select Case Rxcycle
Case Is < 75 ' kleiner 600 µs
Count = 42 ' reset bitcounter
Case 75 To 125 ' 600-1000µs, 0-bit
Rxbit = 0 ' empfangenes Bit = 0
Rxready = 1 ' Auswertung fertig
Case 126 To 175 ' 1008-1400 µs, 1-bit
Rxbit = 1 ' empfangenes Bit = 1
Rxready = 1 ' Auswertung fertig
Case Is >= 176 ' größer 1400 µs
Count = 42 ' reset bitcounter
End Select
Return
|
Die letzte Interruptroutine wird durch einen Überlauf von Timer 1 aufgerufen. Sollte der Taster betätigt sein, so wird die LED eingeschaltet und nach 5 Sekunden ins Setup gewechselt. Die LED beginnt nach Ablauf dieser Zeit zu blinken. Wenn vor Ablauf dieser Zeit der Taster nicht mehr geschlossen ist, wird die LED ausgeschaltet und der Timer wieder angehalten. Nach einer Minute wird der Setup-Modus wieder abgebrochen.
Tmr1_ovfl:
Incr Sekunde ' Sekundenzaehler
Timer1 = Tmr1_pre ' Timer laden
If Pina.7 = 1 Then ' wenn Taster betätigt
If Setup = 0 Then
Reset Led1 ' LED einschalten
End If
If Sekunde >= 10 Then ' nach 5 Sekunden
Setup = 1 ' Setup aktivieren
End If
End If
If Pina.7 = 0 And Setup = 0 Then ' Taster nicht betätigt
Set Led1 ' LED ausschalten
Sekunde = 0
Stop Timer1 ' Sekunden-Timer anhalten
End If
If Setup = 1 Then
Toggle Led1 ' LED blinkt
End If
If Sekunde >= 120 Then ' nach 60 Sekunden
Setup = 0 ' Setup deaktivieren
Sekunde = 0 ' Sekundenzaehler auf 0
Stop Timer1 ' Sekunden-Timer anhalten
Set Led1 ' LED ausschalten
End If
Return |