Control of a servo, using the rotational speed signal of a Rotary incremental encoder

Good afternoon.
Im trying to control a servo using the rotational speed of a shaft.
I've already achieved to control the servo with the position that the rotary encoder gets.
But now, i would like to control its position using the shaft's rotational speed.
This is the script that I am using to control the servo:

void loop() {
  // Read the current state of inputCLK
  currentStateCLK = digitalRead(inputCLK);
  
  // If the previous and the current state of the inputCLK are different, then a pulse has occurred
  if (currentStateCLK != previousStateCLK) {
    // If the inputDT state is different than the inputCLK state, then the encoder is rotating clockwise
    if (digitalRead(inputDT) == currentStateCLK) { // Invertida la condición
      counter--;
      if (counter < 0) {
        counter = 0;
      }
    } else {
      // Encoder is rotating counterclockwise
      counter++;
      if (counter > 180) {
        counter = 180;
      }
    }

    // Move the servo
    myservo.write(counter);

    Serial.print("Position: ");
    Serial.println(counter);
  }
  // Update previousStateCLK with the current state
  previousStateCLK = currentStateCLK;
}

How can I for example make the servo to get in 90º when the shaft achieves 4500 rpm?
My encoder gives 600 pulses when making one turn.

Thank you in advance.

this git code is an example that output rpm using an encoder as input.

once to have you rpm readout, you could use the map function to translate that to a servo angle

counter  = map(rpm, rpmMin, rpmMax, AngleMin, AngleMax);
myservo.write(counter);

hope that helps....

2 Likes

do you need to count encoder tics or simply measure the time between 2 ticsi? (speed = 1/ time)

how do you know when to stop? or do you simply want to move to some endpoint at some rate?

what happens if you're already at the end point? do you want to reverse?

1 Like

Which is the opposite direction of what the thread-starter wants

rotational speed = rpm of the encoder is the input
output is angular position of a servo
= rpm-gauge

You measure the rpm and the rpm defines the servo-angle
For measuring rpm a single encoder-input is enough

best regards Stefan

thanks for clarifying

My encoder gives 600 pulses when making one turn.

What encoder are you using to get the rpm of the shaft? I there a z output of the encoder with one count per rotation. A 600 ppr quadrature encoder is not best suited for your task.

There are many available tutorials about measuring rpm with an Arduino.

How fast is the shaft rotating? You may want to use interrupts instead of polling to read the encoder.

if this is what you want, the servo will move clockwise (?) as you spin the encoder and return to it's zeroth (CCW position) when you stop.

presumably a speed calculation is possible(!?) with each increment of the encoder by measuring the time between increments (speed = 1/ time) and there is a servo write with each increment, calculation.

what happens if you miss one increment? divide the time by 2, 3? i've found that i need to use an interrupt when turning an encoder with fingers (and doing lottsa other stuff)

If you mean an an RC servo, you cannot control rotation speed, only position by controlling width of input pulses. Speed is fixed by internal controller.

The thread-starter want to do a different thing

Input rpm of of rotating shaft through a yet unkown rotary-encoder
Output position of the yet unkown servo.

@ioritz_mbx7r you should post links to the datasheets of the rotary-encoder and the servo
at least

  • write how many pulses does the rotary-encoder create per rotation
  • write if your servo is a "standard"-RC´-Servo rotating 0 degree to 180 degree
    or a continuos rotation-servo

The code you have posted does not work as you described the wanted functionality

your code will turn the servo
In case of a "standard"-RC-servo to a bigger / smaller angle but independent of

Each encoder-pulse regardless of the rotational speed increases / decreases the servoangle

In case of a continous rotation-servo the rpm Each encoder-pulse regardless of the rotational speed increases / decreases the servos rpm

best regards Stefan

Good morning @gcjr
The thing i want to do is to continously change the position of the servo depending on the measured shaft's RPM.

So glad for your help with my little proyect. :smiling_face:

Best regards,

Ioritz

Thank you! @sherzaad
Im working at the moment, i will try you suggestions this afternoon.

So glad for your help` :smiling_face:

Best regards, Ioritz

Good morning @StefanL38
I think you got the Idea.

So glad for your help :smiling_face:

Best regards, Ioritz

This is the encoder that I'm using for my project: https://amzn.eu/d/1GFGBBw
The max rpm i want to measure is 4500 rpm.

Thank you guys.

So, tuning in late.

It sounds like the servo is to be used to move an indicator so you would have a speedometer-like instrument.

Then it seems that post #2 answers your question.

Use the code linked to develop RPM from the encoder.

Use RPM to calculate the angle for the servo.

Since we are still helping, in what way were you not helped by @sherzaad in #2 above?

Or do we not yet understand your goal? Take a few more words and tell us more about the hole thing.

a7

Good afternoon @alto777
The true is that i want to control a brushless esc with the encoder's signal.

The esc moves with the same signal than the servo, so i had explained my problem with the servo because i think that usually we are more familiarized to work with servos.

Im building a hybrid rc car, synchronizing a nitro thermic motor and a brushless electric motor.
So, I will try the solutioin that our buddy @sherzaad sugested to me.

Thank you all.

The truth is that you are having more fun than I am.

This could turn out to be very challenging - as far as you have described, you have an open loop control problem. The simple idea of measuring the RPM and dictating to the ESC by its servo signal may not achieve a very satisfactory synchronization.

But like I said, fun!

a7

1 Like

So, you are using the encoder as a tachometer for speed control, you will need to use a PID loop, are you familiar with that?

1 Like

I took @ioritz_mbx7r's description to mean they are measuring the nitro thermic engine speed and using that to control a brushless DC motor.

Hybrid power system.

a7

1 Like

You could very well be correct! :thinking:

1 Like
/*
  Encoder details: 600pulses/rev
  Max rpm to be registed 4500rpm -> 2,700,000pulses/min -> 45000pulses per second
*/

/*using Timer1 exernal clock input a pulse counter
  Therefore cannot use Servo.h library since it also uses timer1.
  Therefore using ServoTimer2.h instead
*/

#include <ServoTimer2.h>

#define PERIOD 1000  //1000ms

ServoTimer2 myservo;

uint32_t oldTime;

void setup() {
  //Serial.begin(115200);
  
  myservo.attach(2);  // attach a pin to the servos and they will start pulsing

  //----------------------
  noInterrupts();
  TCNT1 = 0;                 //reset timer1 counter register
  TCCR1A = 0x00;             //reset timer 1 A register
  TCCR1B = 0b00000111;       //set up timer1 to use external clk T1 (pin D5 on UNO)
  TIMSK1 &= ~(1 << OCIE1A);  // turn off the timer1 interrupt
  interrupts();
  //----------------------

  oldTime = millis();
}
void loop() {
  uint16_t pulse_cnt, servo_angle;

  //check pulse count and update servo position every 1s
  if (millis() - oldTime >= PERIOD) {
    noInterrupts();
    pulse_cnt = TCNT1;         //get counter value
    TCNT1 = 0;                 //reset counter value
    interrupts();
    oldTime = millis();
    servo_angle  = map(pulse_cnt, 0, 45000, 0, 90);
    myservo.write(servo_angle);  //update servo postion
  }
}

https://github.com/nabontra/ServoTimer2

just for the fun of it... :slight_smile:

hope that helps....

1 Like