ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

PID controler in arduino

asked 2017-01-23 08:45:10 -0600

ghaith gravatar image

updated 2017-01-24 07:21:28 -0600

hi i am trying to move the robot with PID code implement in the arduino code and drive the robot by teleop twisted now i have problem in response i use rosserial as interface between ros and arduino. loop time in the pid code is 100ms that mean its 10hz as frequency and i publish the encoder data at 10 hz but while i am changing the direction or move for left to forward there is some lake of response i tryed to play with the parameter but not help is there any way that i can use PID in ROS and just controll the movement of the robot by telope twisted without and lake of response just move it around and speed controled by ros not arduino . i use arduino due and ros indigo this is the PID code in arduino :

    int updatePid(int id, int command, double targetValue, double currentValue) {
      double pidTerm = 0;                            // PID correction
      double error = 0;
      double new_pwm = 0;
      double new_cmd = 0;
      static double last_error1 = 0;
      static double last_error2 = 0;
      static double int_error1 = 0;
      static double int_error2 = 0;

      error = targetValue-currentValue;
      if (id == 1) {
        int_error1 += error;
        pidTerm = Kp*error + Kd*(error-last_error1) + Ki*int_error1;
        last_error1 = error;
      else {
        int_error2 += error;
        pidTerm = Kp*error + Kd*(error-last_error2) + Ki*int_error2;
        last_error2 = error;

  return constrain(double(command)+ pidTerm,-120, 120);

i toke this code from : now this code work for him with just proportional gain for me there is a lake of response if i use just proportional gain so i use Kp and Ki its better but still have some problem . i am using 2 h-bridge IBT-4 arduino i hope all of this information can help you to give some answer. thanks.

edit: here is the code that give the speed to motor:

if(time-lastMilli>= LOOPTIME)   {      // enter tmed loop
    PWM_val1 = updatePid(1, PWM_val1, r1, rpm_act1);
    PWM_val2 = updatePid(2, PWM_val2, r2, rpm_act2);

 if (PWM_val2> 0){
  if (PWM_val2<0) {

  if (r2==0) {

  if (PWM_val1>0) {
if (PWM_val1<0) {
if (r1==0) {

    lastMilli = time;
  if(time-lastMilliPub >= LOOPTIME) {
  //  publishRPM(time-lastMilliPub);
    lastMilliPub = time;


now if return an int to the PWM and used kp and ki gain on this case the motor will move forward without any change in direction but if i change PWM to r1 or r2 while r1 and r2 is the subscribe value from ROS it will move in all direction without any problem and with very high response i hope any one can help me to solve this problem how i can git the same response of the last case with the accuracy that i had when i return a double not int.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2017-01-23 12:16:30 -0600

AndyZe gravatar image

updated 2017-01-23 12:17:34 -0600

2 issues I see:

  • The variables "new_cmd" & "new_pwm" are never used, so they could be deleted.
  • It returns an int, so it will be rounding to integer values. My guess with proportional gain failing is it rounded a decimal (like 0.4) down to zero.

If you want to move the PID away from the Arduino, you could

  • Publish "state" (aka currentValue) and "setpoint" (aka command) topics
edit flag offensive delete link more


hi thanks for replay but it must return an int because it will return pwm value not flot speed. is it wrong to return PWM value I hope u can answer. thanks again.

ghaith gravatar image ghaith  ( 2017-01-23 15:54:41 -0600 )edit

Oh. Well then you need to convert a double from the PID to an int. Just scale it according to the largest values you expect. Say your "command" from the PID controller is expected to range from -10.0 : 10.0 and the PWM ranges from -256 : 256. Conversion: pwm_command = int (25.6*pid_command)

AndyZe gravatar image AndyZe  ( 2017-01-23 16:24:46 -0600 )edit

hi thanks again for replay i have 2 question : 1- i update this question i hope u can see the problem above after i change it to int. 2- if i will use PID from ROS the encoder value need to be publish as what left wheel and right wheel. and is the setpoint taken from ROS like teleop twist. thanks.

ghaith gravatar image ghaith  ( 2017-01-24 07:23:34 -0600 )edit

A good strategy to see what's wrong is to print some values to the screen. Tutorial here. It seems the conversion from double to int for pwm still isn't correct.

AndyZe gravatar image AndyZe  ( 2017-01-24 08:28:56 -0600 )edit

the encoder data at first is converted to rpm so I can notice the speed by rostopic echo /rpm and from this I can notice each motor speed. so what I can print to the screen other than encoder value . if u can tell me what the name of topic the PID Node subscribe to receive the encoder data. thanks.

ghaith gravatar image ghaith  ( 2017-01-24 14:32:06 -0600 )edit

I'm not sure -- I don't know anything about your specific hardware. Try rostopic list. If the encoder values aren't published already, you might have write your own publisher.

AndyZe gravatar image AndyZe  ( 2017-01-24 15:46:44 -0600 )edit

thanks for all the information u gave me. its helpful and open new path to look in. thanks a gain.

ghaith gravatar image ghaith  ( 2017-01-24 18:07:58 -0600 )edit

Question Tools



Asked: 2017-01-23 08:45:10 -0600

Seen: 1,732 times

Last updated: Jan 24 '17