Trouble with RF control of servo

Hi all,

This is my first post to this forum so please bear with me. I am trying to build a remote control system for a project using an arduino. I am attempting to us a stand alone ATmega328p taking a reading from a potentiometer as a transmitter sending the pot data with a 433 MHz RF transmitter.
The data is received well by the receiver which is a freetronics arduino clone, it is them printed to the serial monitor and that work fine but when I connect the servos data pin the the corresponding pin(10) on the arduino clone the serial monitor stops printing, the servo doesn't move either. I have attached the receiver and transmitter code.

rh_receiver2.ino (2.6 KB)

rh_transmitter3.ino (6.12 KB)

quick update, I've tried with three other (digital) servos all of which allowed the serial to keep printing the received values but none moved. The servos I'm trying to use are analogue Tower Pro MG995's and if I unplug the servo then change the position of the potentiometer then plug the servo back in it them moves to the new position.
EDIT: I may have been mistaken before when I said that the servo will move if unplugged prior to changing the pot position, but it doesn't do that now.

Your description of the problem suggests to me that you are trying to power the servo from the Arduino and it is drawing too much current causing the Arduino to misbehave - and it might get damaged.

Servos (and motors generally) should have a separate power supply with a common GND with the Arduino.

...R

I initially thought that was the problem but I connected the servo to its own power source and the problem persisted.

UPDATE: I upped the power(1 6v lantern battery and 2 6 volt AA packs) and now the serial is printing values with the servo connected but it still won't move.

I'm not familiar with the 433MHz wireless devices.

What value is the receiver getting?

What value is it using for Servo.write() ?

...R

I'm using the RadioHead library so I'm not exactly sure what's going on with the modules but basically once the receiver has processed the signal and fed it into the ATmega328p it reconstructs the potentiometer reading that would have been picked up by the transmitting arduino. The reading is then printed to make sure that it's working up to that point (which it is) and then fed into an array of servo values (I plan on adding 3 more servos). I then attempted to map these values to the appropriate pulse widths in micro seconds and then write that to the servo (as I am using the ServoTimer2 library) but the servo does not react in any way.

shrimp:
and then fed into an array of servo values (I plan on adding 3 more servos).

Make a simple program that just moves the servos using typical values that would come through the receiver but without having any receiver code to confuse things.

Does the servo-sweep example from the IDE work?

...R

With all the commented lines, I do not see where you actually assign the received value c to servovals[0], and I'm not sure what value it holds for the mapping.

val_1 = map(servovals[0], 0, 1023, 500, 2500);

Sorry I forgot I left it commented out, I've been fiddling with the code since then but it basically remains the same.
Here is the latest iteration;

#include <ServoTimer2.h>

/* N Channel Receiver

This sketch is a multi channel receiver for RF modules. Each channel sends (via UDP-
like transmission) a letter ID to distinguish between channels and a 16-bit number
to indicate joystick position for that channel. The message is printed to the serial
monitor. It is a simple example of how to use the RadioHead library to receive
messages. Implements a simplex (one-way) receiver with an Rx-B1 module.

NOTE: since UDP is unreliable and data can be lost in transmission, this code is only
intended as a learning tool.

Based on Mike McCauley's ASK receiver code for RadioHead. For more details on the
RadioHead Library see RadioHead: RadioHead Packet Radio library for embedded microprocessors

The circuit:

  • 433MHz Rx module connected to 5V, GND and pin 11 to DATA pin

Author: Andrew R. from HobbyTransform (http://hobbytransform.com/)

*/

#include <RH_ASK.h>
#include <SPI.h> // Not actualy used but needed to compile

ServoTimer2 Sev_1; //Not given name because not possible to obtain position values based on name

int val_1;

uint8_t buflen = RH_ASK_MAX_MESSAGE_LEN;

RH_ASK driver;
int servovals[1];

int count;
int chanel_num;

void setup(){
Sev_1.attach(10);
Serial.begin(9600);
Serial.println("setup"); // Prints "Setup" to the serial monitor
if (!driver.init()) // Initiates and sets pin D11 as the RX Pin
Serial.println("init failed");

}

void loop(){
uint8_t buf[buflen];
if (driver.recv(buf, &buflen)){ // Non-blocking
int i;
digitalWrite(13, true); // Flash a light to show received good message
// Message with a good checksum received, dump it.
Serial.print("Got: ");
count = 0;
for (i = 0; i < buflen-2; i += 3){
char chanID = buf*; // Extract channel ID*

  • int c = (buf[i+2] << 8) | buf[i+1]; // Reconstruct 16-bit joystick reading*

  • Serial.print(chanID);*

  • Serial.print(" ");*

  • Serial.print(c);*

  • //val = map(c, 0, 1023, 500, 2500);*

  • //Bucket.write(val);*

  • val_1 = map(c, 0, 1023, 0, 180); //add more vals for more chanels*

  • servovals[count] = val_1;*

  • //Serial.print(count);*

  • count += 1;*

  • //Serial.print(val_1);*

  • //Sev_1.write(val_1);*

  • }*

  • Serial.println("");*

  • digitalWrite(13, false);*

  • //Sev_1.write(servovals[0]);*

  • }*

  • //val_1 = map(servovals[0], 0, 1023, 544, 2400);*

  • //Bucket.write(val);*

  • //val_1 = map(servovals[0], 0, 1023, 500, 2500); //add more vals for more chanels*

  • Sev_1.write(servovals[0]);*

  • //Serial.print("test");*

  • //Serial.print(val_1);*

}

Please read the sticky post on how to use this forum, and in particular how to post using the code tags </>.
http://forum.arduino.cc/index.php/topic,148850.0.html

I'm sure your code does not have smiley faces or italics. Also, use auto format on your code before you post.

Robin2:
Make a simple program that just moves the servos using typical values that would come through the receiver but without having any receiver code to confuse things.

Does the servo-sweep example from the IDE work?

...R

I tried it with the standard sweep example from the built in library and then tried it with the following modified version.

#include <ServoTimer2.h>

ServoTimer2 myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object
 Serial.begin(9600);
}

void loop() {
 for (pos = 500; pos <= 2500; pos += 1) { // goes from 0 degrees to 180 degrees
   // in steps of 1 micro second
   Serial.print(pos);
   myservo.write(pos);              // tell servo to go to position in variable 'pos'
   
   delay(15);                       // waits 15ms for the servo to reach the position
 }
 for (pos = 2500; pos >= 500; pos -= 1) { // goes from 180 degrees to 0 degrees
   Serial.print(pos);
   myservo.write(pos);              // tell servo to go to position in variable 'pos'
   
   delay(15);                       // waits 15ms for the servo to reach the position
 }
}

The only difference between the two is when using the standard sweep example the servo moves a full 180 degrees, but when using the modified version above it only moves about 160 degrees.

cattledog:
Please read the sticky post on how to use this forum, and in particular how to post using the code tags </>.
http://forum.arduino.cc/index.php/topic,148850.0.html

I'm sure your code does not have smiley faces or italics. Also, use auto format on your code before you post.

Thanks! I didn't see that there when I looked. Also I don't know what auto format is.

val_1 = map(c, 0, 1023, 0, 180);         //add more vals for more chanels
      servovals[count] = val_1;
 Sev_1.write(servovals[0]);

From my examination of ServoTimer2, the .write() takes an argument between 750 and 2250, and if the argument is less than minimum it defaults to minimum. With your mapping, whatever the analog reading, you will call Ser_1.write(750) which will be at one end of the travel.

Try change the mapping

val_1 = map(c, 0, 1023, 750, 2250);

Thanks but unfortunately that didn't solve the problem. Another thing I've noticed is that the servos allow me to force them in one direction while powered, although it requires a noticeably larger amount of force than if there was no power to the servo. This also occurs with several servos smaller than the ones I plan on using.

shrimp:
The only difference between the two is when using the standard sweep example the servo moves a full 180 degrees, but when using the modified version above it only moves about 160 degrees.

This proves that the Arduino can control the servos so you know they work.

Now make a version of your own program without any wireless code - just leaving the servo code. Does that work?

...R