mcHF : Selbstbau eines digitalen QRP Tranceivers
28. Mai 2017
Alle anzeigen

ELAD AMS-33 Antennenumschalter modifiziert für Remote Control

Antennenumschalter sind fast nicht aus dem Shack wegzudenken. Die vielen Bänder, die dem Amateurfunk zu Verfügung stehen, lassen sich selten mit nur einer Antenne sinnvoll benutzen. Wenn dann noch ein zweiter Sender mit an die Antenne(n) geschalten werden soll, kommt man nicht um solch ein Gerät herum.

Der AMS-33 von ELAD ist ein Antennenumschalter mit drei Eingängen und drei Ausgängen. Über einen an der Frontseite zugänglichen Taster lassen sich alle 7 Schaltmöglichkeiten auswählen. Die gewählte Verschaltung wird über eine LED-Matrix auf der Frontplatte angezeigt. Die Eingänge sind zudem mit Überspannungselementen abgesichert. Das Geräteinnere ist sehr übersichtlich. Ein Dutzend Relais sowie neun LEDs werden durch einen ATMEL Controller angesteuert. Ein Taster für die Wahl der Verschaltung, ein JTAG-Steckplatz und die Treiber für die Relais sind alles was auf der Platine zu finden sind.

Meine erste naive Annahme, dass der 10-pol Anschluss des ATMEL Controller für ISP Programmierung sei, wurde durch ein deutliches Rauchzeichen meines Programmieradapter verneint. Beim Durchmessen der Leitungen entpuppte sich der Anschluss als JTAG Interface. Im Hinterkopf hat sich bei mir noch die Information gehalten, dass mein vor vielen Jahren gekauftes ATMEL-Dragon Board ein solches unterstützt. Zu meiner Verwunderung konnte ich mit dem aktuellen ATMEL-Studio dieses Interface nach einem kurzen automatischen Update auch in Betrieb nehmen. Das Auslesen und Programmieren der originalen Software funktionierte zuverlässig.

Meinen Dank an den Hersteller ELAD, dass er keinen Schutz gegen Neuprogrammieren eingebaut hat. Sowas kann auch einfach durch Ersetzen des Prozessors umgangen werden. ATMEL-Studio habe ich dann einfach dazu benutzt, die Binärdatei in den Controller zu laden.

Die Software selbst musste ich neu schreiben. Dazu benutzte ich BASCOM. Die erste Schwierigkeit war, die genauen Portanschlüsse der Relais, der LEDs, und des Taster zu finden. Die Relais habe ich dazu ausgelötet. Der Rest war dann ein Kinderspiel. Die Originalsoftware hat noch eine Spezialität auf Lager. Sie setzt den Controller nach einigen Sekunden in Tiefschlaf. Dabei werden der Systemtakt und andere Teile des Controller abgeschalten. Der Grund dafür ist, dass sich keine HF des Prozessortakts in den Signalpfad einstreuen kann. Der Systemtakt liegt übrigens bei nur 8 MHz.

Für eine externe Bedienung des Geräts kann ich die bei vielen ATMELs vorhandene UART-Schnittstelle benutzen. Sie ist auch auf dem mehrpoligen Pfostenverbinder J1 verfügbar. Dazu eignen sich die vielen USB <-> UART Konverter die es in fast jedem Bastelshop zu kaufen gibt. Die Spannung wird direkt von J1 verwendet. Achtung! Nur 5V kompatible Typen einsetzen.

Das Protokoll für das Setzen der Antennenmatrix habe ich sehr rudimentär gewählt. Ein gesendetes # gefolgt von der gewünschten Schaltpositionsnummer und ein abschliessendes CR setzt die gewünschte Antennenkonfiguration. Der Controller wird beim Eintreffen von Daten an der seriellen Schnittstelle geweckt. Leider gehen dabei die Zeichen verloren. Ein vom Protokoll unbenutztes gesendetes Zeichen reicht aus, um den Controller zu wecken, um dann etwas später den eigentlichen Steuercode zu senden.

Nach einem Spannungsverlust werden die Eingänge mit den gleichzahligen Ausgängen verbunden. (1=>1 / 2=>2 / 3=>3)
AMS33.bas
'*********************************************
'* HF switch box AMS-33 from ELAD
'* modified firmware for remote control
'* using RS232 terminal => USB converter
'* HB9FZG 2016
'*
'* Connection matrix
'* Pos0 = I1=x I2=x I3=x
'* Pos1 = In1=Out1 In2=Out2 In3=Out3
'* Pos2 = In1=Out1 In2=Out3 In3=Out2
'* Pos3 = In1=Out2 In2=Out1 In3=Out3
'* Pos4 = In1=Out2 In2=Out3 In3=Out1
'* Pos5 = In1=Out3 In2=Out1 In3=Out2
'* Pos6 = In1=Out3 In2=Out2 In3=Out1
'*
'*********************************************

$regfile = "m169pdef.dat"
$crystal = 8000000
$hwstack = 16
$swstack = 32
$framesize = 32
$baud = 9600

CONFIG SUBMODE = NEW

CONST true = 1
CONST false = 0
CONST LEDPWR_ein = 0
CONST LEDPWR_aus = 1
CONST BUTTON_pressed = 0
CONST BUTTON_released = 1
CONST CMDnil = 0
CONST CMDstarted = 1
CONST CMDreceived = 2
CONST SleepDelay = 5
CONST POSnil = 255

LED_O1_I1 Alias PortA.3
LED_O1_I2 Alias PORTC.6
LED_O1_I3 Alias PORTC.7

LED_O2_I1 Alias PORTE.4
LED_O2_I2 Alias PORTE.3
LED_O2_I3 Alias PORTE.2

LED_O3_I1 Alias PORTE.7
LED_O3_I2 Alias PORTE.6
LED_O3_I3 Alias PORTE.5

BUTTON Alias PIND.1
LEDPWR Alias PORTB.1

K1 Alias PORTD.5
K2 Alias PORTC.0
K3 Alias PORTD.7
K4 Alias PORTD.2
K5 Alias PORTD.6
K6 Alias PORTC.4
K7 Alias PORTC.1
K8 Alias PORTC.3
K9 Alias PORTD.3
K10 Alias PORTD.4
K11 Alias PORTC.2
K12 Alias PORTC.5

DDRA = &b00001000
DDRB = &b00000010
DDRC = &b11111111
DDRD = &b11111100
DDRE = &b11111100

DIM Event10ms As Boolean
DIM Event100ms As Boolean
DIM Event1s As Boolean
DIM EventCntr As Integer
DIM Position_Curr As Integer
DIM E_Position_Curr as Eram Integer
DIM Position_New As Integer
DIM i As Integer
DIM x As Integer
DIM d as Byte
DIM cmdValue as Byte
DIM cmdState as Byte
DIM cmdLock as Integer
DIM Button_cntr as Integer
DIM Sleep_cntr as Integer

$include system.inc
$include relaispos.inc

'Init Timer0 (10ms cycle)
CONFIG TIMER0 = TIMER , PRESCALE = 1024
START TIMER0
ON OVF0 isrTimer0_Overflow
ENABLE OVF0

Config COM1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Open "COM1:" For BINARY As #1
On URXC isrRX_DataReceived
Enable URXC

Config Int0 = LOW LEVEL
On Int0 isrINT0 NoSave

'Config PCINT0
Pcmsk0 = &B00000001
On PCINT0 isrPCINT0

ENABLE Interrupts
LEDPWR = LEDPWR_ein
cmdState = CMDnil
Position_Curr = POSnil
Position_New = E_Position_Curr
Sleep_cntr = SleepDelay

Do
  If Position_New <> Position_Curr Then
    ' Open all connections
    Call SetNoConnection
    Waitms 100
    Call SetConfig(Position_New)
    Position_Curr = Position_New
    Sleep_cntr = SleepDelay
  End If

  If Event10ms = true then
    Event10ms = false
    If cmdLock > 0 Then DECR cmdLock
    If Button = BUTTON_pressed Then
      INCR Button_cntr
    Else
      Select Case Button_cntr
        Case 10 to 50
          If Position_New < 6 Then
            INCR Position_New
          Else
            Position_New = 0
          End If
          Button_cntr = 0
        Case Is > 100
          ' do nothing now
            Button_cntr = 0
      End Select
    End If
  End If

  If Event100ms = true then
    Event100ms = false
  End If

  If Event1s = true then
    Event1s = false
    If Sleep_cntr > 0 Then
      DECR Sleep_cntr
    End If
  End If

  If Sleep_cntr = 0 Then
    Call goSleep
  End If
Loop

'ISRs

isrINT0:
  DISABLE INT0
  Sleep_cntr = SleepDelay
RETURN

isrPCINT0:
  Sleep_cntr = SleepDelay
RETURN

isrTimer0_Overflow:
  'set 10ms interval
  TIMER0 = 178
  Event10ms = true
  'Toggle LEDPWR
  Incr EventCntr
  Select Case EventCntr
    Case 10
      Event100ms = true
    Case 20
      Event100ms = true
    Case 30
      Event100ms = true
    Case 40
      Event100ms = true
    Case 50
      Event100ms = true
    Case 60
      Event100ms = true
    Case 70
      Event100ms = true
    Case 80
      Event100ms = true
    Case 90
      Event100ms = true
    Case 100
      EventCntr = 0
      Event1s = true
  End Select
RETURN

'COM1 data received
isrRX_DataReceived:
  d = UDR
  'Toggle LEDPWR
  Select Case d
    Case 35                                                 ' # Command Start received
      cmdState = CMDstarted

    Case 48 to 54                                           ' "0" - "6" = valid relais map positions received
      if cmdState = CMDstarted then
        cmdValue = d - 48                                   'shift the ascii gap
        cmdState = CMDreceived
      end if

    Case 13                                                 ' CR Command End received
      if cmdState = CMDreceived then
        if cmdLock = 0 then
          cmdLock = 100                                     ' set 1 second lock time
          Position_New = cmdValue
        end if
      end if
      cmdState = CMDnil

    Case 10
      'do nothing, just ignore the LF character

    Case else                                               ' invalid command payload
      cmdState = CMDnil

  End Select
RETURN
relaispos.inc
'***********************************
'* Connection matrix
'* Pos0 = I1=x I2=x I3=x
'* Pos1 = In1=Out1 In2=Out2 In3=Out3 (default = powerless Relais)
'* Pos2 = In1=Out1 In2=Out3 In3=Out2
'* Pos3 = In1=Out2 In2=Out1 In3=Out3
'* Pos4 = In1=Out2 In2=Out3 In3=Out1
'* Pos5 = In1=Out3 In2=Out1 In3=Out2
'* Pos6 = In1=Out3 In2=Out2 In3=Out1
'*
'* In1 => Out1 = K4, K1 = off
'* In1 => Out2 = K2, K4, K6
'* In1 => Out3 = K3, K4
'*
'* In2 => Out1 = K1, K5, K9
'* In2 => Out2 = K9, K11, K7, K2 = off
'* In2 => Out3 = K8, K11
'*
'* In3 => Out1 = K1, K5
'* In3 => Out2 = K7, K12
'* In3 => Out3 = K10, K12, K8, K3 = off
'*
'***********************************

Sub SetRelais(ByVal n As Integer , ByVal p As Integer)
  Select Case n
    Case 1
      K1 = p
    Case 2
      K2 = p
    Case 3
      K3 = p
    Case 4
      K4 = p
    Case 5
      K5 = p
    Case 6
      K6 = p
    Case 7
      K7 = p
    Case 8
      K8 = p
    Case 9
      K9 = p
    Case 10
      K10 = p
    Case 11
      K11 = p
    Case 12
      K12 = p
  End Select
End Sub

Sub SetConfig(ByVal n As Integer)
  Select Case n
    Case 0
      Call SetNoConnection

    Case 1
      Call SetIn1Out1
      Call SetIn2Out2
      Call SetIn3Out3

    Case 2
      Call SetIn1Out2
      Call SetIn2Out1
      Call SetIn3Out3

    Case 3
      Call SetIn1Out3
      Call SetIn2Out2
      Call SetIn3Out1

    Case 4
      Call SetIn1Out1
      Call SetIn2Out3
      Call SetIn3Out2

    Case 5
      Call SetIn1Out2
      Call SetIn2Out3
      Call SetIn3Out1

    Case 6
      Call SetIn1Out3
      Call SetIn2Out1
      Call SetIn3Out2

  End Select
End Sub

Sub SetIn1Out1
  Call SetRelais(1 , 0)
  Call SetRelais(4 , 0)
  LED_O1_I1 = true
End Sub

Sub SetIn1Out2
  Call SetRelais(2 , 1)
  Call SetRelais(4 , 1)
  Call SetRelais(6 , 1)
  LED_O2_I1 = true
End Sub

Sub SetIn1Out3
  Call SetRelais(3 , 1)
  Call SetRelais(4 , 1)
  LED_O3_I1 = true
End Sub

Sub SetIn2Out1
  Call SetRelais(1 , 1)
  Call SetRelais(5 , 1)
  Call SetRelais(9 , 1)
  LED_O1_I2 = true
End Sub

Sub SetIn2Out2
  Call SetRelais(2 , 0)
  Call SetRelais(7 , 0)
  Call SetRelais(9 , 0)
  Call SetRelais(11 , 0)
  LED_O2_I2 = true
End Sub

Sub SetIn2Out3
  Call SetRelais(3 , 0)
  Call SetRelais(8 , 1)
  Call SetRelais(9 , 0)
  Call SetRelais(11 , 1)
  LED_O3_I2 = true
End Sub

Sub SetIn3Out1
  Call SetRelais(1 , 1)
  Call SetRelais(10 , 1)
  LED_O1_I3 = true
End Sub

Sub SetIn3Out2
  Call SetRelais(2 , 0)
  Call SetRelais(7 , 1)
  Call SetRelais(10 , 0)
  Call SetRelais(12 , 1)
  LED_O2_I3 = true
End Sub

Sub SetIn3Out3
  Call SetRelais(3 , 0)
  Call SetRelais(8 , 0)
  Call SetRelais(10 , 0)
  Call SetRelais(12 , 0)
  LED_O3_I3 = true
End Sub

Sub SetNoConnection
  'No connections
  Call SetRelais(3 , 0)
  Call SetRelais(4 , 0)
  Call SetRelais(5 , 0)
  Call SetRelais(6 , 0)
  Call SetRelais(7 , 0)
  Call SetRelais(9 , 0)
  Call SetRelais(10 , 0)
  Call SetRelais(11 , 0)
  Call SetRelais(12 , 0)
  Call SetRelais(1 , 1)
  Call SetRelais(2 , 1)
  Call SetRelais(8 , 1)

  LED_O1_I1 = false
  LED_O1_I2 = false
  LED_O1_I3 = false

  LED_O2_I1 = false
  LED_O2_I2 = false
  LED_O2_I3 = false

  LED_O3_I1 = false
  LED_O3_I2 = false
  LED_O3_I3 = false
End Sub
system.inc
Sub goSleep
  LEDPWR = LEDPWR_aus
  E_Position_Curr = Position_Curr
  ENABLE INT0
  ENABLE PCINT0
  CONFIG POWERMODE = POWERDOWN
  Waitms 200
  LEDPWR = LEDPWR_ein
End Sub
Deutsch