pulsin for Model Radio Control.

the old fart

Senior Member
I've used pulsin for lots of my RC projects, with great success.
It works fine as long as the program is not too long.
Am I right in believing that I can't use the servo command because I'm using the pulsin command, something to do with internal timing.

Is it possible to use multiple interrupts to read the input signals, like, I hate to say, the Ard***o?

TOF
 

techElder

Well-known member
You didn't say what processor you are using, but what about adding a "servo system" that includes it's own 08M2 and eliminate all the balderdash specific to servos? You could separate some sensors to that "system", too.
 

the old fart

Senior Member
08m2, 20M2, 20x2, 40x2.

In the lifeboat that I'm building I have 2 20M2 for lights, relays, mosfets, and a 20X2 just for the speed control / servo system.

On other projects, I've used 08M2 to detect input pulse, and if no signal then give out a neutral signal (1.5ms) every 20ms.

Present project has 3 inputs, throttle, rudder and bow thruster.
Plus potentiometers for % reduction, min speed, max speed.

Outputs port throttle, starboard throttle, rudder, bow thruster, and some indication leds.

Output throttles dependent on rudder position and throttle input.
Bow thruster dependent on throttle input level and thruster input.

Looking at the output pulses, with DPScopeSE, the 20ms repeat time is exceeded.
increasing processor speed above 8mHz does not help, as it's real world timing, as opposed to processor timing.
 

goom

Senior Member
Sounds like the code between successive pulsin reads takes too long, and misses the next set of pulses from the receiver. You could try ramping up he processor speed after the pulsin statements, then returning to normal speed for the pulsouts and next pulsins.
Alternatively you could output using servopos which would maintain the 20ms frame rate despite missing some inputs. The response to transmitter inputs would be a little slower, but likely not a issue for your application.
 

the old fart

Senior Member
increasing the processor speed makes little difference.
servopos cannot be used, I believe, because the pulsin command utilities the internal timer.
Unless someone knows differently.
 

goom

Senior Member
Here is some code which does work. It does something very similar to what you are trying to achieve. In my case there is a third propeller, somewhat equivalent to your bow thruster.
You may get more help if you post your code.


Code:
'PICAXE-14M connections are:
'	Leg 1	                  +5V
'	Leg 2 (Serial in)       Tie to Ground through 10K resistor (to avoid floating)
'	Leg 3 (In4/ADC4)        Wiper of 10K pot (mix proportion)
'	Leg 4 (In3)             From receiver throttle channel
'	Leg 5 (In2)		      Tie to Ground through 10K resistor & switch to +5V
'	Leg 6 (In1)	   	      From receiver rudder channel        
'	Leg 7 (In0/ADC0) 	      Wiper of 10K pot (center motor proportion)
'	Leg 8 (Out5)            Stbd motor LED indicator
'	Leg 9 (Out4)            Center motor LED indicator
'	Leg 10(Out3)            Port motor LED indicator
'	Leg 11(Out2)            Center motor speed control
'	Leg 12(Out1)            Port motor speed control
'	Leg 13(Out0)            Stbd motor speed control
'	Leg 14                  Ground


symbol PW_Thr_null=b0	'Name the null position throttle input pulse width
symbol PW_Rud_null=b1	'Name the null position rudder input pulse width
symbol PW_Thr=w1		'Name the throttle input pulse width
symbol PW_Rud=w2		'Name the rudder input pulse width
symbol Mix_Prop=b6		'Name the mix proportion ADC signal
symbol CM_Prop=b7		'Name the center motor proportion (in reverse)
symbol PW_Port=b8		'Name output pulse to port motor
symbol PW_Stbd=b9		'Name output pulse to stbd motor
symbol PW_Ctr=b10		'Name output pulse to center motor
symbol Temp=b11






initialise:
setint %00000100,%0000100     'Set interrupt when pin2 goes high
let pins=%00111000		'Motor outputs low, indicators high
pause 250				'Wait 1/4 second initially


pulsin 3,1,PW_Thr_Null	'Read zero throttle input pulse width
pulsin 1,1,PW_Rud_Null	'Read center rudder input pulse width
if PW_Thr_Null<135 or PW_Thr_Null>165 then initialise'Go back if no valid throttle null input detected
if PW_Rud_Null<135 or PW_Rud_Null>165 then initialise'Go back if no valid rudder null input detected


readadc 4,Mix_Prop	'Read the mix proportion
readadc 0,CM_Prop		'Read the center motor proportion (for reverse operation)


pulsout 0, PW_Thr_Null	'Send null pulses to each motor
pulsout 1, PW_Thr_Null
pulsout 2, PW_Thr_Null


restart1:
pulsin 3,1,PW_Thr		'Read throttle input pulse width
pulsin 1,1,PW_Rud		'Read rudder input pulse width


setfreq m8			'Speed things up for the calculations


if PW_Rud>=PW_Rud_Null then 		    'Temp = absolute deviation of rudder from null position
   Temp=PW_Rud-PW_Rud_Null*Mix_Prop/256 'times the proportion determined by Mix_Prop
else
   Temp=PW_Rud_Null-PW_Rud*Mix_Prop/256
endif


if Temp<3 then		'Add a bit of hyteresis
   Temp=0
endif


if PW_Thr>=PW_Thr_null then
   PW_Ctr=PW_Thr						'Forward	
   if PW_Rud>=PW_Rud_null then
      PW_Port=PW_Thr+Temp max 200 min 100
      PW_Stbd=PW_Thr-Temp max 200 min 100
   else   
      PW_Port=PW_Thr-Temp max 200 min 100
      PW_Stbd=PW_Thr+Temp max 200 min 100
   endif
else								'Reverse
   PW_Ctr=PW_Thr_Null-PW_Thr*CM_Prop/256
   PW_Ctr=PW_Thr_Null-PW_Ctr				'Set reverse throttle to a proportion based on CM_Prop
   if PW_Rud>=PW_Rud_null then
      PW_Port=PW_Thr-Temp max 200 min 100
      PW_Stbd=PW_Thr+Temp max 200 min 100
   else   
      PW_Port=PW_Thr+Temp max 200 min 100
      PW_Stbd=PW_Thr-Temp max 200 min 100
   endif
endif


if PW_Port>=PW_Thr_Null then
   High 3				'Turn on port motor forward indicator
else 
   Low 3				'Turn on port motor reverse indicator
endif
if PW_Stbd>=PW_Thr_Null then
   High 5				'Turn on stbd motor forward indicator
else 
   Low 5				'Turn on stbd motor reverse indicator
endif
if PW_Ctr>=PW_Thr_Null then
   High 4				'Turn on center motor forward indicator
else 
   Low 4				'Turn on center motor reverse indicator
endif


setfreq m4			      'Slow back down for output of pulses


pulsout 0, PW_Stbd		'Send pulse to stbd motor speed controller
pulsout 1, PW_Port		'Send pulse to port motor speed controller
pulsout 2, PW_Ctr		      'Send pulse to center motor speed controller


goto restart1


interrupt:				'Allows re-read of ADC values and null positions
   setfreq m4
   pulsout 0, PW_Thr_Null	'Stop each motor
   pulsout 1, PW_Thr_Null
   pulsout 2, PW_Thr_Null
   pause 15
   if pin2=1 then interrupt   'Loop until pin2 goes low again
   setint %00000100,%0000100  'Reset interrupt
   readadc 4,Mix_Prop		'Re-read the mix proportion
   readadc 0,CM_Prop		'Re-read the center motor proportion
   pulsin 3,1,PW_Thr_Null	'Re-read zero throttle input pulse width
   pulsin 1,1,PW_Rud_Null	'Re-read center rudder input pulse width
return
 

hippy

Technical Support
Staff member
The main problem with SERVO and PULSIN is that the PICAXE cannot maintain servo loop timing while the program is waiting for PULSIN. It is possible to do both ...

Code:
Do
  PulsIn  RC_PIN, 1, w0
  PulsOut SERVO_PIN, w0
Loop
The servo loop timing will synchronise to the RC loop timing. There will be some jitter as the pulse length itself varies but most servos are tolerant to that.

It is also possible to read multiple channels ...

Code:
Do
  PulsIn  RC_A_PIN, 1, w0
  PulsIn  RC_B_PIN, 1, w1
  PulsIn  RC_C_PIN, 1, w2
  PulsOut SERVO_PIN, w0
Loop
But there are three potential issues there -

If RC_B_PIN is output before RC_A_PIN there will be an upto 20ms wait after the read of RC_A_PIN to reading RC_B_PIN, and possibly another long wait to reading RC_C_PIN. That can end up as a much longer than 20ms servo loop time.

If the RC_B_PIN pulse immediately follows the RC_A_PIN pulse, it may be that the first is read but, by the time the PICAXE is ready for the next that has been missed, adding a 20ms wait until that turns up again, and the same perhaps for the next.

Even if in the right order and each can be read within a single loop, RC_C_PIN may come almost 20ms after RC_A_PIN. Outputting the servo pulse can mean that the next RC_A_PIN pulse is missed, meaning a 20ms wait, and a longer servo loop time.

If any calculation time is too long that can also cause the PICAXE not to be ready for the next pulse when it arrives, adding a wait for the next pulse to arrive.
 

goom

Senior Member
A possible solution may be to read only 1 RC channel at a time, and would be essential if the receiver outputs all channels simultaneously as I believe some do. This will increase the time between updates, but may not be an issue in this application. It will also solve the issue of the receiver not outputting channels in the order in which you read them.

ch=1 'set to read channel 1 initially
restart1:


if ch=1 then 'Read each channel alternately (needed if both channel pulses are output simultaneously)
pulsin C.3,1,PW_Thr 'Read throttle input pulse width
else
pulsin C.1,1,PW_Rud 'Read rudder input pulse width
endif


setfreq m32 'Speed things up for the calculations to ensure Picaxe is ready for the next pulsin's.

'Do all of your stuff here


setfreq m4 'Slow back down for output of pulses


pulsout B.2, PW_Stbd 'Send pulse to stbd motor speed controller
pulsout B.1, PW_Port 'Send pulse to port motor speed controller


if ch=1 then 'Switch the channel to be read
ch=2
else
ch=1
endif


goto restart1
 

the old fart

Senior Member
Hippy's example shows the problem.

polling the inputs is a way to reduce waiting time.

Also by altering the sequence of reading can alter the speed.

ie instead of A B C, try A C B.
would need to scope to determine.

This is why I asked if I could use interrupts to read the inputs in the background.
 

hippy

Technical Support
Staff member
Using interrupts to read pulse length isn't easy on a PICAXE. The pulse will have started before the interrupt occurs and then there's no easy and accurate mechanisms to determine how long it took to enter the interrupt routine or measure how long until the pulse ends.

One can interrupt on some other pulse which precedes the one being measured then wait for the one wanted but that's no better than waiting anyway.

A dual PICAXE solution may help because the pulse receiver can get all that it needs no matter how long it takes, then tell the one controlling the servo how it should be positioned. HSERIN can be useful for that.
 

the old fart

Senior Member
Thanks Hippy,

Looks like I will need to redesign the PCB.

I've not used HSRIN before, but can see how it works, I think.

4 word values would need to be transferred.

20M2 / 20X2 pin 10 ----------------14M2 pin12 should work?

08M2 can't give out 4 servo pins?

A bit of code would be appreciated, nudge nudge...

TOF
 

hippy

Technical Support
Staff member
Before even thinking about redesigning the PCB or creating code it would be necessary to define exactly what the system needs to do, work out how best to do that, define the inputs, outputs and processing needed, exactly how much data needs to be transferred in a multi-PICAXE system.

For an 'easiest to put together' multi-servo system it may be best to use one 08M2 per servo and have another sending each its servo position data.

I think it is always best to design for an 'easiest to put together' solution, then refine that to reduce parts or cost. Any reduction in easiness usually results in complexity and difficulty so best to start with a solution which should work, even if not the solution finally chosen.
 

the old fart

Senior Member
Inputs, 3 off pulsin.
3 pots for setup
various buttons / leds
(all basic stuff)


4 digital outputs for polling.


Output Hserout from 20x2 to 4 08m2 hserin, via a polled 'AND' gate chip.

Will need some more thought.

TOF
 

the old fart

Senior Member
using 20X2,
servo only allowed from port B.

Code:
#PICAXE 20x2

SETFREQ M8

servo b.0,75
servo b.1,75
servo b.2,75
servo b.3,75
servo b.4,75
servo b.5,75
servo b.6,75
servo b.7,75


main:

for w1= 100 to 240
	
pause 50
servopos b.0,w1
servopos b.1,w1
servopos b.2,w1
servopos b.3,w1
servopos b.4,w1
servopos b.5,w1
servopos b.6,w1
servopos b.7,w1

next w1

goto main
maximum pulse out is around 245, higher than that and servo b.7 does not go low. 220 is normally highest required. but some TX use 125% instead of 100%

this would suit the two prop esc, the rudder, the thruster, and the sound board( 2 ch).
so this will produce the required outputs.

But how to get 4 words over the Hserout connection, which is only 1 word long?


split w1 into 2

b8-b17 servo2
bo-b7 servo1
 

the old fart

Senior Member
Using 2 20M2 chips.

.1uf caps on each chip
servo and scope on b.4
servo on separate supply and 330 ohm resistor in signal line.
on controlling chip I am pulsing out on C.7 to show data sent and cause delay in program.

on slow speed I get a glitch to the servo/scope, tried two servo and with servo disconnected.

output:
Code:
#PICAXE 20M2
SetFreq M4
HSerSetup B9600_8, %000
B1=100

transmit:
INC B1
IF B1>200 THEN LET B1=100:ENDIF
hserout 0,(b1)       'Send Trigger message. (A number 1)
PULSOUT C.7, 750
;PAUSE 100
GOTO TRANSMIT
input:
Code:
#PICAXE 20M2
SetFreq M4

servo b.4,150 ; MID POSITION

B4=150

HSerSetup B9600_8, %000

Do	
	LOW C.2 ; IND LED
  W0 = 0
  Do
    HSerIn w0
  Loop Until W0 > 0
 ;DEBUG
  B4=B0  ; PUT INPUT VALUE INTO B4 
  HIGH C.2
  servoPOS b.4,B4
Loop
 

hippy

Technical Support
Staff member
Not sure; you would have to put a scope on it. Or you could go for a bit-banged servo solution which should be entirely jitter free, untested ...

Code:
#Picaxe 20M2
HSerSetup B9600_4, %000
Low B.4
w0 = 150
Do
  w1 = 0
  HSerin w1
  If w1 > 0 Then
    w0 = w1
  End If
  PulsOut B.4, w0
  w1 = 2000 - w0
  PauseUs w1
Loop
That only checks the HSERIN every 20ms so one should not send too frequently. This should drive it backwards and forwards, 2.5 seconds per sweep ...

Code:
#Picaxe 20M2
HserSetup B9600_4, %000
Do
  For b0 = 100 To 199
    HSerOut 0,(b0)
    Pause 25
  Next
  For b0 = 200 To 101 Step -1
    HSerOut 0,(b0)
    Pause 25
  Next
Loop
The sender does not need to use HSEROUT, can use SEROUT, and that would be better if controlling multiple slaves, one per servo, each on a separate control line.
 

the old fart

Senior Member
servo's working :

Code:
#Picaxe 20M2
HSerSetup B9600_4, %000

servopos b.4,150

w0 = 150

do	
	w1=0
	hserin w1
	 if w1 >100 and w1 <201 then
		 w2=w1
endif 
if w1<100 then high c.5:else:low c.5:endif ; green led
if w1>203 then high c.7:else:low c.7:endif ;red led

servo b.0,w2
servo b.1,w2
servo b.2,w2
servo b.3,w2
servo b.4,w2
servo b.5,w2
servo b.7,w2
pause 20

loop
should be able to control 2 independent servo with one word, low byte, high byte.
enough for today. brain hurts...

TOF


edit:
youtube video
Code:
https://youtu.be/-Ojkl8l9Dz8
 
Last edited:
Top