Serin hang workaround

moxhamj

New Member
Sometimes it is necessary to send data between two picaxe chips but not have the chips hang forever waiting for a serin. This code sends a packet of 11 bytes. Receiving picaxes can poll one line or any number of input lines, so long as the status of the lines is tested at least 6 times a second. In general terms;

main:
gosub testinputs
do other things
possibly a pause
goto main

The code uses pulsin and pulsout - and sends a low bit as a short pulse and a high bit as a long pulse.

This code was written for the 18X but works on any sort of picaxe. The order of the bytes is not important - so long as the order is the same for the receiver and transmitter!

Code:
Get_Packet:' test for packets arriving on pins 6,2, and 1 (example for an 18X, can change for other picaxe chips)	and pin 7 from radio 08
	let b7=pins' read pins
	b7=b7 and %11000110' mask off other input pins so only look at pins that expecting an input from	
	select case b7' can't convert directly to a number because small chance two lines might be high at the same time
	  case %00000010
	    b1=1' change pins binary to pin number
	  case %00000100
	    b1=2
	  case %01000000
	    b1=6
	  case %10000000
	    b1=7 ' from radio 08 buffer picaxe  
	  else
	   b1=0' zero if all tested input pins are zero
	endselect
	if b1=0 then goto end_packet' no packet so exit subroutine
	' now know which pin to read
	  pause 300' pin goes high for 250ms and low for 300ms so if it was high, then if wait 300ms then it must be low. 
	  b6=210' scratchpad location to store
	  for b4=1 to 11' count 11 bytes 
	    b7=1' value to add 
	    b0=0' start as zero, read LSB in first
	    for b5=1 to 8' count 8 bits, build byte b0
	      pulsin b1,1,w1' read pulse
	      if w1>100 then
			b0=b0+b7 ' assume if <100 then is a zero - a checksum on this packet sorts out any errors
	      endif
	      if w1=0 then goto end_packet' should be 73-77 and 148 to 152. Zero means timeout.
	      b7=b7*2' value to add multiply by 2
	    next b5
	    poke b6,b0' store the byte
	    b6=b6+1' increment the scratchpad location
	  next b4
	'now have the numbers in 210 to 220
	peek 210,b12
	peek 211,b13
	peek 212,b2
	peek 213,b3
	peek 214,b4
	peek 215,b5
	peek 216,b6
	peek 217,b7
	peek 218,b8
	peek 219,b10
	peek 220,b11
end_packet: return
To send a packet, use

Code:
Send_Packet:' sends data packout out using pwm data protocol. To pin number in b5 eg on an 18X can be pin 0 to 7
	' 11 bytes, scratchpad 210 to 220
	' this can't do radio, as random noise will start pwm and then will hang for 0.65535 seconds and miss the data packet
	' so if it is not radio, then no need to worry about making the high and low periods the same
	' we are storing 11 bytes - pauses between each one so can store
	low b5' so definitely low
	pulsout b5,25000' wakeup pulse 250ms
	pause 300' wait 300ms with line low (must be shorter than 0.65535 secs). 300ms is a good compromise.
	for b0=210 to 220' scratchpad locations - 11 bytes
	  peek b0,b1' get the byte
	  for b2=1 to 8
	    b3=b1 and %00000001' test the right bit
	    if b3=0 then
	        pulsout b5,75' send a 'low' pulse
	      else
	        pulsout b5,150' send a 'high' pulse
	    endif
	    pause 20' wait a bit - time for getpacket to store bytes, do calcs etc. 20 is reliable. 10 is mostly reliable
	    b1=b1/2' shift right
	  next b2
	next b0
	return
It may also be useful to translate serial data to pulsewidth data - eg when interfacing to a PC. An 08 can do the job - it sits and waits for data from the PC, and then forwards it on in pulswidth format to another chip, eg an 18X. (The 18X can send data directly back to the PC using serout.)

Code:
' This code uses an 08 chip but will also run on an 08M. (08 chips are cheaper)
' It is identical to the radio receiver except that the radio receiver has opposite polarity on the serin.

main:serin 2,T2400,("ID"),b12,b13,b2,b3,b4,b5,b6,b7,b8,b10,b11
	low 1' start low
      pulsout 1,25000' wakeup pulse
      pause 300' pause low
	b0=b12
	gosub send08
      b0=b13
      gosub send08
      b0=b2
      gosub send08
      b0=b3
      gosub send08
      b0=b4
      gosub send08
      b0=b5
      gosub send08
      b0=b6
      gosub send08
      b0=b7
      gosub send08
      b0=b8
      gosub send08
      b0=b10
      gosub send08
      b0=b11
      gosub send08
	goto main

Send08:' send byte in b0 to pin 1.Uses b0, b1 and b9 as these are unused in the data packet
     for b1=1 to 8
       b9=b0 and %00000001 ' test the right bit
       if b9=0 then
         pulsout 1,75 ' send a low pulse
        else
         pulsout 1,150
       endif
       pause 20' wait a bit
       b0=b0/2   
     next b1
     return
For talking to a PC a MAX232 is used, and this inverts the signal so it is usually high coming into the picaxe. Hence serin T2400 is used. For talking via radio modules where the resting state is low, a serin N2400 is used.
 
Last edited:
Top