Pages: [1]   Go Down
Author Topic: Servo sweep speed controlling with rc transmitter  (Read 1988 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

Right now I do have a servo which is doing a sweep movement. This works pretty fine. I do controll the speed of the sweep movement by reading in the signal of an rc receiver. Unfortunatly the servo speed doesn't change instantly. The servo needs to finish its sweep movement and starts a new movement. But I want that the servo speed change instantly when the rc receiver signal changes.
For that I already changed a bit my code but It doesn't work yet.
Code:
//Imports servo library
#include <Servo.h>
//Initializes servos
Servo servo;
unsigned long transmitterThrottlee=0;     //these store the current transmitter positions/values
unsigned long transmitterThrottleeLow=0;  //these store the current transmitter positions/values

//Constants for actual frequency, minimum target angle, and maximum target angle
const int minAngle=45;
const int maxAngle=135;

void setup()
{
  servo.attach(11);
  pinMode (9, INPUT);    //Input of Throttle
  transmitterThrottleeLow = ((pulseIn (9, HIGH, 100000))/10);
}

void loop()
{
   sweepfunction();
}

CheckTransmitterFunction

Code:
void checkTransmitter()
{
  transmitterThrottlee = ((pulseIn (9, HIGH, 100000))/10)-transmitterThrottleeLow; //read RC channel, wait max of 0.1 seconds for pulse

  if (transmitterThrottlee > 42000)
    transmitterThrottlee =0;
}

Sweepfunction

Code:
void sweepfunction()
{
  int i=0;
  checkTransmitter();
  if(transmitterThrottlee>=5&&transmitterThrottlee<95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {
      if (i=5)                          //
      {                                  //
        checkTransmitter();     // I want to check every 5 degres the rc receiver signal and use the new one. But it doesn't work
        i=0;
      }
      i++;
      servo.write(pos);
      delay((transmitterThrottlee*-.1143)+13.4286);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {    
      if (i=5)
      {
        checkTransmitter();
        i=0;
      }  
      i++;    
      servo.write(pos);
      delay((transmitterThrottlee*-.1143)+13.4286);
    }
  }

  else if(transmitterThrottlee>=95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {        
      if (i=5)
      {
        checkTransmitter();  
        i=0;
      }  
      i++;
      servo.write(pos);        
      delay(2);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {          
      if (i=5)
      {
        checkTransmitter();  
        i=0;
      }    
      i++;                      
      servo.write(pos);
      delay(2);
    }
  }
  else
  {
    servo.write(90);
  }
}

I think the way I tried to do is will never work. I thought about coding an event in the function checkTransmitter which recognize the change of the rc signal. This should make an interrupt which let start the function sweep again.
But I don't know if this might work and I don't really find many information about interrupts and Arduino. Who knows any solution for my problem and might help me?
Please feel free to ask me as many questions as you need.

Thanks for your help
Robert
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
    You can have a look around on my blog, most people find it useful, there are posts with code for reading from an RC Transmitter and others for controlling servos, its not too big a jump to put the two together and get what you want.

Have a look around - rcarduino.blogspot.com

Duane B
Logged


Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17259
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
    You can have a look around on my blog, most people find it useful, there are posts with code for reading from an RC Transmitter and others for controlling servos, its not too big a jump to put the two together and get what you want.

Have a look around - rcarduino.blogspot.com

Duane B

I really like how you show using interrupt function for reading RC receiver PPM pulses rather then the more common pulseIn() command which I have always found to be rather flaky.

Lefty
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Duane,

thx for the link to your blog. It looks very interesting and useful. I am going to read it asap.
I hope it will help me with my probleme I described above.

Robert
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   I saw your PM, but in the interest of sharing I will put the response here.

   If I understand correctly you want to use a receiver channel to vary the speed of a sweeping servo.

   On my blog you should be able to find a code sample to sweep multiple servos, on this web site there is also code to sweep a single servo and if I understand you correctly you already have your own code that sweeps a servo.

   Now what you need to do is alter something that will cause the speed of the sweep to change. You have two choices here 1) You can change the delay between calls to servo.write or you can change the rate of increment i.e pos += X where X is controlled through the RC Receiver signal. Changing the delay is easier for you as then you do not have to change anything that deals with direction changes.

  If you use my code sample for reading the throttle signal, the value will be changing in the background so it will always reflect the current RC Input while your code is running. I would suggest that you look up the 'map' function and think about how you could use this together with the RC Input value to adjust the delay between servo position updates.

  Over to you ...

  Duane B.

Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

   If I understand correctly you want to use a receiver channel to vary the speed of a sweeping servo.

correct

   On my blog you should be able to find a code sample to sweep multiple servos, on this web site there is also code to sweep a single servo and if I understand you correctly you already have your own code that sweeps a servo.

correct. I already do have a code. The my code in my first post

   Now what you need to do is alter something that will cause the speed of the sweep to change. You have two choices here 1) You can change the delay between calls to servo.write or you can change the rate of increment i.e pos += X where X is controlled through the RC Receiver signal. Changing the delay is easier for you as then you do not have to change anything that deals with direction changes.

I already are able to change the speed by your first described method. I change the delay time.

  If you use my code sample for reading the throttle signal, the value will be changing in the background so it will always reflect the current RC Input while your code is running. I would suggest that you look up the 'map' function and think about how you could use this together with the RC Input value to adjust the delay between servo position updates.

I will use your code. But i don't know, if the for loop, which is responsible for the sweep movement, will automaticly work with the new value (See my code above). The map function is a nice opportunity to calculate the delay value. Right now I do this manually (see code above).

Robert
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   I don't want to post a solution for you as you seem to have enough of the building blocks to work it out for yourself. Try a few things see what works or doesnt, then if you get really stuck I can help.

Have you tried running my sample code and just printing the receiver signal to serial ? if so how could you use map inside your loops to do something with the values you get ?

Duane B.

rcarduino.blogspot.com
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I figured out, what is the mistake in my first program. (which is in my first post)
I am now working on the interrupt method of reading in the signal.
There is one part, I don't really understand
Code:
nThrottleIn = (int)(micros() - ulStartPeriod);
why do you subtract micros from ulStartPeriod? I do know that micros is a function which start counting when the program does start. What is the program? The main loop? Or the loop calcInput()?

Robert
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everybody,
good news, I solved most of the problems. The reading in function with the interrupt is integrated in my project and works pretty fine. The map function works very good, too.
The servo now change its speed instantly, when I change the joystick position of the radio. I am very happy about that result smiley-grin Thanks Duane for your interesting blog!

But i still do have a problem.
If the joystick is at zero position, the servo shall go instantly in middle position. But this doesn't work. It take the servo one whole sweep to go to zero position. Does anybody know, why? Is there anything wrong with my if conditions?
It would be great, if someone might have a lock on my code.
Robert

Code:
void sweepfunction()
{
  if(nThrottleIn>=5&&nThrottleIn<95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {
      servo.write(pos);
      delay((nThrottleIn*-.1143)+13.4286);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {   
      servo.write(pos);
      delay((nThrottleIn*-.1143)+13.4286);
    }
  }

else if(nThrottleIn>=95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {         
      servo.write(pos);     
      delayMicroseconds(1550);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {                     
      servo.write(pos);
      delayMicroseconds(1550);
    }
  }

  else if (nThrottleIn<5)
  {
    servo.write(90);
  }
}
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   What is the end result of what you are trying to do, there may be better approaches,

Duane B

rcarduino.blogspot.com
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
The end result should be a servo which does a sweeping movement. This sweeping movement should be controlled by 2 parameters. First is the speed of the servo. The RC signal is read in by the method shown on Duane's blog. Then I map this signal to a range of 0 up to 100. From 0 up to 5 the servo should stay in his middle position. From 5 up to 95 the servo speed shall change linear with the RC signal and if the signal is higher than 95 the servo shall sweep with full speed. Everything works fine, except for the area from 0 up to 5. If the servo is doing a sweep movement it needs to finish the whole movement and goes then to middle position. But this should happen instantly.
The second parameter should be the angle of the movement. This shall be realized by another RC receiver signal. But realizing this shouldn't be too complicated if I get everything else to run.

Robert
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

EDIT : Rewrite of a previously confusing response.

  At the moment your code is inside out for what you want to achieve. You should move you if statements inside a single loop. At the moment you use if to check a condition and then get into a fixed loop, you should turn this around to that you check the condition inside the loop. This will also allow you to deal with the special case of <5 which I assume means stop sweeping, return to center now and then stay there.

Duane B

« Last Edit: February 19, 2012, 02:33:31 pm by DuaneB » Logged


Pages: [1]   Go Up
Jump to: