Proof of concept: servo speed and rotation

Hi again!

As I was kindly invited to Porvoo to speak at the Point College Internet of Things day, I thought I’d finally formalize a concept I have been thinking about for a while now: servo rotation direction and speed controlled by a potentiometer.

This little combo is not much on its own of course, but as it happens, it can be used for a multitude of things. To get us started with servos and potentiometers, see this two axis camera stand:

This is an older proof of concept in which I use two 180° servos with two potentiometers. Tilting things is a nice application for these semicircular movement servos, but for moving things from one place to another, we need full rotation or 360° servos.

As always I suggest that when you start learning how to use a new tool or device, it’s a good idea to split the project into smaller units. If the main idea is to use a potentiometer to run a servo in two directions at selected speeds, it can be seen as a sum of three smaller things:

  1. How to read values from the potentiometer
  2. How to rotate the servo both ways
  3. How to use the values from the potentiometer to govern direction and speed of the servo

The parts you need are cheap indeed. An Arduino clone sets you back some 5-8 euros, a potentiometer is a couple of euros, and the servo costs maybe 6 euros. Some wires and soldering tools are useful too.

The potentiometer

Arduino and potentiometer

Arduino and potentiometer

This device is merely a resistor with adjustable resistance. It has three pins, voltage in, resistance value, and ground. To see the values it is sending, you can use the Serial Monitor feature in Arduino. This nifty device will show on your computer screen what the potentiometer is sending.

The wiring is as seen on the picture. Pin 1 is Voltage in, so it is stuck in the +5V pin on the Arduino. Pin 2 is the value to be read from the potentiometer, and it can be stuck in any of the six analog ports on the Arduino – Arduino is then programmatically told which pin to read. And the third is the ground, and it can be stuck in one of the three ground pins of the board.

The code is as follows:

int sensorValue;

void setup() {
 Serial.begin(9600);
 pinMode(A0, INPUT);
}

void loop() {
 sensorValue = analogRead(A0);
 Serial.println(sensorValue);
 delay(100);
}

This is a good example of a very simple Arduino program. At the top, a single variable is declared, namely sensorValue. It holds the value read from the potentiometer.

In the setup block we open the connection into the serial monitor for display purposes. Pin A0 is declared as an input pin, and as we stuck the lead from the pot into this pin, it is now available for the Arduino.

The loop block reads the value using analogRead() and stores it in the sensorValue variable. It then waits for the 100 milliseconds and reads again. This gives you ten measurements per second.

When you run this code, Arduino will display the value on the screen as a running set of numbers. You will see that at one end of the potentiometer, the value is 0, and at the other end, 1023. Make note of these values, they will be needed later.

The servo

Arduino and servoThe 360 degree servo is governed by a control pulse. If the length of the pulse is 1200 milliseconds, the servo will run clockwise at full steam. If it is 1800, it will run counterclockwise, at an equally maniacal pace.

Theoretically, if the control pulse is 1500ms, it will stop the servo, but this is subject to individual servo settings. Luckily, with this program, you can easily find out what is the stop value for your servo. Mine stops at 1485ms, incidentally.

Connections are equally easy for this part of the project. Connect the brown wire of the servo to an available ground pin, the red into the 5V pin, and the yellow control wire to a digital pin. I will use 2 for this. The servo can be run off the Arduino if it is the only device connected, but when we add the resistor, the servo will need to be powered from a power source.

The code to use is as follows:

#include <Servo.h>          //use a library for servo control

Servo myTransportServo;     //declare a servo object
int speed = 1200;           //set the starting speed value
int step = 25;              //set the loop stepping value   

void setup() {
 myTransportServo.attach(2);//connect servo to digital pin 2
 Serial.begin(9600);        //open the monitor connection
}

void loop() {
 rollit(speed);             //go to function rollit
 delay(10);                 //wait a little
 if (speed > 1800){         //adjust the step as needed
 step = -25;
 }
 if (speed < 1200){
 step = +25;
 }
 Serial.print("Speed: ");   //print the current speed
 Serial.println(speed);
 speed = speed + step;      //adjust the speed with step
}

void rollit (int rollspeed){ //run the servo at the speed
 myTransportServo.writeMicroseconds(rollspeed);
 delay (500);
}

So this code loops between the full speed rotations in both directions, stopping in the center. If you want to find out the null value for your servo, use 1450 instead of 1200, 1550 instead of 1800, and a step of 1. Then note the value in the serial monitor when the servo stops.

The whole shebang

Arduino and potentiometer and servo

Arduino and potentiometer and servo

This last mile merely connects the two previous parts and merges the code. As I said, you have to supply the power for the servo separately now, because the servo and the resistor will drain Arduino’s power supply. For this purpose I have printed a little box that houses a 9V battery and has both a 2.5mm plug and two pins. It is necessary to have a common ground for Arduino and any devices connected to it, so using this setup is handy in that sense too.

The connections now are the same as for the part 1 on the potentiometer, but the servo has its power pins plugged to the power source. The servo control pin is again #2.

The code is as follows now:

#include <Servo.h>
#include <Math.h>
Servo myServo;

int sensorValue;
float control;

void setup() {
 Serial.begin(9600);
 pinMode(A0, INPUT);
 digitalWrite(A0, HIGH);
 myServo.attach(2);
}

void loop() {

sensorValue = analogRead(A0);
 delay(10);
 control = map(sensorValue, 14, 1023, 1200, 1800);
 Serial.print(sensorValue);
 Serial.print(" - ");
 Serial.print(control);
 Serial.println();
 myServo.writeMicroseconds(control); //1505
 delay(10); 
}

The new feature of this last program is the introduction of the map function. It takes five parameters: input value, value in low, value in high, value out low, value out high. To visualise this, if you had

control = map(5, 1, 10, 100, 1000),

the value of variable control would be 500.

And now, the control value is mapped from 14-1023 to 1200-1800. The servo will then rotate at full speed one way first, slow down as you move the lever on the pot, then go full speed the other way.

And now you will ask, what is the fun in this? Nothing. It is a proof of concept, void of usability as such. But I can think of three applications for it straight off the box:

  1. a camera dolly, using a worm screw and a nut attached to it
  2. a game of labyrinth, but vertical, two servos moving a horizontal bar supporting the ball
  3. any application where you have to have rotation converted into a two way movement.

And this is by far the most interesting part of using Arduinos – coming up with as many proofs of concept you can think of and assembling a library of them for the day the real need arises.

See it in action here, and stay tuned for the dolly, coming up soon.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *

*