Reliable infra-red system (bi-directional)

tiscando

Senior Member
Hi,
I was creating and testing a very reliable infrared morse-pulse system, which is also flexible.
At this time, I created a master-slave format of my bi-directional protocol. It works just like the I2C protocol, but the data is sent via IR. So, I would call this 'I2R'.
I've thoroughly tested this in picaxe VSM. If you encounter any problems using this, then notify me in this thread.


Morse pulse master.bas
Code:
symbol ad0=bit8		'variables
symbol ad1=bit9
symbol ad2=bit10
symbol ad3=bit11
symbol ad4=bit12
symbol ad5=bit13
symbol ad6=bit14
symbol ad7=bit15
symbol rw=b4
symbol adres=b1
symbol plv=w3

symbol iredout=0	'pins
symbol iredin=pin0
symbol iredin1=0

symbol hitime=100		'settings
symbol lotime=50		'half of the hi-time
symbol midtime=75		'150% (1.5) of low-time
symbol xhitime=200	'double of hi-time
symbol adresbits=4		'number of address bits

setfreq m8			'required for fast operation

main:
'whatever you have...
rw=?				'0=read slave, 1=write to slave
b0=?				'data: not required for read mode
adres=?				'0 to 1, 3, 7, 15, 31, 63, 127 or 255
				'    1bit,2, 3, 4,  5,  6,   7,  or 8bit
gosub sendvar0
'...
goto main
'...

sendvar0:
if rw=2 then 
	rw=0
elseif rw=3 then
	rw=1
endif
b5=b0
b6=adres
high iredout			'start signal
if iredin=0 then sendvar0
low iredout			'end of start signal
low iredout
for b3=1 to 2

for b2=1 to adresbits		'how many address bits there are
	if iredin=1 then invcom
	if ad0=1 then		'address
		pulsout iredout,hitime
		if iredin=1 then invcom
	else
		pulsout iredout,lotime
		if iredin=1 then invcom
		low iredout	'pause for short time
	endif
	adres=adres/2
	low iredout		'pause for short time
	low iredout
	low iredout
next b2

low iredout
if iredin=1 then invcom
if rw=1 then
	pulsout iredout,hitime	'write bit
	if iredin=1 then invcom
else
	pulsout iredout,lotime	'read bit
	if rw=2 then recvar
	rw=2
	goto readsk
endif

pause 1
for b2=1 to 8
	if iredin=1 then invcom
	if bit0=1 then		'data
		pulsout iredout,hitime
		if iredin=1 then invcom
	else
		pulsout iredout,lotime
		if iredin=1 then invcom
		low iredout	'pause for short time
	endif
	b0=b0/2
	low iredout		'pause for short time
	low iredout
	low iredout
next b2

readsk:
pause 1
b0=b5
adres=b6
next b3

b0=b5
adres=b6
for b3=1 to 250
if iredin=1 then out1		'wait for ack
pause 1
next b3
goto sendvar0			'try again if ack not recieved.

invcom:
low iredout
for b2=1 to 10
if iredin=1 then invcom
pause 1
next b2
goto sendvar0


recvar:
adres=b6
for b3=1 to 2
b5=b0
b0=0
for b2=1 to 8
pulsin iredin1,1,plv	'data
if plv>midtime then
	if plv>xhitime then invcom
	bit7=1
elseif plv=0 then
	goto invcom
endif
if b2<8 then 
	b0=b0/2 
endif
next b2

next b3

pause 1
if b5<>b0 then sendvar0
if iredin=1 then sendvar0

out1:
if iredin=1 then out1
return

Morse pulse slaves.bas
Code:
symbol plv=w3		'variables
symbol adres=b1
symbol ad0=bit8
symbol ad1=bit9
symbol ad2=bit10
symbol ad3=bit11
symbol ad4=bit12
symbol ad5=bit13
symbol ad6=bit14
symbol ad7=bit15
symbol rw=b5

symbol iredout=0		'pins
symbol iredin=pin0
symbol iredin1=0		'for pulsin command, sane pin number as iredin

symbol hitime=100		'settings
symbol lotime=50		'half of the hi-time
symbol midtime=75		'150% (1.5) of low-time
symbol xhitime=200	'double of hi-time
symbol adresbits=4		'number of address bits

setfreq m8		'required for fast and reliable operation
setint %1,%1
main:
'whatever you have...
'...
goto main
'...

interrupt:
for b4=1 to 15
if iredin=0 then fail
pause 1
next b4
b0=0
adres=0
rw=0
waitin1:
high iredout
if iredin=1 then waitin1
low iredout

vloop:
for b4=1 to adresbits'how many address bits there are
pulsin iredin1,1,plv'address
if plv>midtime then
	if plv>xhitime then fail
	ad3=1		'ad? where ?=adresbits-1
elseif plv=0 then
	goto fail
endif
if b4<4 then 
	adres=adres/2 
endif
next b4

pulsin iredin1,1,plv'r/w bit
if plv<midtime then
	if plv=0 or rw=3 then fail
	if rw=2 then 
		goto validate
	else
		rw=0
	endif
	goto rvalid
elseif plv>xhitime then
	goto fail
else 
	if rw=2 then fail
	if rw<>3 then
		rw=1
	endif
endif

for b4=1 to 8
pulsin iredin1,1,plv'data
if plv>midtime then
	if plv>xhitime then fail
	bit7=1
elseif plv=0 then
	goto fail
endif
if b4<8 then 
	b0=b0/2 
endif
next b4

if rw=2 or rw=3 then validate
b2=b0
rvalid:
b3=adres		're-use the above to save space
adres=0
b0=0
rw=rw+2
goto vloop

validate:
if b3<>adres then fail
if rw=2 then readadres
if b2<>b0 then fail

pause 2
pulsout iredout,xhitime'ack
write adres,b2	'Write recieved data to EEPROM.
hi2cflag=1
fail:
out1:
setint %1,%1
'Any extra bits you would like to add to this sub-procedure
'(like you do with the 'setintflags'-hi2cflag interrupt)...
return


readadres:
for rw=1 to 2
read adres,b0	'Read from EEPROM at address variable.
for b4=1 to 8
	if iredin=1 then fail
	if bit0=1 then	'data LSB
		pulsout iredout,hitime
		if iredin=1 then fail
	else
		pulsout iredout,lotime
		if iredin=1 then fail
		low iredout	'pause for short time
	endif
	b0=b0/2
	low iredout		'pause for short time
	low iredout
	low iredout
next b4
next rw
goto out1
edit1: This is not really good for sequential writes incase one datum gets written to the slave EEPROM, and then again on the next address.


To test this system, then add the below code between the 'setfreq m8' and 'sendvar0:' in the master program, replacing the code already there.

  • Create two infared picaxe circuits, both with an IR emitting diode, and an IR reciever. use 'x', 'x1' or 'x2' parts, as the other ones don't have enough program space.
  • connect the IR recievers according to picaxe manual 2, the infrain command.
  • connect the IR diodes with a 270-330 ohm (max. picaxe output current) resistor in series between a picaxe output, and 0V (gnd). check the diode is the right way round. make sure the the IR diode's beam and reciever's line of sight is parallel to each other, and place a baffle between both on the same board to prevent direct feedback. see the picture below.
  • specify the pin numbers on the pin-labelling symbols of both programs.
  • download the master program in one picaxe, and the slave program in another one.
  • keep the picaxe with the master program connected to your computer, running PE's serial terminal set to 9600 baud.
If you have the test program in your code, then place both circuits with the IR sides facing each other, and then power both picaxes in any order, and you should see data appear in your computer's terminal window, if everything is connected correctly. If it doesn't work, look for the obvious faults, before reporting thoroughly to me in this thread.

Unfortunately, I can't download my full connection diagram because it was too big, so Ive made a version that only shows the infared junction

Debugging code for picaxe master.bas (placed between the 'setfreq m8' and 'sendvar0:', replacing the starter code already there.):
Code:
main:				'start writing to slave
b0=45
adres=0
rw=1
gosub sendadr
gosub sendvar0

b0=90
adres=1
rw=1
gosub sendadr
gosub sendvar0

b0=142
adres=2
rw=1
gosub sendadr
gosub sendvar0

b0=63
adres=3
rw=1
gosub sendadr
gosub sendvar0

b0=2
adres=4
rw=1
gosub sendadr
gosub sendvar0

b0=98
adres=5
rw=1
gosub sendadr
gosub sendvar0

b0=76
adres=6
rw=1
gosub sendadr
gosub sendvar0

b0=12
adres=7
rw=1
gosub sendadr
gosub sendvar0

b0=241
adres=8
rw=1
gosub sendadr
gosub sendvar0

b0=121
adres=9
rw=1
gosub sendadr
gosub sendvar0

b0=34
adres=10
rw=1
gosub sendadr
gosub sendvar0

b0=222
adres=11
rw=1
gosub sendadr
gosub sendvar0

b0=7
adres=12
rw=1
gosub sendadr
gosub sendvar0

b0=51
adres=13
rw=1
gosub sendadr
gosub sendvar0

b0=186
adres=14
rw=1
gosub sendadr
gosub sendvar0

			'start reading and validating from slave
adres=0
rw=0
gosub sendvar0
b12=45
gosub sendata

adres=1
rw=0
gosub sendvar0
b12=90
gosub sendata

adres=2
rw=0
gosub sendvar0
b12=142
gosub sendata

adres=3
rw=0
gosub sendvar0
b12=63
gosub sendata

adres=4
rw=0
gosub sendvar0
b12=2
gosub sendata

adres=5
rw=0
gosub sendvar0
b12=98
gosub sendata

adres=6
rw=0
gosub sendvar0
b12=76
gosub sendata

adres=7
rw=0
gosub sendvar0
b12=12
gosub sendata

adres=8
rw=0
gosub sendvar0
b12=241
gosub sendata

adres=9
rw=0
gosub sendvar0
b12=121
gosub sendata

adres=10
rw=0
gosub sendvar0
b12=34
gosub sendata

adres=11
rw=0
gosub sendvar0
b12=222
gosub sendata

adres=12
rw=0
gosub sendvar0
b12=7
gosub sendata

adres=13
rw=0
gosub sendvar0
b12=51
gosub sendata

adres=14
rw=0
gosub sendvar0
b12=186
gosub sendata

pins=0
wait 10
goto main

sendata:
sertxd (#adres,": send ",#b12,", rec ",#b0,13,10)
return

sendadr:
sertxd ("writeI2R: ",#adres,13,10)
Return
The terminal data should look like this: (repeats every 15 seconds)
Code:
writeI2R: 0
writeI2R: 1
writeI2R: 2
writeI2R: 3
writeI2R: 4
writeI2R: 5
writeI2R: 6
writeI2R: 7
writeI2R: 8
writeI2R: 9
writeI2R: 10
writeI2R: 11
writeI2R: 12
writeI2R: 13
writeI2R: 14
0: send 45, rec 45
1: send 90, rec 90
2: send 142, rec 142
3: send 63, rec 63
4: send 2, rec 2
5: send 98, rec 98
6: send 76, rec 76
7: send 12, rec 12
8: send 241, rec 241
9: send 121, rec 121
10: send 34, rec 34
11: send 222, rec 222
12: send 7, rec 7
13: send 51, rec 51
14: send 186, rec 186
 

Attachments

Last edited:

tiscando

Senior Member
:eek::eek: I've just found out that an IR reciever actually idles high, with infared pulses entering pulsing it low. Anyway, use these program instead:

Morse pulse master.bas:
Code:
symbol ad0=bit8		'variables
symbol ad1=bit9
symbol ad2=bit10
symbol ad3=bit11
symbol rw=b4
symbol adres=b1
symbol plv=w3

symbol iredout=0	'pins
symbol iredin=pin0
symbol iredin1=0	'for pulsin command, same pin number as iredin.
symbol ihi=0		'set for use with 3-pin ir reciever
symbol ilo=1'opposite number of ihi.

symbol hitime=100	'settings
symbol lotime=50	'half of the hi-time
symbol midtime=75	'150% (1.5) of low-time
symbol xhitime=200	'double of hi-time
symbol adresbits=4	'number of address bits

setfreq m8			'required for fast operation

main:
'whatever you have...
'...
adres=?			'address
rw=?			'0=read to b0, 1=write from b0
b0=?			'neccessary for write mode
gosub sendvar0
'...
goto main

othersubs:
'...
return

sendvar0:	'Uses and corrupts b0 to b7.
if rw=2 then 
	rw=0
elseif rw=3 then
	rw=1
endif
b5=b0
b6=adres
high iredout			'start signal
if iredin=ilo then sendvar0
low iredout				'end of start signal
low iredout
for b3=1 to 2

for b2=1 to adresbits	'how many address bits there are
	if iredin=ihi then invcom
	if ad0=1 then		'address
		pulsout iredout,hitime
		if iredin=ihi then invcom
	else
		pulsout iredout,lotime
		if iredin=ihi then invcom
		low iredout		'pause for short time
	endif
	adres=adres/2
	low iredout			'pause for short time
	low iredout
	low iredout
next b2

low iredout
if iredin=ihi then invcom
if rw=1 then
	pulsout iredout,hitime	'write bit
	if iredin=ihi then invcom
else
	pulsout iredout,lotime	'read bit
	if rw=2 then recvar
	rw=2
	goto readsk
endif

pause 1
for b2=1 to 8
	if iredin=ihi then invcom
	if bit0=1 then		'data
		pulsout iredout,hitime
		if iredin=ihi then invcom
	else
		pulsout iredout,lotime
		if iredin=ihi then invcom
		low iredout		'pause for short time
	endif
	b0=b0/2
	low iredout			'pause for short time
	low iredout
	low iredout
next b2

readsk:
pause 1
b0=b5
adres=b6
next b3

b0=b5
adres=b6
for b3=1 to 250
if iredin=ihi then out1	'wait for ack
pause 1
next b3
goto sendvar0			'try again if ack not recieved.

invcom:
low iredout
for b2=1 to 10
if iredin=ihi then invcom
pause 1
next b2
goto sendvar0


recvar:
adres=b6
for b3=1 to 2
b5=b0
b0=0
for b2=1 to 8
pulsin iredin1,ihi,plv	'data
if plv>midtime then
	if plv>xhitime then invcom
	bit7=1
elseif plv=0 then
	goto invcom
endif
if b2<8 then 
	b0=b0/2 
endif
next b2

next b3

pause 1
if b5<>b0 then sendvar0
if iredin=ihi then sendvar0

out1:
if iredin=ihi then out1
return
Morse pulse slaves.bas:
Code:
symbol plv=w3		'variables
symbol adres=b1
symbol ad0=bit8
symbol ad1=bit9
symbol ad2=bit10
symbol ad3=bit11
symbol rw=b5

symbol iredout=0	'pins
symbol iredin=pin0
symbol iredin1=0	'for pulsin command, same pin number as iredin
symbol ihi=0		'set for use with 3-pin ir reciever
symbol ilo=1'opposite number of ihi.


symbol hitime=100	'settings
symbol lotime=50	'half of the hi-time
symbol midtime=75	'150% (1.5) of low-time
symbol xhitime=200	'double of hi-time
symbol adresbits=4	'number of address bits

setfreq m8			'required for fast and reliable operation
setint %1,%1
main:
'whatever you have...
'...
goto main

interrupt:				'Uses and corrupts b0 to b7
for b4=1 to 15
if iredin=ilo then fail
pause 1
next b4
b0=0
adres=0
rw=0
waitin1:
high iredout
if iredin=ihi then waitin1
low iredout

vloop:
for b4=1 to adresbits'how many address bits there are
pulsin iredin1,ihi,plv'address
if plv>midtime then
	if plv>xhitime then fail
	ad3=1			'ad? where ?=adresbits-1
elseif plv=0 then
	goto fail
endif
if b4<4 then 
	adres=adres/2 
endif
next b4

pulsin iredin1,ihi,plv'r/w bit
if plv<midtime then
	if plv=0 or rw=3 then fail
	if rw=2 then 
		goto validate
	else
		rw=0
	endif
	goto rvalid
elseif plv>xhitime then
	goto fail
else 
	if rw=2 then fail
	if rw<>3 then
		rw=1
	endif
endif

for b4=1 to 8
pulsin iredin1,ihi,plv'data
if plv>midtime then
	if plv>xhitime then fail
	bit7=1
elseif plv=0 then
	goto fail
endif
if b4<8 then 
	b0=b0/2 
endif
next b4

if rw=2 or rw=3 then validate
b2=b0
rvalid:
b3=adres			're-use the above to save space
adres=0
b0=0
rw=rw+2
goto vloop

validate:
if b3<>adres then fail
if rw=2 then readadres
if b2<>b0 then fail

pause 2
pulsout iredout,xhitime'ack
write adres,b2
hi2cflag=1
fail:
out1:
setint %1,%1
'Any extra bits you would like to add to this sub-procedure
'(like you do with the 'setintflags'-hi2cflag interrupt)...
return


readadres:
for rw=1 to 2
read adres,b0
for b4=1 to 8
	if iredin=1 then fail
	if bit0=1 then	'data LSB
		pulsout iredout,hitime
		if iredin=ihi then fail
	else
		pulsout iredout,lotime
		if iredin=ihi then fail
		low iredout	'pause for short time
	endif
	b0=b0/2
	low iredout			'pause for short time
	low iredout
	low iredout
next b4
next rw
goto out1
 
Last edited:

tiscando

Senior Member
I've created the code using the 28x1, but it's designed to fit onto any picaxe chip with enough program memory space. (you may need to change the pin numbers in the 'symbol ...={pin}#' statements.)
 
Top