PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RC5+Memorizer für Intelligent Interface von fischertechnik



-tomas-
18.12.2006, 22:39
Bevor es auf der Festplatte untergeht, will ich hier ein fertiges Projekt reinstellen, das vielleicht einem veralteten Intelligent Interface von Fischertechnik wieder etwas Leben einhauchen kann.

In Anlehnung an FT-Memorizer von http://www.ft-fanpage.de/memorizer/memorizer.htm habe ich einen Memorizer mit RC5 Fernsteuerung (=FT Fernsteuerung) programmiert. Da ft-fanpage.de seinen ASM-Code nicht zur Verfügung stellen wollte, habe ich die Idee in BASCOM umgesetzt.

Zweck:
Das Intelligent Interface von fischertechnik speichert sein Programm im "Download-Modus" nur im ungepufferten RAM. Nach einer Unterbrechung der Stromversorgung wird ein PC benötigt, um das Programm wieder neu zu laden.
Der Memorizer hängt zwischen PC und FT und schneidet den Code mit.
Ohne PC kann durch drücken des Tasters des letzte Programm in das Intelligent Interface geschoben werden.
Solange der Taster nicht gedrückt wurde, nimmt der RC5Memorizer die Signale der FT-Fernsteuerung auf Kanal 2 auf und steuert damit M1 bis M4 des Intelligent Interfaces.

Software:
Bascom mit ISR-RC5-Code (verwendet 2 Timer und Soft-UART)

Hardware:
Atmega8 mit Bootloader für einfache Updates
ext. Speicher: 32KByte ROM 24C256
Gehäuse: FT 9V Batteriekasten



'DEMO für FT-PC Kommunikation
'Speicherung des Datenstroms vom PC in ein I2C EEPROM
'Datenstruktur
' Beginn der Kommunikation wird mit E0h eingeleitet
' -> Interface schaltet in den Programmiermodus
' Datenstruktur Byte 0 = Länge des 1. Blocks (B1)
' Byte 1 bis n = 1. empfangener Block
' Byte n+1 = Länge des 2. Blocks (B2)
' Byte n+2 ... = 2. empfangener Block
' letztes Byte = &H00 als Endemarkierung
'
' |---| bezeichnet einen kompletten Datensatz (Block) der vom FT-Interface bestätigt wird
' Länge von 1 bis 119 Byte
'
' |S1|---|S2|-----|S3|---------|...|-------|00
' | 1. 2. 3. n. Block
' |
' |---------------------------->Block_Count Platzhalter bis Blocklänge bekannt
' |------------------------------------>I2C_Count letztes empfangenes Zeichen
'
' Page_Count = 1...16
' Alle empfangenen Zeichen werden in dem Array Page(Page_Count) gespeichert
' und als 16 Byte Page ins EEPROM gewschrieben
'
' LED an Portb.1 signalisiert Schreibvorgänge zum EEPROM bzw. zum Interface
'
' Version 1.0 vom 18.12.06

$regfile = "m8def.dat" 'Die Anweisung bestimmt Controllertyp, hier AVR Mega 16
$framesize = 32 'Stackanweisungen, die eigentlich nur bei größeren Programmen
$swstack = 32 'wirklich nötig werden
$hwstack = 64
$crystal = 8000000 'Die Frequenz des verwendeten Quarzes


'Hardware UART
Config Serialin = Buffered , Size = 120 'serial input buffer to PC , max 120 Byte je Datensatz
$baud = 9600 'Die Baudrate für RS232 Ausgabe.

'Software UART
Open "comD.4:9600,8,n,1" For Output As #1 'pin for output
Open "comD.2:9600,8,n,1" For Input As #2 'INT0 pin for input

'Hardware TWI
$lib "I2C_TWI.LBX"
Config Twi = 200000 'Bustakt in Hz
Config Sda = Portc.4
Config Scl = Portc.5
I2cinit

'LED
Config Pinb.1 = Output 'LED 1
Portb.1 = 0
Led1 Alias Portb.1

'Taster
Config Pinb.3 = Input 'Taster 1
Portb.3 = 1 'Pull Up Taster 1
Taster1 Alias Pinb.3


'Funktionen für EEPROM 24C256 definieren
Declare Sub Page_write
Declare Sub Write_eeprom(byval Adr As Word , Byval Value As Byte)
'Declare Sub Read_eeprom(byval Adr As Word , Value As Byte)
Const Addressw = &HA0 'slave write address
Const Addressr = &HA1 'slave read address
Dim Adresse As Word , Value As Byte , T1 As Byte

Dim Block(16) As Byte '16 Byte Array als Rollspeicher (Abbild des EEPROM)

'die beiden Hauptmodule
Declare Sub Transfer2eeprom
Declare Sub Transfer2ft

'*************** Soft UART ************************************************** ****
'Initialise INT0 für Soft UART
On Int0 Int0_int 'Nosave würde 52 Takte = 6,5uS sparen
Enable Int0
Config Int0 = Change
Dim S As Byte 'Variable der INT0-Routine

'***************Timer0 für RC5 ************************************************** ****
Config Portd.3 = 0 'INT 1
Rc5_pin Alias Pind.3 'Pin für TSOP1736

Config Timer0 = Timer , Prescale = 8
On Timer0 Timer_irq
Const Timervorgabe = 78 'Timeraufruf alle 178µs (10 Samples = 1 Bit = 1,778ms)
Enable Timer0 'Hier wird der Timer aktiviert

'Timing für 10 Samples Per Bit = 1,778ms
Const Samples_early = 8 'Flanke Frühestens Nach 8 Samples
Const Samples_late = 12 'Flanke Spätestens Nach 12 Samples
Const Samples_min = 3 'Flanke Vor 3 Samples - > Paket Verwerfen

'Variablen der ISR
Dim Sample As Byte 'eigentlich Bit, spart aber 46Byte ROM
Dim Ir_lastsample As Byte 'zuletzt gelesenes Sample
Dim Ir_bittimer As Byte 'zählt die Aufrufe von Timer_IRQ
Dim Ir_data_tmp As Word 'Bitstream
Dim Ir_bitcount As Byte 'Anzahl gelesener Bits

'Rückgabewerte der ISR
Dim Address_rc5 As Byte , Command_rc5 As Byte , Rc5_getflag As Bit
Dim Rc5_sendflag As Bit

'************* TIME OUT Timer: 8000 = 1sec ************************************************** ************************
'Timer
Config Timer1 = Timer , Prescale = 1024
Enable Timer1
Const Time_out = 39063 ' *1024 Takte (5,0sec) bis Abbruch des Downloads

'************************************************* ***********************
'Interrupts aktivieren
Enable Interrupts


'Variablen
Dim A As Byte , B As Byte , Page As Byte
Dim I As Word , J As Word , K As Word
Dim End_flag As Bit
Dim I2c_count As Word , Block_count As Word , Page_count As Word
Dim Rc5(11) As Byte 'Vektor Zuordnung RC5 -> FT-Codes

Reset End_flag 'Erkennung für String Anfang
I2c_count = 0

'main
Restore Rc5_codes
For B = 1 To 11 'einlesen der FT Fernsteuercodes
Read Rc5(b)
Next

Reset Rc5_getflag
Reset Rc5_sendflag

Do
If Rc5_getflag = 1 Then
If Address_rc5 = &H1E Then 'FT Remote Control Channel 2
Timer1 = 0
Command_rc5 = Command_rc5 And &B01111111 'clear the RC5 toggle bit
A = Rc5(command_rc5) 'Printbin auf Array ist fehlerhaft
Disable Timer0 'Timer0 Interrupt alle 178µs stört Soft-UART
Printbin #1 , &HC1 ; A 'Ausgabe an FT
Enable Timer0
Printbin Address_rc5 ; Command_rc5 ; &HC1 ; A 'Kontrollausgabe an PC ******************
Reset Rc5_getflag
Set Rc5_sendflag 'Schaltsignal an FT (Motoren schalten erst mach 300msec alleine ab)
End If
End If

If Rc5_sendflag = 1 Then 'wenn >150msec kein neuer RC5-Code schalte Motoren ab
If Timer1 >= 1170 Then '=150msec
Reset Rc5_sendflag
Disable Timer0 'Timer0 Interrupt alle 178µs stört Soft-UART
Printbin #1 , &HC1 ; &H00
Enable Timer0
Printbin &HC1 ; &H00 'Kontrollausgabe an PC ******************
End If
End If

If Taster1 = 0 Then 'Taste gedrückt => Ausgabe des ROM
Disable Timer0
Gosub Transfer2ft
Enable Timer0
End If
While Ischarwaiting() = 1
Disable Timer0
A = Inkey() 'get it from PC
Printbin #1 , A 'send to FT
If End_flag = 1 And A = &HE0 Then 'neuer String beginnt Startkriterium E0h
Call Transfer2eeprom
End If
Reset End_flag
Enable Timer0
Wend
Loop
End


'**************************** Soft UART ********************************
'INT0 lesen eines Byte von FT mit Soft-UART
Int0_int: 'Interrupt Handler For Int0
S = Inkey(#2) 'get it from FT
Printbin S 'send to PC
Set End_flag 'Flag für FT sendet Daten
Timer1 = 0 'Timer zurücksetzen
Gifr = Gifr Or &H40 'clear Flag Int0
Return

'************************** RC5 ***************************************
'RC5 FT Steuercodes
Rc5_codes:
Data 16 , 32 , 64 , 128 , 0 , 0 , 1 , 2 , 4 , 8 , 0

'Lesen der RC5 Codes
Timer_irq:
Timer0 = Timervorgabe
Sample = Not Rc5_pin

'bittimer erhöhen (bleibt bei 255 stehen)
If Ir_bittimer < 255 Then Incr Ir_bittimer

'flankenwechsel erkennen
If Ir_lastsample <> Sample Then

If Ir_bittimer <= Samples_min Then
'flanke kommt zu früh: paket verwerfen
Ir_bitcount = 0
Else
'nur Flankenwechsel in Bit-Mitte berücksichtigen
If Ir_bittimer >= Samples_early Then
If Ir_bittimer <= Samples_late Then
'Bit speichern
Shift Ir_data_tmp , Left , 1
Ir_data_tmp = Ir_data_tmp + Sample
Incr Ir_bitcount
Else
'Flankenwechsel zu spät: Neuanfang mit gemessener Flanke
Ir_bitcount = 1
Ir_data_tmp = Sample
End If
'bittimer zurücksetzen wenn Timer > Samples_early
Ir_bittimer = 0
End If
End If

'Kontrolle des Startbits auf 1
If Ir_bitcount = 1 Then Ir_bitcount = Ir_data_tmp.0

'Alle 14 Bits gelesen?
If Ir_bitcount >= 14 Then
Command_rc5 = Ir_data_tmp 'Bit 6 und 7 siehe unten
Shift Ir_data_tmp , Right , 6
Address_rc5 = Ir_data_tmp And &B00011111
'For extended RC5 code, the extended bit is bit 6 of the command.
Command_rc5.6 = Not Ir_data_tmp.6
'The toggle bit is stored in bit 7 of the command
Command_rc5.7 = Ir_data_tmp.5
'Paket erfolgreich gelesen
Set Rc5_getflag
'paket zurücksetzen
Ir_bitcount = 0
End If

End If
'sample im samplepuffer ablegen
Ir_lastsample = Sample

Return

'******************** SUB ************************************************** *****

'Download vom PC to EEPROM
Sub Transfer2eeprom 'sub without parameters
'Timer1 = 0 'Timer für TimeOut ca. 0,5sec
Block_count = 0 'erster Platzhalter für erste Blocklänge
I2c_count = 0 'Startadresse des ersten Zeichens
Page_count = 0 'Startadresse des nächsten Page_Write
Page = 1 'wegen Platzhalter 1. Block (Counter für Array)
Gosub Push_byte_a 'Startzeichen &HE0 sichern -> Page_Count=2
Do
If Ischarwaiting() = 1 Then 'neues Zeichen vom PC
A = Inkey() 'get it from PC
If End_flag = 1 Then 'Anfang eines neuen Blocks erkannt
Gosub Save_block_count 'bekannte Blocklänge sichern
Gosub Push_byte_a 'neuer Platzhalter für Blocklänge
Block_count = I2c_count 'Adresse Platzhalter sichern
Reset End_flag 'warten auf Begin eines neuen Blocks
End If
Gosub Push_byte_a 'empfangenes Byte sichern
Printbin #1 , A 'zu FT senden, wenn EEPROM Speicherung abgeschlossen
'erst am Ende - wichtig für Timing von 1-Byte Befehlen
End If
I = I2c_count - Block_count
Loop Until I > 130 Or Timer1 > Time_out 'd.h. FT reagiert nicht mehr (ready)
Gosub Save_block_count 'bekannte Blocklänge sichern
A = 0
For I = 1 To 17 'Auffüllen
Gosub Push_byte_a 'Ende Markierung 00 setzen und mind. eine Page schreiben
Next
End Sub

'Platzhalter mit Blocklänge füllen
Save_block_count:
I = I2c_count - Block_count 'Länge des letzen Blocks
If I < Page Then 'Testen ob Platzhalter noch in ungesicherter Page liegt
B = Page - I
Block(b) = I
Else
Waitms 10
B = Low(i) 'wait for 10 milliseconds - see datasheet
Call Write_eeprom(block_count , B) 'Platzhalter im EEPROM mit Blocklänge füllen
Waitms 10
End If
Return

'Byte in das Array ablegen
Push_byte_a:
Incr Page 'Zähler hochzählen
Incr I2c_count
Block(page) = A
If Page = 16 Then 'Page ist voll
Call Page_write '16 Byte ins EEPROM schreiben
Page = 0 'Zähler zurücksetzen
End If
Return

'16 Byte page write to EEPROM AT24Cxx
Sub Page_write 'Page_Count Byte ab Adresse I2C_Count schreiben
Led1 = 1
I2cstart 'start condition
I2cwbyte Addressw 'slave address
T1 = High(page_count)
I2cwbyte T1 'upper address of EEPROM
T1 = Low(page_count)
I2cwbyte T1 'lower address of EEPROM
For B = 1 To 16
I2cwbyte Block(b) 'Page write 16 Byte
Next
Page_count = Page_count + 16 'neue Startposition
I2cstop 'stop condition
'waitms 10 'entfällt da im Hauptprogramm
Led1 = 0
End Sub


'page read from EEPROM AT24Cxx and send to FT
Sub Transfer2ft
'Printbin #1 , &HD2 ; &H00 ; &H0A
'Gosub Wait_ft

I2c_count = 0
I2cstart 'generate start
I2cwbyte Addressw 'slave adsress (write)
I2cwbyte 0 'upper address of EEPROM
I2cwbyte 0 'lower address of EEPROM
I2cstart 'repeated start
I2cwbyte Addressr 'slave address (read)
I2crbyte Value , Ack '1. Blocklänge lesen

While Value > 0
K = Value 'Blocklänge byte -> word
For I = 1 To K
Incr I2c_count
I2crbyte Value , Ack 'Block lesen
'Printbin Value '******* send to pc
Printbin #1 , Value 'send to ft
Next

Reset End_flag
Led1 = 1 'Aktiviere Warte-LED

Timer1 = 0 'Zähler Warteschleife zurücksetzen
Do
Waitms 10 'warten ob FT antwortet
Loop Until End_flag = 1 Or Timer1 > Time_out 'Abbruch nach max xx sec Umschaltstartsequenz [E0] -> E0 / [05 05 05] ->3,1sec-> 10 30

'Printbin &HAB 'Endemarkierung an PC senden
Do 'warten bis FT nicht mehr antwortet
Reset End_flag
Waitms 20
Loop Until End_flag = 0 'End_flag wird bei INT0 gesetzt

Led1 = 0 'Warte-LED löschen
I2crbyte Value , Ack 'nächste Blocklänge mit ACK bestätigen
Wend
I2crbyte Value , Nack 'read last byte with NO ACK
I2cstop 'generate stop
End Sub


'writing a byte to EEPROM AT24Cxx
Sub Write_eeprom(byval Adr As Word , Byval Value As Byte)
I2cstart 'start condition
I2cwbyte Addressw 'slave address
T1 = High(adr)
I2cwbyte T1 'upper address of EEPROM
T1 = Low(adr)
I2cwbyte T1 'lower address of EEPROM
I2cwbyte Value 'value to write
I2cstop 'stop condition
'Waitms 10 'wait for 10 milliseconds - see datasheet
End Sub



Eagle Schaltplan etc. siehe Anhang

Cornu
19.12.2006, 15:54
Moin
Danke..
Bin auch besitzer des intelligent interface und mich hat auch immer gestört, das die Programme nur flüchtig gespeichert wurden und bin so jetzt auf mikrokontroller gekommen und bastel jetzt damit.
Ich werd den memmorizer bei Gelegenheit mal nachbauen und kann so ja doch das interface mal wieder auskramen.
Vielen Dank für den Hinweis.
MfG Cornu