Philips RC-5 IR output on PICAXE (bit-banged) and TV/STB control examples

nick12ab

Senior Member
PICAXE has the irout command but it is very limited - not only can it only do the SIRC protocol but you can only set the command and not the device. I couldn't find much at all about bit-banging proper IR interfaces on PICAXE - there was plenty of info on using serout instead but that can't be used to control other devices.

RC-5 looks like an easy interface to bit bang. There are few bits and it uses manchester encoding rather than the popular alternative of varying pauses depending on whether the bit is a 1 or 0. That is important as it means that there is now only one time period value to guess rather than two values (you can't just use a pauseus command with the value pulled from the specification due to the overhead of the interpreter) plus the inverted part of the bit can be generated really easily.



I used a PICAXE-14M2 at 32MHz.

In this example code, signalpin is a pin variable (remember to set the pin as an output first!), bitperiod is a constant, flipbit/addressx/datax are bit variables. The flipbit bit variable should be toggled so that it indicates whether any interruption in the signal was because of something blocking the signal or because the button was released and pressed again.

The addressx bits control which device is to be controlled and the datax bits control what command is to be sent to the device.
Code:
send:
	signalpin = 1
	pauseus bitperiod
	signalpin = 0			'data6 + 1 for 7-bit commands
	pauseus bitperiod	
	signalpin = 1			'data6 for 7-bit commands
	pauseus bitperiod
	signalpin = flipbit
	pauseus bitperiod
	signalpin = flipbit + 1
	pauseus bitperiod
	signalpin = address4 + 1
	pauseus bitperiod
	signalpin = address4
	pauseus bitperiod
	signalpin = address3 + 1
	pauseus bitperiod
	signalpin = address3
	pauseus bitperiod
	signalpin = address2 + 1
	pauseus bitperiod
	signalpin = address2
	pauseus bitperiod
	signalpin = address1 + 1
	pauseus bitperiod
	signalpin = address1
	pauseus bitperiod
	signalpin = address0 + 1
	pauseus bitperiod
	signalpin = address0
	pauseus bitperiod
	signalpin = data5 + 1
	pauseus bitperiod
	signalpin = data5
	pauseus bitperiod
	signalpin = data4 + 1
	pauseus bitperiod
	signalpin = data4
	pauseus bitperiod
	signalpin = data3 + 1
	pauseus bitperiod
	signalpin = data3
	pauseus bitperiod
	signalpin = data2 + 1
	pauseus bitperiod
	signalpin = data2
	pauseus bitperiod
	signalpin = data1 + 1
	pauseus bitperiod
	signalpin = data1
	pauseus bitperiod
	signalpin = data0 + 1
	pauseus bitperiod
	signalpin = data0
	pauseus bitperiod
	signalpin = 0
	return
The placement of the data6 bit is believed to be correct but it might not be because the Wikipedia article wasn't 100% clear about it.

If multiple devices need to be controlled then the addressx bits can be assigned to variables - if not then they can be constants. If 4 or less (2 or less if using data6) devices are to be controlled, the relevant addressx bits can use the remaining bit variables that are part of the same byte variable as the datax bits are part of allowing the device controlled and the command sent to both be set using a single let command. Any number of devices can be controlled this way if a word variable is used.

I will use the above technique in the example below that can control a TV and a set top box.

This example code can control six functions of the TV or STB using six buttons wired between the pins defined in the symbol definitions and 0V - the internal pullups are used. The datasent bit variable is used to determine whether to toggle the flipbit variable or not. The pause 800 added to the send sub is to create a delay between repeated executions of the send sub.

The pwmout command is used to generate a 36KHz carrier signal with ~30% duty cycle. The bitperiod constant sets the period of each half-bit and may or may not need tweaking to work with all devices for the reason described earlier.

The constants for the commands for the set top box are ORed with 128 to set the device bit when those constants are used eliminating the need for a second variable to set which device is used or to manually do this in code at runtime. Since they are constants, they are calculated by the compiler rather than processed by the PICAXE at runtime but doing it this way allows it to be easily seen what the command codes are for the different commands.
Code:
#picaxe 14m2
#no_data
#no_end
#terminal off

symbol pwmpin = B.2
symbol signal = B.0
symbol signalpin = pinB.0
symbol button1 = pinC.0
symbol button2 = pinC.1
symbol button3 = pinC.2
symbol button4 = pinC.3
symbol button5 = pinC.4
symbol button6 = pinB.5

symbol flipbit = bit0
symbol datasent = bit1

symbol command = b1
symbol data0 = bit8
symbol data1 = bit9
symbol data2 = bit10
symbol data3 = bit11
symbol data4 = bit12
symbol data5 = bit13
symbol device = bit15

symbol address0 = 0
symbol address1 = 0
symbol address2 = 0
symbol address4 = 0

symbol bitperiod = 570

symbol doubledigit	= 10
symbol standby		= 12
symbol mute			= 13
symbol PP			= 14
symbol volup		= 16
symbol voldown		= 17
symbol channellist	= 18
symbol down			= 19
symbol up			= 20
symbol left			= 21
symbol right		= 22
symbol PRup			= 32
symbol PRdown		= 33
symbol lastpr		= 34
symbol audiomode		= 35
symbol hold			= 41
symbol subcode		= 42
symbol size			= 43
symbol reveal		= 44
symbol update		= 45
symbol mix			= 46
symbol index		= 47
symbol menu			= 48
symbol yellow		= 50
symbol blue			= 52
symbol OK			= 53
symbol green		= 54
symbol red			= 55
symbol AVbutton		= 56
symbol text			= 60
symbol TVbutton		= 63

symbol STB_back		= 10 | 128
symbol STB_standby	= 12 | 128
symbol STB_mute		= 13 | 128
symbol STB_AV		= 14 | 128
symbol STB_volup		= 16 | 128
symbol STB_voldown	= 17 | 128
symbol STB_up		= 18 | 128
symbol STB_down		= 19 | 128
symbol STB_OK		= 20 | 128
symbol STB_left		= 21 | 128
symbol STB_right		= 22 | 128
symbol STB_wide		= 30 | 128
symbol STB_PRup		= 32 | 128
symbol STB_PRdown		= 33 | 128
symbol STB_EPG		= 34 | 128
symbol STB_subtitle	= 38 | 128
symbol STB_yellow		= 50 | 128
symbol STB_blue		= 52 | 128
symbol STB_menu		= 53 | 128
symbol STB_green		= 54 | 128
symbol STB_red		= 55 | 128
symbol STB_text		= 60 | 128
symbol STB_info		= 63 | 128

main:
	pullup %0001111100100000
	disconnect
	setfreq m32
	pwmout pwmpin,221,267
	do
		if button1 = 0 then
			[B]command = standby[/B]
			gosub send
			[B]command = PRup[/B]
			gosub send
			do : loop until button1 = 1
			pause 10
		elseif button2 = 0 then
			[B]command = AVbutton[/B]
			gosub send
		elseif button3 = 0 then
			[B]command = STB_PRdown[/B]
			gosub send
		elseif button4 = 0 then
			[B]command = STB_PRup[/B]
			gosub send
		elseif button5 = 0 then
			[B]command = voldown[/B]
			gosub send
		elseif button6 = 0 then
			[B]command = volup[/B]
			gosub send
		elseif datasent = 1 then
			flipbit = flipbit + 1
			datasent = 0
		end if
	loop

send:
	signalpin = 1
	pauseus bitperiod
	signalpin = 0
	pauseus bitperiod
	signalpin = 1
	pauseus bitperiod
	signalpin = flipbit
	pauseus bitperiod
	signalpin = flipbit + 1
	pauseus bitperiod
	signalpin = address4 + 1
	pauseus bitperiod
	signalpin = address4
	pauseus bitperiod
	signalpin = device + 1
	pauseus bitperiod
	signalpin = device
	pauseus bitperiod
	signalpin = address2 + 1
	pauseus bitperiod
	signalpin = address2
	pauseus bitperiod
	signalpin = address1 + 1
	pauseus bitperiod
	signalpin = address1
	pauseus bitperiod
	signalpin = address0 + 1
	pauseus bitperiod
	signalpin = address0
	pauseus bitperiod
	signalpin = data5 + 1
	pauseus bitperiod
	signalpin = data5
	pauseus bitperiod
	signalpin = data4 + 1
	pauseus bitperiod
	signalpin = data4
	pauseus bitperiod
	signalpin = data3 + 1
	pauseus bitperiod
	signalpin = data3
	pauseus bitperiod
	signalpin = data2 + 1
	pauseus bitperiod
	signalpin = data2
	pauseus bitperiod
	signalpin = data1 + 1
	pauseus bitperiod
	signalpin = data1
	pauseus bitperiod
	signalpin = data0 + 1
	pauseus bitperiod
	signalpin = data0
	pauseus bitperiod
	signalpin = 0
	pause 800
	datasent = 1
	return
The chosen functions for the buttons are:
  • Standby (TV) - this button is done differently to the others because the TV will only come out of standby if PRup, PRdown or a channel number is used and not when the standby button is pressed again so sending both the standby and PRup commands in quick succession and not repeating this signal when the button is held down causes it to go into standby if it on and turn on if it is in standby.
  • AV (TV) - cycles between the AV inputs and analogue TV mode
  • STB_PRdown (STB) - P- on set top box
  • STB_PRup (STB) - P+ on set top box
  • voldown (TV) - decreases the volume on the TV
  • volup (TV) - increases the volume on the TV
These functions can be changed by changing which command is used for each button in that if...elseif...else...endif part of the code. Every command available on the TV/STB remote controls is listed in the symbol definitions area in the code.

I used an AND gate to modulate the signal on to the carrier. Another way of doing this is to use additional transistors as shown in westaust55's IR tutorial. The output of the AND gate feeds into the base of an NPN transistor through a resistor and this transistor drives the LED.

This worked perfectly on a Freeview box and 2 TVs (all rebadged Vestels) and should work on most store brand (and Hitachi now?) TVs.
Cannot explain any more due to reaching the forum character limit.

irtransmitter.JPG

Next thing to work on - modulating the signal onto the carrier inside the PICAXE rather than use external components.
 

nick12ab

Senior Member
PICAXE IR Modulation With No Additional Components Required (PICAXE-14M2)

PICAXE isn't too slow to toggle PWM on and off for IR purposes so it is possible to output the RC-5 IR signal already modulated onto the carrier without the need for an external AND gate or transistors. A transistor can optionally be used to provide high pulse currents to the LED (e.g. 100mA) to improve the range.

The PICAXE needs to be operating at 32MHz but when it's not sending anything it doesn't so the setfreq command can be used to lower the clock speed to improve battery life. I found that 250kHz was the minimum required for the signal to be repeated fast enough.

Some other changes have been made - one button has been removed so there are now only 5 buttons (due to the stripboard remote that will be posed soon not having anough room for 6). The bitperiod value had to be re-guessed because the slow PICAXE interpreter causes the addition of the gosub with the pwmout commands to add an extra delay to each bit. The new value is much lower.
Code:
#picaxe 14m2
#no_data
#no_end

symbol pwmpin = B.2
symbol signal = B.0
symbol button1 = pinC.2
symbol button2 = pinC.3
symbol button3 = pinC.4
symbol button4 = pinC.1
symbol button5 = pinC.0
'symbol button6 = pinB.5

symbol flipbit = bit0
symbol sendbit = bit1
symbol datasent = bit2

symbol command = b1
symbol data0 = bit8
symbol data1 = bit9
symbol data2 = bit10
symbol data3 = bit11
symbol data4 = bit12
symbol data5 = bit13
symbol device = bit15

symbol address0 = 0
symbol address1 = 0
symbol address2 = 0
symbol address4 = 0

symbol bitperiod = 80

symbol doubledigit	= 10
symbol standby		= 12
symbol mute			= 13
symbol PP			= 14
symbol volup		= 16
symbol voldown		= 17
symbol channellist	= 18
symbol down			= 19
symbol up			= 20
symbol left			= 21
symbol right		= 22
symbol PRup			= 32
symbol PRdown		= 33
symbol lastpr		= 34
symbol audiomode		= 35
symbol hold			= 41
symbol subcode		= 42
symbol size			= 43
symbol reveal		= 44
symbol update		= 45
symbol mix			= 46
symbol index		= 47
symbol menu			= 48
symbol yellow		= 50
symbol blue			= 52
symbol OK			= 53
symbol green		= 54
symbol red			= 55
symbol AVbutton		= 56
symbol text			= 60
symbol TVbutton		= 63

symbol STB_back		= 10 | 128
symbol STB_standby	= 12 | 128
symbol STB_mute		= 13 | 128
symbol STB_AV		= 14 | 128
symbol STB_volup		= 16 | 128
symbol STB_voldown	= 17 | 128
symbol STB_up		= 18 | 128
symbol STB_down		= 19 | 128
symbol STB_OK		= 20 | 128
symbol STB_left		= 21 | 128
symbol STB_right		= 22 | 128
symbol STB_wide		= 30 | 128
symbol STB_PRup		= 32 | 128
symbol STB_PRdown		= 33 | 128
symbol STB_EPG		= 34 | 128
symbol STB_subtitle	= 38 | 128
symbol STB_yellow		= 50 | 128
symbol STB_blue		= 52 | 128
symbol STB_menu		= 53 | 128
symbol STB_green		= 54 | 128
symbol STB_red		= 55 | 128
symbol STB_text		= 60 | 128
symbol STB_info		= 63 | 128


main:
	pullup %0001111100100000
	disconnect
	disablebod
	setfreq k250
	do
		if button1 = 0 then
			command = standby
			gosub send
			command = PRup
			gosub send
			do : loop until button1 = 1
		elseif button2 = 0 then
			command = prup
			gosub send
		elseif button3 = 0 then
			command = prdown
			gosub send
		elseif button4 = 0 then
			command = volup
			gosub send
		elseif button5 = 0 then
			command = voldown
			gosub send
		elseif datasent = 1 then
			flipbit = flipbit + 1
			datasent = 0
		end if
	loop

send:
	setfreq m32
	sendbit = 1
	gosub send2
	pauseus bitperiod
	sendbit = 0
	gosub send2
	pauseus bitperiod
	sendbit = 1
	gosub send2
	pauseus bitperiod
	sendbit = flipbit
	gosub send2
	pauseus bitperiod
	sendbit = flipbit + 1
	gosub send2
	pauseus bitperiod
	sendbit = address4 + 1
	gosub send2
	pauseus bitperiod
	sendbit = address4
	gosub send2
	pauseus bitperiod
	sendbit = device + 1
	gosub send2
	pauseus bitperiod
	sendbit = device
	gosub send2
	pauseus bitperiod
	sendbit = address2 + 1
	gosub send2
	pauseus bitperiod
	sendbit = address2
	gosub send2
	pauseus bitperiod
	sendbit = address1 + 1
	gosub send2
	pauseus bitperiod
	sendbit = address1
	gosub send2
	pauseus bitperiod
	sendbit = address0 + 1
	gosub send2
	pauseus bitperiod
	sendbit = address0
	gosub send2
	pauseus bitperiod
	sendbit = data5 + 1
	gosub send2
	pauseus bitperiod
	sendbit = data5
	gosub send2
	pauseus bitperiod
	sendbit = data4 + 1
	gosub send2
	pauseus bitperiod
	sendbit = data4
	gosub send2
	pauseus bitperiod
	sendbit = data3 + 1
	gosub send2
	pauseus bitperiod
	sendbit = data3
	gosub send2
	pauseus bitperiod
	sendbit = data2 + 1
	gosub send2
	pauseus bitperiod
	sendbit = data2
	gosub send2
	pauseus bitperiod
	sendbit = data1 + 1
	gosub send2
	pauseus bitperiod
	sendbit = data1
	gosub send2
	pauseus bitperiod
	sendbit = data0 + 1
	gosub send2
	pauseus bitperiod
	sendbit = data0
	gosub send2
	pauseus bitperiod
	sendbit = 0
	gosub send2
	datasent = 1
	setfreq k250
	return

send2:
	if sendbit = 1 then
		pwmout pwmpin,223,224
	else
		pwmout pwmpin,off
	end if
	return
 
Top