Remote switch plug

steliosm

Senior Member
Hello all.

I have started playing around with a remote switch plug kit I got. I've seen on the internet that there are a couple of DIY projects controlling those plugs through a uC and an RF transmitter and I though that this could make a nice Picaxe project.

After reading about the protocol and especially looking at the code at this site I had a better understanding about what I needed to implement and the correct timing I had to use. I used a 20X2 chip running at 32MHz and I was able to turn on and off the plug.

This is the code I used to switch on a plug:

Code:
'
' PicAxe remote switch controller
' Emulates the output from a PT2262 encoder chip.
'
' ver 0.1(Proof-Of-Concept), by Steliosm (steliosm@gmail.com)
' based on project rc-switch (http://code.google.com/p/rc-switch/)
'
'

' Overclock the chip 
setfreq m32

' Define the timings - each pulse should be about 300-500uS depending on the receiver.
' The following timing value seem to work OK.
symbol waitShort = 150
symbol waitLong =  3 * waitShort
symbol waitSync = 31 * waitShort

'
' Bit-bang the RF Nexa protocol
'
main:
  '
  ' This should be done in a better way :-)
  '
  for b0 = 1 to 3
    ' Group address (dip switches set at 10001)
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address (dip switches set at 01000)
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    ' SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync
    gosub sendSync
  next
  ' End
end

send1:
  ' Send tri-State 1
  for b1 = 1 to 2
    high 4
    pauseus waitLong
    low 4
    pauseus waitShort
  next
return 

send0:
  ' Send tri-State 0
  for b1 = 1 to 2
    high 4
    pauseus waitShort
    low 4
    pauseus waitLong
  next
return

sendF:
  ' Send tri-State F
  high 4
  pauseus waitShort
  low 4
  pauseus waitLong
  high 4
  pauseus waitLong
  low 4
  pauseus waitShort
return

sendSync:
  ' Send sync sequence
  high 4
  pauseus waitShort
  low 4
  pauseus waitSync
return
I'm trying to make the code run at 16MHz speed by altering the pulse length (waitShort). My target is to run this code on a 08M2 chip overclocked. Any ideas about what I could do to save me a few CPU cycles on the chip and run the code a bit faster at 16MHz speed?
 

steliosm

Senior Member
I'm not at home to test this concept, but is there any change that pulsout can spare a few CPU cycles?
I was thinking of using these routines to send out the bits:

Code:
send1:

  ' Send tri-State 1

  pulsout 4, waitLong

  pauseus waitShort

  pulsout 4, waitLong

  pauseus waitShort
return 

send0:
  ' Send tri-State 0

   pulsout 4, waitShort

   pauseus waitLong

   pulsout 4, waitShort

   pauseus waitLong
return

sendF:
  ' Send tri-State F

  pulsout 4, waitShort

  pauseus waitLong

  pulsout 4, waitLong

  pauseus waitShort
return

sendSync:
  ' Send sync sequence
  pulsout 4, waitShort
  pauseus waitSync
return
Is there a good soundcard based scope or logic analyser?
 

hippy

Technical Support
Staff member
I don't know about soundcard based but we're very impressed by the Saleae "Logic" logic analyser - http://www.saleae.com/logic

Dropping from 32MHz to 16MHz notionally requires just halving the PAUSEUS delay. I can't see any problem using PULSOUT in this case and you could also use PULSOUT on an unused pin for the low timing as well.

You can use another PICAXE running a PULSIN to determine what the timing is for a particular pulse if you put a HIGH-PAUSEUS-LOW / PULSOUT in a test program.
 

steliosm

Senior Member
Saleae logic looks very good but if I was to buy one I would prefer to eitget an opensource hardware logic probe, like the Logic Shrimp.

Now, about clocking the chip from 32MHz to 16MHz, the obvious thing would be to cut the delay values by half. It didn't work yesterday while I was testing it. I even shifted the delay values a bit up and down, but still no luck. What worries me is that the lower clock speed will increase the command execution time and so I will have to take that under consideration and fine tune the pulse delays.

The pulsin trick sounds like a good idea to test out while I'm trying to figure out what is going on and how long my commands take to execute. Thanks for the tip Hippy.
 

hippy

Technical Support
Staff member
That's true; doubling the command overhead isn't necessarily compensated for by simply halving the time period. if "PAUSEUS 10" has 100us of overhead plus 100us of delay, doubling brings 200us of overhead and requires no additional delay. For "PAUSEUS 20" it at first glance seems to work; 100us plus 200us changes to 200us requiring 100us delay so that would appear to be "PAUSEUS 10", but then the 10us unit delay has increased to a 20us unit, thus "PAUSEUS 5".

At the initial speed, "PAUSEUS N" ...

T = Toverhead + ( N * Tunit )

N = ( T - Toverhead ) / Tunit

At half speed ...

T = ( Toverhead * 2 ) + ( N * Tunit * 2 )

N = ( T - ( Toverhead * 2 ) ) / ( Tunit * 2 )
 

steliosm

Senior Member
Interesting maths you got there Hippy.

The good news is that I found out that my Bus Pirate device can work as a low speed (~1MHz) logic analyzer using a Sump protocol compatible client :) This speed should be able to provide me with info about what is going on in the picaxe and may be help me tune my code.

I hope to have the new 082 chips by next week so I can test my theory.
 

hippy

Technical Support
Staff member
That maths ( or rather just the change in Tunit ) had me stumped for a while as to why you can't just halve ( or double ) N. I'd tripped over that myself in writing an IR remote recently and changed operating speeds. It suddenly came to me as to why when writing the answer !

Given that T, Tunit and N for a certain speed are known, it should be possible to determine Toverhead and what N would need to be for another speed. It's probably easier though to just put a scope / analyser on things and look at the timing which is what I did to tweak the values used.

Watch for value changes that go between ranges 0-1, 2-15, 15-255, 256-65535 as that can shift code alignment and alter the timing. Best to put the timing sensitive code at the start of the code and jump round it to 'poweron:' or 'main:', work on getting timing right from top to bottom.

One other tip to remember is to measure at the receiver not transmitter if you are trying to match closely what an original device ( eg, hand held remote ) puts out. For IR, a 50:50 square wave modulator to the IR LED won't usually give 50:50 at the receiver output because there's usually some delay while the AGC and filtering sorts itself out when IR first appears.
 
Last edited:

steliosm

Senior Member
Good news everyone!
I managed to get the speed down to 16MHz and have the code working fine. I had to use a Logic Analyzer to get to the correct timings (+/- 10uS). Each byte has about 360uS time-frame.

The following code switch on plug with id 00100 from group 10001:

Code:
' PicAxe remote switch controller
' Emulates the output from a PT2262 encoder chip.
'
' ver 0.1(Proof-Of-Concept), by Steliosm (steliosm@gmail.com)
' based on project rc-switch (http://code.google.com/p/rc-switch/)
'
'
' Overclock the chip 
setfreq m16
#no_table


' At 8Mhz for X2 parts pauseus
symbol waitShort = 61
symbol waitLong =  183
symbol waitLongLast = 118
symbol waitShortLast = 10
symbol waitSync = 31 * waitShort

'
' Bitbang the RF protocol
' F0000F00FFF0
'
main:
for b0 = 1 to 3
  ' Group address
  gosub send0
  gosub sendF
  gosub sendF
  gosub sendF
  gosub send0
  ' Plug address
  gosub sendF
  gosub sendF
  gosub send0
  gosub sendF
  gosub sendF
  'SendCommand (FF-on/F0-off)
  gosub sendF
  gosub sendF
  ' Send Sync 
  gosub sendSync
next b0
pause 10000
goto main
' End
end

send1:
    high 4
    pauseus waitLong
    low 4
    pauseus waitShort
    high 4
    pauseus waitLong
    low 4
    pauseus waitShortLast
return 

send0:
    high 4
    pauseus waitShort
    low 4
    pauseus waitLong
    high 4
    pauseus waitShort
    low 4
    pauseus waitLongLast
return

sendF:
  high 4
  pauseus waitShort
  low 4
  pauseus waitLong
  high 4
  pauseus waitLong
  low 4
  pauseus waitShortLast
return

sendSync:
  high 4
  pauseus waitShort
  low 4
  pauseus waitSync
return
I had to figure out the gosub/return command execution delays and abstract them from the pauseus values. I used extensively the logic analyzer to test different values and get the correct ones. The next move would be to test the code on a 08m2 chip, probably next week, and of course sending serial commands to turn on/off my lights :)
 
Last edited:

steliosm

Senior Member
The one I'm using it's branded as "Elro", you can get more info about the product if you look here.
Based on the research I did on the Internet, it's a Nexa-protocol compatible remote switch. Actually, if you read this page you will see at the section Supported Wall-Plug Socket Receiver Brands that there are quite a few devices manufactured by ArcTech and are sold under different brand but all of them use the same protocol.
 

steliosm

Senior Member
Hippy, that is about what I'm thinking of doing to make it run a bit faster. Since I would like my PC to control the lights/appliances, I was thinking of using a simple 2 bytes serial protocol.
Let me explain this:

Nexa protocol: 5bits for Group ID + 5bits for Device ID + 2 bits for command (on/off) = 12bit
2bytes = 16bits

S, I can store all the data that I need in just a couple of bytes. Then, I can have my little PC application creating my 2 bytes and then have the Picaxe code shifting through the bits and calling the appropriate subroutine.

Hippy, please note that the document you're linking to refers to the protocol use for a different type of appliances/remote: The ones that do not have a 10-size dip on their back. This document could be used as a reference http://code.google.com/p/rc-switch/source/browse/trunk/RCSwitch.cpp.

From the following links you can see the signal displayed on a Logic Analyzer. I used the Bus Pirate device to capture the signal, it worked great and helped me to check the speed execution of the program. First screen shows 3 bursts of the signal originating from the Picaxe and the second screen shows the signal's 0 and F bits.

Quiz: Can you decode the signal? (Of course you can, it's written in the code in the previous post ;-) )

Image 1
Image 2
 
Last edited:

steliosm

Senior Member
I'm switching the code to shift through the values stored in the w0 variable.
This statement seems to take more than a few 10s uSecs, and it's making the whole code not to function correctly.

This is the code I'm using now. Any ides on how I could make is run a bit faster, especially the shifting through the values in the w0 variable?

Code:
main:
  ' Load the command bits into an immutable variable
  w1 = %0111011011110000
  
'
' Bitbang the RF protocol
'
transmit:
  ' Repeat the transmission 3 times
  for b10 = 1 to 3
    ' Reset the variable
    let w0 = w1
    ' Shift left the w0 values for 12 times - since we need only 12 bits of data
    for b11 = 1 to 12
      ' Read the bit0 value and then shift left the w0
      ' Debug it
      'sertxd (#bit15)
      if bit15 = 1 then
        gosub sendF
      else
        gosub send0
      endif
     ' Shift the values - this probably takes some time
     let w0 = w0 * 2
  next

  ' Send the Sync signal
  gosub sendSync
  
  ' Debug
  'sertxd (10,13)

  ' Next transmission
  next b10
  
  ' Make a small pause
  pause 5000
  ' Debug
  'sertxd (10,13)
  ' Start again
  goto main
' End
end
 

steliosm

Senior Member
After testing for a bit I concluded that shifting through the bits added quite a bit of delay in the process making the pulse length differ from each other. What I did in the end was to keep the high/delay/low/delay routines and create new routines to turn on or off the appliances using fixed calls to the send0/sendF routines. I added the code to receive the appliace ID and action (1:eek:n, 0:eek:ff) and everything worked fine.

I got the 08m2 chips yesterday and started moving the code from the 20x2 to the 08m2 chip. What I noticed was that running the 08m2 at higher speed, 16MHZ or even 32MHz, yield unstable results. The length of pulses kept changing duration. I used the logic probe to tune the delay values for the pulses but I was still getting variable pulse lengths, eg. the first high pulse from the second data burst was either 400uS or 500uS. I was able to turn on/off an appliance but the timing in the pulses tends to change by about 10uS.

I will give the 08m2 another try but I'm starting to think that the 20x2 running at 16MHz is the suitable picaxe for the work, although I only need 3 pins :)
 

hippy

Technical Support
Staff member
After testing for a bit I concluded that shifting through the bits added quite a bit of delay in the process making the pulse length differ from each other.
What you perhaps need to do is move the 'send0' and 'sendF' code out of subroutines and into the IF-THEN-ELSE of the code, remove the overhead of the GOSUB-RETURN.

Not sure why you'd see different timings; are those consistent or random variations ? If consistent it may be that you are using the same timing constants in a number of places whereas they may need to be individually tweaked to cater for differences of time through various code paths.
 

steliosm

Senior Member
Hello hippy.
I will post the code as soon as I get home. Moving the send0/sendF function under the IF/THEN/ELSE will probably not be that easy. I'll post the code and we can see if this is possible.

They seem to be random. I tune a specific pulse and another one seems to change. I actually have to tune:
- the pulse: T (~350uS)
- the long pulse at the end of a bit: 3 x T - (time-to-execute-commands)
- the pulse at the end of a bit: T - (time-to-execute-commands)

I'll do a bit more testing with the probe before going back to 20x2.
 

steliosm

Senior Member
This is the code now:

Code:
'
' PicAxe remote switch control application
'
' ver 0.4, Stelios M.
' based on project rc-switch (http://code.google.com/p/rc-switch/)
'
'

#no_data
#picaxe 08m2

setfreq m16

' Define the timers
symbol waitShort = 61
symbol waitLong =  3 * waitShort
symbol waitLongLast = 90
symbol waitShortLast = 10
symbol waitSync = 31 * waitShort

'
' Read the data from the serial (device id: 1..4, command: 1(on), 0 (off) )
'
main:
  ' Readthe device ID and the action (on/off) from the serial port
  serin 3, t4800_16, #b10, #b11
  ' Check if the values are valid
  if b10 < 1 or b10 > 4 then
    'serout 2, t4800_16, ("Error in device ID", 10,13)
    goto main
  endif
  if b11 > 1 then
    'serout 2, t4800_16, ("Error in command", 10,13)
    goto main
  endif
  ' Call the apropriate subroutine
  if b10 = 1 then
    branch b11, (turn_1_off, turn_1_on)
  elseif b10 = 2 then
    branch b11, (turn_2_off, turn_2_on)
  elseif b10 = 3 then
    branch b11, (turn_3_off, turn_3_on)
  elseif b10 = 4 then
    branch b11, (turn_4_off, turn_4_on)    
  endif
  ' Go back to start
  goto main
end


turn_1_on:
  ' Switch device 1 On
  'serout 2, t4800_16, ("Switching device 1 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_1_off:
  ' Switch device 1 Off
  'serout 2, t4800_16, ("Switching device 1 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_2_on:
  ' Switch device 2 On
  'serout 2, t4800_16, ("Switching device 2 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_2_off:
  ' Switch device 2 Off
  'serout 2, t4800_16, ("Switching device 2 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_3_on:
  ' Switch device 3 On
  'serout 2, t4800_16, ("Switching device 3 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_3_off:
  ' Switch device 3 Off
  'serout 2, t4800_16, ("Switching device 3 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_4_on:
  ' Switch device 4 On
  'serout 2, t4800_16, ("Switching device 4 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_4_off:
  ' Switch device 4 Off
  'serout 2, t4800_16, ("Switching device 4 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main


send0:
  '
  ' Send a tri-State 0 bit
  '
  high 4
  pauseus waitShort
  low 4
  pauseus waitLong
  high 4
  pauseus waitShort
  low 4
  pauseus waitLongLast
return

sendF:
  '
  ' Send a tri-State F bit
  '
  high 4
  pauseus waitShort
  low 4
  pauseus waitLong
  high 4
  pauseus waitLong
  low 4
  pauseus waitShortLast
return

sendSync:
  '
  ' Send the sync sequence
  '
  high 4
  pauseus waitShort
  low 4
  pauseus waitSync
return
 

hippy

Technical Support
Staff member
There is some jitter in pulse times and I'd guess that was 'time' ticking plus other events internally that may cause the firmware to do something slightly different, timer overflows etc. There may also be some variation in all commands which depend on what the values actually used are.

I tested my 08M2 and the attached code seemed quite stable and any receiver should tolerate a few microseconds of jitter. I used a 300us 'T' so you'd have to tweak that to get it to match what you want but should give a good foundation to work on. I didn't totally fine tune to exact time. Timing may differ anyway depending on temperature, voltage, chip, day of week, phase of moon :)

Note the 'w0 = w0 * 2' was moved so it always fits in a long period, minimises the time after a 1 ('X') to when next bit is sent. I also use 'bit12' as msb ( after shifting / multiplying by two ). That means you don't need any lsb padding when setting 'w0'. I don't generate a sync but should be easy enough to add.

Code:
#Picaxe 08M2
#No_Data

;       ___           ___
; 0 => |   |_________|   |_________
;
;      |300|   900   |300|   900   |

;       ___           _________
; 1 => |   |_________|         |___
;
;      |300|   900   |   900   |300|

Goto PowerOnReset

SendW0:
  For b11 = 1 to 12
    Toggle 4 : PauseUs 154
    Toggle 4 : PauseUs 545
    w0 = w0 * 2
    Toggle 4
    If bit12 = 0 then
      PauseUs 81
      Toggle 4
      PauseUs 400
    Else
      PauseUs 515
      Toggle 4
      PauseUs 12
    End If
  Next
  Return

PowerOnReset:
  SetFreq M32
  DisableTime
  Low 4
  Do
    w0 = %001100110011
    Gosub SendW0
    Pause 1000
  Loop
 
Last edited:

steliosm

Senior Member
hippy, thanks for the code and the tips. Moving the shifting code (w0 = w0 * 2) in side the long pulse is something I couldn't have thought of.
I was hoping on running the picaxe at 16MHz and not pushing it at 32MHz, but it didn't work that way. Too much tuning, flashing, probing, analyzing those few days :) Hippy, you used pulsein to count the pulse lengths or did you used you logic probe?
Everything seems to work OK. With the following code I can control all four devices for the group "0FFF0".

Note: Pulse duration is about 400uS

Code:
'
' PicAxe remote switch application
' Emulates PT2262 encoder chip.
'
' ver 0.4, Stelios M.
' based on project rc-switch (http://code.google.com/p/rc-switch/)
'
'

#no_data
#picaxe 08m2

setfreq m32

' Define the timers
symbol waitShort = 250
symbol waitLong =  900
symbol waitLongLast = 520
symbol waitShortLast = 1
symbol waitSync = 31 * waitShort

'
' Read the data from the serial
'
main:
  '
  ' Readthe device ID and the action (on/off) from the serial port
  serin 3, t4800_32, #b10, #b11
  ' Check if the values are valid
  if b10 < 1 or b10 > 4 then
    serout 2, t4800_32, ("Error in device ID", 10,13)
    goto main
  endif
  if b11 > 1 then
    serout 2, t4800_32, ("Error in command", 10,13)
    goto main
  endif
  ' Call the apropriate subroutine
  if b10 = 1 then
    branch b11, (turn_1_off, turn_1_on)
  elseif b10 = 2 then
    branch b11, (turn_2_off, turn_2_on)
  elseif b10 = 3 then
    branch b11, (turn_3_off, turn_3_on)
  elseif b10 = 4 then
    branch b11, (turn_4_off, turn_4_on)    
  endif
  ' Go back to start
  goto main
end


turn_1_on:
  ' Switch device 1 On
  serout 2, t4800_32, ("Switching device 1 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_1_off:
  ' Switch device 1 Off
  serout 2, t4800_32, ("Switching device 1 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_2_on:
  ' Switch device 2 On
  serout 2, t4800_32, ("Switching device 2 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_2_off:
  ' Switch device 2 Off
  serout 2, t4800_32, ("Switching device 2 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_3_on:
  ' Switch device 3 On
  serout 2, t4800_32, ("Switching device 3 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_3_off:
  ' Switch device 3 Off
  serout 2, t4800_32, ("Switching device 3 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_4_on:
  ' Switch device 4 On
  serout 2, t4800_32, ("Switching device 4 On", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub sendF
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main

turn_4_off:
  ' Switch device 4 Off
  serout 2, t4800_32, ("Switching device 4 Off", 10,13)
  for b0 = 1 to 3
    ' Group address
    gosub send0
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    ' Plug address
    gosub sendF
    gosub sendF
    gosub sendF
    gosub send0
    gosub sendF
    'SendCommand (FF-on/F0-off)
    gosub sendF
    gosub send0
    ' Send Sync 
    gosub sendSync
  next b0
  ' Go back to start
  goto main


send0:
  '
  ' Send a tri-State 0 bit
  '
  high 4
  pauseus waitShort
  low 4
  pauseus waitLong
  high 4
  pauseus waitShort
  low 4
  pauseus waitLongLast
return

sendF:
  '
  ' Send a tri-State F bit
  '
  high 4
  pauseus waitShort
  low 4
  pauseus waitLong
  high 4
  pauseus waitLong
  low 4
  pauseus waitShortLast
return

sendSync:
  '
  ' Send the sync sequence
  '
  high 4
  pauseus waitShort
  low 4
  pauseus waitSync
return
 

hippy

Technical Support
Staff member
I was hoping on running the picaxe at 16MHz and not pushing it at 32MHz, but it didn't work that way.
It's always a challenge with high-speed bit-banging and finding the ideal balance between small code size needing loops but faster execution against slower speeds needing in-lining and more code.


Hippy, you used pulsein to count the pulse lengths or did you used you logic probe?
Logic analyser. It's simple to just put the mouse within a pulse and read off its time and you can work with all pulses of varying length at a time, though easiest to start with fewer pulses and build it up.

It can be a laborious process getting it spot-on, but you can usually hit 5% or better quite easily and that's often good enough. "Binary chop" is the secret here; for example try PAUSEUS 100 and 400 measure the times, find the middle number value ( 300 here ), then you know if the time you need is between 100-300 or 300-500, try the number half way ( 200 or 400 ), repeat and it quickly closes in.
 

steliosm

Senior Member
I was playing around with the transmitter yesterday, it seems to work fine. All four appliances were turning on and off without problems or without having to re-send the command. Time to make a small PCB to put it all together now.

hippy thank you for your help and the tips.
 

Dermotx

Member
Hi,

I want to send a 433MHz signal to turn on an RF socket from a 08M2 picaxe. I have already done this using an arduino UNO R3. I sniffed the signals coming from the remote control using the arduino and the screenshot is attached.

From this you can see that the first button push (turning ON socket N0.1) generates a binary code of 100111101111101000001111 and the pulse length is 314 microseconds.



I’ve gone through the various threads on the forum, especially by Stelious, and understand some of it but not all. The type of plug/socket he uses is different to mine which is a Status type available on amazon.co.uk.

I just want to send this binary code to the socket using a simple 433MHz transmitter to see if I can turn on the socket.



I also attach the very basic code that I used which of course doesn’t work.
Code:
'picaxe08M2
' binary code to turn on plug no.1 is 100111101111101000001111
Start:
high C.0        '1
pauseus 31
low C.0        '0
pauseus 31
low C.0        '0
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
low C.0        '0
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
low C.0        '0
pauseus 31
high C.0        '1
pauseus 31
low C.0        '0
pauseus 31
low C.0        '0
pauseus 31
low C.0        '0
pauseus 31
low C.0        '0
pauseus 31
low C.0        '0
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
high C.0        '1
pauseus 31
pause 5000
goto Start
arduino code sniffer.pngarduino code sniffer.png



Any help to get me on the right track would be much appreciated. Thank you,



Dermot
 

AllyCat

Senior Member
Hi,

Your (main) problem is that PICaxe Basic is an "interpreted" language so each instruction takes a significant time to execute. Typically, a HIGH or LOW takes about 400 us to execute and PAUSEUS has an "overhead" of about 600 us. So each of your bit periods will be about 1300 us (1.3 ms).

The first thing you will need to do is increase the clock frequency probably to 32 MHz (SETFREQ M32) and then adjust the PAUSEUS value by trial and error. The actual numerical increments (of PAUSEUS or PULSOUT, etc.) are "accurate", so should be 1.25 us with a 32 MHz clock. But you might not be able to do much better than the crude linear structure of the program because program loops take even longer to execute. :(

Cheers, Alan.
 

Dermotx

Member
Thanks for that Alan. So I should try the PAUSEUS command at about 250 (314/1.25) and trial and error from then on.
Regards
Dermot
 

AllyCat

Senior Member
Hi,

No, I estimate the HIGH / LOW will still take around 50 us (with a 32 MHz clock) and the PAUSEUS overhead around 75 us, so the additional delay should be about (314 - 125 ) / 1.25 = 151. Therefore I'd start with a PAUSEUS 150.

Cheers, Alan.
 

Dermotx

Member
Thanks for that Alan. So I should try the PAUSEUS command at about 250 (314/1.25) and trial and error from then on.
Regards
Dermot
Oops, I'm wrong there I think. I forgot to take account of the HIGH and LOW (400/8=50) and the PAUSEUS (600/8=75) so my PAUSEUS length should be about 125?
 

Dermotx

Member
Hi Alan. Sorry I didn't see your last post when I posted my last comment. You are right, it should be about 150 not 125. thanks again. I'll let you know how I get on.
Regards
Dermot
 

hippy

Technical Support
Staff member
From this you can see that the first button push (turning ON socket N0.1) generates a binary code of 100111101111101000001111 and the pulse length is 314 microseconds.
This thread might be of interest if these happen to be the same type of RF switches -


There's some code in post #30 which sends 433MHz to control those. I'd have to study that to say exactly how it works but I guess it's forming up 24 bits then just putting them out ten times with the correct timing.
 

Dermotx

Member
Thanks for that hippy. I've looked at your code but I'm afraid it's beyond me. I think I may just go for the less elegant option of wiring the buttons on the remote control to a small relay.
 

Dermotx

Member
Hi,

No, I estimate the HIGH / LOW will still take around 50 us (with a 32 MHz clock) and the PAUSEUS overhead around 75 us, so the additional delay should be about (314 - 125 ) / 1.25 = 151. Therefore I'd start with a PAUSEUS 150.

Cheers, Alan.
Hi Allen. I've tried a lot of different delays around 150 but it doesn't work unfortunately. It must be more complicated than just a simple delay between each 0 and 1.Thanks for your help anyway.
 

AllyCat

Senior Member
Hi,

Are you sure you've interpreted the Arduino analysis correctly? Do you have a 'scope or Logic Analyser to verify what the waveform looks like?

The sequence of "raw" data appears to be some form of pulse-width modulation (primarily around 300 and 900 us but with enormous variations), which is much more common for radio communications than just a simple NRZ (Non Return to Zero) string of bits. Have you checked the description of "Protocol 1"?

Cheers, Alan.
 

Dermotx

Member
Hi,

Are you sure you've interpreted the Arduino analysis correctly? Do you have a 'scope or Logic Analyser to verify what the waveform looks like?

The sequence of "raw" data appears to be some form of pulse-width modulation (primarily around 300 and 900 us but with enormous variations), which is much more common for radio communications than just a simple NRZ (Non Return to Zero) string of bits. Have you checked the description of "Protocol 1"?

Cheers, Alan.
Hi Alan. Thanks for your continued interest with my problem.

I don’t have a logic analyser or ‘scope. I got the info about the rf signal from a receiver attached to an arduino. I was then able to use this info to transmit the signal with an rf transmitter attached to the arduino and it operates the plugs flawlessly.

The procedure is described here:

https://randomnerdtutorials.com/decode-and-send-433-mhz-rf-signals-with-arduino/

A special RCSwitch.h library is used in the sketch. This is used to sniff the codes in the receive sketch. This info is then inserted into the transmit sketch which again uses the RCSwitch.h library.

The problem may be that this RCSwitch.h library does stuff to the binary code that is not obvious. It may automatically adjust the pulse length between different parts of the binary code. I haven’t been able to get any information on what it does or what the specification of the Protocol 1. There is a github page here but I can’t get any useful information from it with my level of expertise.


Incidentally, I have also been able to control the socket with a cheap ESP8266 connected to a rf transmitter as well. I may use that in conjunction with a picaxe to control the plug.

Regards and thanks again
Dermot
 

AllyCat

Senior Member
Hi,

Thanks for the clarification. Yes the "problem" with Arduinos is that a lot of the "nasty stuff" just gets hidden from the normal users, by the libraries.

However, is the "raw data" you showed in your first post, EXACTLY the same as you successfully programmed into the Arduino? The reason I ask is that the example data in the randomnerdtutorials article looks quite "clean", i.e. values of around 400 and 1200 (us) and the decoded binary largely alternating between 0 and 1. However, your data looks "all over the shop" with values as low as 16 and as high as 2770, and also "runs off the edge of the page". Note also that the first number in the raw data is quite large - that's possibly a runin signal to stabilise the AGC.

Maybe somebody will be prepared to delve into that library, but sorry, not me. Personally, I would use a PICaxe to receive and analyse the transmissions; there have been several threads on the topic. Perhaps surprisingly, it can be easier to receive data from those devices than to transmit it. One reason is that you can ignore items like runin , framing / address codes and checksums, etc., whilst usually they must all be correct for the switches to respond to a transmission.

Cheers, Alan.
 

Dermotx

Member
Hi Alan. I didn't program the raw data into the Arduino, just the binary code. I think the binary code may then be manipulated in some way or converted into the raw code by the RCSwitch.h library. I've since looked in more detail at the github on this and I will ask a few questions on their forum but I think it will be way above my pay grade! A few cheap relays attached to the pins on the remote control looks a far more realistic option for me.

Sometimes you've just got to accept your limitations:)
 

Dermotx

Member
By "you" I mean me accepting my limitations. I'm sure you would have the expertise to solve this if you had the time.
 

AllyCat

Senior Member
Hi,

One of the problems is that neither the "randomnerd" tutorial nor your attachment in #23 contains "real" data, just images of numbers. Personally, I'm not prepared to spend lots of time transcribing those images into text files. Also, it appears that the "raw" data is heavily truncated (i.e. much of it is missing).

However, it looks as if the "raw" data represents the periods (in us) that the transmitter should be alternately ON and OFF. Take a look at the randomnerd picture:

23841

All the rows of "raw data" start with a very large number (e.g. 12924) which is probably the "Run-In" of continuous carrier to stabilise the receiver's AGC. Then there are pairs of numbers, one "Small" (~390) approximtely equal to the "PulseLength" (415) and the other "Large" (~1270), approximately equal to three times the (average) PulseLength. Compare those pairs of times with the digits in the "Binary" code and it looks as if "0" is represented by a Short (gap) followed by a Long (carrier pulse) and a "1" represented by Long-Short. That seems to work for the first 12 or so bits, which are all that are shown as Raw data.

However, your raw data attached to #23 is much more erratic (with some values nowhere near to PulseLength or 3 * PulseLength). There's an old computer adage "garbage in garbage out", which is why I have little confidence that that particular Binary data will be "correct", even if converted back to pulse duty cycle (OOK) data.

Cheers, Alan.
 

Dermotx

Member
Hi Alan. I didn't program the raw data into the Arduino, just the binary code. I think the binary code may then be manipulated in some way or converted into the raw code by the RCSwitch.h library. I've since looked in more detail at the github on this and I will ask a few questions on their forum but I think it will be way above my pay grade! A few cheap relays attached to the pins on the remote control looks a far more realistic option for me.

Sometimes you've just got to accept your limitations:)
I haven't looked into the raw data before. In the raw data is the first value the height of the pulse and the second value the duration of the pulse?
 

Dermotx

Member
Crossing posts again:) You've answered my question. Thanks. I attach the raw data in a text file just in case you are interested. I do not of course expect you to do anything with it. thanks for all the help.
 

Attachments

Top