Create a PPM Signal with PICAXE?

I am flying RC-models as well as CL-models. For CL flying I already realized some PICAXE projects such as a timer with an active rpm control for electric powered models. In the scale category of CL flying in addition to the control lines RC transmitters are allowed to handle special functions just as landing gear, motor power, lights and so on. Using a standard RC transmitter during CL flying is very bulky. So my idea is to create a small module with 2 sensors for landing gear and motor power based on a PICAXE, which sends a PPM servo sum signal to an available industrial 2.4 GHz HF-module. Now my question is, weather this is possible with a PICAXE or rather not? Has anyone already done such a job?

p.s. Please excuse my certainly not perfect English, its more than 40 years ago I learned it …
 

Goeytex

Senior Member
It should be quite possible with a Picaxe.

The TX side is straight forward. A thumb pot is read by a PICAXE ADC and converted to usable data for the motor control data byte. A switch ( or Pot) is monitored for the the landing gear data byte . These two bytes of data are sent to the RF Module TX.

The RX Side RF module receives the data bytes and makes them available to the RX side Picaxe. The Picaxe then uses this data to generate 2 servo control signals, one for the motor and one for the landing gear.

The two data byes are stored in a "buffer" by the RX side Picaxe, Then every 20 ms the bytes are read and the SERVOPOS value is updated for each servo.

If you tell us what RF modules you want to use, someone may have some sample code for them. I may have some Picaxe BASIC code for Nordic NRF24L01.
 
Last edited:
For my own models I will use the JETI Duplex EX HF transmitter module and inside the model a Jeti Duplex receiver. For friends of mine we want to use a SPECTRUM transmitter module and receiver as well as the FRSKY products. Other producers just as Futaba, Multiplex or Graupner should also be supported, because all the HF modules will accept a PPM servo sum signal for 8 servos. That’s the reason for it, that I cannot use the PICAXE standard servo command.
 

Peter Graat

New Member
It is already 5 years ago that I "updated" an old analog transmitter from Robbe that had jitter on the channels. I completely removed all electronics and replaced this with a small PCB with the picaxe 20X2. Also I used the Corona Hack module to get a 2.4 GHz transmitter. Here is the code I made with some help of others: see comments in code.....
Code:
'Version 2    13-5-2011			P Graat
'
'HARDWARE DEFINITIONS   PICAXE 20X2 on 64 MHz
'
'First idea from RickHarris 11-8-2008 on thread "Radio Control"
'with additions from Hippy of PICAXE-forum
'
'With changes specific for the Robbe Compact 2 transmitter with
'Corona 2.4 GHz Hack-Module
'
'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
symbol ch1_temp = w13
symbol ch2_temp = w14

'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 MIN 384 -384
	ch1=ch1*25/4		
	ch1=ch1+correction      

	READADC10 B.1, ch2
	ch2=ch2 MIN 369 -369
	ch2=ch2*29/5
	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 = 11400-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
Specifiic values for channel 1 and 2 are to correct for the specific potentiometer.
 
O.K. it works with a PICAXE 08m2 on a AXE 0231 module. I can define the limits for the servo movements and also can reverse the servo direction of travel. For the landing gear switch I realized a servo movement delay up to about 30 seconds. All parameters are stored in the EEPROM, so that they are easy to change for different applications. For tests I used a Jeti Profibox and a Jeti R5 receiver.

Next to do: A Windows program to change the parameters most easy via serial communication without using the PICAXE Editor.

For all who are interested here the code:
Code:
#rem

Fesselflugsender

Hardware: PICAXE 08M2

Alle Pin Funktionen (C.0 nur Ausgang, C.2 pwmout, C.3 nur Eingang)
                       
                     +---v---+                           
                 Vdd |1     8| Vss                       
           RxD/I C.5 |2     7| C.0 O/TxD                 
   Touch/ADC/O/I C.4 |3     6| C.1 I/O/ADC/Touch         
               I C.3 |4     5| C.2 I/O/ADC/Touch/PWM/TUNE
                     +-------+                           


Funktion: 
	Fesselflugsender mit 2 Gebern. 
	1. Geber fuer Motor = Poti
	2. Geber fuer Fahrwerk = Schalter (oder Taster?)
	3. Servoendstellungen fuer beide Geber variabel einstellbar
	4. Servolaufrichtung fuer beide Geber umkehrbar
	5. Servogeschwindigkeit fuer Schalter einstellbar
	
	Der Modul erzeugt ein Servosummensignal, das jedem beliebiegen Standard
	RC HF-Modul vorgesetzt werden kann. Als Empfaenger ist dann ein Ermpfaenger
	des HF-Modul Herstellers zu verwenden.
	
	Framerate fuer das gesamte Signal = 22,5 mSek
	Pause zwischen den einzelnen Servosignalen = ca. 0,4 mSek 
	
Versionsnachweis:

V0.1	Erste Testversion (Testhardware = FFS 2b)
				

Praefix Konventionen:

ps_	= Pinstatus
pi_	= Pin fuer input
po_	= Pin fuer output
c_	= Constant
b_	= Byte Variable
w_	= Word Variable
l_	= Label
s_	=	Subroutine
r_	= RAM Pointer (Adresse)
e_	= EEPROM Pointer (Adresse)

#endrem

;EEPROM Adressen
symbol e_poti_links = 0
symbol e_poti_rechts = 1
symbol e_schalter_links = 2
symbol e_schalter_rechts = 3
symbol e_schalter_tempo = 4

;EEPROM mit Werten versorgen
;damit koennen die Servo-Endstellungen vorgegeben werden
;auszerdem kann die Drehrichtung der Servos umgekehrt werden
;Werte werden wie fuer servopos Befehl angegeben
eeprom e_poti_links,(100)				
eeprom e_poti_rechts,(200)
eeprom e_schalter_links,(100)
eeprom e_schalter_rechts,(200)
eeprom e_schalter_tempo,(8)

;Pinbelegungen 
;(zum Test wie FFS2, sodass dieser als Testhardware verwendet werden kann.)
symbol po_led = C.1
symbol po_summsig = C.2 		
symbol ps_schalter = pinC.3
symbol pi_poti = C.4					;Pin Poti = Pin Motor vom FFS2


;Konstanten
symbol c_freqmult = 8					;Faktor fuer 32 MHz
symbol c_codezeit = 3800			;inkl. freqmult, muss bei Codeaenderungen zur Signalberechnung angepasst werden
symbol c_pause_low = 240			;Pause zwischen den einzelnen Servosignalen = ca. 0,4 mSek
symbol c_framerate = 2250			;= 22,5 mSek
symbol c_ein = 1							;Schalterstellung auf ein
symbol c_aus = 0							;Schalterstellung auf aus
symbol c_sig_korr = 40				;Grund noch unklar, aber damit tut's

;fix vergebene Variablen			
symbol b_poti_links = b0			;b0 bis b4 werden aus dem EEPROM uebernommen
symbol b_poti_rechts = b1
symbol b_schalter_links = b2
symbol b_schalter_rechts = b3
symbol b_schalter_tempo = b4
symbol b_work1 = b5						;Arbeitsvariable
symbol b_schalter_stand = b6

symbol w_sig_poti = w5				;Signallaenge Motorservo	
symbol w_sig_schalter = w6		;Signallaenge Fahrwerksservo
symbol w_sig_rest = w7				;fuer Servos 3 bis 8
symbol w_sig_ges = w8					;Signallaenge aller Servosignale 
symbol w_sig_start = w9				;Signallaenge Startsignal

symbol w_work1 = w10					;Arbeitsvariable
symbol w_sig_schalter_ziel = w11


;Programmsteuerung
l_start:
	setfreq m32
	high po_led						;Betriebsanzeige
	gosub s_lesen_eeprom	;Servoendstellungen vom EEPROM in Bytevariablen uebernehmen
	
	if ps_schalter = c_ein then
		w_sig_schalter = b_schalter_rechts * c_freqmult
		b_schalter_stand = c_ein
	else
		w_sig_schalter = b_schalter_links * c_freqmult
		b_schalter_stand = c_aus
	endif
	w_sig_schalter_ziel = w_sig_schalter

;Endlosschleife	
l_loop:
	gosub s_sigber	;Signallaengen berechnen
	gosub s_sigaus	;Summensignal ausgeben
goto l_loop


;Unterprogramm Lesen EEPROM
;Servoendstellungen werden in die Bytevariablen b0 bis b3 uebernommen
s_lesen_eeprom:
	for bptr = 0 to 4
		read bptr,@bptr
		if bptr < 4 then
			@bptr = @bptr - c_sig_korr
		endif
next
return


;Unterprogramm Signallaengen berechnen
s_sigber:
;Signal fuer Poti berechnen
	readadc pi_poti,w_work1
	w_work1 = w_work1 + 1
	if b_poti_rechts > b_poti_links then	; normale Laufrichtung
		b_work1 = b_poti_rechts - b_poti_links
		w_sig_poti = b_work1 * w_work1 / 256 + b_poti_links * c_freqmult
	else	;= invertierte Laufrichtung
		b_work1 = b_poti_links - b_poti_rechts
		w_sig_poti = b_work1 * w_work1 / 256
		w_sig_poti = b_poti_links - w_sig_poti * c_freqmult
	end if
	'sertxd (#w_work1,"/",#w_sig_poti,cr,lf)
;Signal fuer Schalter berechnen
	if ps_schalter = c_ein and b_schalter_stand = c_aus then
		w_sig_schalter_ziel = b_schalter_rechts * c_freqmult
		b_schalter_stand = c_ein
		;sertxd ("ps ein/stand aus:", #b_schalter_links,"/",#b_schalter_rechts,"/",#w_sig_schalter, "/", #w_sig_schalter_ziel, cr,lf)	
	end if
	if ps_schalter = c_aus and b_schalter_stand = c_ein then
		w_sig_schalter_ziel = b_schalter_links * c_freqmult
		b_schalter_stand = c_aus
		;sertxd ("ps aus/stand ein:", #b_schalter_links,"/",#b_schalter_rechts,"/",#w_sig_schalter, "/", #w_sig_schalter_ziel, cr,lf)	
	end if
	if w_sig_schalter < w_sig_schalter_ziel then
		w_sig_schalter = w_sig_schalter + b_schalter_tempo max w_sig_schalter_ziel
	end if
	if w_sig_schalter > w_sig_schalter_ziel then
		w_sig_schalter = w_sig_schalter - b_schalter_tempo	min w_sig_schalter_ziel
	endif

;Signal fuer nicht benutzte Kanaele berechnen
	w_sig_rest = 150 - c_sig_korr * c_freqmult				;fix auf Mitte
;Signallaenge fuer Startsignal berechnen (ohne Programmlaufzeit)
	w_work1 = c_pause_low * 8 
	w_sig_ges = w_sig_rest*6 + w_sig_poti + w_sig_schalter + w_work1
	w_sig_start = c_framerate * c_freqmult - w_sig_ges - c_codezeit
	return
	
	
;Unterprogramm Summensignal ausgeben
s_sigaus:
	low po_summsig										;Startsignal beenden
	pauseus c_pause_low
	pulsout po_summsig,w_sig_poti			;alle 8 Servosignale hintereinander absetzen
	pauseus c_pause_low
	pulsout po_summsig,w_sig_schalter
	pauseus c_pause_low
	pulsout po_summsig,w_sig_rest
	pauseus c_pause_low	
	pulsout po_summsig,w_sig_rest
	pauseus c_pause_low
	pulsout po_summsig,w_sig_rest
	pauseus c_pause_low
	pulsout po_summsig,w_sig_rest
	pauseus c_pause_low
	pulsout po_summsig,w_sig_rest
	pauseus c_pause_low
	pulsout po_summsig,w_sig_rest
	pauseus c_pause_low
	high po_summsig										;Startsignal starten
	pauseus w_sig_start						
return
 
Top