0
$\begingroup$

Rosanswers logo

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 : https://sungjik.wordpress.com/ 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
    getMotorData(time-lastMilli);
    PWM_val1 = updatePid(1, PWM_val1, r1, rpm_act1);
    PWM_val2 = updatePid(2, PWM_val2, r2, rpm_act2);

 if (PWM_val2> 0){
    analogWrite(motor1_pin1,abs(PWM_val2));
  analogWrite(motor1_pin2,0);
  }
  if (PWM_val2<0) {
    
  analogWrite(motor1_pin1,0);
  analogWrite(motor1_pin2,abs(PWM_val2));
}
  if (r2==0) {
    
  analogWrite(motor1_pin1,0);
  analogWrite(motor1_pin2,0);
}
  if (PWM_val1>0) {
    analogWrite(motor2_pin1,abs(PWM_val1));
    analogWrite(motor2_pin2,0);
  }
if (PWM_val1<0) {
analogWrite(motor2_pin1,0);
analogWrite(motor2_pin2,abs(PWM_val1));
}
if (r1==0) {
  analogWrite(motor2_pin1,0);
analogWrite(motor2_pin2,0);
}
 

    
    publishRPM(time-lastMilli);
    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.


Originally posted by ghaith on ROS Answers with karma: 89 on 2017-01-23

Post score: 1

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

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
  • Subscribe to a "control_effort" topic
  • Launch a pid control node

Originally posted by AndyZe with karma: 2331 on 2017-01-23

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by ghaith on 2017-01-23:
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.

Comment by AndyZe on 2017-01-23:
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)

Comment by ghaith on 2017-01-24:
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.

Comment by AndyZe on 2017-01-24:
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.

Comment by ghaith on 2017-01-24:
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.

Comment by AndyZe on 2017-01-24:
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.

Comment by ghaith on 2017-01-24:
thanks for all the information u gave me. its helpful and open new path to look in. thanks a gain.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.