Introduction: Arduino ServoTimer2 and VirtualWire 433MHz Receiver

Picture of Arduino ServoTimer2 and VirtualWire 433MHz Receiver

The Idea:

  • Use low cost radio control components + Arduino to control the movements of a Servo

The Challenges

Other Solutions

Components

The Breakthrough

  • The Servo and Receiver do not like to play together so make them play apart.

Explanation

  • In most examples the servo is attached in the setup function. Similarly, the receiver is started in the setup function.
  • However, I guessed there might be a function to undo an attached servo and similarly to stop a receiver. A little investigation revealed that that was the case.

Step 1: Components & Code

Components

  • 10K Trimpot
  • 2 x Arduino (e.g. Uno, Duemilanove)
  • 433 MHz Transmitter & Receiver
  • Servo [I have a full rotation servo]
  • The usual prototyping paraphernalia - Computer, Breadboard, USB cables, Hookup wires

Virtual Wire

ServoTimer2

Step 2: Transmitter

Picture of Transmitter

The transmitter is the easy part.

  1. Read value from a Potentiometer
  2. Send it

Step 3: Receiver

Picture of Receiver

NOTE: You may get a compile error that has the text:

error: conflicting declaration 'typedef uint8_t boolean'

This is easy to resolve

  • Use a Text Editor to edit ServoTimer2.h
  • Comment out the two offending lines (lines 76 and 77) and SAVE

typedef uint8_t boolean;
typedef uint8_t byte;

Change these lines to:

// typedef uint8_t boolean;
// typedef uint8_t byte;

This seems to be due to ServoTimer2 being written a while ago before those types were defined.

Step 4: Conclusion

I wasn't expecting it to be so hard to get these components to work together.

I learnt a bit about timers & libraries along the way which was interesting.

The full rotation servo that I have stutters along because it is attached & detached. I don't have any other type of servo so I'd be interested in how different types of servo respond using the same setup.

Comments

slo91 (author)2016-12-01

hi there

thank you very much for this post and the continuous help, i finally got the circuit working as expected.

shah191295 (author)slo912017-02-08

Hey can you please share your code that you used to run three servo with three potentiometer. And did you have to use more than two arduino or just two.

slo91 (author)2016-11-28

hello

i tried to follow your instructions and modify your codes, but i didnt get the result i wanted as all 3 potentiometers are only controlling one servo. i have attached my tx and rx codes for you to have a look and correct if you find mistakes. please bare in mind i am a beginner at programming.

tx code:

#include <VirtualWire.h>

// Digital pin for LED

const int led_pin = 13;

// Digital pin for transmitter

const int transmit_pin = 3;

// Analog pin for Pot

int potPin1 = 3;

int potPin2 = 4;

int potPin3 = 5;

int potVal1 = 0;

int potVal2 = 0;

int potVal3 = 0;

byte encodedVal[6];

void setup()

{

// Initialise the transmitter

vw_set_tx_pin(transmit_pin);

vw_setup(2000); // Bits per sec

// The LED isn't necessary but gives a visual

// indication that something is happening

pinMode(led_pin, OUTPUT);

}

void loop()

{

// Read the pot

potVal1 = analogRead(potPin1);

potVal2 = analogRead(potPin2);

potVal3 = analogRead(potPin3);

// Convert int (PotVal) to byte array (encodedVal)

encode1(potVal1, encodedVal);

digitalWrite(led_pin, HIGH);

encode2(potVal2, encodedVal);

digitalWrite(led_pin, HIGH);

encode3(potVal3, encodedVal);

// Flash a light to show transmitting

digitalWrite(led_pin, HIGH);

// Send the byte array using the transmitter

send(encodedVal);

digitalWrite(led_pin, LOW);

// Wait a little bit before repeating

delay(10);

}

// Convert int to a 2 byte array

void encode1(int val1, byte *encoded ) {

encoded[0] = lowByte(val1);

encoded[1] = highByte(val1);

}

void encode2(int val2, byte *encoded ) {

encoded[2] = lowByte(val2);

encoded[3] = highByte(val2);

}

void encode3(int val3, byte *encoded ) {

encoded[4] = lowByte(val3);

encoded[5] = highByte(val3);

}

// Send byte array

void send (byte *message)

{

vw_send(message, sizeof(message));

vw_wait_tx(); // Wait until the whole message is gone

}

rx code:

#include <VirtualWire.h>

#include <ServoTimer2.h>

#define MIN_PULSE 750

#define MAX_PULSE 2250

const int led_pin = 13;

const int receive_pin = 4;

const int servo_pin1 = 10;

const int servo_pin2 = 11;

const int servo_pin3 = 12;

// a buffer to store the incoming messages

byte message[VW_MAX_MESSAGE_LEN];

// the size of the message

byte messageLength = VW_MAX_MESSAGE_LEN;

// Value decoded from message

int decodedVal1;

int decodedVal2;

int decodedVal3;

// Value mapped from Pot to Servo

int mappedVal1;

int mappedVal2;

int mappedVal3;

ServoTimer2 servo1;

ServoTimer2 servo2;

ServoTimer2 servo3;

void setup()

{

pinMode(led_pin, OUTPUT);

// Initialise the IO and ISR

vw_set_rx_pin(receive_pin);

vw_setup(2000); // Bits per sec

}

void loop()

{

readMessage();

}

void readMessage() {

vw_rx_start();

tryGetMessage(10);

vw_rx_stop();

}

void tryGetMessage(int times) {

bool gotMessage = false;

int i = 0;

while(i++ < times && !gotMessage) {

if (vw_get_message(message, &messageLength)) {

if (message[7] ==0) {

gotMessage = true;

// Flash a light to show received good message

digitalWrite(led_pin, HIGH);

decode1(message, decodedVal1);

decode2(message, decodedVal2);

decode3(message, decodedVal3);

mappedVal1 = map(decodedVal1, 0, 1023, MAX_PULSE_WIDTH, MIN_PULSE_WIDTH);

mappedVal2 = map(decodedVal2, 0, 1023, MAX_PULSE_WIDTH, MIN_PULSE_WIDTH);

mappedVal3 = map(decodedVal3, 0, 1023, MAX_PULSE_WIDTH, MIN_PULSE_WIDTH);

digitalWrite(led_pin, LOW);

}

}

}

delay(10);

servo1.attach(servo_pin1);

servo1.write(mappedVal1);

delay(20);

servo1.detach();

delay(20);

servo2.attach(servo_pin2);

servo2.write(mappedVal2);

delay(20);

servo2.detach();

delay(20);

servo3.attach(servo_pin3);

servo3.write(mappedVal3);

delay(20);

servo3.detach();

delay(20);

}

// Convert the two bytes back to int

void decode1(byte * encoded, int & decoded ) {

decoded = (short)(((encoded[1]) & 0xFF) << 8 | (encoded[0]) & 0xFF);

}

// Convert the two bytes back to int

void decode2(byte * encoded, int & decoded ) {

decoded = (short)(((encoded[3]) & 0xFF) << 8 | (encoded[2]) & 0xFF);

}

// Convert the two bytes back to int

void decode3(byte * encoded, int & decoded ) {

decoded = (short)(((encoded[5]) & 0xFF) << 8 | (encoded[4]) & 0xFF);

}

RussellM37 (author)slo912016-11-28

I presume you have a roll, pitch and yaw. I would be inclined to use an additional arduino at the receiver. I was just wanting to see if this could be done with only 1 Arduino at the receiver end. What I have shown is that it can be done but it's not the best technique. The movement is jerky due to all those delays + time taken to attach/detach.

Have a look at this instructable that I referenced earlier

https://www.instructables.com/id/How-to-build-433-MHZ-RC-to-control-servos-100-Ardu/

===

I'm not sure that the check is even valid in my original code but change (message[7] ==0) to (message[6] == 0).

You can use Serial.print as a debugging tool. You don't need to write 3 functions that do basically the same thing. E.g. instead of your 3 decode functions you can have one:

void decode(byte * encoded, int & decoded, int idx ) {

decoded = (short)(((encoded[idx+1]) & 0xFF) << 8 | (encoded[idx]) & 0xFF);

}

Fewer functions = fewer places for things to go wrong + less code to check.

slo91 (author)RussellM372016-11-29

after changing those 2 lines in the receiver code, here the error i get:

void decode(byte * encoded, int & decoded, int idx ) {

^

Multiple libraries were found for "ServoTimer2.h"

Used: C:\Program Files (x86)\Arduino\libraries\ServoTimer2

Not used: C:\Users\elijah\Documents\Arduino\libraries\ServoTimer2-master

exit status 1

too few arguments to function 'void decode(byte*, int&, int)'

RussellM37 (author)slo912016-11-29

Hmmm... The example I gave is such that you need to pass an additional parameter. I'll leave it to you to work out what you should pass in that parameter/

slo91 (author)RussellM372016-11-30

Ok. One more thing though. Apparently it's only sending the first 2 bytes from the first potententiometer. Only one servo is rotating. What do you think could be the problem? Is it on my tx side or my rx side?

RussellM37 (author)slo912016-11-30

How do you know whether it is sending only the first two bytes? Did you use Serial.print as I suggested? There is no point to guessing what is happening in the code - just use Serial.print to find out what is actually happening.

slo91 (author)slo912016-11-29

error message:

C:\Users\elijah\Desktop\_2\_2.ino: In function 'void tryGetMessage(int)':

_2:58: error: too few arguments to function 'void decode(byte*, int&, int)'

decode(message, decodedVal);

^

C:\Users\elijah\Desktop\_2\_2.ino:69:6: note: declared here

void decode(byte * encoded, int & decoded, int idx ) {

^

Multiple libraries were found for "ServoTimer2.h"

Used: C:\Program Files (x86)\Arduino\libraries\ServoTimer2

Not used: C:\Users\elijah\Documents\Arduino\libraries\ServoTimer2-master

exit status 1

too few arguments to function 'void decode(byte*, int&, int)'

slo91 (author)2016-11-25

Hi there
Thank you it finally compiles. But I need your help with my project. I want to control 3* servo motors using 3* potentiometers. Do you think it's possible to modify your codes and get it to work. Please help me if you can, I'm a final year student. thank you

RussellM37 (author)slo912016-11-26

The basics would be to send through a 6 byte array with 2 bytes for each pot. Do three reads instead of one in the loop. You will need to encode each of the 3 values in turn and then create the 6 byte array before sending that. At the other end the message will be 6 bytes long and you will decode each of the three sets of 2 bytes that correspond to the servos.

slo91 (author)2016-11-25

Hi there
Thank you it finally compiles. But I need your help with my project. I want to control 2 servo motors using 2 potentiometers. Do you think it's possible to modify your codes and get it to work. Please help me if you can, I'm a final year student. thank you

InevitableCraftsLab (author)2016-11-23

Hi thanks for the Tutorial, but as soon as comment out the two lines, i get all sorts of Timer Errors. Do you know any reason why this could happen? :)

I know it compiles on version 1.6.5 of the Arduino IDE. You may be using a later version - I see that its up to 1.6.13. First try downloading 1.6.5 from https://www.arduino.cc/en/Main/OldSoftwareReleases#previous - it should work on that version. I've been busy making a DIY Raspberry Pi Arcade machine so haven't been keeping up on the Arduino side.

Hi, thanks for the quick replay. In the meantime i tried it differently:

The 433Rx module is connected to a pro trinket, that decodes the array it got via 433 and sends the variables over I2C to a feather M0.

The Servos are connected to the feather m0

bauderate is 9600 and everything runs flawless :)

Maybe i will make a shield for an Atiny8 and the 433 module in the near future :)

slo91 (author)2016-11-09

hi there

thanks for sharing your project. im dong a similar project and im still getting that error: conflicting declaration 'typedef uint8_t boolean' even after editing ServoTimer2.h as you explained. what should i do now??please help, im a final year student. thank you!

RussellM37 (author)slo912016-11-11

An error of conflicting declaration 'typedef uint8_t boolean' definitely means that this line of code is somewhere! typedef uint8_t boolean;

Look carefully through the code till you find it and remove or comment it. Any instance of that code will cause that error since it is creating a definition that will conflict.

LightningLion (author)2016-10-08

I get compilation errors when using Arduino IDE 1.6, which one did you use?

RussellM37 (author)LightningLion2016-10-08

I used 1.6.5

Did you get the error: conflicting declaration 'typedef uint8_t boolean'

If so, see the instructions above about editing ServoTimer2.h

LightningLion (author)RussellM372016-10-08

Yeah, that didn't help. But compiles on ide 1.5

alisir (author)2016-10-08

Your sketches dont match the code or vice versa

RussellM37 (author)alisir2016-10-08

Yes you are right - I need to take more care about that if I post another instructable! The grey and yellow in receiver should be swapped - grey (servo) to 11, yellow (receiver) to 4. Green wire in transmitter sketch should go to pin 3.

seamster (author)2016-08-13

Very nice, thanks for sharing!

About This Instructable

5,831views

8favorites

License:

More by RussellM37:Arduino ServoTimer2 and VirtualWire 433MHz Receiver
Add instructable to: