Picaxe to PPM for picaxe control of RC plane

#1
This is just a short tread.

I attempted last night to try and generate a PPM (pulse position modulation) with a picaxe 18M2 chip. without a scope and some more testing equipment it will be difficult to get more accuracy. This is only the early stages of the code :
Code:
' Picaxe to PPM testing.
' Picaxe 18M2
' Original code by JOELY87

symbol stp = 220
symbol L = 560
symbol H = 1320
symbol lead = 11040
setfreq m32

main:
low B.4,5,6,7
'pause 100
'serout C.2,T4800_8,("R","T")
serin C.1,T4800_8,("CK"),b0,b1,b2,b3,b4,b5,b6
'debug
if b6 = 0 then one
if b0 < 90 then two
if b1 < 90 then three
if b0 > 160 then four
if b1 > 160 then five
goto main

one:high B.4
pulsout B.3, H
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus lead
goto main

two:high B.5
pulsout B.3, L
pauseus stp
pulsout B.3, H
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus lead
goto main

three:high B.6
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, H
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus lead
goto main

four:high B.7
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, H
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus lead
goto main

five:high B.4,7
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, H
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus stp
pulsout B.3, L
pauseus lead
goto main
the idea was that i could generate signals each of the 5 chanels for my DX5e in with stick potions from each extreme. if I could get this to work i could get into some maths and use variables rather than full stick.

here is some info about spektrum PPM
http://www.insecure.ws/2010/03/09/control-rc-aircrafts-from-your-computer-for-0 I used this as a basis but there was also another website http://www.mftech.de/ppm_en.htm that said general ppm was the timing I have used. Unfortunately I don't event have my DX5e to test the output as i sent it home for my little brother to learn


I was able to get the 18m2 chip to send pulses out and using a mono 3.5 jack my laptop and a oscilloscope program http://www.zelscope.com/ I could generate the signal required (approximately)

I was hoping to send ppm data to a spectrum DX5e using the trainer port. This requires 8 high pulses (minimum .7ms and max 1.7ms) with stop pulses of .3ms. The range between .7 and 1.7 is the stick position nothing to full. The lead in is (22.5ms - (sum(8 pulses) + 8*(.3ms)).

I tried a simplified version of this using 8 pulsout and 8 pause commands. In each block of code I left 7 pulses at .7ms and one at 1.7ms. I believe this worked ok in its simple form. The problem is when I put a serin line of code the program spent too long waiting, receiving then doing and therefore the lead pulse was too long.

So unless anyone has any ideas to overcome my PPM problem I think I am on the search for a Tx and Rx capable of operating at 16Mhz T4800 accurately with a range of 100- 500m.

I have a septate post going for this project you might want to check out if your interested in Wii communication, RC servo control. http://www.picaxeforum.co.uk/showthread.php?t=16664

Thanks all,
 
Last edited:
#3
I started writing some pseudo code for the PPM as an idea and i think i finished it without actually testing:
Code:
'Code for picaxe to PPM NOT TESTED

#picaxe20X2

symbol stp = 240 			'0.3ms x 8 (frequency change) x 100 (us) length of stop (low period) this would need some tinkering to get to 3ms
symbol trainer = B.3		'this will be the output to the trainer jack carrying the PPM signal
symbol ch7 = b12			'chanel 7
symbol ch8 = b13			'chanel 8
let ch7 = 0				'chanel 7 set to minimum high period
let ch8 = 0				'chanel 8 set to minimum high period

setfreq m64 

hsersetup B9600_64, %00 	'baud 9600 at 16MHz

main:
hserin [1000,main],0,6 		'receive 6 bytes into sp
put 6,ch7
put 7,ch8
ptr = 0  				'reset sp pointer
'hserout 0,(@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptr) ' i dont think i need hserout 


lp:
let w1 = 0
high trainer 			' I believe spektrum uses positive PPM
for b9 = 0 to 7 			' Eight channels
get b9,b1				' Get byte from scatch pad 0 - 7, and put in b1
let w3 = b1*100/255+70*8	' Convert byte from 0 to 255 to 70 to 170 the times by 8 due to increased frequency
low trainer				' set PPM low
pauseus stp				' pause low for Stop time 3ms 
high trainer			' set PPM high
pauseus w3	' 			' pause high for varible time between 0.7ms --> 1.7ms
let w1 = w1+w3+stp 		' add up all the low times and all high times
next b9

let w2 = 2250*8 - w1 		' 2250 x 8 for increased freq - all high and low times.
pauseus w2				' Lead in 
' I AM UNSURE WHETHER LEAD IS ABLE TO GO AT THE END. I HAVE A FUNNY FEELING I WILL NEED TO CALCULATE THIS PRIOR TO FIRST LOW COMMAND.
'All times will need tweeking with oscilloscope depending on the time it takes to process code.

goto main


ALTERNATIVE LP:
let w1 = 0
high trainer 			' I believe spektrum uses positive PPM
for b9 = 0 to 7 			' Eight channels
get b9,b1				' Get byte from scatch pad 0 - 7, and put in b1
let w3 = b1*100/255+70*8	' Convert byte from 0 to 255 to 70 to 170 the times by 8 due to increased frequency
let w1 = w1+w3+stp 		' add up all the low times and all high times
next b9
let w2 = 2250*8 - w1 		' 2250 x 8 for increased freq - all high and low times.
pauseus w2

let w1 = 0
high trainer 			' I believe spektrum uses positive PPM
for b9 = 0 to 7 			' Eight channels
get b9,b1				' Get byte from scatch pad 0 - 7, and put in b1
let w3 = b1*100/255+70*8	' Convert byte from 0 to 255 to 70 to 170 the times by 8 due to increased frequency
low trainer				' set PPM low
pauseus stp				' pause low for Stop time 3ms 
high trainer			' set PPM high
pauseus w3	' 			' pause high for varible time between 0.7ms --> 1.7ms
let w1 = w1+w3+stp 		' add up all the low times and all high times
next b9
goto main
'THIS IS JUST CUT AN PASED FROM THE ORIGINAL LOOP it will use many more calculation and hense more procesing time but the lead in loop is at the start of each command.
If anyone has any idea about PPM i would it would be much appreciated.

also for those of you that have successfully used HSERIN could you please tell me whether i have set this up correctly to run in the background on an 20X2 and collect 6 bytes?
 

hippy

Technical Support
Staff member
#4
also for those of you that have successfully used HSERIN could you please tell me whether i have set this up correctly to run in the background on an 20X2 and collect 6 bytes?
main:
hserin [1000,main],0,6

Not quite. This will wait until six bytes have been received so is similar to using SERIN. As the timeout simply restarts the command you can leave that part out.
 
#5
Thanks hippy

So I will be sending 6 bytes from the second picaxe in one string. So are you saying I have the command right except I don't need the timer part
Main:
hserin [1000,main],0,6

Instead use
Main:
hserin 0,6

Cheers
Joel
 

hippy

Technical Support
Staff member
#6
Yes, "HSERIN 0,6".

What I'm really saying is that it's not "background receive"; that is it will wait for the six bytes of data rather than carries on executing other code while data is / is not being received.

It may just be a terminology issue. It depends upon what you want the code to do. At the moment, if there's no data received the code waits and does nothing.
 
#7
Ok I think i understand

Hsein will start a serial in but allow other code to be processed while it receives data. By telling it to collect 6 bytes it is waiting just like a serin would. If I omitted the 6 would this then be true background.

The reason I am trying background Is due to the time my last code took to process the serin.

In reality it needs to read the data from the other picaxe and perform the loop in 22.5 ms. Do you think this is practical??
 

hippy

Technical Support
Staff member
#8
Yes, I believe it's entirely practical though there are a few ways to do it so it's debatable as to what is best; I'll admit I haven't read all the posts but the idea is sound.

The PPM Transmitter has to produce 8 signals in a frame of 22.5ms. Each signal has a maximum of 1.7ms+0.3ms gap = 2ms per signal, so 16ms for 8 signals. That gives 8.5ms for receiving and processing.

If your sending PICAXE sends serial, six bytes every 22.5ms, and the time taken to send those and process them afterwards is less than 8.5ms you can have a loop which waits for serial, processes, sends signals then waits again, no need for any background receive or anyting complex.

Either SERIN or HSERIN would work for that. HSERIN is better because it can use higher baud rates so the time to transfer six bytes of data can be reduced - also if using an 18M2 you don't have full 'background receive into scratchpad' as is available on the X2's so you would be limited in choices anyway. You could use either 18M2 or 20X2.

Doing full background receive on a 20X2 wouldn't be much harder if needed though the challenge is somewhat reversed; not sending data too fast such that it's missed while executing long PULSOUTS.

Attached is a 20X2 program which generates a PPM output using SETTIMER to set the farme rate which may be of interest. It doesn't include receiving data nor calculating the width of the PPM signals.
 

Attachments

#9
A stand-alone demonstration program for background receive can be found here.

The example is written for an X1 chip. The only change for the X2 is the mode parameter on the hSerSetup, requires 3 bits.
 
#10
Working PPM-pulse train

Hello,

This is a somewhat older thread but maybe I can give some ideas to others. I have used first ideas from RickHarris some years ago with some remarks from Hippy. Those ideas let to the next code.

Code:
'Version 1    13-5-2011			Peter Graat
'
'HARDWARE DEFINITIONS   PICAXE 20X2 on 64 MHz
'
'First idea from RickHarris with additions from Hippy of PICAXE-forum
'
'
'generate PPM-pulse train for 8 channels between 1ms and 2ms
'400 micro sec inter channel break
'8 channels - 0 to 5v input to ADC.
'frame rate stable 22.5ms
'
'				  PICAXE 20X2
'                        --------------
'       +5 Volt        -|1     \/    20|-   0 Volt
'       Serial in      -|2           19|-   Serial out
'       channel 3      -|3 C.7   B.0 18|-   channel 1
'                      -|4       B.1 17|-   channel 2
'                      -|5       B.2 16|-   channel 4
'                      -|6       B.3 15|-   channel 5
'       channel 7      -|7 C.3   B.4 14|-   channel 6
'       channel 8      -|8 C.2   B.5 13|-   
'                      -|9       B.6 12|-   PPM-pulse train
'                      -|10      B.7 11|-   Dummy
'                        --------------	      
'
'
'variables like: correction, sync, rust, pauze, mult and div are
'itterations after carefully studying oscilloscoop-pictures
'

#PICAXE 20X2
#NO_TABLE
OUTPUT B.6,B.7					'define outputs
INPUT B.0,B.1,C.7,B.2,B.3,B.4,C.3,C.2	'define input

'VARIABLE DEFENITIONS
SYMBOL ch1 = w0		'channel 1  
SYMBOL ch2 = w1	
SYMBOL ch3 = w2	
SYMBOL ch4 = w3	
SYMBOL ch5 = W4	
SYMBOL ch6 = W5
SYMBOL ch7 = W6
SYMBOL ch8 = W7		

SYMBOL correction = w8
SYMBOL sync = w9
SYMBOL rust = w10
SYMBOL pauze = w11
SYMBOL mult = b24
SYMBOL div = b25

'CONSTANT DEFINITIE

'PIN-DECLARATIE
SYMBOL PPM = B.6
SYMBOL DUMMY = B.7

'INITIALISATION
init:
	SETFREQ m64			
	LET ADCSETUP = %0000000111111110
	sync = 460			'approx. 400usec at 64 MHz
	correction = 980		'1ms - 400usec = 600usec = correction
	mult = 8			'mult & div to correct ADC to msec
	div = 5
	LOW PPM
	HIGH DUMMY

main:

	READADC10 B.0, ch1   	'1msec = 0 = 0 Volt and 2mec = 1024 = 5 Volt
	ch1=ch1*mult/div		
	ch1=ch1+correction      

	READADC10 B.1, ch2
	ch2=ch2*mult/div
	ch2=ch2+correction       

	READADC10 C.7, ch3
	ch3=ch3*mult/div
	ch3=ch3+correction       

	READADC10 B.2, ch4
	ch4=ch4*mult/div
	ch4=ch4+correction       

	READADC10 B.3, ch5
	ch5=ch5*mult/div
	ch5=ch5+correction       

	READADC10 B.4, ch6
	ch6=ch6*mult/div
	ch6=ch6+correction       

	READADC10 C.3, ch7
	ch7=ch7*mult/div
	ch7=ch7+correction       

	READADC10 C.2, ch8
	ch8=ch8*mult/div
	ch8=ch8+correction    

	rust = ch1+ch2+ch3+ch4+ch5+ch6+ch7+ch8
	rust = rust/2
	pauze = 13400-rust


	'send pulse stream out
	LOW PPM
	PULSOUT DUMMY,sync : PULSOUT PPM,ch1
	PULSOUT DUMMY,sync : PULSOUT PPM,ch2
	PULSOUT DUMMY,sync : PULSOUT PPM,ch3
	PULSOUT DUMMY,sync : PULSOUT PPM,ch4
	PULSOUT DUMMY,sync : PULSOUT PPM,ch5
	PULSOUT DUMMY,sync : PULSOUT PPM,ch6
	PULSOUT DUMMY,sync : PULSOUT PPM,ch7
	PULSOUT DUMMY,sync : PULSOUT PPM,ch8
	PULSOUT DUMMY,sync : HIGH PPM
	PAUSEUS pauze

	goto main
Feel free to comment. First I had all the variables calculated but discovered thru looking to the oscilloscoop that the overhead of the processor made things took longer. I have tried to copy the signal from a Robbe / Futaba FC16 transmitter. Usually the synchronisation pulse is given as an 300 usec pulse but om the FC16 this pulse is 400 usec. Also the repetition of the signal looks stable. The frame-length is approx 22.5 msec.
 
Top