loading

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

The transmitter is the easy part.

  1. Read value from a Potentiometer
  2. Send it

Step 3: 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.

<p>hi there</p><p>thank you very much for this post and the continuous help, i finally got the circuit working as expected. </p>
<p>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.</p>
<p>hello</p><p>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.</p><p>tx code:</p><p>#include &lt;VirtualWire.h&gt;</p><p>// Digital pin for LED</p><p>const int led_pin = 13;</p><p>// Digital pin for transmitter</p><p>const int transmit_pin = 3; </p><p>// Analog pin for Pot</p><p>int potPin1 = 3;</p><p>int potPin2 = 4;</p><p>int potPin3 = 5;</p><p>int potVal1 = 0;</p><p>int potVal2 = 0;</p><p>int potVal3 = 0;</p><p>byte encodedVal[6];</p><p>void setup()</p><p>{</p><p> // Initialise the transmitter</p><p> vw_set_tx_pin(transmit_pin);</p><p> vw_setup(2000); // Bits per sec</p><p> // The LED isn't necessary but gives a visual</p><p> // indication that something is happening</p><p> pinMode(led_pin, OUTPUT);</p><p>}</p><p>void loop()</p><p>{ </p><p> // Read the pot</p><p> potVal1 = analogRead(potPin1);</p><p> potVal2 = analogRead(potPin2);</p><p> potVal3 = analogRead(potPin3);</p><p> // Convert int (PotVal) to byte array (encodedVal)</p><p> encode1(potVal1, encodedVal);</p><p> digitalWrite(led_pin, HIGH); </p><p> encode2(potVal2, encodedVal);</p><p> digitalWrite(led_pin, HIGH); </p><p> encode3(potVal3, encodedVal);</p><p> // Flash a light to show transmitting</p><p> digitalWrite(led_pin, HIGH); </p><p> // Send the byte array using the transmitter</p><p> send(encodedVal);</p><p> digitalWrite(led_pin, LOW);</p><p> // Wait a little bit before repeating</p><p> delay(10);</p><p>}</p><p>// Convert int to a 2 byte array</p><p>void encode1(int val1, byte *encoded ) {</p><p> encoded[0] = lowByte(val1);</p><p> encoded[1] = highByte(val1);</p><p>}</p><p>void encode2(int val2, byte *encoded ) {</p><p> encoded[2] = lowByte(val2);</p><p> encoded[3] = highByte(val2);</p><p>}</p><p>void encode3(int val3, byte *encoded ) { </p><p> encoded[4] = lowByte(val3);</p><p> encoded[5] = highByte(val3);</p><p>}</p><p>// Send byte array</p><p>void send (byte *message) </p><p>{ </p><p> vw_send(message, sizeof(message)); </p><p> vw_wait_tx(); // Wait until the whole message is gone </p><p>}</p><p>rx code:</p><p>#include &lt;VirtualWire.h&gt;</p><p>#include &lt;ServoTimer2.h&gt;</p><p>#define MIN_PULSE 750</p><p>#define MAX_PULSE 2250</p><p>const int led_pin = 13;</p><p>const int receive_pin = 4;</p><p>const int servo_pin1 = 10;</p><p>const int servo_pin2 = 11;</p><p>const int servo_pin3 = 12;</p><p>// a buffer to store the incoming messages </p><p>byte message[VW_MAX_MESSAGE_LEN]; </p><p> // the size of the message</p><p>byte messageLength = VW_MAX_MESSAGE_LEN;</p><p>// Value decoded from message</p><p>int decodedVal1;</p><p>int decodedVal2;</p><p>int decodedVal3;</p><p>// Value mapped from Pot to Servo</p><p>int mappedVal1; </p><p>int mappedVal2;</p><p>int mappedVal3; </p><p>ServoTimer2 servo1;</p><p>ServoTimer2 servo2;</p><p>ServoTimer2 servo3;</p><p>void setup()</p><p>{</p><p> pinMode(led_pin, OUTPUT);</p><p> // Initialise the IO and ISR</p><p> vw_set_rx_pin(receive_pin);</p><p> vw_setup(2000); // Bits per sec</p><p>}</p><p>void loop()</p><p>{</p><p> readMessage();</p><p>}</p><p>void readMessage() {</p><p> vw_rx_start();</p><p> tryGetMessage(10);</p><p> vw_rx_stop(); </p><p>}</p><p>void tryGetMessage(int times) {</p><p> bool gotMessage = false;</p><p> int i = 0;</p><p> while(i++ &lt; times &amp;&amp; !gotMessage) {</p><p> if (vw_get_message(message, &amp;messageLength)) { </p><p> if (message[7] ==0) {</p><p> gotMessage = true;</p><p> // Flash a light to show received good message</p><p> digitalWrite(led_pin, HIGH); </p><p> decode1(message, decodedVal1);</p><p> decode2(message, decodedVal2); </p><p> decode3(message, decodedVal3);</p><p> mappedVal1 = map(decodedVal1, 0, 1023, MAX_PULSE_WIDTH, MIN_PULSE_WIDTH);</p><p> mappedVal2 = map(decodedVal2, 0, 1023, MAX_PULSE_WIDTH, MIN_PULSE_WIDTH);</p><p> mappedVal3 = map(decodedVal3, 0, 1023, MAX_PULSE_WIDTH, MIN_PULSE_WIDTH);</p><p> digitalWrite(led_pin, LOW);</p><p> }</p><p> }</p><p> }</p><p> delay(10); </p><p> servo1.attach(servo_pin1);</p><p> servo1.write(mappedVal1);</p><p> delay(20);</p><p> servo1.detach();</p><p> delay(20);</p><p> servo2.attach(servo_pin2);</p><p> servo2.write(mappedVal2);</p><p> delay(20);</p><p> servo2.detach();</p><p> delay(20);</p><p> servo3.attach(servo_pin3);</p><p> servo3.write(mappedVal3);</p><p> delay(20);</p><p> servo3.detach();</p><p> delay(20);</p><p> }</p><p>// Convert the two bytes back to int</p><p>void decode1(byte * encoded, int &amp; decoded ) {</p><p> decoded = (short)(((encoded[1]) &amp; 0xFF) &lt;&lt; 8 | (encoded[0]) &amp; 0xFF);</p><p>}</p><p>// Convert the two bytes back to int</p><p>void decode2(byte * encoded, int &amp; decoded ) {</p><p> decoded = (short)(((encoded[3]) &amp; 0xFF) &lt;&lt; 8 | (encoded[2]) &amp; 0xFF);</p><p>}</p><p>// Convert the two bytes back to int</p><p>void decode3(byte * encoded, int &amp; decoded ) {</p><p> decoded = (short)(((encoded[5]) &amp; 0xFF) &lt;&lt; 8 | (encoded[4]) &amp; 0xFF);</p><p>}</p>
<p>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. </p><p>Have a look at this instructable that I referenced earlier</p><p>https://www.instructables.com/id/How-to-build-433-MHZ-RC-to-control-servos-100-Ardu/</p><p>===</p><p>I'm not sure that the check is even valid in my original code but change (message[7] ==0) to (message[6] == 0).</p><p>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:</p><p>void decode(byte * encoded, int &amp; decoded, int idx ) {</p><p> decoded = (short)(((encoded[idx+1]) &amp; 0xFF) &lt;&lt; 8 | (encoded[idx]) &amp; 0xFF);</p><p>}</p><p>Fewer functions = fewer places for things to go wrong + less code to check.</p>
<p>after changing those 2 lines in the receiver code, here the error i get:</p><p> void decode(byte * encoded, int &amp; decoded, int idx ) {</p><p> ^</p><p>Multiple libraries were found for &quot;ServoTimer2.h&quot;</p><p> Used: C:\Program Files (x86)\Arduino\libraries\ServoTimer2</p><p> Not used: C:\Users\elijah\Documents\Arduino\libraries\ServoTimer2-master</p><p>exit status 1</p><p>too few arguments to function 'void decode(byte*, int&amp;, int)'</p>
<p>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/ </p>
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?
<p>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.</p>
<p>error message:</p><p>C:\Users\elijah\Desktop\_2\_2.ino: In function 'void tryGetMessage(int)':</p><p>_2:58: error: too few arguments to function 'void decode(byte*, int&amp;, int)'</p><p> decode(message, decodedVal);</p><p> ^</p><p>C:\Users\elijah\Desktop\_2\_2.ino:69:6: note: declared here</p><p> void decode(byte * encoded, int &amp; decoded, int idx ) {</p><p> ^</p><p>Multiple libraries were found for &quot;ServoTimer2.h&quot;</p><p> Used: C:\Program Files (x86)\Arduino\libraries\ServoTimer2</p><p> Not used: C:\Users\elijah\Documents\Arduino\libraries\ServoTimer2-master</p><p>exit status 1</p><p>too few arguments to function 'void decode(byte*, int&amp;, int)'</p>
Hi there<br>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
<p>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.</p>
Hi there<br>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
<p>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? :)</p>
<p>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.</p>
<p>Hi, thanks for the quick replay. In the meantime i tried it differently:</p><p>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.</p><p>The Servos are connected to the feather m0</p><p>bauderate is 9600 and everything runs flawless :)</p><p>Maybe i will make a shield for an Atiny8 and the 433 module in the near future :)</p>
<p>hi there</p><p>thanks for sharing your project. im dong a similar project and im still getting that <em>error: conflicting declaration 'typedef uint8_t boolean' </em>even after editing ServoTimer2.h as you explained. what should i do now??please help, im a final year student. thank you!</p>
<p>An error of <em>conflicting declaration 'typedef uint8_t boolean' </em>definitely means that this line of code is somewhere! <em>typedef uint8_t boolean;</em></p><p>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.</p>
<p>I get compilation errors when using Arduino IDE 1.6, which one did you use?</p>
<p>I used 1.6.5 </p><p>Did you get the <em>error: conflicting declaration 'typedef uint8_t boolean'</em></p><p>If so, see the instructions above about editing ServoTimer2.h</p>
Yeah, that didn't help. But compiles on ide 1.5
<p>Your sketches dont match the code or vice versa</p>
<p>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.</p>
<p>Very nice, thanks for sharing!</p>

About This Instructable

4,312views

8favorites

License:

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