consulta. PID u otro modo- para posicion de motor-avances

hola gente. aqui nuevamente consultando. hace tiempo que tengo una idea y no he podido concretarla.
el tema es el siguiente. necesito un servo con gran torque. para ello la idea era utilizar un atornillador a bateria.
una idea similar a esta fieroaddiction.com

inicialmente he intentado utilizar un servo RC (aprovechando la simpleza del codigo para moverlo) utilizando como señal la alimentacion del motor del mismo, luego a esto lo llevaba a las entradas de un puente H, in a, in b. este puente H haria mover el atornillador, quien a su vez por unas varillas moveria el servo rc, determinando la posicion. con esta idea surgieron problemas. como ser que los servos al estar inmovil envian positivo en ambas salidas al motor, esto genero cortos al puente H, que no esta preparado para recibir señal en in a y b al mismo tiempo. para solucionar esto intente hacer un interlock. quien funciono bien en una prueba solitaria. pero al utilizarlo con el puente y el servo,,,,, bueno no anduvo...
lo que comente anteriormente fue inspirado en estos ejemplos y muchos otros que se encuentran en internet:
http://www.fieroaddiction.com/servo.html

tras el fracaso anterior :frowning: comenze a investigar sobre PID para utilizar solamente el arduino y un potenciometro mas un puente h.

el tema es que no se de programacion... apenas estoy comenzando con arduino... y algunos codigos...
podrian uds indicarme como comenzar con PID.... como utilizar el ejemplo basico que creo que esta en la libreria?
basicamente necesito mover un motor (como el atornillador) a la posicion que necesito como un servo normal.
es muy dificil lo que pienzo?
gracias gente por pasar por aqui

Hola,

Te cuento que estoy en algo similar pero a menor escala, ya tuve un avance pero sin usar PID, puedes verlo acá : Disque Geek...: Progreso 4 - 7 Oct (Arduino RF links y avance de Servo homemade) Parte 2-3

es muy sencillo lo que hice, pero te puede dar una idea de hacia donde ir, ahora quiero implementar PID para mejorar la retroalimentación del pot del motoreductor.

Si has encontrado información que me puedas compartir te lo agradecería, cualquier cosa te cuento si avanzo en algo.

hola
muchas gracias por responder. la verdad tu idea es lo que estoy buscando justamente. :smiley:
al no saber usar pid en mi caso, pensaba en utilizar solo funciones de apagado encendido y comparaciones. no me habia puesto a escribir pero pensaba algo similar a lo tuyo. el problema es que al no saber tanto de programacion no sabia por donde comenzar. esto tuyo creo que me va a ser super util.
lo de la escala de motor ya solo depende seguramente del puente h que usemos cada uno
yo uso el siguiente por si te gusta. es muy simple de hacer. yo lo hice y soy novato total en electronica

en cuanto tenga un poco de tiempo voy a intentar lo de tu ejemplo. esta barbaro para mi.
solo algunas dudas tengo pero seguro tendre respuesta u otras dudas cuando lo pruebe.
te aviso si avanzo en algo.
PD esta muy interesante ese blog tuyo si te interesa arduino y videos juegos puedes ver lo que postie antes. un tacometro. y un mini simulador para xsim.
saludos. muchas gracias maestro

hola gente estuve intentando escribir algo para lo que mencione antes. intentar definir la posicion de un motor como si fuera un servo
entre lo que busque en internet y lo que compartio selda, pude definir algo....
queria saber que opinan uds. sobre este codigo a ver si funcionaria o que le falta...
aclaro. anterior a este codigo que subo, habia probado uno mas simple. que funciono bien. era para apagar o encender un led dependiendo si el valor del potenciometro era mayor o menor a un valor ya definido en una variable.
el siguiente codigo no pude probarlo aun. pero queria ver que opinan.
muchas gracias por pasar por aqui :smiley:

/*
 ejemplo encender 2 leds y apagar respectivamente, izquierda y derecha, dependendiendo 
 del valor del potenciometro se enciende uno y otro.comparado con el serial read, por donde se envia un valor para la posicion actual deseada. los leds se utilizan indicando el sentido de giro del motor. emulando la señal que se envia a un puente h para el movimiento respectivo.
 
 */
 
int pinSensor = A0;    // Entrada para el potenciómetro.posicion actual del motor. en este ejemplo moveria el pot manualmente emulando el moviento del motor, indicado por los leds.
int pinLed2= 10; // led de posicion derecha, emularia la señal para el encendido del motor por el puente h en direccion a la derecha
int pinLed = 9; //led de posicion izquierda. idem anterior a la izquierda.
int valorSensor = 0;   // variable para el valor del sensor.
int posact = 0; //creo que es necesario que la variable empiece de cero.

int sigpos = 0; // abreviatura de siguiente posición, valor que seria enviado por serial.

void setup() {
  // Declaramos el pin del Led como salida:
  pinMode(pinLed, OUTPUT);
  pinMode(pinLed2, OUTPUT);
  Serial.begin(9600);
}
 
void loop() {
  // verificamos que haya valores enviados y lo almacena en sigpos, 
  if (Serial.available()>0 ){
  int sigpos = Serial.read();
  valorSensor = analogRead(pinSensor); //valorsensor igual al valor del potenciometro de posicion actual
  Serial.println(  valorSensor); // para chequear en que posición esta el potenciometro.
  
  //en este caso si el valor siguiente es menor al del potenciometro, enciende el led de la izquierda, seria el atraso del motor.
   if (sigpos < valorSensor) {
    digitalWrite (pinLed, HIGH);
    digitalWrite (pinLed2,LOW);
  }
// en este caso si el valor siguiente es superior al del potenciometro, entonces enciende el led de la derecha, que seria el avance del motor.
else if (sigpos > valorSensor) {
  digitalWrite (pinLed2, HIGH);
  digitalWrite (pinLed,LOW);
}
//en este caso al ser iguales los valores se apagarian los led.
else if (sigpos == valorSensor) {
  digitalWrite (pinLed2, LOW);
  digitalWrite (pinLed, LOW); }

  
  
  
 
}}

Hola!

Entiendo por tu código, que quieres mandarle un valor por puerto serie para compararlo con la lectura del conversor analógico-digital de Arduino y en función del resultado de esa comparación, hacer una u otra cosa.

Si te puede ayudar, aquí tienes un tuto sobre servos http://www.arduteka.com/2011/12/componentes-el-servomotor/

Al final de él, también tienes un enlace en el que hice un "chupitómetro" para mostrar como enviar a un servo a una posición determinada.

Si lo que quieres es mover un servo directamente con un potenciómetro, échale un vistazo a la instrucción map, con ella puedes transformar proporcionalmente los 1024 valores de la entrada analógica al rango de grados del motor.

Un saludo!

Viejo,

Así había hecho inicialmente, voy a probar el PID ver que tal y te cuento.

slds

hola gente.
Arduteca (pablo?). gracias por responder. soy seguidor de tu pagina. es una de las mejores de arduino en español. te hice comentarios en algun post.
te comento que lo que en realidad quiero hacer es utilizar un motor DC como servo motor(con un puente h obvio) . es decir poder ubicar al motor en la posicion que yo necesite. ya sea a travez de serial u otro modo. no importa tanto eso. sino el hecho de poder lograr que el arduino lea la posicion en la que se encuentre el motor a travez de un potenciometro y realizar una accion.

Selda81. espero tu avance :D. tu post en tu blog me inspiro para saber por donde ir. difiero en algunas cosas... pero es obvio todo esta a prueba. espero que el pid te de resultado. :smiley: exitos :smiley:

bueno esta noche intentare probar mi codigo cuando salga del trabajo :sleeping:

saludos amigos.

nicko_esx:
te comento que lo que en realidad quiero hacer es utilizar un motor DC como servo motor(con un puente h obvio) . es decir poder ubicar al motor en la posicion que yo necesite. ya sea a travez de serial u otro modo.
saludos amigos.

Por curiosidad el PID que pinta en todo esto?
Para ubicar la posición de un motor DC de forma exacta tienes que usar un encoder.

yOPERO hola
gracias por comentar. en realidad cuando estuve averiguando que necesitaba para manejar posicionamiento de motor.. encontre en internet muchas respuestas que se vinculaban a PID. :roll_eyes: y como dije al comienzo. no se utilizarlo. averigue que es pero no se mas que eso...
por eso consulto sobre algun otro modo.
necesito basicamente poder mover un motor y retroalimentacion de posicion del mismo y arduino actuara en base a eso. repito la intencion es hacer un servo grande con un motor DC. utilizando arduino como controladora + un puente h.

yOPERO no se como utilizaria el encoder... se que es. pero no imagino como utilizarlo. creo que se me complicaria determinar posiciones en grados.

El encoder es el feedback, si, vas a saber donde esta (o cuantas vueltas dió) pero como haces efectivo tu posicionamiento...con el PID (método de sistema de control) vas a optimizar la salida del sistema, reduciendo el error, ya que lo ajustas progresivamente.

Aunque su uso depende de la aplicación ( si lo amerita) yo personalmente he revisado varios post acerca del uso de este método en fabricación de servos casero, y la precisión es bárbara ( claro que para lograr esta precisión, se requiere de caracterización matemática del proceso - mathlab/simulink/labview)

Yo voy a tratar de hacer un seudo (PD) realizando el ajuste manual (sin la caracterización) ya que lo que estoy haciendo, no tiene que ser tan preciso (aplicación de motor en un sistema de dirección de un carro RC)

Slds

Selda81
buena explicación. :smiley:
espero con ganas ese seudo pid :smiley:
lo del encoder si lei en internet. pero es todo un tema lograr fijar posicion. algunos me dijeron que podria usarlo como motor pap. y para saber la posicion seria necesario que el motor se mueva de un punto extremo a otro de deste modo se contarian los "pasos" y ubicariamos al motor por pasos que en el caso del encoder serian pulsos... es muy complejo me parece para lo que queremos hacer.

hola gente. aqui otra vez. pude probar el codio que subi antes. funciona. pero se genera una confucion. y es el hecho que al enviar datos por serial y a la vez imprimir por serial un valor. aparentemente por no haberlos distinguido correctamente entonces se genera una confucion de valores.... estoy viendo como separar estos valores.. tal vez con caracteres anteponiendolos....

por ahora quiero compartir otro modelo de codigo. en este caso utilizo un potenciometro para ingresar un valor, con el cual el potenciometro anterior de posicion actual se comparan. es decir un pote indica una posicion futura y se compara con el actual. en base a esto encienden los leds de izq o derecha. al mover el pote de posicion actual al valor indicado. se apagan los leds... funciona ok. espero explicarme bien. tal vez a alguien le sirva este codigo como ejemplo de practica.... tengo esperanzas que al utilizarlo con un motor y un puente h funcione de igual manera....

/*
 ejemplo encender 2 leds y apagar respectivamente, izquierda y derecha, dependendiendo 
 del valor del potenciometro se enciende uno y otro.comparado con el potenciometro2 de posicion requerida o futura, 
 o actual deseada. los leds se utilizan indicando el sentido de giro del motor. emulando la señal que se envia a un puente h para el movimiento respectivo.
 
 */
 
int pinSensor = A0;    // Entrada para el potenciómetro.posicion actual del motor. en este ejemplo moveria el pot manualmente emulando el moviento del motor, indicado por los leds.
int pinSensor2 = A1; //potenciometro de posicion requerida o futura
int pinLed2= 10; // led de posicion derecha, emularia la señal para el encendido del motor por el puente h en direccion a la derecha
int pinLed = 9; //led de posicion izquierda. idem anterior a la izquierda.
int valorSensor = 0;   // variable para el valor del sensor.
int posact = 0; //creo que es necesario que la variable empiece de cero.
int valorSensor2 = 0; //variable para el potenciometro 2
int sigpos = 0; // abreviatura de siguiente posición, valor que seria enviado por serial.

void setup() {
  // Declaramos el pin del Led como salida:
  pinMode(pinLed, OUTPUT);
  pinMode(pinLed2, OUTPUT);
  Serial.begin(9600);
}
 
void loop() {
   
  
  valorSensor2 = analogRead (pinSensor2);//lee los datos del potenciometro 2 de posicion requerida
    int sigpos = valorSensor2 ; 
  valorSensor = analogRead(pinSensor); //valorsensor igual al valor del potenciometro de posicion actual
  Serial.print ("valorSensor");
  Serial.println ( valorSensor); // para chequear en que posición esta el potenciometro del motor.
  delay(200); //le doy delay para que se pueda leer los datos impresos. de lo contrario pasan demaciado rapido
  Serial.print ("valor del sensor sig");
  Serial.println(valorSensor2); //para chequear la posicion requerida del pote2
  delay(200);
  //en este caso si el valor siguiente es menor al del potenciometro, enciende el led de la izquierda, seria el atraso del motor.
   if (sigpos < valorSensor) {
    digitalWrite (pinLed, HIGH);
    digitalWrite (pinLed2,LOW);
    delay(200);
  }
// en este caso si el valor siguiente es superior al del potenciometro, entonces enciende el led de la derecha, que seria el avance del motor.
else if (sigpos > valorSensor) {
  digitalWrite (pinLed2, HIGH);
  digitalWrite (pinLed,LOW);
  delay(200);
}
//en este caso al ser iguales los valores se apagarian los led.
else if (sigpos == valorSensor) {
  digitalWrite (pinLed2, LOW);
  digitalWrite (pinLed, LOW);
 delay(200); }
  
 
}

espero les guste

Amigo, por ahí estuve cacharreando con lo del PID y ya va tomando forma, entra a mi blog y revisa el ejemplo, todavía se debe mejorar el sketch, o mejor aún usar la libreria PID existente.

Como te ha ido a ti? que has avanzado?

Cualquier cosa me cuentas.

hola selda. estoy parado esperando que me lleguen uns TIP que queme en la puente h en una prueba. teoricamente esta semana deberian tener los tip.
yo probe el ultimo codigo que subi con leds y funciona... pero bueno hay que ver con el motor que onda.
me parese muyyyy interesante lo tuyo. esta muy bueno. creo que terminaras con algo bueno. y sera de mucho interes para muchos. es un lindo proyecto :smiley:
nos vemos.

amigo Selda.
tengo algunos avances...
comienzo comentando que el puente h que utilizo es el siguiente.10A H-Bridge Motor Controller - Introduction | PyroElectro - News, Projects & Tutorials
por su facilidad de construccion y posibilidades de potencia.

el codigo que logre hasta hoy es el siguiente.

/*
 ejemplo mover motor a direcciones dependiendo valores comparados de dos potenciometros.
 uno de posicion actual y otro de posicion futura
 
 */
 
int pinSensor = A0;    // Entrada para el potenciómetro.posicion actual del motor. en este ejemplo moveria el pot manualmente emulando el moviento del motor, indicado por los leds.
int pinSensor2 = A1; //potenciometro de posicion requerida o futura
int pinLed2= 10; // pin de direccion derecha,  señal para el encendido del motor por el puente h en direccion a la derecha
int pinLed = 9; //pin de izquierda. idem anterior a la izquierda.
int valorSensor = 0;   // variable para el valor del sensor.
int posact = 0; //creo que es necesario que la variable empiece de cero.
int valorSensor2 = 0; //variable para el potenciometro 2
int sigpos = 0; // abreviatura de siguiente posición, valor que seria enviado por serial.
int difvalors =0; //diferencia entre sigpos y valor sensor
void setup() {
  // Declaramos el pin del Led como salida:
  pinMode(pinLed, OUTPUT);
  pinMode(pinLed2, OUTPUT);
  Serial.begin(9600);
}
 
void loop() {
   
  
  valorSensor2 = analogRead (pinSensor2)/2;//lee los datos del potenciometro 2 de posicion requerida
    int sigpos = valorSensor2 ; 
  valorSensor = analogRead(pinSensor)/2; //valorsensor igual al valor del potenciometro de posicion actual
  
  difvalors = abs (sigpos - valorSensor);
  
  
  Serial.print ("valorSensor");
  Serial.println ( valorSensor); // para chequear en que posición esta el potenciometro del motor.
  delay(1); //le doy delay para que se pueda leer los datos impresos. de lo contrario pasan demaciado rapido
  Serial.print ("valor del sensor sig");
  Serial.println(valorSensor2); //para chequear la posicion requerida del pote2
  delay(1);
  //en este caso si el valor siguiente es menor al del potenciometro, , seria el atraso del motor.
   if (sigpos < valorSensor  && difvalors > 10 ) {
    digitalWrite (pinLed, HIGH);
    analogWrite (pinLed, 60); //pwm 
    digitalWrite (pinLed2,LOW);
    delay(1);
  }
// en este caso si el valor siguiente es superior al del potenciometro, ,  seria el avance del motor.
else if (sigpos > valorSensor  && difvalors > 10)  {
  digitalWrite (pinLed2, HIGH);
  analogWrite (pinLed2, 60); //pwm 
  digitalWrite (pinLed,LOW);
  delay(1);
}
//en este caso al ser iguales los valores se apagaria el motor.
else if (sigpos == valorSensor || difvalors < 10 ) {
  digitalWrite (pinLed2, LOW);
  digitalWrite (pinLed, LOW);
 delay(1); }

  
  
  
 
}

el video se los subo a la noche.
el esquema es simple. el arduino conectado por pin 9 y 10 a la puente h. el puente alimenta un motor, estoy utilizando la caja reductora de un servo mediano. mediante el reductor muevo un potenciometro para la posicion del motor.
otro potenciometro es el que indica el valorfuturo o posicion deseada. que muevo manualmente obvio.
basicamente el motor se mueve a la direccion necesaria hasta llegar a su posicion y parar.
tengo que seguir depurando el codigo seguramente por los siguientes comportamientos:

  1. el motor en algunas ocaciones al llegar al valor indicado, ocacionalmente avanza unos grados mas y vuelve a retroceder, nuevamente avanza unos grados pero menos que el anterior y retrocede o queda quieto. aparentemente buscaria la posicion.
  2. ocurre tambien que el motor avanza hasta el valor indicado pero no se detiene exactamente sino que retrocede y avanza constantemente en unos pequeños grados...<<>> siempre en la "zona" del grado indicado.

estos comportamientos ocurrian constantemente, es decir nunca se detenia el motor en algun grado exacto sino que se acercaba y quedaba avanzando y retrocediendo.. hasta que modifique el codigo agregando lo que seguro vieron de la variable difvalors y tambien el tema de 10. con esto buscaba que el motor solo se moviera si la diferencia entre la posicion actual y la deseada eran mayores o menores a 10. como una especie de zona muerta para que el motor no quede en constante busqueda o avance retroceso pasandose de los valores. y tambien creo que sirve a modo de sanar el grado de error que tienen estos potenciometros economicos.

espero que les guste a los novatos. y a los expertos que me ayuden a mejorarlo.
saludos

aqui les dejo el video prometido. creo que se puede observar algunos errores de posición que les comentaba anteriormente.
veremos de poder mejorar el codigo con la ayuda de esta comunidad :smiley:
saludos :smiley:

Hola Nicko,

bien por tu avance, lo que veo es q dejas el PWM constante a 60 y para q aumente la precisión debes hacer proporcional el pwm a la diferencia del valor del sensor con el pot 2.

Te cuanto que apenas fabrique mi nuevo puente H con el L298n, falta volver a configurar los valores y revisar el método PID de mi sketch. seguire pendiente de tus avances ya que apenas en q semana retomó yo.

Slds

hola selda.
lo del pwm lo dejo constante. por que fui probando y a mayor velocidad que esa, el motor se pasa del punto indicado. y queda bailando de un lado al otro sin poder encontrar el punto justo o medio. a pesar de haberle dejado ese +-10 de "zona muerta" por asi decirlo.
tambien lo probe con un motor de atornillador a bateria. y este con mucha mas potencia obvio, se pasa y jamas queda quieto.
no me habia percatado de variar la velocidad en base a la diferencia de los valores.. intentare algo al respecto.
tambien estaba pensando.. que podria conseguir potenciometros de mayor presicion.
lo que tambien me genera duda es si es mejor un potenciometro de mayor o menor K (resistencia). ahora utilizo unos de 100k lineales.

bueno. yo por mi lado estoy investigando lo del pid. pero es muy complejo para mi conocimiento en programacion por ahora.
a tu codigo mucho no lo entiendo... es la primera vez que toco lenguajes de programacion :smiley:
nos vemos hasta la victoria siempre :smiley:

Hola Nicko,

Si no requieres tanta precisión entonces lo que has hecho esta bien, bueno y tampoco es que mi código sea la panacea, tambien estoy aprendiendo jajaja... trata con algo así (lo ley en la web)

Setpoint = analogRead(pinSensor2)

feedback= analogRead(pinSensor)

error = Setpoint - feedback

PWM = error*K

donde K es una constante que hallaras por ensayo y error, delimitas a PWM para que si es > 255 entonces sea 255 y si es < 0 entonces sea 0, algo así es lo que hago, has visto un par de videos que saque de youtube? miralo y ve la precisión que alcanzan..mi reto es llegar a ese grado.

slds

selda ahora entiendo! muchas gracias por la aclaracion. hoy mismo pruebo eso.
tambien estaba pensando que el motor se me pasaba del punto por ser el del un taladro o atornillador a bateria el cual tiene reductores pero es normal que gire unos grados mas cuando se le corta la alimentacion....
entonces estoy pensando buscar un motor de eleva cristales de automovil. un amigo mecanico me prometio uno.
esos funcionan con un sin fin en el eje del motor lo cual al quitar alimentacion traban el mecanismo. tal vez lograria que se detenga justo a tiempo.eso mas tu consejo seguro lograre algo mejor. espero tenerlo pronto :smiley: