MODIFIZIERTER GRAUPNER DECODER NACH T. GIETENBRUCH

Vor ein paar Jahren habe ich im RC-Line Forum einen Thread gefunden, der sich mit der Programmierung von Microcontrollern, hier speziell die von Atmel, befasst.

Als Beispiel hatte der Auto Torsten Gietenbruch praktischerweise einen Decoder für Graupner Schaltmodule programmiert. Diesen Decoder habe ich damals erstmal nach Vorlage nachgebaut um zu schauen, ob das Dingen auch funktioniert. Hat er, sogar ganz gut!

Ich kann mich wohl erinnern, dass der Decoder ziemlich widerwillig beim programmieren war. Es hat lange gedauert, bis ich das Teil zum laufen bekam, aber das lag im Endeffekt nur an den sogenannten Fuses. Diese "Schalter" sind wichtig für die richtige Funktion des Atmels als solches, eine Falschprogrammierung wird gnadenlos mit Fehlfunktion quittiert.

Zwischendurch habe ich im Laufe der Jahre bei meinen PICAXE Experimenten mit selbstgebauten Schaltern experimentiert, aber diesen Decoder hier nie so ganz aus den Augen verloren.

Nach langer Zeit habe ich mich jetzt nun wieder daran gemacht diese Elektronik an meine Bedürfnisse anzupassen und zu ändern. Als erstes sollte die Setup Funktion raus. Diese war als zusätzliches Feature vom Autor hinzuprogrammiert worden um sich vom Original Decoder abzuheben, ich hingegen brauchte das nicht und wollte Code und Hardware verschlanken. 

Also wurde die alte Hardware wieder hervorgekramt, der MC19 Sender mit dem Sendemodul ausgestattet und am Originalcode in meiner gewohnt stümperhaften Art herumgepfuscht.

Da ich kein Programmierer bin und auch nur wenig Talent für Programmierung oder sogar Programmperfektionierung habe, muss ich da auf die bewährte Try and Error Methode zurückgreifen.

Die alte Hardware lief noch bestens, alle Ausgänge funktionierten korrespondierend zu den Schaltern am Sender. Eine gute Ausgangsposition. Nach den Modifikationen an der Software musste das Programm in den Atmel überspielt werden. Ich konnte mich noch daran erinnern, dass ich das früher mit Ponyprog über die serielle Schnittstelle meines alten IBM 600x gemacht habe. Das muss besser gehen!

 

Die Software wurde in BASIC mit einem Programm namens BASCOM geschrieben. Die Software kann gratis heruntergeladen werden und funktioniert als Demoversion bis zu einer Codegrösse von 4kB. Das reicht für viele Programme und auch für den Decoder. Innerhalb von BASCOM gibt es die Möglichkeit, den Code mit verschiedensten Programmieradaptern auf den Zielprozessor zu spielen. Eine Möglichkeit ist das sog. USBASP Interface. Dieses ist recht preiswert, und ich hatte aus diversen Quellen im Laufe der Jahre ein paar Programmer zusammengetragen. Die sollten es werden!

Also wurde eine kleine Platine zusammengelötet die den Prozessor und ein Flachbandkabel zur Konnektierung an den Programmer aufnahm.

Der Code wurde nun auf die überflüssigen Programmteile untersucht. Durch die hervorragende Dokumentierung des Autors konnte ich schnell den entsprechenden Programmteil ausmachen. Dieser wurde zusammen mit ein paar anderen Zeilen gelöscht welche sich beim weiteren Studium als obsolet herausstellten. Dieser Code wurde nun in einen frischen ATMega8 überspielt. Nachdem der Chip in die Hardware gesteckt wurde funktionierte die Software...

... so ziemlich garnicht...

Und nicht nur das, sie funktionierte überhaupt nicht! Auch nachdem ich den originalen Code wieder in den Chip gespielt hatte funktionierte immer noch nichts. Auf der alten Hardware waren einige Tasten und der Drehschalter für das Setup verbaut, mit dem alten Chip gingen beim Drücken eines Taster eine LED an die die Zustand anzeigte. Hier tat sich garnichts.

Verdammt!

Ich habe die nächsten Abende damit zugebracht, die verschiedensten Programmierszenarien herzustellen. Gestartet habe ich unter Linux mit einer virtuellen Win10 Maschine für diese Zwecke, mein normales Arbeitsumfeld. Dem Chip war kein Lebenszeichen zu entlocken. Weiter gings mit Win7. Hier wurde BASCOM installiert um den Chip zu programmieren, aber auch hier funktionierte der Chip nach der Programmierung nicht. Zwischendurch habe ich verschiedene ATMega8 ausprobiert, kann ja sein, dass der erste Chip ne Macke hat.

Als auch hier nichts ging habe ich einen alten IBM X40 mit einem frischen WindowsXP aufgesetzt. Der noch ältere 600x existierte noch, war aber auch mir unerfindlichen Gründen unglaublich langsam und machte keinen Spass. Als auch hier der Chip nicht zur Funktion zu überreden war habe ich das alte Ponyprog aufgespielt. Die Docking Station, die zum x40 gehört besitzt einen seriellen Ausgang. Den hab ich sonst abgesehen als USB Dongle nirgends mehr ausser am 600x.

Auch hier war es zum verzweifeln. Die Software wurde kompiliert und als .hex Datei abgespeichert sodass sie vom Ponyprog gelesen werden konnte. Sie wurde auch ohne irgendwelche Fehlermeldungen in den ATMega8 übertragen, funktionierte aber dennoch nicht. Nur dieser alte Chip mit dem ich vor ein paar Tage wieder gestartet war ging. Was war anders? Die Chips waren identisch und wenn ich mich recht erinnerte, sogar aus der gleichen Bestellung da ich damals mehr Decoder bauen wollte und immer auf Vorrat kaufe.

 

Nach einiger Zeit dämmerte es mir, es mussten diese verdammten Fuses sein. Die Dinger, welche ich eingangs nicht ohne Hintergedanken erwähnte, hatte ich praktischerweise VÖLLIG vergessen. Nachdem der alte Chip ausgelesen war, konnte ich in der Tat eine andere Konfiguration zum Lieferzustand erkennen. Diese wurde sofort in einen neuen Chip einprogrammiert und den originalen Code von T. Gietenbruch hinterher geschoben.

Bingo! 

Der Chip lief auf Anhieb! Als nächstes folgte der modifizierte Code. Auch jetzt hatte ich auf Anhieb Erfolg. Die Ausgänge schalteten nur noch im Tastbetrieb, so wie es der Schalter im Sender vorgibt und ich es haben wollte.

Eine Erweiterungsplatine für mein 212 steht schon in den Startlöchern. Dort gibt es einige Dinge zu schalten, u.A. soll die Ballastverschiebung mit Motor anstatt Servo gelöst werden um einen Proportionalkanal zu sparen.

 

DAS PROGRAMM

'******************************************************

'Projekt: Atmel-Programmierung für Einsteiger

'

'Prozessor: ATMega 8-16

'Bascom-Version: 1.11.8.1

'

'Auswertung für Graupner Nautic Expert Baustein

'

'Version: 1.0

'Version: 1.1

'Programm verschlankt auf das Nötigste. Drehschalter und Setup entfernt.  SS

'

'Hardware:

'R/C-Kanal an D.2 (INT0)

'

'18.08.2006 T. Gietenbruch

'16.12.2017 S. Schmitz

'

'******************************************************

 

'======================================================

'System-Einstellungen

'======================================================

'Definition für Mega 8

$regfile "m8adef.dat"

 

'Angabe der Taktfrequenz (4Mhz)

$crystal = 4000000

 

'======================================================

'Konfigurationen

'======================================================

 

 

'Konfiguration der I/O-PortsŽs

Ddrb = &B11111111

Ddrc = &B11111111

Ddrd = &B00000011

 

'Timer 1 für R/C-Signal

Config Timer1 = Timer , Prescale = 1

 

'Konfiguration des INT0

'Interrupt bei jedem Flankenwechsel (0->1 und 1->0)

Config Int0 = Change

 

'======================================================

'Deklarationen

'======================================================

Dim N As Byte

Dim N_old As Byte

Dim Signals As Byte

Dim Reading As Bit

Dim Rc_value(10) As Word

Dim Error As Bit

Dim Sync_detect As Bit

Dim X As Word

Dim Switch_up As Byte

Dim Switch_dn As Byte

Dim Sync_ok As Bit

Dim Cycle_done As Bit

Dim Switchhold As Byte

Dim Number As Byte

Dim Watch_dog As Word

Dim Code_raw As Byte

Dim Code_value As Byte

Dim Code_old As Byte

Dim Memory_up As Byte

Dim Memory_down As Byte

Dim Row_up As Bit

Dim Flash As Bit

Dim Flash_delay As Byte

Dim Bit_adr As Byte

 

'======================================================

'Konstanten

'======================================================

Const Sync_low = 8000

Const Sync_high = 9000

Const Switch_dn_low = 4000

Const Switch_dn_high = 5500

Const Switch_up_low = 7000

Const Switch_up_high = 7900

 

'======================================================

'Initialisierungen

'======================================================

'Zuweisung der Interrupt-Service-Routinen

On Timer1 Rc_error

On Int0 Rc_read

 

'Interrupt-Freigaben

Enable Timer1

Stop Timer1

 

Enable Int0

 

 

'Ports initialisieren

Portb = &B00000000

Portc = &B00000000

Portd = &B00000000

 

'Rücklesen der EEPROM-Variablen

Memory_up = 0

Memory_down = 0

 

'Freigabe aller Interrupt-Routinen

Enable Interrupts

 

'Etwas warten, falls die Signale den Watchdog auslösen

 

X = 0

While X < 10000 And Error = 0

Incr X

Wend

 

 

'Konfiguration des internen Watchdogs

Config Watchdog = 512

 

 

'======================================================

'Synchronisationsroutine

'======================================================

Syncronize:

Signals = 1

N = 1

Sync_detect = 0

X = 0

 

'Rücksetzen aller Schaltersignale

For X = 0 To 7

   Switch_up.x = 0

   Switch_dn.x = 0

Next X

'Rücksetzen der Ports

Portb = 0

Portc = 0

 

 

'Warten auf ersten Synchronisationswert

While Sync_detect = 0

Wend

N = 2

Sync_detect = 0

 

'Warten auf zweiten Synchronisationswert

'Begrenzt durch Zählschleife

X = 0

While X < 5000 And Sync_detect = 0

   Incr X

Wend

 

'Auswertung des Synchronisationsergebnisses

If X < 5000 And Rc_value(1) > Sync_low And Rc_value(2) > Sync_low Then

   N = 3

   Signals = 10

Else

   Goto Syncronize

End If

 

Watch_dog = 0

 

'Wartezeit, falls Watchdog doch noch zubeisst

Waitms 2000

 

 

'======================================================

'Hauptprogramm-Schleife

'======================================================

Do

 

'Auswertung der gelesenen Werte (im Block)

If Cycle_done = 1 And Reading = 0 And Error = 0 Then

   Cycle_done = 0

 

   'Überprüfung der Synchronisationssignale

   If Rc_value(1) > Sync_low And Rc_value(2) > Sync_low And Error = 0 Then

      Sync_ok = 1

   Else

      Sync_ok = 0

      Goto Syncronize

   End If

 

   'Aktualisierung der Schaltersignale

   If Sync_ok = 1 Then

      For X = 3 To Signals

         Number = X - 3

         'Schalter nach oben betätigt

         If Rc_value(x) > Switch_up_low And Rc_value(x) < Switch_up_high Then

            If Switchhold.number = 0 Then

               Switchhold.number = 1

               Toggle Switch_up.number

            End If

         'Schalter nach unten betätigt

         Elseif Rc_value(x) > Switch_dn_low And Rc_value(x) < Switch_dn_high Then

            If Switchhold.number = 0 Then

               Switchhold.number = 1

               Toggle Switch_dn.number

            End If

         'Schalter in Mittelstellung

         Else

            Switchhold.number = 0

            'Schaltersignal rücksetzen, wenn nicht remanent

            If Memory_up.number = 0 Then Switch_up.number = 0

            If Memory_down.number = 0 Then Switch_dn.number = 0

         End If

      Next X

 

'Zuweisung der Hardwareports

Portc.0 = Switch_up.0

Portc.1 = Switch_up.1

Portc.2 = Switch_up.2

Portc.3 = Switch_up.3

Portc.4 = Switch_up.4

Portc.5 = Switch_up.5

Portd.0 = Switch_up.6

Portd.1 = Switch_up.7

 

Portb.0 = Switch_dn.0

Portb.1 = Switch_dn.1

Portb.2 = Switch_dn.2

Portb.3 = Switch_dn.3

Portb.4 = Switch_dn.4

Portb.5 = Switch_dn.5

Portb.6 = Switch_dn.6

Portb.7 = Switch_dn.7

 

   End If

End If

 

'Soft-Watchdog

If N = N_old Then

   Incr Watch_dog

   If Watch_dog > 5000 Then Goto Syncronize

Else

   N_old = N

   Watch_dog = 0

End If

 

Loop

 

'Programmende (nur formal)

End

 

 

'======================================================

'ISR für INT0 - Signalfolge lesen

'======================================================

Rc_read:

 

'Den Timer starten mit steigender Flanke

If Reading = 0 And Pind.2 = 1 Then

   Start Timer1

   Reading = 1

'Den Timer stoppen mit fallender Flanke

Else

   Stop Timer1

   Rc_value(n) = Timer1

   Timer1 = 0

   Reading = 0

   'Validierung des gelesenen Wertes

   If Rc_value(n) < Switch_dn_low Or Rc_value(n) > Sync_high Then Goto Rc_error

   'Prüfung auf Sync-Signal

   If N < 3 And Rc_value(n) > Sync_low And Rc_value(n) < Sync_high Then

      Sync_detect = 1

   End If

   '...wenn die Synchronisation fertig ist

   If Signals > 2 Then

      Incr N

   End If

   If N > Signals Then

      N = 1

      Cycle_done = 1

   End If

End If

'Error-Bit rücksetzen

Error = 0

Return

 

'======================================================

'ISR für Timer1 - Fehlerhandling

'======================================================

Rc_error:

'Error-Bit setzen

Error = 1

Reading = 0

Stop Timer1

 

'Reset erzwingen

Disable Interrupts

Start Watchdog

Waitms 10000

Return

Nachdem ich einige Zeit mit dem Decoder herumgespielt hatte, wurmte mich die Sache mit der nicht funktionierenden ISP Programmierung doch sehr. Es konnte doch nicht sein, dass es mit BASCOM bzw dem USBASP Programmer nicht läuft. Also wurde der Sache nochmal mit etwas Abstand auf den Grund gegangen.

Dabei fiel auf, dass die Belegung des 6pol Steckers für das Flachbandkabel falsch war. Ich hatte im Internet nur nach einem Bild mit einer Belegung gesucht und das Erstbeste genommen. Das dieses Bild aus einem Thread in einem Forum war, in welchem sich der Threadersteller über eine nicht funktionierende Programmierschnittstelle ausließ habe ich nicht völlig übersehen.

Ich Depp!

Naja, man ist ja noch jung und hat viel Zeit...

Nachdem ich die Belegung zum Turnigy USBASP Adapter genommen hatte funktionierte die Programmierung des Chips einwandfrei. Die Programmierung der Fuses konnte ich leider nicht mehr testen, da ich keinen jungfräulichen Atmega8 mehr hatte, wird aber noch getestet sobald ich neue Prozessoren habe.

Ich hatte auch auf die Schnelle ein Layout erstellt. Damit die Verbindungen vom Atmel zu den Treibern kurz sind habe ich im Schaltplan einige Änderungen machen müssen. Das sieht nun nicht mehr so aufgeräumt aus, aber ein einfaches Layout ist mir lieber.

 

Hier mal die neue Version der Pläne:

Auf dem letzten Bild ist der Decoder auf eine meiner Platinen im 212 aufgebaut. Hier werden (noch) die drei A123 Akkupacks angeschlossen. Der BTS oben links steuert den hier noch nicht aufgebauten Fahrregler des Bugstrahlruders.

 

Zu einem 16K Decoder gehört auch der passende Encoder. Basierend auf der originalen Graupner Senderplatine habe ich einen Schaltplan und ein Layout erstellt. Natürlich ungetestet und ohne Gewähr.

Nachtrag zum Decoder:

Wie ich leider feststellen muss funktioniert der Decoder NICHT mit einem Corona RP8D1. Schuld ist hier wohl die Signalaufbereitung des Empfängers. Einen entsprechenden Eintrag zu diesem anscheinend generellen Problem habe ich hier gefunden.