Interpreting PWM and creating mixes for servos?

I am pretty green to programming. I fly a lot of RC planes / helicopters and I am getting into FPV/UAVs. I know right now I can't make a full GPS, navigation , telemetry system to have a plane taxi out, fly a sortie and land where I program it to. I intend to use it for some mixing, eventually add 3 axis gyros, maybe a barometric pressure sensor and the On screen display shield somehow so I can get an artificial horizon, altitude, nav points, ect. (Still dreaming!)

Right now it is baby steps, just finished the Arduino inventors kit tutorials and was able to write a few simple, crude programs to get LED's to blink in a certain order and speed. (After hunting down missing } and ; 's of course) The heart of my long term project is servo control. The Arduino was my first choice after seeing how much support it had and the servo library. The other thing I need to be able to do is connect an RC receiver up to the Arduino. The Arduino must see the PWM inputs and mix them. In other words, if I give the plane throttle, the Arduino will take a single input and turn it into two outputs to go to two servos.

I can do those mixes with my radio, but there are somethings the radio wont do. Say if I build an Ornithopter where the wings must flap (IE, servo goes back and forth) I would need to give it a stick input and the arduino would be able to move 1 or more servos back and forth with the speed varying on stick position. Another example would be a walking robot where two or more servos will need to move back and forth.

I have done a lot of reading and some research. I chose servos because I have a bunch on hand, RC receivers because of their long range and I am just used to them. But I did not see any threads on how to do what I am doing. If anyone could point me in the right direction, Ill try to figure it out.

Thanks!

pwm != ppm

I suggest you get one of the very small servo controllers like pololu makes and have the arduino just tell it what to do to allow the arduino to do more important things.

I was actually already thinking about getting one or two of those to free up the Arduino CPU. A buddy of mine just gave me some Freescale parts to play with. (a few accelerometers, pressure sensors, ect)

I think the general flow of the program would be something like this:

Connect RX to analog pins 1-6
Find minimum value, find center value, find max value, convert to digital
Take analog input, duplicate, replicate or modify signal to get a certain "mix"
Send new mixed single out to servos.

Not sure how to use the serial servo controller but I am willing to learn.

I think this is a good starting point if you are interested in RC flying

The say:

  • Can be used for an autonomous aircraft, car or boat.
  • Built-in hardware failsafe that uses a separate circuit (multiplexer chip and ATTiny processor) to transfer control from the RC system to the autopilot and back again. Includes ability to reboot the main processor in mid-flight.
  • Multiple 3D waypoints (limited only by memory)
  • Altitude controlled with the elevator and throttle
  • Comes with a 6-pin GPS connector for the 4Hz uBlox5 or 1hz EM406 GPS module.
  • Has six spare analog inputs (with ADC on each) and six spare digital input/outputs to add additional sensors
  • Supports addition of wireless modules for real-time telemetry
  • Based on a 16MhZ Atmega328 processor. Total onboard processing power aprox 24 MIPS.
  • Very small: 30mm x 47mm
  • Can be powered by either the RC receiver or a separate battery
  • Four RC-in channels (plus the autopilot on/off channel) can be processed by the autopilot. - Autopilot can also control four channels out.
  • LEDs for power, failsafe (on/off), status and GPS (satellite lock).

I have no commercial relationship, I've just been watching its progress, on and off.

HTGH
GB

Connect RX to analog pins 1-6

I think you may have misunderstood the nature of R/C PPM signals (as well as zero-origin indexing).
The signal from an R/C receiver is digital.

I was thinking since the servos used a PWM input, the output on the RX must be PWM.

I wanted to start small with simple things like an RC robot before risking an airplane. I wanted to get the Ardupilot but since I am new to programing, I wouldnt know what to do with it.

I tried to write another program today to get a potentiometer to set the speed and amount a servo sweeps back and forth. I know there are three main things. The speed of sweep, amount forward from center and amount back from center of sweep. (Might move 90 degrees forward but only 10 degrees back, but as of now that is above my head) It sort of worked. When I move the pot far right, the servo cycles but does not respond to any other position.

// Controlling a servo position using a potentiometer (variable resistor) 
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott> 

#include <Servo.h> 
 
Servo myservo;   
int potpin = 0;  
int val;  
 
void setup() 
{ 
  myservo.attach(9); }
 
void loop() 
{ 
  for(val = 0; val < 180; val += 1)
  {
   myservo.write(val);
   delay(15);
  }
  
{
  for(val = 180; val>=1; val-=1)
   val = analogRead(potpin);    
   val = map(val, 0, 1023, 0, 179);

 }
  myservo.write(val);    
  delay(15);                        
  }

I was thinking since the servos used a PWM input, the output on the RX must be PWM.

The servos don't use PWM, they use PPM.
PPM != PWM.

"analogWrite", despite the name, does not produce an analogue output, it produces a digital output (PWM).

You'll have great difficulty reading a PPM or a PWM signal with "analogRead".
"pulseIn" may be more appropriate.

 for(val = 180; val>=1; val-=1)
   val = analogRead(potpin);    
   val = map(val, 0, 1023, 0, 179);

You're missing braces after the "for" - all this is doing is performing "analogRead" in the loop.

I put the braces in, ran the program and the servo just jitters like it is having a seizure.

Right now I am just using a potentiometer but once I see how to get the servos to vary the sweep and speed with the Pot, I will modify the code to accept PPM. (I know a pot isnt like PPM, but they have a physical 0-100% setting like my aircraft radio)

the servo just jitters like it is having a seizure.

Not surprising:

 for(val = 180; val>=1; val-=1) {
   val = analogRead(potpin);    
   val = map(val, 0, 1023, 0, 179);
   myservo.write(val);    
   delay(15);                        
  }

You're changing the loop control inside the loop.

Can I suggest you spend a while longer on the tutorials, modifying and experimenting?

[edit]Here's an idea: once you've got the servo properly under control of the pot (still not sure why you've got the "for" loop around the pot-controlled section), why not try passing the PPM output controlling the servo into an input pin, and try measuring the pulses using "pulseIn"?[/edit]

There are two servo tests programs included in the Arduino IDE.
Have you tried them? One, 'sweep', looks like the program you posted.

The other one allows a potentiometer to be used to adjust the position of a servo, and is at
File->Examples->Servo->Knob

It is simpler than the example you've posted, and so may be a good base for experiments.

[edit]The loop() function is continuously run over and over, so if the goal is to make the servo slowly move to match the potentiometer, there is no need for a 'for loop' around the analogRead. Read the potentiometer once, then use the 'for loop' to move to that position.

Also the Arduino is much faster than the speed that the servo can change position, and that the further the servo needs to move, the longer it will take. The servo only gets an update of position every 20 milli seconds, so delay(15) is too small to be useful.[/edit]

Originally I was using the Knob tutorial, then tried to add in sweep. I can get the servo to match the position, but that is not what I am after.

Right now my circuit is just a Pot connected to arduino on pin 0 with a servo on pin 9.

I need to measure the range of the Pot I am using, but say the analog value it puts out is 0 to 100.

The servo moves 0 to 180 degrees in 0.25 seconds (just using a random realistic number)

When I set the Pot to "0," I want the servo to go a predetermined position.
When I set the Pot to "50," I want the servo to go from 0 degrees to 90 degrees in 0.50 seconds and sweep back and forth
When I set the Pot to "100," I want the servo to go from 0 to 180 degrees at 0.25 seconds and sweep back and forth.

Of course I wont be using 0 , 50 and 100. I want to program it so it knows what to do if I was at, say "75"

When I get an firm understanding of how to do that, I will start using PPM signals instead of the analog Pot.

Ill keep playing around with it till I get it right. Been reading a lot of tutorials and they tell you how to go from "crude programming" to more efficient programming by using variables and equations instead of "send servo to 0, then to 180 then to 0"

I great way to learn about PPM is to build your own stick that will interface via the trainer port of your radio.

This will give you the basis to having an Arduino fly a plane from the ground.

Ian.

I need to measure the range of the Pot I am using

No you don't - assuming it's wired correctly, it will go from (near enough) zero to (near enough) 1023.

Ill have to read up some more. I thought analog input returned a voltage that varied and the arduino read the voltage and converted it to a value between 0 and 255. I know better than to trust my few hundred dollar plane to my programing skills (or lack there of)

When I set the Pot to "0," I want the servo to go a predetermined position.
When I set the Pot to "50," I want the servo to go from 0 degrees to 90 degrees in 0.50 seconds and sweep back and forth
When I set the Pot to "100," I want the servo to go from 0 to 180 degrees at 0.25 seconds and sweep back and forth.

Of course I wont be using 0 , 50 and 100. I want to program it so it knows what to do if I was at, say "75"

It looks like you're using the pot as a simulation of 'lots of buttons', with different actions associated with part of the potentiometers range, i.e. each 'pseudo button'?

If that is the idea, a simple technique is to use map to convert the range of values returned by analogRead into a smaller range of 'buckets'.
For example
int buttonNumber = map(analogRead(0), 0, 1023, 0, 7);

would convert a sensor reading (e.g. the potentiometer) to give buttonNumber a value in the range 0 to 7.

Then you could do (ignoring switch/case for a few minutes):

if (buttonNumber == 0) {
servo go a predetermined position
} else if (buttonNumber == 1) {
servo go from 0 degrees to 90 degrees in 0.50 seconds and
sweep back and forth
} else if (buttonNumber == 2) {
servo to go from 0 to 180 degrees at 0.25 seconds and
sweep back and forth
} else if (buttonNumber == 3) {
...
} else if ... {
...
} else {
...
}

(you might want to look at switch/case at some point too)

HTH
GB

I did a little reading, the arduino converts analog to digital on a 1024 step scale. Bytes are 0-255 Integers are -32,768 to 32,767

Looks like I could use the map() function to convert the range from the Pot (0 to 1024) to 0 to 180 degrees to go to the servo. The speed of which the servo cycles would also depend on the value of the pot.

I used the "0, 50, 100" on the pot as an example. I want it to be like turning up the volume on a stereo, it gets louder. (The servo moves more and faster) The volume on a stereo isn't "low medium high"

I could simplify the program for now by ignoring the speed and just focusing on having the pot control the magnitude of the servo cycling.

That sounds like a plan :slight_smile:

You might want to note that there are more kinds of whole number.
A long is -2,147,483,648 to +2,147,483,647

An unsigned long is 0 to 4,294,967,295
and it is used for millis, delay, and micros, so you might need it to calculate how long things have happened, or you want to happen.

Just wondering, would this help me out at all?

$100 is my price range at the moment, I cant afford a $250 USB type kind let alone a real $5000+ one. I am just trying to read some PPM and PWM signals from my radio, receiver and from the arduino.

Is there a way to use the serial monitor to see what input the arduino is "seeing"?

I've considered getting one, but I got a second hand (pre-loved?) oscilloscope for free. A local organisation was throwing away old CRT-based oscilloscopes, and I got one, on the basis I agreed to take responsibility for disposal. In many countries, traditional electronic engineering is shrinking at a frightening rate, and equipment is surplus.

Yes, you could capture data with an Arduino. You could use Processing to graph it on a host PC. A chum did that.

PPM and PWM data would be easy. They are digital, so you aren't hampered by the Arduino's slow analogue to digital (ADC) converters.
All PPM or PWM needs are durations when the values are high or low, so it is reasonably compact data too. That oscilloscope would give more infrmation, but using your Arduino saves $100 to spend on your RC models :slight_smile: