ELAD AMS33 hacked for Remote Control
The ELAD AMS-33 is a 3x3 matrix antenna switch. The button on the front panel let you choose one of the 7 possible combinations. The actual combinations are displayed via a LED matrix.
After opening the box, the interior is well made. Near the processor is a 10 pole connector marked J11. My first assumption, it is a ISP programming port was wrong. It killed my ISP-programmer output. Further test showed that it is a JTAG port. Luckily, I was able to use my old DRAGON board with the actual version of ATMEL Studio after a short automatic firmware update. The reading and programming of the original software worked reliably. Thanks to ELAD not protecting the chip against reprogramming. Of course, the chip can be replaced with an new, unprotected one.
I used BASCOM for the new software. The first difficulty was finding the exact port connections of the relays, the LEDs, and the button. I desoldered all the relais to have a clear view on the PCB wiring. The original software has a special behavior. After switching, it turns of the controllers clock to avoid injecting noise into the receiver. A press on the button wake up the controller again.
For an external operation of the device I can use the UART interface available in many of ATMEL controllers. It is also available on the multipole post connector J1 including 5V power and ground.
The protocol for setting the antenna matrix is very rudimentary. Sending # followed by the desired switching position number and a final CR sets the desired IN/OUT configuration. The controller is now also awakened when data is received at the serial interface. Unfortunately, the first characters are lost. An unused sent character from the protocol (like space CHR(h20)) is sufficient to wake up the controller. After 200 ms, send the real control sequence.
After a voltage loss, the inputs are connected to the same outputs. (1=>1 / 2=>2 / 3=>3)
pictures
downloads
update
Dezember 2017: Connecting my RigExpert 230-Zoom to the Switch showed infinite SWR on the antenna which has a SWR on the 5W transceiver of 1:1.3. The result was the relais cannot handle such small current efficiently. If you knock the relais while transmitting 5W you will see changes in SWR as well.
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