PID control de motor DC con Encoder Incremental y Arduino

Hola:

Soy un asiduo usuario de Arduino, tengo 3 años de utilizar Arduino para hacer pequeños proyectos caseros cuando tengo tiempo, todo lo que se, lo aprendi viendo video tutoriales de Arduino en U-tube y leyendo las paginas y comentarios de gigantes en esta materia, hace mas de 8 meses que vengo informandome acerca de : Como controlar un Motor DC utilizando:

Modulo ide Arduino UNO, un servo motor DC con encoder incremental optico (MITSUMI PART # L24515 M28N-1 R-147319) y un L293D H Bridge.

logrado leer los pulsos del encoder del channel A y B, pero no he podido hacerlo funcionar para lograr controlar un motor de DC hasta que me di cuenta que la libreria que tengo que utilizar para este es una libreria PID. Hoy logre encontrar un sketch en internet lo escribi en Arduino UNO y cuando lo compilo me da una serie de errores, alguien me podria ayudar por favor:

El primer error es:

Encoder0PinA was not declared in this scope y me imagino que habra mas errores.

#include <PID_v1.h>

//Define Variables we'll be connecting to

volatile unsigned long lasTime;
volatile unsigned long duration, CapTime, LastCapTime;
volatile double errSum, lastErr, lastErr_2;
volatile double lastOutput;
volatile double dT;
volatile int count = 0;

double PV, Output;
double kp, ki, kd;
double ref;

void setup()
{
 pinMode(encoder0PinA, INPUT);
 pinMode(encoder0PinB, INPUT);
 digitalWrite(encoder0PinA, HIGH); //turn on pull up resistor
 digitalWrite(encoder0PinB, HIGH); //turn on pull up resistor
 
 pinMode(MotorIN_1, OUTPUT);
 pinMode(MotorIN_2, OUTPUT);
 pinMode(MotorPWM, OUTPUT);
 attachInterrupt(0, doEncoder, RISING);
 
 capTime = 0;
 LastCapTime = 0;
 
 //Controller Parameter
 kp = 0.01; ki = 0.00; kd = 0.00;
 Output = 0;
 Serial.begin (9600);
 
 //Interrupt subroutine function
 void doEncoder(){
   LastCapTime =CapTime;
   CapTime = millis();
 }  
   
   void loop()
 {
   unsigned long now;
   double Freq; 
   now = millis();
   dT (double)(now - lasTime) / 1000; //Our Sampling Time
   if(dT>=0.01){        //Do control loop every 10mS
   duration = CapTime - LastCapTime;  //get the period in mS
      LastCapTime = CapTime;
      if(duration==0){
        Freq = 0;
      }
      else{
        Freq = 1000/(double)duration; //in Hz unit
      }
      PV = Freq*60/2;   //rpm unit
      compute(ref, PV);   //Find controller output
      sendCommand(Output);   //send command to DC motor
      lastTime = now;
   }
   //receive command
   byte val;
   if(Serial.available()){
     val = Serial.read();
     switch (val){
       case 'A': ref = 0; break;
       case 'W': ref += 100; break;
       case 'S': ref -= 100; break;
       case 'O': kp += 0.01; Serial.println(kp); break;
       case 'L': kp -= 0,01; Serial.println(kp); break;
       case 'I': ki += 0.01; Serial.println(ki); break;
       case 'K': ki -= 0.01; Serial.println(ki); break;
       case 'U': kd += 0.001; Serial.println(kd); break;
       case 'J': kd -= 0.001; Serial.println(kd); break;
       }
   }
   //display setpoint and measured value
   if(count>50){
     Serial.print(ref);
     Serial.print(' ');
     Serial.print(PV);
     Serial.print(' ');
     Serial.print(Output);
     Serial.println(' ');
     count = 0;
   }else{count++;}
   
   //the "sendCommand" function
   void sendCommand(int cmd){
     if(cmd>0) {
       analogWrite(MotorPWM, cmd);
       digitalWrite(MotorIN_1, LOW);
       digitalWrite(MotorIN_2, HIGH);
     }
     else if(cmd<0){
       analogWrite(MotorPWM, -cmd);
       digitalWrite(MotorIN_1,HIGH);
       digitalWrite(MotorIN_2,LOW);
     }
     else{
       analogWrite(MotorPWM, 0);
       digitalWrite(MotorIN_1,LOW);
       digitalWrite(MotorIN_2,LOW);
     }
   }
   //The PID controller algorithm (Velocity PID Algorithm)
   void compute(double Setpoint, double Measured)
   {
     double error = Setpoint - Measured;
      /*Compute PID Output*/
      Output = kp*(error - lastErr) + ki*error*dT + kd*(error -2*lastErr + lastErr-2) / dT
      + lastOutput;
      
      /*Max 255, Min -255*/
       if(Output >255){Output =255;}
       else if(Output <-255){Output = 255;}
       else{}
       
       /*Remember some variables for next time*/
       lastOutput = Output;
       lastErr_2 = lastErr;
       lastErr = error;
   }

Muchas gracias de Antemano

Dherreiros

Muy buena descripción de lo que pretendes.
Luego dos fallos: 1) no pones el link de la librería PID y con ello limitas nuestras respuestas. 2) no usas los tag correspondiente para insertar códigos asi que por favor edita tu post#1 para que luzca mejor.

Completa tambien lo que te pido con el link para poder ayudarte con tu librería, sino te sugiero alguna y seguimos adelante.

Bueno los primeros errores que citas son porque no asignaste pines del arduino (que no indicaste tampoco cual es) asi que todo lo que ves en el setup debe tener una correspondencia previa en asignaciones.

pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinA, HIGH); //turn on pull up resistor
  digitalWrite(encoder0PinB, HIGH); //turn on pull up resistor
 
  pinMode(MotorIN_1, OUTPUT);
  pinMode(MotorIN_2, OUTPUT);
  pinMode(MotorPWM, OUTPUT);

Supongo un UNO entonces un encoder va donde testan las iterrupciones pin 2 y 3 de modo que

const byte encoder0PinA = 2;
const byte encoder0PinB = 3;
const byte MotorIN_1     = 4;       // chequear esta asignación
const byte MotorIN_2     = 5;       // chequear esta asignación
const byte MotorPWM     = 6;       // tiene que ser una salida PWM ver si es la correcta

Hola Surbyte:

Gracias por tu respuesta y ofrecerme tu ayuda, me he demorado en contestarte porque trabajo lejos de casa en los cayos al sur de la Florida, soy mecanico de maquinaria pesada y vivo en Miami y regreso a casa los viernes y en esta semana no pude logearme a internet para revisar los mensaje, de todas formas muchas gracias.

Si me gustaria si puedes sugerirme una libreria y el ayudarme a mejorar la redaccion del sketch porque este sketch lo descargue del internet:

https://cis.ait.asia/course_offerings/92/handouts/378

Disculpame si lo que me escribiste lo entiendo muy poco no soy programador ni mucho menos me gusta la electronica y tengo un espiritu inquieto por aprender, de esta misma forma aprendi desde cero con utube y me contrui una maquina CNC hace unos 4 anos atras, luego me intereso seguir aprendiendo mas y me interese en Arduino, la programacion hasta ahora lo estoy aprendiendo, no manejo assembler, ni C++, tu, me imagino eres un ingeniero o programador y no te llego a los talones y puede que mi respuesta te aburra o decepcione y no te culpo, porq nadie que tiiene 15 anos se quiere juntar con un nino de 8 anos porq busca a otros de su misma edad porq no hablan el mismo idioma, tu entiendes eso verdad?, dicen los chinos que la mejor forma de aprender es haciendo y rompiendo.

Muchos videos en u tube estan muy bien realizados y lo que hago es copiar los sketches paso a paso, si el que subio el video no lo postea y de esta forma logro reproducirlos en Arduino, muchos de ellos no funcionan cuando los compilo con Arduino y me tardo a veces semanas tratando de encontrar el problema y al final lo logro y es una gran satisfaccion que se obtiene al lograrlo. Hay muchos videos tambien sobre control de motores DC controlados por PWM utilizando electronica analogica, pero muy pocos controlados por PID y si los hay, los realizadores no comparten sus sketches.

He visto muchos videos de encoders, se que hay dos tipos de ellos solamente pero la forma de manejar los pulsos obtenidos de los encoders incrementales tambien los hay de varios formas:
using Interrupts, por polling, velocity estimation. todo esto gracias a Utube y muchos Hobbistas y profesores que les gusta compartir su saber con los demas como es el caso de Dr. Robert Paz en

Hands On Arduino 2: Incremental Encoders, Part 1 - YouTube.

Bueno de todas formas perdone los errores gramaticales pero mi idioma en mi PC esta seteado en ingles.

Gracias nuevamente por tu ayuda.

Dherreiros

Hola dherreiros. Ahora comprendo todo el problema.
Por un lado obtuviste ese código del pdf corresondiente.
Por otro tienes la librería PID_v1.h
Pero ahora quiere unir la librería con el ejemplo que incluye el enconder.
OKay.

Lo que veo es una diferencia en la salida de uno y otro programa.
Esta claro que el enconder me devuelve una medida de la velocidad en RPM del motor que tu quieres fijar via serial.
Pero no se que estas usando como control del motor.
Puedes ser mas específico?

quiero medir velocidad con encoder
me pueden facilitar el codigo y dar una explicacion de como funciona?

saludos

me_1: el código lo tienes en el post#1 con las correcciones que yo le hice. Podemos ver si funciona o no.
En eso estamos.
Si respondes acá no hace falta que crees un nuevo post pidiendo lo mismo. Yo no voy a responder dos post con el mismo tema.
Lee las normas del foro respecto al doble post.

Hola.
Me_1, te respondo aquí al privado que me ha llegado tuyo, con la misma pregunta.
La verdad es que no estoy muy familiarizado con los encoders, aunque supongo que al final todo se reduce a recibir impulsos en dos interrupciones que incrementarán un contador de vueltas. Sólo tienes que calcular los millis transcurridos entre una o varias vueltas, o bien las vueltas en un determinado periodo de millis, y lo tienes hecho.
Lo primero, como dice surbyte, contar vueltas a ser posible en interrupciones.

Hola Surbyte:

Perdona la demora. Contestando tu pregunta sobre que dispositivo estoy utilizando para mover el motor, Ok? Lo podes ver aqui:

http://www.ebay.com/itm/Push-Pull-Four-Channel-Motor-Driver-Module-ST-L293D-/130579781652

Gracias

Bien entonces tienes un L293 para el control del motor.
Cuales son los pines que usarás para manejar el L293?

Para el L293Dual H Bride voy a utilizar los pines #1 (para habilitar la salida de los pines que van al motor), #3 y #6 que son los que van al DC motor.

Hi Surbyte:

Tengo ahora la disposicion de los pines que voy a utilizar (No tomes en cuenta la respuesta anterior).

Pin2 de Arduino Uno Va conecatdo al Encoder CH-A
Pin3 de Arduino Uno Va conecatdo al Encoder CH-B
Pin4 de Arduino Uno Va conectado a IN1 en el L293D
Pin5 de Arduino Uno va conectadoi a IN2 en el L293D
El Enable1 del L293D va a 5V para habilitar la salida del DCmotor1. Es esto correcto?
Gracias

Dejame chequearlo y te respondo aca mismo

saludos, lograstes completar el proyecto?, estoy revisando el código enviado por ti, por que tengo que realizar un control de velocidad de un motor DC

Desde 29-01-2015 que el hilo no tienes respuesas.
Por favor no respondas hilos viejos.
Crea tu propio tema.
Lee las normas del foro por favor!!

hola, tengo un proyecto y he estado investigando pero estoy un poco desorientado, agradeceria toda la yusa que me puedan brindar.

estoy tratando de colocar una medida en centímetros introducida manualmente via serial y que esta se almacene en una variable, un motor paso a paso moverá una guía que marcara su posición con un sensor Ir o ultrasónico o también puede ser un encoder óptico y que pare hasta obtener la distancia que se almaceno en la variable.

agradeceria muchisimo todas sus sugerencias.

saludos.

@Jorge_pacheco no revivas hilos con mas de 120 dias sin movimientos, es la 3ra advertencia que te hago.