Transformada z para procesamiento de señales, controles PID...

2,086 views
Skip to first unread message

Jose Pico

unread,
Mar 23, 2017, 7:34:57 PM3/23/17
to FPGAwars: explorando el lado libre
Hola:

Estoy intentando informarme un poco sobre un tema que me parece más que interesante.


La idea es:

   Como un circuito analógico se puede expresar como   H(s)   función de transferencia  expresada usando la transformada de Laplace  y esta a su vez se puede convertir a  H(z) su transformada z y a su vez esto se puede
   expresar como en sumas y diferencias, funciones del tipo  y(k) = -a1 y(k-1) -a2 y(k-2) + b1 u(k-1) + b2 u(k-2)

   Si una señal de entrada la muestreamos con un convertidor A/D y los datos digitales los introducimos a nuestro FPGA donde mediante la combinación de sumas de valores anteriores de entradas y salidas,
   podemos pues, obtener el resulado   de salida de un circuito ante una señal de entrada, que serán un conjunto de muestras digitales que si a su vez la extraemos de la FPGA a un convertidor D/A , podemos crear digitalmente el   funcionamiento    de   cualquier circuito analógico.

Bueno! esto dicho así parece muy fácil pero entiendo que tiene su miga.
Pero estas cosas me surgen al releer algún apunte de cuando era estudiante y me quedé frustado con una gran cantidad de formulaciones que nos daban sin sentido y que nunca llegabamos a comprender porque nunca se hacía nada práctico.
Ahora, con esto de las FPGAs libres estoy intentando  reordenar todas aquellas ideas que al final muchas de ellas seguro que con dos conceptos básicos y claros se pueden hacer maravillas.

Aquí os dejo un poco una hoja recuperada de unos apuntes de los cuales me he inspirado para iniciar este nuevo tema ( Por cierto, me acuerdo poco  o casi nada de estos temas matemáticos jejejej )


Si alguien sabe algo más del tema y conoce de ejemplo prácticos,etc


Saludos y Gracias




Auto Generated Inline Image 1

1138-4EB

unread,
Mar 24, 2017, 4:46:54 AM3/24/17
to FPGAwars: explorando el lado libre
Hola José,

Disclaimer 1: no me gustá nada de nada utilizar números no enteros. Por eso me dedico a la electrónica digital :D.
Disclaimer 2: las personas que trabajan en teoría de control son matemáticas, o tienen una base de conocimiento matemático muy sólida. Por mi aversión a los números no enteros, no soy una de ellas.

Dicho lo anterior, mi Proyecto Final de Carrera fue la implementación de un controlador PID de una FPGA. La metodología que seguí fue hacer el ajuste de parámetros con un PID continuo y después aplicarlos a un PID discreto. El fundamento teórico es que si la FPGA funciona suficientemente rápido, el modelo discreto se comporta de forma equivalente al continuo. Aquí, "continuo" quiere decir "en el dominio de Laplace", y "discreto" en el de la transformada Z. Voy a explicarlo de la forma más cutre posible. Si cualquiera percibe un error de concepto matemático, por favor no seáis muy duros.


Como ha comentado José esto tiene relación con los conversores A/D y D/A. Pero vamos a empezar por lo más básico:

- ¿Qué es la derivada de una función? La inclinación de la misma en un punto dado.
- ¿Qué es una integral? El área que hay entre una función y la abscisa, entre dos valores de x.

Supongo que todos os acordáis de las integrales por partes, el cuento de la vieja, etc. Tranquilos, que no vamos a hacerlo XD. Sólo recordad que siempre integramos/derivamos una función, f(x).

Cuando leemos una señal con un conversor A/D (pensemos en una entrada analógica de Arduino), capturamos diferentes puntos de la misma. Digamos que lo que mide esa señal es el caudal de riego de un invernadero. Queremos que Arduino nos avise cuando haya un incremento muy llamativo del caudal. También queremos que nos indique cuántos litros hemos gastado en las últimas 24h. ¿Cómo lo hacemos? Efectivamente, lo primero es la derivada de la función y lo segundo es la integral. Pero... ¡no existe función! No tenemos una expresión matemática que defina la señal que estamos leyendo (si la hubiera, no tendríamos que leerla XD).

Aquí entra en juego la transformada Z. Cuando estamos capturando una señal, el número mínimo de capturas es una. Con eso no podemos hacer nada, porque derivar/integrar requiere noción del tiempo y en una muestra aislada no existe el tiempo. Así pues, cogemos dos muestras. Ahora sí tenemos noción del tiempo, que es lo que hemos tardado entre una muestra y la siguiente. Concretamente tenemos tres números con los que trabajar: x(0), x(1) y T.

Juguemos a ser niños:

- Fulanito, ¿cómo calculas la inclinación entre estos dos puntos?
- x(1)-x(0)
- Muy bien, ¡eso es una derivada en el dominio Z!
- Menganito, ¿cómo calculas el área entre esos dos puntos y la abscisa?
- x(0)*T (rectángulo) + x(1)-x(2)*T/2 (triángulo).
- Perfecto, ¡eso es una integral en el dominio Z! Se llama transformada de Tustin, o transformada bilinear.

Un dibujo para entender qué estan viendo los niños:



Esta sacada de la página 1-23 de la memoria de mi proyecto.

A mayores, la transformada Tustin es una de las existentes. Existen también la transformada de Euler y la backward. La diferencia con respecto a Tustin (ver Figura) es que en estas últimas la integral se calcula mediante un rectángulo sólo (ya sea x(0)*T ó x(1)*T). Por lo tanto, simplemente se está ignorando el triángulo, y se incurre en un error de aproximación mayor. No obstante, si el sistema se ejecuta lo suficientemente rápido con respecto a la señal, el área del triángulo será despreciable con respecto al del rectángulo. Por eso a veces se utilizan Eurler/Bacward, que numéricamente requieren menos operaciones de computación.

En cuanto a la relación entre el dominio del tiempo, Laplace y Z, hay formas de convertir las expresiones de cualquiera de ellas a cualquier otra. Ver ejemplo en la página 1-22 de la memoria. Cuál se use depende del área en el que te muevas. Z es muy habitual en procesamiento de digital de señal. Y los algoritmos clásicos de control (PID, redes de adelanto, filtros paso-bajo, etc.) son procesamiento de señal. En la página 1-25 de la memoria hay un ejemplo del PID expresado en términos de la transformada Z y al lado lo que sería el circuito con registros y sumadores/multiplicadores.

Lo que comenta José de los conversores D/A está muy relacionado con esto, pero al mismo tiempo no tiene nada que ver. Cuando capturamos una señal continua con un sistema digital, estamos leyendo unos pocos valores instantáneos de los infinitos puntos infinitesimales que tiene la señal en el tiempo. Existen varios teoremas, entre ellos el de Shannon y Nyquist, que son indican cómo de rápido tenemos que leer una señal para asegurarnos de que podemos indentificarla de forma única. Es decir, que si una señal puede cambiar su estado 4 veces por segundo y nosotros sólo la leemos una vez por segundo, hay infinitas señales diferentes que nosotros pensaremos que son iguales, porque tienen 1 de 4 puntos en común, y es el que leemos.

Por lo tanto, siempre que se digitalice una señal, se deberá hacer, al menos, al doble de la frecuencia natural (o máxima) del sistema que la está generando. De hecho, para control, se muestrea 10, 20 o 50 veces más rápido. En la página 1-28 de la memoria se muestra la diferencia de comportamiento del mismo controlador, sólo varian la frecuencia con la que se lee la señal. Como veis, Shannon está muy bien teóricamente, pero es insuficiente.

NOTA: esta es la razón por la que muchos sistemas de control con Arduino funcionan mal. No hay ningún problema con el código, simplemente no puede trabajar todo lo rápido que necesita. Por cierto, la librería PID de arduino utiliza una transformada bilinear. http://brettbeauregard.com/blog/?s=PID

Por lo tanto, José, la relación es esta: los requisitos en el tiempo de muestreo para estar seguros de que estamos capturando la señal deseada y no otra muy parecida. La elección es sensible, porque en caso de muestrear demasiado rápido, capturaremos ruido que no nos interesa. A veces, se incluye un filtrado digital de la señal para eliminar ese ruido ahorrándonos un filtro analógico. Ahí entra en juego la Z. Pero, si no se implementa filtro, que muchas veces no es necesario, la señal se puede volver a generar con un D/A directamente con los valores leídos del A/D.

Nota adicional: siempre se suele muestrear en periodos constantes de tiempo. Hay dos razones principales: por un lado, de otra forma tendríamos que guardar no sólo el dato, sino también el tiempo que ha pasado desde la última captura. Por otro lado, que el el periodo sea constante facilita el análisis matemático y la demostración de teoremas basados en series de datos.

A lo largo de todo el mensaje he considerado que se utilizan Zero-Order-Hold. Es decir, que los datos se leen directamente del A/D y, si hay que generarlos, el D/A mantiene un valor constante entre una actualización y la siguiente. Sin embargo, en ocasiones, especialmente en sistemas donde no se puede capturar/generar lo suficientemente rápido, se pueden utilizar First-Order-Hold: https://en.wikipedia.org/wiki/First-order_hold  o soluciones más elaboradas. El objetivo es "inventarse" con cierta sensatez la forma que tiene la señal muestreada/reconstruida entre cada pareja de muestras. Una vez más, estos retenedores se pueden diseñar en el dominio del tiempo, de Laplace o de la transformada Z.

Espero que te haya servido para refrescar un poco la memoria,

Un saludo
Auto Generated Inline Image 1

Juanma Rico

unread,
Mar 24, 2017, 5:43:31 AM3/24/17
to FPGAwars: explorando el lado libre

¡La madre que te parió Unai! ¡Voy muy contento a leer tu proyecto... y está en vasco! jajajajajajajajaja
Me tendré que guiar por los dibujitos... ;)

En Industriales este tema se daba en una asignatura cuatrimestral solo para ella, era el complemento de otra anual (Control Automático)... Control Digital, creo recordar que se llamaba, si alguien está interesado y quiere mis apuntes se los escaneo y mando.

Creo recordar que había una forma de controlar directamente los sistemas digitales que se hacía con un número limitado de muestras (en un par de ellas los sistemas de uno o varios polos en su función de transferencia se controlaban, ¿deathbeat se llamaba?), con esto quiero decir que no hacía falta "digitalizar" un PID (que es eminentemente analógico, Proporcional-Integral-Derivativo), hay sistemas de control directamente digitales, pero se usa el PID porque los ingenieros industriales están acostumbrados a ellos y los operadores tienen un algoritmo de sintonización más que estudiado para usarlo en cualquier sistema a controlar y por otros motivos que ahora no recuerdo... :)

Que nadie se caliente... aunque el controlador ¿deathbeat? permite controlar sistemas en un par de muestras, hay que conocer perfectamente la función de transferencia del sistema y no se ha hablado nada de la potencia necesaria para usarlo porque, aunque los sistemas de digitales de control cuenten con esa potencia para emitir la señal de control necesaria, lo normal es que los sistemas que vas a controlar (eminentemente analógicos) saturen y no admitan esa señal de control... en fin, un rollo.

Usábamos como libro de cabecera los dos del Ogata, yo tengo ambos comprados en papel, pero imagino que lo podéis encontrar por la web o en alguna biblioteca universitaria cercana.
Eso sí, como dice Unai, de las matemáticas no te libra nadie.

Lo dicho, quien tenga interés en ver cómo se explican estas cosas en la ETSII de la Universidad de Málaga (que imagino que no es la mejor... o sí, no sé) que avise y yo le paso mis apuntes de ambas asignaturas. :)

Saludos.



El viernes, 24 de marzo de 2017, 9:46:54 (UTC+1), 1138-4EB escribió:
Hola José,

1138-4EB

unread,
Mar 24, 2017, 7:12:06 AM3/24/17
to FPGAwars: explorando el lado libre
¡La madre que te parió Unai! ¡Voy muy contento a leer tu proyecto... y está en vasco! jajajajajajajajaja

Desde la guardería y hasta el master hice todos mis estudios en euskera XD. Bueno, lo que me permitieron (no todas las asignaturas están disponibles en la uni), y a excepción de un año que estuve en Ferrol. Desde entonces, en inglés. Poco contenido académico he producido en lengua cervantina.
 
Me tendré que guiar por los dibujitos... ;)

Eso te iba a decir, que las mates y los circuitos digitales son un lenguaje universal :D
 
En Industriales este tema se daba en una asignatura cuatrimestral solo para ella, era el complemento de otra anual (Control Automático)... Control Digital, creo recordar que se llamaba, si alguien está interesado y quiere mis apuntes se los escaneo y mando.

Yo la curśe como anual en Galicia y, diría que también en Bilbo. Pero en ninguna de ellas se veía la transformada Z, sólo Laplace. La Z la veían quienes cursaban alguna asignatura específica para hacer sistemas de control con PICs. Yo me la "empollé" para el PFC.
 
Creo recordar que había una forma de controlar directamente los sistemas digitales que se hacía con un número limitado de muestras (en un par de ellas los sistemas de uno o varios polos en su función de transferencia se controlaban, ¿deathbeat se llamaba?), con esto quiero decir que no hacía falta "digitalizar" un PID (que es eminentemente analógico, Proporcional-Integral-Derivativo), hay sistemas de control directamente digitales, pero se usa el PID porque los ingenieros industriales están acostumbrados a ellos y los operadores tienen un algoritmo de sintonización más que estudiado para usarlo en cualquier sistema a controlar y por otros motivos que ahora no recuerdo... :)

Efectivamente, el PID hoy día es una patata. Hay algoritmos más eficientes, que producen un mejor control y además son más fáciles de ajustar a un problema concreta. Que se disponga de un modelo exacto de la planta o no es secundario (hay algoritmos para ambos casos). El número de muestras utilizado también depende del algoritmo y de cuánta "memoria" quieres que tenga. Lo de los polos o el lugar de las raíces es genérico para cualquier controlador. Hay múltiples circuitos que pueden dar como resultado una misma regla de control, y por tanto tener el mismo número de ceros/polos.

Como dices, se sigue usando por "es lo que hemos usado toda la vida y funciona bien". Aunque "funciona bien" depende, como dices de "un agoritmo de sintonización más que estudiado". Sólo que ese "más que estudiado" es "más que probado". Todas las tablas para ajuste automático de PIDs son experimentales. Revisadas y mejoradas durantes años, sí. Pero exprimentales al fin y al cabo.
 
De hecho, el enfoque de mi PFC viene de ahí: proveer a un operario un chip equivalente al controlador que ya utiliza, y en el que puede introducir los mismos parámetros de configuración.

¿Cuál es el problema principal de los PID, al margen de todo lo anterior? Son para sistemas Single-Input-Single-Output. En cuanto tienes un motor y quieres controlar dos variables, por ejemplo la velocidad y el par, las cosas se empiezan a complicar porque necesitas dos PID. Si quieres velocidad, posición y par, es más interesante. Hasta que directamente las cosas funcionan de churro, o con experimentaciones eternas para ajustarlo todo a base de prueba y error.

Que nadie se caliente... aunque el controlador ¿deathbeat? permite controlar sistemas en un par de muestras, hay que conocer perfectamente la función de transferencia del sistema y no se ha hablado nada de la potencia necesaria para usarlo porque, aunque los sistemas de digitales de control cuenten con esa potencia para emitir la señal de control necesaria, lo normal es que los sistemas que vas a controlar (eminentemente analógicos) saturen y no admitan esa señal de control... en fin, un rollo.

He omitido esto anteriormente, pero ese el problema principal del PID. De hecho, muchísimos PID en realidad están funcionando como P o PI.

Cuando la señal de referencia (la velocidad a la que queremos que gire el motor) no coincide con la medida (a qué velocidad está girando en realidad), tenemos una señal de error. El objetivo del factor I es reducirla a cero, por lo que fuerza la salida en el sentido adecuado. Si el motor tarda mucho en responder, el factor I sigue acumulando diferencia, sigue acumulando.... hasta que directamente da igual lo digan P y D, la salida se bloquea al máximo (o mínimo). Si es más peligroso que un motor gire a tope de velocidad o se quede parado, depende de la aplicación. En cualquier caso, nunca es deseable.
 
Ese problema se denomina "windup" y hay varias técnicas para reducir su impacto, que no evitarlo: https://en.wikipedia.org/wiki/Integral_windup

Por otro lado, el factor derivativo responde a los cambios instántaneos en la planta. Lo cual quere decir que amplifica cualquier cambio en la consigna y también el ruido. Por ejemplo, si un operario golpea sin querer una máquina y se lee un valor menor que el real, el término derivativo forzará la salida para compensarlo. Esa compensación no era necesaria, por lo que inmediatamente después tendrá que revertirla para volver a poner la planta en su sitio. Es fácil intuir que, si D tiene un peso importante, esto puede amplificar cualquier oscilación hasta llevar a la planta a una situación de inestabilidad. También hay varias estrategias para frontar esto.

La librería PID de Arduino creo que saturaba el término I y por otra parte introducía directamente la señal de realimentación al término D (en vez de usar la señal de error). Son las dos soluciones más habituales (junto con algún filtrado paso bajo de D, definido en el dominio Z), por simples y funcionales.

Sólo por redondearlo, cualquiera de las "otras técnicas más modernas" que comentaba lo que hacen es tener en cuenta explícitamente las limitaciones físicas de la planta y el controlador, para ajustar los cambios a las mismas. A esto se le llama "constrained control". Evidentemente, desde un punto de vista matemático, son bastante más complejos y normalmente se reducen a sistemas optimización matricial. Por eso es muy interesante conocer en profundidad el PID, sus bondades y limitaciones, como primer paso antes de zambullirse en literatura sobre control.

Usábamos como libro de cabecera los dos del Ogata, yo tengo ambos comprados en papel, pero imagino que lo podéis encontrar por la web o en alguna biblioteca universitaria cercana.
Eso sí, como dice Unai, de las matemáticas no te libra nadie.

Echa un ojo a las referencias, que esas están en inglés ;). Como dices, no conozco biblioteca de escuela técnica que no tenga Ogata, Astrom, Kuo, Murray...
 
Lo dicho, quien tenga interés en ver cómo se explican estas cosas en la ETSII de la Universidad de Málaga (que imagino que no es la mejor... o sí, no sé) que avise y yo le paso mis apuntes de ambas asignaturas. :)

Saludos.

Saludos

Juanma Rico

unread,
Mar 24, 2017, 9:34:29 AM3/24/17
to FPGAwars: explorando el lado libre

Unai, lo que se aprende contigo y lo rápido que bajas la prepotencia (y a veces la moral... jajajajajajaja) :D

Que nadie se asuste que para programar una FPGA (y ahora menos con icestudio) y hacer experimentos de control con ella, no se necesita saber de control automático, ni función de transferencia, ni transformada Z, ni nada de eso... ¡Unai es que sabe de todo! jajajajajaja
Y claro, ya uno se aprovecha para que le envíe referencias aunque sean en euskera, que siempre viene bien aprender cosas... :-P

José Pico, como te veo interesado y a mi también me gusta el tema, si quieres elegimos una "digitalización" del PID (alguna ya hecha de Arduino puede valer), montamos un proyecto con github y trabajamos sobre ello en la FPGA, no tanto por lo bueno del control del PID, sino por la parte didáctica que pueda tener.

Lo más sencillo es trabajar sobre el control de un motor de corriente contínua (velocidad, par, posición... ), pero elige el sistema dinámico que tú quieras para poner a prueba el control PID (ten encuenta que no solo necesitamos el ADC, sino también el DAC para actuar sobre el motor y un tacómetro para realimentar el bucle de control).

Cuando lo tengamos probado sería muy interesante dejarlo como un bloque en icestudio para poder acoplarlo a motores de corriente continua y usarlo así en otros tipos de robots que no usen servos (los motores de juguete DC no cuestan más de un euro y pueden ser interesantes).

Con el proyecto github montado se puede trabajar sin asustar a nadie y así dejamos el grupo para comentarios y preguntas... ¡Que contestará Unai, claro! jajajajajaja :)

Así que si te animas a repasar los apuntes de la transformada Z, yo encantado, busco los mios y hacemos el bloque PID entre los dos y todo aquel que se quiera apuntar... :)

Yo ando con el sistema Cold/Warm Boot de nuestra placa, un proyecto de simulación del antiguo microcontrolador 4004 de Intel (que he tenido que aparacar por el tema de las puertas triestado), el SimpleZ y alguno que otro más... es decir, que ando falto de tiempo en el tema de FPGAS, pero también quería probar el ADC que trae la iceZUM Alhambra  y creo que este puede ser un proyecto útil con el que probarla, así que con tu ayuda abriremos otro frente más... Esperemos que con tantos frentes abiertos no perdamos la guerra... :-)

Tú me dices si te apetece.

Saludos.

Unai Martinez

unread,
Mar 24, 2017, 9:44:54 AM3/24/17
to FPGA-WARS: explorando el lado libre
Referencia muy-muy rápida:
  • No necesitáis un DAC, podéis controlar el motor por PWM. Sólo necesitais un driver, que puede ser un transistor o, si queréis que gire en dos sentidos, un puente H (cuatro transistores).
    • Tip: los motores son "integradores de corriente" de por sí. Van a convertir la PWM en continua.
  • Un ventilador de PC os cuesta entre 2-10€. Si es de tres cables (molex pequeño, no el que va a la fuente de alimentación) incluye un sensor de efecto Hall, que podéis convertir a tensión sólo con un resistencia. Os ahorráis un tacómetro adicional.
    • Si el ventilador es de cuatro cables, el cuarto es para meterle una PWM directamente. Así, ni siquiera necesitáis el "driver", lo lleva incluido.
    • Aunque sea de tres hilos, como no tiene sentido hacer girar un ventilador en sentido contrario, podéis usar sólo un transistor, sin puente H.
      • Aunque no mueva el aire, no pasa nada si hacéis girar el ventilador de PC al revés. Funcionará, pero por la forma de las aspas no hará nada útil.
PD: no sé de todo, pero llevo desde los quince años cacharreando y he tenido la suerte de tener recursos suficientes a mano. Mientras no os salgáis mucho de los ejercicios de cacharreo clásicos, podré seguir los pasos ;)

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/fpga-wars-explorando-el-lado-libre/d71bae95-a138-46e9-b8a1-3468ab0895a4%40googlegroups.com.

Para acceder a más opciones, visita https://groups.google.com/d/optout.

Unai Martinez

unread,
Mar 24, 2017, 9:48:42 AM3/24/17
to FPGA-WARS: explorando el lado libre
Pestaña 'ohkis'. Está en euskera también. Pero incluye diagramas y código en VHDL. No hay ningún PID, es un control en lazo abierto. Lo que os puede ser útil es cómo se generan las PWM y/o el LCD (el típico hitachi). Como curiosidad, la máquina de estados del LCD genera símbolos personalizados (la ROM del controlador lo permite), de forma que se puede mostrar un "logo" uniendo varios caracteres. Hay dibujos de todos los pasos en la memoria.

Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-lib...@googlegroups.com.

Juanma Rico

unread,
Mar 24, 2017, 9:56:04 AM3/24/17
to FPGAwars: explorando el lado libre

Imposible Unai, creo que ni a propósito nos podemos salir de un "cacharreo clásico" que tú no sepas... jejejejejeje

Unai, muy rápido, sé que andas corto de tiempo y tienes entrega... pero me interesa el tema de los ventiladores, es verdad que tienen un hall que puede servir de tacómetro, tengo muchos ventiladores para cacharrear...

¿Crees que los ventiladores de las CPU's podrían tener potencia para mover un pequeño robot educativo? Por lo que veo el par que tienen es bajísimo y se paran sin más que rozarlo con los dedos... pero si se les puede aumentar el par sin quemarlos sería genial. ¿Se podría aumentar el par de giro o directamente ni lo intento?

Gracias como siempre.
Saludos
Message has been deleted

Juanma Rico

unread,
Mar 24, 2017, 9:57:28 AM3/24/17
to FPGAwars: explorando el lado libre

Ya estaba yo curioseando... jejejejeje :)


El viernes, 24 de marzo de 2017, 14:48:42 (UTC+1), 1138-4EB escribió:

Unai Martinez

unread,
Mar 24, 2017, 10:21:38 AM3/24/17
to FPGA-WARS: explorando el lado libre
Mira, ahí me has pillado totalmente fuera de lugar XD.

He trabajado bastante con motorcillos, pero las máquinas eléctricas se me resisten. Igual tengo conocimientos teóricos un poco más avanzados que tú, por haber hecho la especialidad de electrónica, pero lo justo. Aún así, me cuesta mucho "verlos" en la práctica.

En principio puedes incrementar el par dándole más corriente. Pero claro, si el motor ya está funcionando a su velocidad nominal, al incrementar la corriente estás haciéndolo sufrir. Lo que se me ocurre es que las escobillas den más chispazos y se desgasten antes. O que los propios cables que están en un chasis de plástico no lo lleven bien. O que pete el sensor de efecto Hall. También puede no pasar nada.

Mi referencia son los Brushless (BLDC): un motor DC pero quitándole las escobillas y haciendo la conmutación de forma electrónica. Son muy parecidos a las máquinas síncronas y también a los motores paso a paso. En realidad son nombres diferentes para referirse a lo mismo en diferentes escalas y con diferentes estrategias de control. En estos casos, si quieres incrementar la corriente hay que hacerlo de forma cuidadosa ya que incrementarla hace que se queden "pegados" a una posición. Por lo tanto, hay que coordinar bien el incremento de corriente con la secuencia de cambio, por el riesgo de que se salte un paso y empiece a girar en sentido contrario. Asimismo, como en un paso a paso, incrementarla cuando está fijo en una posición hace que tenga muchísima más capacidad de retención, pero a costa de un "cortocircuito" magnético por así decirlo.

Un DC no tiene estos problemas que comento, pero los efectos electromagnéticos y las corrientes por dentro son iguales.

Por lo tanto, por el precio que te cuesta un motor DC de un coche teledirigido (en cualquier tienda de hobbys y maquetas), no merece la pena. La sugerencia del ventilador es porque es lo más rápido para probar sólo el PID y centraros en el diseño dentro de la FPGA. A partir de ahí, lo suyo es coger un motor DC un poquillo más grande y hacer un encoder con una cartulina pintada a rayas y un fototransistor. Después, cambiarlo por un taco y usar un ADC. Después volver a la tienda de maquetas, y coger un motor de coche teledirigido, pero brushless. O, mejor aún, pedir en aliexpress un motor brushless + controlador por 8-10€. El controlador es como un puente H, pero compuesto por seis transistores. Un proyecto bonito es montarlo en una protoboard.... A mayores, la realimentación de los BLDC se puede hacer con tres sensores de efecto hall, o sin sensores, sólo midiendo la tensión en cada fase en el orden adecuado. Lo cual es una aplicación muy útil para el ADC de la Alhambra. Por las velocidades a las que se tiene que ejecutar es muy probable que el Arduino no sea capaz, pero la iCE40 sí.

¡Por cierto! Los motores brushless + controlador de aliexpress los venden para drones. Sí, con cuatro instancias del PID y cuatro de esos podéis controlar un dron con la Alhambra. Nota: añadiendo una CPU (Arduino) que haga la orquestación de los cuatro motores, leyendo algún acelerómetro/giroscopio.

Todos estos temas los tienes trilladísimos en foros de aficionados a vehículos RC. Muchos controladores incluyen un AVR, como Arduino, y hay varios usuarios que han diseñado firmwares específicos para coches, camiones, aviones, helicópteros...

Sí, también tengo hecho un generador de secuencia de control para motores BLDC en VHDL. Pero, paso a paso. Esa referencia no los la doy todavía, que os explota la cabeza :P. Pedidla cuando queráis.

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Unai Martinez

unread,
Mar 24, 2017, 10:25:26 AM3/24/17
to FPGA-WARS: explorando el lado libre
Yo vendiéndo los BLDC y no os digo lo más importante: los coches eléctricos (los grandes, los Tesla y cia) funcionan con un BLDC, igual que el de juguete pero en grande. Los ascensores también. El secador de pelo también. Cualquier motor que creáis que es DC y consuma más que unos pocos watios, seguramente será un BLDC.

Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-lib...@googlegroups.com.

Juanma Rico

unread,
Mar 24, 2017, 12:48:16 PM3/24/17
to FPGAwars: explorando el lado libre

Buenasssss....


El viernes, 24 de marzo de 2017, 15:21:38 (UTC+1), 1138-4EB escribió:
Mira, ahí me has pillado totalmente fuera de lugar XD.

 
jajajajajajaj, ¡no puede ser! ¡eso no me lo creo! :)
 
He trabajado bastante con motorcillos, pero las máquinas eléctricas se me resisten. Igual tengo conocimientos teóricos un poco más avanzados que tú, por haber hecho la especialidad de electrónica, pero lo justo. Aún así, me cuesta mucho "verlos" en la práctica.

A mi me sacas de la "jaula de ardilla" y me pierdo... tanta libertad... jejejejejeje :)


En principio puedes incrementar el par dándole más corriente. Pero claro, si el motor ya está funcionando a su velocidad nominal, al incrementar la corriente estás haciéndolo sufrir. Lo que se me ocurre es que las escobillas den más chispazos y se desgasten antes. O que los propios cables que están en un chasis de plástico no lo lleven bien. O que pete el sensor de efecto Hall. También puede no pasar nada.

Ese era mi miedo y la confirmación que te pedía... siempre podemos hacer una buena reductora mecánica... ;)
 

Mi referencia son los Brushless (BLDC): un motor DC pero quitándole las escobillas y haciendo la conmutación de forma electrónica. Son muy parecidos a las máquinas síncronas y también a los motores paso a paso. En realidad son nombres diferentes para referirse a lo mismo en diferentes escalas y con diferentes estrategias de control. En estos casos, si quieres incrementar la corriente hay que hacerlo de forma cuidadosa ya que incrementarla hace que se queden "pegados" a una posición. Por lo tanto, hay que coordinar bien el incremento de corriente con la secuencia de cambio, por el riesgo de que se salte un paso y empiece a girar en sentido contrario. Asimismo, como en un paso a paso, incrementarla cuando está fijo en una posición hace que tenga muchísima más capacidad de retención, pero a costa de un "cortocircuito" magnético por así decirlo.

Ahora que lo pienso... ¿No son los motores de la CPU también brushless? Por lo menos yo he desmontado unos cuantos y no encuentro las escobillas... pero vamos... que siempre que trato con motores también me pierdo... nunca sé donde acaba la electrónica y empieza la parte mecánica para llamarlos de una forma o de otra... o es quizás el controlador el que le da nombre... y cada fabricante con sus submodelos... conocimientos teóricos muchos (suficientes), pero luego cuando llego a la fábrica no sé diferenciar un motor síncrono del extintor.... (menos mal que nadie se da cuenta)  jejejeje
 

Un DC no tiene estos problemas que comento, pero los efectos electromagnéticos y las corrientes por dentro son iguales.

Por lo tanto, por el precio que te cuesta un motor DC de un coche teledirigido (en cualquier tienda de hobbys y maquetas), no merece la pena. La sugerencia del ventilador es porque es lo más rápido para probar sólo el PID y centraros en el diseño dentro de la FPGA. A partir de ahí, lo suyo es coger un motor DC un poquillo más grande y hacer un encoder con una cartulina pintada a rayas y un fototransistor.

Sí, recuerdo que Demócrito en este hilo hizo un control básico por comparación con icestudio (no os perdáis el vídeo porque es alucinante).
Si pudiéramos crear un bloque con el PID e integrarlo en icestudio sería genial, para distintos motores solo se necesitaría repetir el bloque... incluso una colección con bloques de controles automáticos para poder aplicar la teoría de control moderna.... soñar no cuesta nada. :)

<inciso>
Por cierto, ahora que me acuerdo, lanzo la pregunta desde aquí por si Obijuan me lee... Juan, creo haber leido que las ondas senoidales que usabas para tus robots modulares las generabas con una especie de tabla interna en la FPGA... Imagino que ya se te habrá ocurrido, pero te pregunto para que me digas realmente las dificultades o por qué no lo pudiste hacer... ¿Pensaste en algún momento en generar la onda senoidal en un circuito exterior y utilizar el ADC de la placa para alimentar internamente el movimiento del servo?
Imagino que generar una señal seno, cambiar su frecuencia, amplitud y demás, en un pequeño circuito externo es más fácil que sintetizarlo en la FPGA... ¿no?
</inciso>

Fin del inciso, perdona, Unai, es que me acabo de acordar y llevaba un tiempo por preguntarlo y siempre se me olvidaba... si Juan no me lee ya busco el hilo y pregunto en el propio hilo. (Espero no olvidarme).

 
Después, cambiarlo por un taco y usar un ADC. Después volver a la tienda de maquetas, y coger un motor de coche teledirigido, pero brushless. O, mejor aún, pedir en aliexpress un motor brushless + controlador por 8-10€. El controlador es como un puente H, pero compuesto por seis transistores. Un proyecto bonito es montarlo en una protoboard.... A mayores, la realimentación de los BLDC se puede hacer con tres sensores de efecto hall, o sin sensores, sólo midiendo la tensión en cada fase en el orden adecuado. Lo cual es una aplicación muy útil para el ADC de la Alhambra. Por las velocidades a las que se tiene que ejecutar es muy probable que el Arduino no sea capaz, pero la iCE40 sí.

Apunto esa idea. :)
 

¡Por cierto! Los motores brushless + controlador de aliexpress los venden para drones. Sí, con cuatro instancias del PID y cuatro de esos podéis controlar un dron con la Alhambra. Nota: añadiendo una CPU (Arduino) que haga la orquestación de los cuatro motores, leyendo algún acelerómetro/giroscopio.

¡Otra idea más al saco! :)


Todos estos temas los tienes trilladísimos en foros de aficionados a vehículos RC. Muchos controladores incluyen un AVR, como Arduino, y hay varios usuarios que han diseñado firmwares específicos para coches, camiones, aviones, helicópteros...

Investigaremos.
 

Sí, también tengo hecho un generador de secuencia de control para motores BLDC en VHDL. Pero, paso a paso. Esa referencia no los la doy todavía, que os explota la cabeza :P. Pedidla cuando queráis.

Gracias, mi cabeza te lo agradece... :P

Pues listo, gracias Unai... José Pico... ¿Qué? ¿nos animamos a mover primero un ventilador con el PID digital y luego.... ¡el mundo! ? jejejejeje :)
 

1138-4EB

unread,
Mar 24, 2017, 3:17:00 PM3/24/17
to FPGAwars: explorando el lado libre

Ahora que lo pienso... ¿No son los motores de la CPU también brushless? Por lo menos yo he desmontado unos cuantos y no encuentro las escobillas... pero vamos... que siempre que trato con motores también me pierdo... nunca sé donde acaba la electrónica y empieza la parte mecánica para llamarlos de una forma o de otra... o es quizás el controlador el que le da nombre... y cada fabricante con sus submodelos... conocimientos teóricos muchos (suficientes), pero luego cuando llego a la fábrica no sé diferenciar un motor síncrono del extintor.... (menos mal que nadie se da cuenta)  jejejeje

Pues la verdad es que sí. Me ha despistado el "ball-bearing" que lo tengo asociado a motores DC. Pero eso hace referencia a los rodamientos, que son independientes de que sea DC o BLDC. Es más, tiene sentido que incluyan un Hall, porque es necesario para hacer las "escobillas virtuales".
 
Si pudiéramos crear un bloque con el PID e integrarlo en icestudio sería genial, para distintos motores solo se necesitaría repetir el bloque... incluso una colección con bloques de controles automáticos para poder aplicar la teoría de control moderna.... soñar no cuesta nada. :)

La idea es muy deseable, pero ahora mismo icestudio está limitado para ello. Por un lado, no tiene entradas/salidas parametrizables, que es prácticamente obligatorio para un PID en FPGA. Por otro lado, no tiene noción de entidad/arquitectura, por lo que no resulta intuitivo cambiar de un algoritmo a otro. Es decir, serían todo cajas negras que referenciarían a conjuntos de fuentes en verilog. Puede que en una próxima versión sí se le pueda dar un enfoque más didáctico.

Lo que sí se puede hacer es acordar un tamaño de salida "estandar" (léase 8, 12 o 16 bits) y ajustarnos a ello, confiando en que el sintetizador optimice los sobrantes cuando se utilicen menos a la salida. Jesús, ¿se pueden indicar varios ficheros Verilog dentro de una caja negra en icestudio?
 
<inciso>
Por cierto, ahora que me acuerdo, lanzo la pregunta desde aquí por si Obijuan me lee... Juan, creo haber leido que las ondas senoidales que usabas para tus robots modulares las generabas con una especie de tabla interna en la FPGA... Imagino que ya se te habrá ocurrido, pero te pregunto para que me digas realmente las dificultades o por qué no lo pudiste hacer... ¿Pensaste en algún momento en generar la onda senoidal en un circuito exterior y utilizar el ADC de la placa para alimentar internamente el movimiento del servo?
Imagino que generar una señal seno, cambiar su frecuencia, amplitud y demás, en un pequeño circuito externo es más fácil que sintetizarlo en la FPGA... ¿no?
</inciso>


Mientras se pasa Juan... a veces esas tablas son el duty-cycle variable de una señal PWM, por que realmente no se genera ninguna señal con forma senoidal. Habría que integrar la PWM para verla. Por otro lado, los circuitos analógicos son más sensibles al ruido, y es más difícil cambiar los parámetros de forma remota, o que se ajusten al contexto variable de la planta.

Jose Pico

unread,
Mar 24, 2017, 5:56:05 PM3/24/17
to FPGAwars: explorando el lado libre


El viernes, 24 de marzo de 2017, 9:46:54 (UTC+1), 1138-4EB escribió:
Hola José,

Disclaimer 1: no me gustá nada de nada utilizar números no enteros. Por eso me dedico a la electrónica digital :D.
Disclaimer 2: las personas que trabajan en teoría de control son matemáticas, o tienen una base de conocimiento matemático muy sólida. Por mi aversión a los números no enteros, no soy una de ellas.

  Dudo mucho que no te gusten las matemáticas, el problema es que no nos las han explicado bien y nos han motivado lo suficiente con la práctica REAL y PALPABLE, pero  ahor tenemos FPGAs y podemos enmendarlo.  JJejjejeje 

Jose Pico

unread,
Mar 24, 2017, 6:19:28 PM3/24/17
to FPGAwars: explorando el lado libre


El viernes, 24 de marzo de 2017, 9:46:54 (UTC+1), 1138-4EB escribió:
Hola José,

Disclaimer 1: no me gustá nada de nada utilizar números no enteros. Por eso me dedico a la electrónica digital :D.
Disclaimer 2: las personas que trabajan en teoría de control son matemáticas, o tienen una base de conocimiento matemático muy sólida. Por mi aversión a los números no enteros, no soy una de ellas.
 
Jejeje: Dudo que tengas mucha aversión por las matemáticas, el problema es que no nos las han explicado bien y menos aún nos han dado una formación práctica REAL. Pero ahora tenemos las FPGAs y quizás lo podemos enmendar o que otros lo enmienden... 
 

Dicho lo anterior, mi Proyecto Final de Carrera fue la implementación de un controlador PID de una FPGA. La metodología que seguí fue hacer el ajuste de parámetros con un PID continuo y después aplicarlos a un PID discreto. El fundamento teórico es que si la FPGA funciona suficientemente rápido, el modelo discreto se comporta de forma equivalente al continuo. Aquí, "continuo" quiere decir "en el dominio de Laplace", y "discreto" en el de la transformada Z. Voy a explicarlo de la forma más cutre posible. Si cualquiera percibe un error de concepto matemático, por favor no seáis muy duros.


Como ha comentado José esto tiene relación con los conversores A/D y D/A. Pero vamos a empezar por lo más básico:

- ¿Qué es la derivada de una función? La inclinación de la misma en un punto dado.
    
    Añadiría que la derivada es el FUTURO ( hacia donde parece que tiende la señal )
 
- ¿Qué es una integral? El área que hay entre una función y la abscisa, entre dos valores de x.
     
   La integral sería el PASADO  ( Acumulación de información ) 

Supongo que todos os acordáis de las integrales por partes, el cuento de la vieja, etc. Tranquilos, que no vamos a hacerlo XD. Sólo recordad que siempre integramos/derivamos una función, f(x).

Cuando leemos una señal con un conversor A/D (pensemos en una entrada analógica de Arduino), capturamos diferentes puntos de la misma. Digamos que lo que mide esa señal es el caudal de riego de un invernadero. Queremos que Arduino nos avise cuando haya un incremento muy llamativo del caudal. También queremos que nos indique cuántos litros hemos gastado en las últimas 24h. ¿Cómo lo hacemos? Efectivamente, lo primero es la derivada de la función y lo segundo es la integral. Pero... ¡no existe función! No tenemos una expresión matemática que defina la señal que estamos leyendo (si la hubiera, no tendríamos que leerla XD).

Aquí entra en juego la transformada Z. Cuando estamos capturando una señal, el número mínimo de capturas es una. Con eso no podemos hacer nada, porque derivar/integrar requiere noción del tiempo y en una muestra aislada no existe el tiempo. Así pues, cogemos dos muestras. Ahora sí tenemos noción del tiempo, que es lo que hemos tardado entre una muestra y la siguiente. Concretamente tenemos tres números con los que trabajar: x(0), x(1) y T.

Juguemos a ser niños:

- Fulanito, ¿cómo calculas la inclinación entre estos dos puntos?
- x(1)-x(0)
- Muy bien, ¡eso es una derivada en el dominio Z!
- Menganito, ¿cómo calculas el área entre esos dos puntos y la abscisa?
- x(0)*T (rectángulo) + x(1)-x(2)*T/2 (triángulo).
- Perfecto, ¡eso es una integral en el dominio Z! Se llama transformada de Tustin, o transformada bilinear.

Un dibujo para entender qué estan viendo los niños:



Esta sacada de la página 1-23 de la memoria de mi proyecto.

A mayores, la transformada Tustin es una de las existentes. Existen también la transformada de Euler y la backward. La diferencia con respecto a Tustin (ver Figura) es que en estas últimas la integral se calcula mediante un rectángulo sólo (ya sea x(0)*T ó x(1)*T). Por lo tanto, simplemente se está ignorando el triángulo, y se incurre en un error de aproximación mayor. No obstante, si el sistema se ejecuta lo suficientemente rápido con respecto a la señal, el área del triángulo será despreciable con respecto al del rectángulo. Por eso a veces se utilizan Eurler/Bacward, que numéricamente requieren menos operaciones de computación.

En cuanto a la relación entre el dominio del tiempo, Laplace y Z, hay formas de convertir las expresiones de cualquiera de ellas a cualquier otra. Ver ejemplo en la página 1-22 de la memoria. Cuál se use depende del área en el que te muevas. Z es muy habitual en procesamiento de digital de señal. Y los algoritmos clásicos de control (PID, redes de adelanto, filtros paso-bajo, etc.) son procesamiento de señal. En la página 1-25 de la memoria hay un ejemplo del PID expresado en términos de la transformada Z y al lado lo que sería el circuito con registros y sumadores/multiplicadores.

Lo que comenta José de los conversores D/A está muy relacionado con esto, pero al mismo tiempo no tiene nada que ver. Cuando capturamos una señal continua con un sistema digital, estamos leyendo unos pocos valores instantáneos de los infinitos puntos infinitesimales que tiene la señal en el tiempo. Existen varios teoremas, entre ellos el de Shannon y Nyquist, que son indican cómo de rápido tenemos que leer una señal para asegurarnos de que podemos indentificarla de forma única. Es decir, que si una señal puede cambiar su estado 4 veces por segundo y nosotros sólo la leemos una vez por segundo, hay infinitas señales diferentes que nosotros pensaremos que son iguales, porque tienen 1 de 4 puntos en común, y es el que leemos.

Por lo tanto, siempre que se digitalice una señal, se deberá hacer, al menos, al doble de la frecuencia natural (o máxima) del sistema que la está generando. De hecho, para control, se muestrea 10, 20 o 50 veces más rápido. En la página 1-28 de la memoria se muestra la diferencia de comportamiento del mismo controlador, sólo varian la frecuencia con la que se lee la señal. Como veis, Shannon está muy bien teóricamente, pero es insuficiente.

   Nuestra FPGA ICE40 trabaja a 12MHz.  Entiendo que se puede muestrear bastante bien para realizar una gran infinidad de cosas. 

NOTA: esta es la razón por la que muchos sistemas de control con Arduino funcionan mal. No hay ningún problema con el código, simplemente no puede trabajar todo lo rápido que necesita. Por cierto, la librería PID de arduino utiliza una transformada bilinear. http://brettbeauregard.com/blog/?s=PID

Por lo tanto, José, la relación es esta: los requisitos en el tiempo de muestreo para estar seguros de que estamos capturando la señal deseada y no otra muy parecida. La elección es sensible, porque en caso de muestrear demasiado rápido, capturaremos ruido que no nos interesa. A veces, se incluye un filtrado digital de la señal para eliminar ese ruido ahorrándonos un filtro analógico. Ahí entra en juego la Z. Pero, si no se implementa filtro, que muchas veces no es necesario, la señal se puede volver a generar con un D/A directamente con los valores leídos del A/D.

Nota adicional: siempre se suele muestrear en periodos constantes de tiempo. Hay dos razones principales: por un lado, de otra forma tendríamos que guardar no sólo el dato, sino también el tiempo que ha pasado desde la última captura. Por otro lado, que el el periodo sea constante facilita el análisis matemático y la demostración de teoremas basados en series de datos.

   Muestrearíamos a 12MHz o frecuencias inferiores, pero claro está constante  ( T - periodo del reloj  elegido como muestreo) 
 
A lo largo de todo el mensaje he considerado que se utilizan Zero-Order-Hold. Es decir, que los datos se leen directamente del A/D y, si hay que generarlos, el D/A mantiene un valor constante entre una actualización y la siguiente. Sin embargo, en ocasiones, especialmente en sistemas donde no se puede capturar/generar lo suficientemente rápido, se pueden utilizar First-Order-Hold: https://en.wikipedia.org/wiki/First-order_hold  o soluciones más elaboradas. El objetivo es "inventarse" con cierta sensatez la forma que tiene la señal muestreada/reconstruida entre cada pareja de muestras. Una vez más, estos retenedores se pueden diseñar en el dominio del tiempo, de Laplace o de la transformada Z.

  Entiendo que hay una gran cantidad comercial de DACs y ADCs que tienen su sample and hold implementados y solo necesitaremos comunicarnos con ellos  ( del proceso de Sample and hold ya se encargarán ellos )

Espero que te haya servido para refrescar un poco la memoria,

    Todo un placer.  Muchas Gracias

Jose Pico

unread,
Mar 24, 2017, 6:35:05 PM3/24/17
to FPGAwars: explorando el lado libre


El viernes, 24 de marzo de 2017, 10:43:31 (UTC+1), Juanma Rico escribió:

¡La madre que te parió Unai! ¡Voy muy contento a leer tu proyecto... y está en vasco! jajajajajajajajaja
Me tendré que guiar por los dibujitos... ;)

En Industriales este tema se daba en una asignatura cuatrimestral solo para ella, era el complemento de otra anual (Control Automático)... Control Digital, creo recordar que se llamaba, si alguien está interesado y quiere mis apuntes se los escaneo y mando.

Creo recordar que había una forma de controlar directamente los sistemas digitales que se hacía con un número limitado de muestras (en un par de ellas los sistemas de uno o varios polos en su función de transferencia se controlaban, ¿deathbeat se llamaba?), con esto quiero decir que no hacía falta "digitalizar" un PID (que es eminentemente analógico, Proporcional-Integral-Derivativo), hay sistemas de control directamente digitales, pero se usa el PID porque los ingenieros industriales están acostumbrados a ellos y los operadores tienen un algoritmo de sintonización más que estudiado para usarlo en cualquier sistema a controlar y por otros motivos que ahora no recuerdo... :)

Que nadie se caliente... aunque el controlador ¿deathbeat? permite controlar sistemas en un par de muestras, hay que conocer perfectamente la función de transferencia del sistema y no se ha hablado nada de la potencia necesaria para usarlo porque, aunque los sistemas de digitales de control cuenten con esa potencia para emitir la señal de control necesaria, lo normal es que los sistemas que vas a controlar (eminentemente analógicos) saturen y no admitan esa señal de control... en fin, un rollo.

Usábamos como libro de cabecera los dos del Ogata, yo tengo ambos comprados en papel, pero imagino que lo podéis encontrar por la web o en alguna biblioteca universitaria cercana.

  Tengo un par de libros de Ogata que compré con buenas intenciones pero se quedaron prácticamente sin abrir por no tener motivación suficiente. Quizás ahora recupere esa motivación... Quién sabe! jejejjejej
 
Eso sí, como dice Unai, de las matemáticas no te libra nadie.

Lo dicho, quien tenga interés en ver cómo se explican estas cosas en la ETSII de la Universidad de Málaga (que imagino que no es la mejor... o sí, no sé) que avise y yo le paso mis apuntes de ambas asignaturas. :)

Gracias por tu oferta, pero normalmente no he entendido ni mis propios apuntes así que los de los otros ( podrías ser la excepción jejejejj ) lo veo complicado.
De todas formas si los llegaras a escanear siempre serán de agradecer.

Saludos

Jose Pico

unread,
Mar 24, 2017, 6:54:52 PM3/24/17
to FPGAwars: explorando el lado libre
Hola a todos:


El viernes, 24 de marzo de 2017, 12:12:06 (UTC+1), 1138-4EB escribió:
¡La madre que te parió Unai! ¡Voy muy contento a leer tu proyecto... y está en vasco! jajajajajajajajaja

Desde la guardería y hasta el master hice todos mis estudios en euskera XD. Bueno, lo que me permitieron (no todas las asignaturas están disponibles en la uni), y a excepción de un año que estuve en Ferrol. Desde entonces, en inglés. Poco contenido académico he producido en lengua cervantina.
 
Me tendré que guiar por los dibujitos... ;)

Eso te iba a decir, que las mates y los circuitos digitales son un lenguaje universal :D
 
En Industriales este tema se daba en una asignatura cuatrimestral solo para ella, era el complemento de otra anual (Control Automático)... Control Digital, creo recordar que se llamaba, si alguien está interesado y quiere mis apuntes se los escaneo y mando.

Yo la curśe como anual en Galicia y, diría que también en Bilbo. Pero en ninguna de ellas se veía la transformada Z, sólo Laplace. La Z la veían quienes cursaban alguna asignatura específica para hacer sistemas de control con PICs. Yo me la "empollé" para el PFC.
 
Creo recordar que había una forma de controlar directamente los sistemas digitales que se hacía con un número limitado de muestras (en un par de ellas los sistemas de uno o varios polos en su función de transferencia se controlaban, ¿deathbeat se llamaba?), con esto quiero decir que no hacía falta "digitalizar" un PID (que es eminentemente analógico, Proporcional-Integral-Derivativo), hay sistemas de control directamente digitales, pero se usa el PID porque los ingenieros industriales están acostumbrados a ellos y los operadores tienen un algoritmo de sintonización más que estudiado para usarlo en cualquier sistema a controlar y por otros motivos que ahora no recuerdo... :)

Efectivamente, el PID hoy día es una patata. Hay algoritmos más eficientes, que producen un mejor control y además son más fáciles de ajustar a un problema concreta. Que se disponga de un modelo exacto de la planta o no es secundario (hay algoritmos para ambos casos). El número de muestras utilizado también depende del algoritmo y de cuánta "memoria" quieres que tenga. Lo de los polos o el lugar de las raíces es genérico para cualquier controlador. Hay múltiples circuitos que pueden dar como resultado una misma regla de control, y por tanto tener el mismo número de ceros/polos.

Como dices, se sigue usando por "es lo que hemos usado toda la vida y funciona bien". Aunque "funciona bien" depende, como dices de "un agoritmo de sintonización más que estudiado". Sólo que ese "más que estudiado" es "más que probado". Todas las tablas para ajuste automático de PIDs son experimentales. Revisadas y mejoradas durantes años, sí. Pero exprimentales al fin y al cabo.
 
De hecho, el enfoque de mi PFC viene de ahí: proveer a un operario un chip equivalente al controlador que ya utiliza, y en el que puede introducir los mismos parámetros de configuración.

¿Cuál es el problema principal de los PID, al margen de todo lo anterior? Son para sistemas Single-Input-Single-Output. En cuanto tienes un motor y quieres controlar dos variables, por ejemplo la velocidad y el par, las cosas se empiezan a complicar porque necesitas dos PID. Si quieres velocidad, posición y par, es más interesante. Hasta que directamente las cosas funcionan de churro, o con experimentaciones eternas para ajustarlo todo a base de prueba y error.

    En una de mis etapas de estudio estuve dando cosas llamadas  "LOGICA DIFUSA" ,redes neuronales donde se daban cosas como de autoaprendizaje... usé redes Neuronales de Matlab así como una herramienta fantástica llamada  XFUZZY ( universidad de Sevilla ) donde se pueden generar circuitos de lógica difusa y te llega a convertir a VHDL. Se implementó una práctica para realizar el aparcamiento de un coche de forma automática....
Lo bueno de la lógica difiusa a diferencia de los PIDs típicos es que no son Single Input Single Output, se pueden implementar complejos sistemas.
Como siempre lo estudié de una forma tan teórica que hoy por hoy no se nada de aquello que dí y fue una pena no realizar todo aquello que se explicaba o daba en un FPGA real, quizás la  oportunidad que me habéis brindado en FPGA Wars me permita  a mí a muchos más llegar a desarrollar aquellos interesantes temas....

Podría buscar apuntes ( pdfs de aquello que dí y colgarlos en Drive o algún sitio por si alguien con inquietudes quiere  ir adaptándolo a  FPGAs )

Algunos enlaces de Xfuzzy  ( Quizás máquinas como vosotros le saquéis fruto )




Ostras! Yo también mando deberes!  ejjejejejejejeje

Jose Pico

unread,
Mar 24, 2017, 7:11:52 PM3/24/17
to FPGAwars: explorando el lado libre


El viernes, 24 de marzo de 2017, 14:34:29 (UTC+1), Juanma Rico escribió:

Unai, lo que se aprende contigo y lo rápido que bajas la prepotencia (y a veces la moral... jajajajajajaja) :D

Que nadie se asuste que para programar una FPGA (y ahora menos con icestudio) y hacer experimentos de control con ella, no se necesita saber de control automático, ni función de transferencia, ni transformada Z, ni nada de eso... ¡Unai es que sabe de todo! jajajajajaja
Y claro, ya uno se aprovecha para que le envíe referencias aunque sean en euskera, que siempre viene bien aprender cosas... :-P

José Pico, como te veo interesado y a mi también me gusta el tema, si quieres elegimos una "digitalización" del PID (alguna ya hecha de Arduino puede valer), montamos un proyecto con github y trabajamos sobre ello en la FPGA, no tanto por lo bueno del control del PID, sino por la parte didáctica que pueda tener.

  Hola Juanma!  es todo un alago que me propongas una colaboración, la verdad es que me encanta tu oferta y por tanto solo puedo que aceptarla.
 Lo único que es que soy un verdadero novato en el aspecto práctico ( he dado mucha teoría de la que gran parte la tengo olvidada y tengo pinceladas de muchas cosas pero con mucha carencia práctica ) y no sé hasta que punto podré aportar algo viendo el nivel que aquí se maneja  a parte de que tampoco dispongo de mucho tiempo ( de hecho nada más que leer vuestros correos me absorve  una gran parte del poco tiempo que tengo después de terminar mi jornada laboral, asuntos familiares y otros )
 Pero como tampoco se pierde nada y lo único que puede pasar es que aprenda ( que al fina y al cabo es lo que quiero, pero aprender de verdad no como mis años de carreras que  me han dejado siempre insatisfecho )

Lo más sencillo es trabajar sobre el control de un motor de corriente contínua (velocidad, par, posición... ), pero elige el sistema dinámico que tú quieras para poner a prueba el control PID (ten encuenta que no solo necesitamos el ADC, sino también el DAC para actuar sobre el motor y un tacómetro para realimentar el bucle de control).

Cuando lo tengamos probado sería muy interesante dejarlo como un bloque en icestudio para poder acoplarlo a motores de corriente continua y usarlo así en otros tipos de robots que no usen servos (los motores de juguete DC no cuestan más de un euro y pueden ser interesantes).

 Dicho así, parece que ya está hecho. Jejjejejej
 

Con el proyecto github montado se puede trabajar sin asustar a nadie y así dejamos el grupo para comentarios y preguntas... ¡Que contestará Unai, claro! jajajajajaja :)

Unai siempre está ahí, es como Dios que nunca te abandona.  Jejejej  Gracias a gente como vosotros se anima uno .... 

Así que si te animas a repasar los apuntes de la transformada Z, yo encantado, busco los mios y hacemos el bloque PID entre los dos y todo aquel que se quiera apuntar... :)

  Perfecto! pero como te he dicho no prometo grandes cosas de inicio ( estoy aprendiendo aún verilog, repasando temas varios, proyectos propios a parte, trabajo y familia ) Puff espero no extresarme demasiado
   

Yo ando con el sistema Cold/Warm Boot de nuestra placa, un proyecto de simulación del antiguo microcontrolador 4004 de Intel (que he tenido que aparacar por el tema de las puertas triestado), el SimpleZ y alguno que otro más... es decir, que ando falto de tiempo en el tema de FPGAS, pero también quería probar el ADC que trae la iceZUM Alhambra  y creo que este puede ser un proyecto útil con el que probarla, así que con tu ayuda abriremos otro frente más... Esperemos que con tantos frentes abiertos no perdamos la guerra... :-)

Tú me dices si te apetece.

  Si me apetece!
  Bueno. 
  Déjame madurar un poco el tema y te propongo algunas pequeñas cosas que puedo ir haciendo o creo que puedo ir haciendo, supongo que en muchas ocasiones tendré paradas técnicas de muchas improductividad pero espero poco a poco avanzar.

Jose Pico

unread,
Mar 24, 2017, 7:19:11 PM3/24/17
to FPGAwars: explorando el lado libre
 Hola:

 tenemos también un PWM en los ejemplos de Icestudio de Jesús.

No lo he probado pero en cuanto pueda lo pruebo.


El viernes, 24 de marzo de 2017, 14:48:42 (UTC+1), 1138-4EB escribió:
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.

Jose Pico

unread,
Mar 24, 2017, 7:36:45 PM3/24/17
to FPGAwars: explorando el lado libre


El viernes, 24 de marzo de 2017, 14:56:04 (UTC+1), Juanma Rico escribió:

Imposible Unai, creo que ni a propósito nos podemos salir de un "cacharreo clásico" que tú no sepas... jejejejejeje

Unai, muy rápido, sé que andas corto de tiempo y tienes entrega... pero me interesa el tema de los ventiladores, es verdad que tienen un hall que puede servir de tacómetro, tengo muchos ventiladores para cacharrear...

¿Crees que los ventiladores de las CPU's podrían tener potencia para mover un pequeño robot educativo? Por lo que veo el par que tienen es bajísimo y se paran sin más que rozarlo con los dedos... pero si se les puede aumentar el par sin quemarlos sería genial. ¿Se podría aumentar el par de giro o directamente ni lo intento?

  Bueno!, yo creo que el bobinado está calculado para una corriente determinada y no se debe forzar, pero es cierto que estos motores giran a altas velocidades por lo cual puedes cambiar velocidad por par, implementado cajas reductoras ( aquí aparece la mecánica pura y dura ), si añades al eje del motor un peqeño piñón y a este se le añade una caja de engranajes se puede conseguir un aumento de par considerable a costa de disminuir la velocidad pero para implementar movimientos de no gran velocidad son muy interesantes

Jose Pico

unread,
Mar 24, 2017, 8:44:27 PM3/24/17
to FPGAwars: explorando el lado libre


El viernes, 24 de marzo de 2017, 17:48:16 (UTC+1), Juanma Rico escribió:

Buenasssss....

El viernes, 24 de marzo de 2017, 15:21:38 (UTC+1), 1138-4EB escribió:
Mira, ahí me has pillado totalmente fuera de lugar XD.

 
jajajajajajaj, ¡no puede ser! ¡eso no me lo creo! :)
 
He trabajado bastante con motorcillos, pero las máquinas eléctricas se me resisten. Igual tengo conocimientos teóricos un poco más avanzados que tú, por haber hecho la especialidad de electrónica, pero lo justo. Aún así, me cuesta mucho "verlos" en la práctica.

A mi me sacas de la "jaula de ardilla" y me pierdo... tanta libertad... jejejejejeje :)


En principio puedes incrementar el par dándole más corriente. Pero claro, si el motor ya está funcionando a su velocidad nominal, al incrementar la corriente estás haciéndolo sufrir. Lo que se me ocurre es que las escobillas den más chispazos y se desgasten antes. O que los propios cables que están en un chasis de plástico no lo lleven bien. O que pete el sensor de efecto Hall. También puede no pasar nada.

Ese era mi miedo y la confirmación que te pedía... siempre podemos hacer una buena reductora mecánica... ;)
 

Mi referencia son los Brushless (BLDC): un motor DC pero quitándole las escobillas y haciendo la conmutación de forma electrónica. Son muy parecidos a las máquinas síncronas y también a los motores paso a paso. En realidad son nombres diferentes para referirse a lo mismo en diferentes escalas y con diferentes estrategias de control. En estos casos, si quieres incrementar la corriente hay que hacerlo de forma cuidadosa ya que incrementarla hace que se queden "pegados" a una posición. Por lo tanto, hay que coordinar bien el incremento de corriente con la secuencia de cambio, por el riesgo de que se salte un paso y empiece a girar en sentido contrario. Asimismo, como en un paso a paso, incrementarla cuando está fijo en una posición hace que tenga muchísima más capacidad de retención, pero a costa de un "cortocircuito" magnético por así decirlo.

Ahora que lo pienso... ¿No son los motores de la CPU también brushless? Por lo menos yo he desmontado unos cuantos y no encuentro las escobillas... pero vamos... que siempre que trato con motores también me pierdo... nunca sé donde acaba la electrónica y empieza la parte mecánica para llamarlos de una forma o de otra... o es quizás el controlador el que le da nombre... y cada fabricante con sus submodelos... conocimientos teóricos muchos (suficientes), pero luego cuando llego a la fábrica no sé diferenciar un motor síncrono del extintor.... (menos mal que nadie se da cuenta)  jejejeje
 

Un DC no tiene estos problemas que comento, pero los efectos electromagnéticos y las corrientes por dentro son iguales.

Por lo tanto, por el precio que te cuesta un motor DC de un coche teledirigido (en cualquier tienda de hobbys y maquetas), no merece la pena. La sugerencia del ventilador es porque es lo más rápido para probar sólo el PID y centraros en el diseño dentro de la FPGA. A partir de ahí, lo suyo es coger un motor DC un poquillo más grande y hacer un encoder con una cartulina pintada a rayas y un fototransistor.

Sí, recuerdo que Demócrito en este hilo hizo un control básico por comparación con icestudio (no os perdáis el vídeo porque es alucinante).
Si pudiéramos crear un bloque con el PID e integrarlo en icestudio sería genial, para distintos motores solo se necesitaría repetir el bloque... incluso una colección con bloques de controles automáticos para poder aplicar la teoría de control moderna.... soñar no cuesta nada. :)

<inciso>
Por cierto, ahora que me acuerdo, lanzo la pregunta desde aquí por si Obijuan me lee... Juan, creo haber leido que las ondas senoidales que usabas para tus robots modulares las generabas con una especie de tabla interna en la FPGA... Imagino que ya se te habrá ocurrido, pero te pregunto para que me digas realmente las dificultades o por qué no lo pudiste hacer... ¿Pensaste en algún momento en generar la onda senoidal en un circuito exterior y utilizar el ADC de la placa para alimentar internamente el movimiento del servo?
Imagino que generar una señal seno, cambiar su frecuencia, amplitud y demás, en un pequeño circuito externo es más fácil que sintetizarlo en la FPGA... ¿no?
</inciso>

Fin del inciso, perdona, Unai, es que me acabo de acordar y llevaba un tiempo por preguntarlo y siempre se me olvidaba... si Juan no me lee ya busco el hilo y pregunto en el propio hilo. (Espero no olvidarme).

  Hola:
  Como comentas, una forma de generar un seno en una FPGA, sería tener en una memoria los valores muestreados de un periodo de la onda y esta repetirla. Las muestras se
  podrían haber calculado en Matlab por ejemplo ( a una frecuencia de muestreo inferior o igual a 12Mhz) y pasarlos a un fichero. 
  Una vez tenidas las muestras para un periodo  e introducidas en una memoria, se pueden extraer  y atacar a un módulo PWM donde el PWM cambia en función del valor digital. Esta señal PWM = función ( valor digital ) --> se extrae a un pin FPGA donde se añade un DAC  tipo PWM. Donde a su salida tendríamos la señal seno almacenada en la FPGA. 
 De esta forma se me ocurre que podemos implementar un generador de funciones ( claro está con sus limitaciones de velocidad de muestreo )

 un ejemplo de DAC PWM sería  ( entiendo que hay DAC PWM comerciales de mejor calidad que el esquema adjuntado ).

Igualmente nos valdría para atacar un motor DC y variar su velocidad ( Siempre teniendo en cuenta la potencia que puede entregar el LM358 o añadir alguna etapa  de potencia con algún transistor)  ---> en verdad con el PWM y un Transistor como bien dice Unai se podría controlar la velocidad del motor DC por PWM ya que el propio bobinado del motor haría de integrador.  En el esquema del cirucito  R-C hacen de integrador y el operacional está en modo seguidor.
 

 
Después, cambiarlo por un taco y usar un ADC. Después volver a la tienda de maquetas, y coger un motor de coche teledirigido, pero brushless. O, mejor aún, pedir en aliexpress un motor brushless + controlador por 8-10€. El controlador es como un puente H, pero compuesto por seis transistores. Un proyecto bonito es montarlo en una protoboard.... A mayores, la realimentación de los BLDC se puede hacer con tres sensores de efecto hall, o sin sensores, sólo midiendo la tensión en cada fase en el orden adecuado. Lo cual es una aplicación muy útil para el ADC de la Alhambra. Por las velocidades a las que se tiene que ejecutar es muy probable que el Arduino no sea capaz, pero la iCE40 sí.

Apunto esa idea. :)
 

¡Por cierto! Los motores brushless + controlador de aliexpress los venden para drones. Sí, con cuatro instancias del PID y cuatro de esos podéis controlar un dron con la Alhambra. Nota: añadiendo una CPU (Arduino) que haga la orquestación de los cuatro motores, leyendo algún acelerómetro/giroscopio.

¡Otra idea más al saco! :)


Todos estos temas los tienes trilladísimos en foros de aficionados a vehículos RC. Muchos controladores incluyen un AVR, como Arduino, y hay varios usuarios que han diseñado firmwares específicos para coches, camiones, aviones, helicópteros...

Investigaremos.
 

Sí, también tengo hecho un generador de secuencia de control para motores BLDC en VHDL. Pero, paso a paso. Esa referencia no los la doy todavía, que os explota la cabeza :P. Pedidla cuando queráis.

Gracias, mi cabeza te lo agradece... :P

Pues listo, gracias Unai... José Pico... ¿Qué? ¿nos animamos a mover primero un ventilador con el PID digital y luego.... ¡el mundo! ? jejejejeje :)

   OK. Vamos a ver que se puede hacer.

    Se me ocurre por ir poco a poco y con mis conocimientos:
   
     1. Primero probar el módulo PWM de jesús.  Se puede cargar en Icestudio y visualizar la señal por u osciloscopio
     2. Crear un módulo donde el PWM varie con valores digitales pasados al PWM
     3  Pasar a este módulo PWM una serie de valores digitales que van desde 000000... a 1111111  y ver que el PWM en el osciloscopio es el correcto
     4  llevar esa señal PWM a un motor DC con un Mosfet de forma que veamos que podemos dar o bajar la velocidad del  motor
     5  Una vez conseguido esto.... Pausa-café-aplauso JJEJJEJEJEJ
     6  Si el motor tiene un hall donde entiendo que cada vuelta extrae un pulso, dicho pulso se debe introducir  por un pin de la FPGA y en esta implementar un contador
         de las vueltas que da, de aquí viendo las vueltas que da por ciclo de reloj sabremos a que velocidad está girando
      7 Llegados a este punto ya tenemos  una planta donde estamos midiendo la velocidad, entiendo que si queremos implementar un PID para controlar el motor a una velocidad
         X, necesitaremos tener una variable o constante con la que marcar la velocidad de giro deseada.
      8 Con la realimentación  de la señal de velocidad y la deseada, implementando un sumador , se calculará la señal de error acometida  y esta se debe aplicar
         al controlador PID especifico donde ahora mismo me pierdo
      9 Supongo que sería algo como coger la función de transferencia de un PID   H(s), pasarlo a H(z) y convertirlo a sumatorio de señales anterirores... 
         aquí estoy perdido
     10 podríamos primero partir de algo más básico; estando en el punto 8, podemos empezar por implementar un controlador proporcional 
         de forma que si la señal de error es positiva se debe  aumentar por un facto Kp la señal PWM y si es negativa se debe disminuir por un factor Kp la señal PWM que ataca         al motor.
        LLegados aquí supongo que nos habremos encontrado con alguna que otra trama y habremos adquirido algo de experiencia para continuar por ejemplo añadiendo un control   derivativo o integral y luego  así teniendo un PID completo.
       En una primera fase calcularemos el Kp más adecuado de forma un tanto experimental ( no sé si hay alguna forma más exacta de calcular el Kp )
     
      Bueno!, esto es un poco lo que se me ocurre.
      El que quiera y tenga ganas que aporte
      
      Creas tú el Github para el proyecto ?
      Yo creé el otro día por primera vez uno mío para ir introduciendo todos los ejemplos que voy realizando en Icestudio ( los compartí también en Github de Icestudio Ejemplos)        Aún no estoy demasiado experimentado en estos temas. También los estoy aprendiendo ahora.



       Por cierto yo todo lo estoy haciendo con IceStick  ( No tengo la Alhambra )
 
     Saludos 
IMG_8099.JPG

Jose Pico

unread,
Mar 24, 2017, 8:47:50 PM3/24/17
to FPGAwars: explorando el lado libre
IMG_8099.JPG

Jose Pico

unread,
Mar 24, 2017, 8:50:27 PM3/24/17
to FPGAwars: explorando el lado libre
IMG_8108.JPG

Juanma Rico

unread,
Mar 25, 2017, 7:50:28 AM3/25/17
to FPGAwars: explorando el lado libre
 
Perfecto José,

¡Pues eah! ¡Otro frente abierto! :-)

Ya está creado el proyecto en mi cuenta de github (https://github.com/juanmard/FPGA-control-PID).
Lo único que he hecho es editar el README.md como declaración de intenciones y hoja de ruta.
Como hoja de ruta he copiado casi literalmente los últimos puntos que pusiste, si a lo largo del proyecto se ve que se deben modificar se modifican.
Por lo demás es un lienzo en blanco, así que acepto TODOS los pull-request que hagáis, aunque sea nada más que crear la estructura de directorios del proyecto. :)

Yo ya ando buscando apuntes y motores en el laboratorio para controlar... :)
¡Estamos en marcha! Estáis todos invitados al proyecto... fundamentalmente se trata de utilizar las posibilidades de las FPGA en el control automático de sistemas en tiempo real (donde los microcontroladores están muy limitados)... Así que... ¡Síganme los buenos! :-)

Saludos.


Democrito

unread,
Mar 25, 2017, 2:04:29 PM3/25/17
to FPGAwars: explorando el lado libre
Os dejo con el mejor enlace que he encontrado sobre este tema y realizado en verilog (lleva LCD y todo). De esa misma web tomé el encoder x4 que puse en otro hilo.


Recomiendo mirar primero el pdf y luego todo lo demás.

Saludos!

Jose Pico

unread,
Mar 25, 2017, 4:10:03 PM3/25/17
to fpga-wars-explora...@googlegroups.com
 Muchas Gracias.
  Esa información tiene buena pinta.


--


Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.


Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.


Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.


Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.

Cristóbal Contreras Rubio

unread,
Mar 25, 2017, 4:12:28 PM3/25/17
to fpga-wars-explora...@googlegroups.com
Este hilo vale su peso en oro, pero joder... ES SUPER DENSO!!!

El 25 de marzo de 2017, 21:09, Jose Pico <josp...@gmail.com> escribió:
 Muchas Gracias.
  Esa información tiene buena pinta.

El El sáb, 25 mar 2017 a las 19:04, Democrito <spo...@gmail.com> escribió:
Os dejo con el mejor enlace que he encontrado sobre este tema y realizado en verilog (lleva LCD y todo). De esa misma web tomé el encoder x4 que puse en otro hilo.


Recomiendo mirar primero el pdf y luego todo lo demás.

Saludos!








--


Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.


Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.


Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.


Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.

Juanma Rico

unread,
Mar 25, 2017, 4:49:32 PM3/25/17
to FPGAwars: explorando el lado libre

José, con esta información de Democrito ya no tenemos excusa...
¡Esto hay que hacerlo como sea! :)

Una pena no disponer de la placa un fin de semana más... :(

Si haces algún avance con la ICEStick (por pequeño que sea) avisa en el hilo, así no duplicamos esfuerzos y nos animamos los unos a los otros. :)

Saludos.

Jose Pico

unread,
Mar 25, 2017, 8:00:53 PM3/25/17
to FPGAwars: explorando el lado libre
Hola Juanma!

Voy a empezar por lo más sencillo,
el PWM, probarlo en un osciloscopio y en un motor que tengo.

La información enviada ciertamente es muy completa....
Saludos y paciencia

1138-4EB

unread,
Mar 25, 2017, 11:00:53 PM3/25/17
to FPGAwars: explorando el lado libre
Dudo mucho que no te gusten las matemáticas, el problema es que no nos las han explicado bien y nos han motivado lo suficiente con la práctica REAL y PALPABLE, pero  ahor tenemos FPGAs y podemos enmendarlo.  JJejjejeje

¡Las mates me gustan! No he dicho lo contrario. Lo que no me motiva es el cálculo. Prefiero álgebra. De hecho, me dedico a implementar algoritmos de álgebra matricial en FPGAs: https://addi.ehu.es/bitstream/10810/13397/2/bildosola14_cnotice.pdf

El algoritmo CORDIC que se utiliza ahí seguro que os resulta interesante. Es bastante "retro".
 
Nuestra FPGA ICE40 trabaja a 12MHz.  Entiendo que se puede muestrear bastante bien para realizar una gran infinidad de cosas.

De hecho 12MHz es una burrada. No puede salir nada bueno de trabajar tan excesivamente rapido XD. Ten en cuenta que un motor con Arduino se controla con un periodo de muestreo de no más menos de 5ms. Eso son 200Hz. Es verdad es algunos motores piden 1ms (1KHz). Y poniéndonos muy exquisitos queriendo controlar un levitador magnético casero, sería como mucho 500KHz. Es decir, que los 12MHz hay que reducirlos, al menos, veinte veces.

La lógica internamente sí es deseable que sea a 12MHz para que las respuestas del controlador sean "instantáneas" y se puedan considerar que el control es causal. Pero el periodo de muestreo y actuación está condicionado por las interfaces y tiene un impacto importante en el consumo. Por ejemplo, en un transistor las pérdidas son proporcionales a la frecuencia de conmutación, por lo que será deseable cambiar la salida lo menos posible. Por otro lado, si se usa un encoder o ADC, la frecuencia máxima está limitada por éstos.
  
  Entiendo que hay una gran cantidad comercial de DACs y ADCs que tienen su sample and hold implementados y solo necesitaremos comunicarnos con ellos  ( del proceso de Sample and hold ya se encargarán ellos )

Aunque se use el mismo término, hay una pequeña diferencia entre los "hold" a los que yo me refería y los de los ADCs. En los ADCs el objetivo es "estabilizar" la señal (analógica) que se quiere muestrear. Un Zero-Order-Hold, First-Order-Hold, o lo que sea, es un módulo digital que se sitúa después del ADC y es para (opcionalmente) generar diferentes valores entre capturas sucesivas del ADC. Es decir, se obtiene una señal con forma de escalera del ADC, y lo que se envía al PID para calcular el error no tiene foma de escalera.

Evidentemente, esto tiene sentido sólo si el ADC es muy lento. Sobre todo cuando se ejecuta el algoritmo de control en un PC, por todo lo que tardan las señales en llegar de la planta al procesador y del procesador a la planta.

Os recomiendo este articulo "Speed Analysis of a Digital Controller in Time Critical Applications": http://yadda.icm.edu.pl/baztech/element/bwmeta1.element.baztech-article-BUJ6-0023-0149 Básicamente habla sobre las velocidades relativas de una planta y el controlador. Clasifica los sistemas en soft real-time y hard real-time. La clasificación es lo de menos. Lo importante es que con FPGAs el objetivo es actuar siempre como en la Figura 2a, de forma que podamos sustituir un sistema analógico. De hecho, una ventaja de las FPGAs es que el tiempo de ejecución es determinisa: sabemos exactamente cuánto va a tardar el procesamiento.

    En una de mis etapas de estudio estuve dando cosas llamadas  "LOGICA DIFUSA" ,redes neuronales donde se daban cosas como de autoaprendizaje... usé redes Neuronales de Matlab así como una herramienta fantástica llamada  XFUZZY ( universidad de Sevilla ) donde se pueden generar circuitos de lógica difusa y te llega a convertir a VHDL. Se implementó una práctica para realizar el aparcamiento de un coche de forma automática....
Lo bueno de la lógica difiusa a diferencia de los PIDs típicos es que no son Single Input Single Output, se pueden implementar complejos sistemas.
Como siempre lo estudié de una forma tan teórica que hoy por hoy no se nada de aquello que dí y fue una pena no realizar todo aquello que se explicaba o daba en un FPGA real, quizás la  oportunidad que me habéis brindado en FPGA Wars me permita  a mí a muchos más llegar a desarrollar aquellos interesantes temas....

Podría buscar apuntes ( pdfs de aquello que dí y colgarlos en Drive o algún sitio por si alguien con inquietudes quiere  ir adaptándolo a  FPGAs )

Algunos enlaces de Xfuzzy  ( Quizás máquinas como vosotros le saquéis fruto )




Ostras! Yo también mando deberes!  ejjejejejejejeje

Actualmente las aplicaciones en las que estoy trabajando son redes neuronales, que en la fase de inferencia son básicamene productos matriciales con algún filtro no lineal intermedio (típicamente una sigmoide logística). Aunque ahora con las GPGPUs y las Deep Networks están de moda las ReLu.

Con técnicas fuzzy no he llegado a trabajar por edad. Para cuando acabé la carrera ya había pasado la etapa del fuzzy. En mi grupo el trabajo ha ido derivando hacia las Extreme Learning Machines: http://www.ntu.edu.sg/home/egbhuang/ Aunque tenga un nombre tan rimbombante, en realidad no es más que la unificación de múltiples soluciones conocidas desde los 90. Básicamente la idea es que las redes neuronales son muy pesadas de entrenar computacionalmente. Por lo que dejan la mitad de los parámetos al azar, de forma que el entrenamiento se reduce a un sistema lineal de ecuaciones, que se resuelve por mínimos cuadrados. El drawback es que suelen salir tamaños de redes bastante más grandes que con otros entrenamientos más precisos. Pero es que... mira qué tontería es el algoritmo resultante para una Single hidden Layer Feedforward Network (SLFN) expresado de forma matricial:

H=B*I;
T
=sig(H);
G
=svd(T)*O;

Donde B es la matriz de pesos de la red de entrada: todo aleatorio. I son el conjunto de vectores de entrada, y T las muestras de la función objetivo (las salidas deseadas). I y T conforman el conjunto de entrenamiento. "sig" es la sigmoide logística (sigmf en matlab). Y "svd" es una función matemática, Singular Value Decomposition, que está disponible en matlab y octave. El paper del que soy coautor (enlazado arriba) es justamente sobre contribuciones algoritmicas al SVD para resolverlo en FPGAs.

Una vez hecho lo anterior, en la FPGA sólo hay que guardar B y G. Cada vez que llega un nuevo vector de datos, la salida se calcula así:

S = G*sig(B*I);

Es decir, dos productos matriz-vector y una transformación no lineal intermedia aplicada a un solo vector.

--------

De todas formas, aunque puede hacerse, es complicado que una red neuronal aprenda una regla de control que incluya las limitaciones de la planta. Por eso, es muy interesante la metodología Model Predictive Controller. Es un tipo de controlador avanzado Multiple-Input-Multiple-Output con contrains, que reduce el problema a una optimización. Una forma de visualizarlo es que, para cada instante de muestro, se "simulan" todas las posibilidades de actuación para los próximos n segundos y se escoge la más adecuada teniendo en cuenta, además de las limitaciones de la planta, criterios de eficiencia. El rendimiento de este tipo de controladores depende mucho del modelo interno que estén utilizando para simular el comportamiento de la planta. Así, es una práctica habitual utilizar una red neuronal como modelo de la planta, y opcionalmente reentrenarla en tiempo de ejecución para que vaya adaptándose a las dinámicas probablemente variables de la misma.

De todas formas, esto último no es mi campo. Supongo que sobre estas técnicas de control MIMO Juan sabrá algo más, ya que son habituales en robótica.


podrían haber calculado en Matlab por ejemplo ( a una frecuencia de muestreo inferior o igual a 12Mhz) y pasarlos a un fichero.

Como pequeñísimo inciso: a veces se genera un número de puntos bastante limitado (digamos 128 o 256) para reducir el consumo de memoria, y luego se hace una interpolación lineal entre ellos. Depende de cuántos pasos tenga la interpolación, los escalones serán más o menos notables.


 9 Supongo que sería algo como coger la función de transferencia de un PID   H(s), pasarlo a H(z) y convertirlo a sumatorio de señales anterirores...
     aquí estoy perdido

 

Tened cuidado con la Figura 12, ya que hay dos divisiones que en hardware simplemente no son realizables. Lo habitual si se usa la forma paralela es incluir la división o multiplicación de Ts en el cálculo de los parámetros Kd y Ki, respectivamente. Ver la imagen anterior.

Por otro lado, parece no haber ningún tipo de control de overflow. Utilizan tamaños de palabra significativamente grandes, por lo que puede tener cierta fiabilidad (aunque sea sub-óptimo). Pero no se gestiona explícitamente.

Por lo demás... ¡ya lo tenéis casi todo hecho!


Una pena no disponer de la placa un fin de semana más... :(

¡Siempre te olvidas de tu amiga la simulación! ¿Sabes generar una secuencia de pulsos? ¡Pues ya tienes el simulador de un motor! Aunque no vayas a querer sintetizarlo, puedes hacer un módulo en verilog que calcule una función de transferencia de primer o segundo orden. Sólo tienes que usar esa salida como la entrada que indique al generador de pulsos con qué frecuencia generarlos, y ya tienes tu simulador de motor con sensor de efecto hall. Echa un vistazo a esos apuntes, o al Ogata para ver cómo se expresa una función de transferencia de segundo orden en el dominio de la transformada Z.
Auto Generated Inline Image 1

1138-4EB

unread,
Mar 25, 2017, 11:10:25 PM3/25/17
to FPGAwars: explorando el lado libre
[ Se me han jodido las tildes :(  ]

Pista para Juanma: la pagina que escaneo y adjunto Jose en el primer mensaje de este hilo, es la transformada Z de un sistema de segundo orden. Sólo tienes que identificar que valor corresponde al coeficiente de amortiguamiento, la ganancia, etc.

Jose Pico

unread,
Mar 28, 2017, 5:41:12 PM3/28/17
to FPGAwars: explorando el lado libre
Hola Juanma!

Ha desaparecido tu github del mapa.
hice un fork e iba a subir una primera versión de pwm pero ha desaparecido.
Esta primera versión he generado un pwm con un periodo de unos 200hz que se va modulando como una rampa más o menos, la he medido en el osciloscopio y ok.
Tengo que  modificar un poco las frecuencias pq he cogido un pwm chino que compré y trabaja a 15kHz ( por lo que he leído 5KHz-15Khz es buena opción para el tema de ruidos...) 

Saludos

Juanma Rico

unread,
Mar 28, 2017, 6:18:10 PM3/28/17
to FPGAwars: explorando el lado libre

Lo siento José,... le cambié el nombre por aquello de no solo incluir el PID en el proyecto, sino otros bloques de control.
No sé como miré, pero pensé que nadie había hecho un fork.

El proyecto con el nuevo nombre está aquí: https://github.com/juanmard/fpga-control

Disculpas otra vez, ganas tengo de ver qué has hecho... :)

Jose Pico

unread,
Mar 28, 2017, 7:27:40 PM3/28/17
to FPGAwars: explorando el lado libre
forkeado !

He añadido dos módulos pwm con dos ejemplos usando ambos módulos.
Pero principalmente el segundo ejemplo genera un PWM de 11.72 Khz en principio bastante adecuado para un motor DC.
Lo he medido en mi osciloscopio y funciona muy bien jejejejjeje
Mañana te pasaré el video del osciloscopio ( me he quedado sin batería en el móvil )
Me falta añadir la etapa de potencia y ya le  puedo enchufar el motor.

He elegido 11.72 Khz porque con 10 bits y a 12 MHz era lo que podía sacar.
He medido un PWM que tengo chino y este trabajana a 15KHz, pero por lo que he leído entre 5Khz y 15KHz no debe ir la cosa muy mal.
Esto es un poco en función del motor.
Podría crear al módulo con 9bits 8 bits 7bits consiguendo frecuencias de PWM algo más rápidas y que así en función del motor se pueda añadir un PWM  más rápido o más lento.
Bueno! poco a poco.

Saludos

Jose Pico

unread,
Mar 28, 2017, 7:48:05 PM3/28/17
to fpga-wars-explora...@googlegroups.com

--


Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.


Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.


Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.


Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.

Jose Pico

unread,
Mar 28, 2017, 7:53:47 PM3/28/17
to fpga-wars-explora...@googlegroups.com
IMG_8162.MOV

Juanma Rico

unread,
Mar 29, 2017, 12:56:07 PM3/29/17
to FPGAwars: explorando el lado libre
¡¡¡Perfecto José!!!

¡Primer hito conseguido! plas, plas, plas :-)
Ya están admitidas tus modificaciones en el proyecto. ;-)

Muchas gracias... ¡a seguir así!

Saludos.

El miércoles, 29 de marzo de 2017, 1:53:47 (UTC+2), Jose Pico escribió:

Jose Pico

unread,
Mar 29, 2017, 6:15:17 PM3/29/17
to FPGAwars: explorando el lado libre
Hola Juanma:

he probado el pwm con un driver L298 que compré de los chinos.
He añadido otro pwm de 9 bits y he probado ambos en dos ejemplos.
Para usar el L298 en el ejemplo he añadido dos salidas para poder configurar el sentido del giro.
te adjuto pequeño video del test.

saludos
PWM DC Motor 11.72KHz.MOV

Jesús Arroyo

unread,
Mar 30, 2017, 10:05:48 AM3/30/17
to FPGAwars: explorando el lado libre
Qué grande Jose!

Esos vídeos son épicos! :)

Jose Pico

unread,
Mar 30, 2017, 10:17:43 AM3/30/17
to fpga-wars-explora...@googlegroups.com
  Jejjeje!

   Un granito de arena a esa fantástica tool Icestudio. 
Eso si que es épico!
   Mola ver como las cosas en Icestudio se hacen de forma fácil, rápida y además parece que funcionan.
Jejejjej


--


Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.


Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.


Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.


Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.


Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.


Juanma Rico

unread,
Apr 2, 2017, 2:09:36 PM4/2/17
to FPGAwars: explorando el lado libre

¡¡Chulísimo José!!

Ando un poco desconectado del grupo, los finales de mes me consumen mucho tiempo este año... pero tienes todo mi apoyo moral... :)
No olvides incluir en github el ejemplo, una foto del controlador y por supuesto el vídeo.
Esto es un nuevo hito del proyecto, así que no olvides hacer un commit, que quede documentado todo... ;-)

En cuanto tenga tiempo quiero ponerme con tus ejemplos y replicarlos, a ver si puedo aprender de ellos... :)

¡¡Saludos y muchas gracias por seguir en la brecha!!



El jueves, 30 de marzo de 2017, 0:15:17 (UTC+2), Jose Pico escribió:

Jose Pico

unread,
Apr 3, 2017, 3:53:55 AM4/3/17
to fpga-wars-explora...@googlegroups.com
Tranquilo!
Hacemos lo q podemos.
Sin presión...

Saludos

--


Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.


Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.


Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.


Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.


Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.


Democrito

unread,
Apr 5, 2017, 5:53:59 AM4/5/17
to FPGAwars: explorando el lado libre
Os dejo con un lector de cuadratura x4 de 32 bits, que tomé de la página que mencioné en el anterior post, lo único que hecho es meter el código Verilog en una cajita de Icestudio. Todo el código está dentro de un zip del este enlace.


Para hacer pruebas de funcionamiento le añadí un registro de desplazamiento de 32 bits (tanto como la resolución del contador reversible del lector del encoder) y lo leo a través de un Arduino de forma serie.

He adjuntado todo lo necesario para quien quiera probarlo, pero de todas formas pongo aquí los "códigos" para echar un vistazo rápido.

Dentro de la cajita del lector de cuadratura. Sigue las reglas del diseño sincrono:

reg [31:0] q=0;                                 // Registro contador de 32 bits de salidas.
reg [2:0] cuadA_retardada=0, cuadB_retardada=0; // Tres 3 bits * 2 flips-flops tipo D.

// Registro de desplazamiento de 3 bits. 
always @(posedge clk) cuadA_retardada <= {cuadA_retardada[1:0], cuadA}; // 3 FFD.
always @(posedge clk) cuadB_retardada <= {cuadB_retardada[1:0], cuadB}; // 3 FFD.

// Lógica con puertas XOR.
wire habilitador_conteo =   (cuadA_retardada[1] ^ cuadA_retardada[2] 
            ^ cuadB_retardada[1] ^ cuadB_retardada[2]);      
wire direccion_conteo   = cuadA_retardada[1] ^ cuadB_retardada[2];

// Decodificación del encoder y puesta a cero del contador.
always @(posedge clk)
begin
    if (rst) q<=0;          // Poner a cero contador si se pone a 1 la patilla 'rst'.
    if(habilitador_conteo)  // Señal enable del contador.
    begin
        if(direccion_conteo)// Si esta señal es 1...
            q<=q+1;         // incrementar el contador.
        else                // En caso contrario (cuando es 0)...
            q<=q-1;         // decrementar el contador.
    end
end
(pulsando Control + e, permite introducir códigos en los post)

Y ahora el contenido de la cajita del registro de desplazamiento, que pese a que todo funciona correctamente, tengo mis dudas de que siga las reglas de sincronización; es un intento de "estar por casa". Sobre esta parte se agradecería críticas o poder ver un ejemplo de cómo sería hacerlo correctamente siguiendo esas reglas.

reg [31:0] shifter;

always @(posedge cp)
    if (ld)
        shifter <= d;
    else
        shifter <= {1'b0, shifter[31:1]};
    
assign qs = shifter[0];


Como el registro de desplazamiento hace una carga paralela de los datos del contador, se usa la señal 'clk' con doble función:

La primera es cargar el registro de desplazamiento cuando 'LD=1' (LD=load) y flanco de subida del 'CLK', y cuando 'LD=0' entonces suceden los desplazamientos por cada flanco de subida del 'CLK'.

Y para terminar, el programa Arduino que hace la lectura del registro de desplazamiento y lo representa en pantalla a través de un puerto de comunicaciones serie (ya sabéis, control +M).

#define NOP __asm__ __volatile__ ("nop\n\t") // "No OPeration", para permitir un ciclo de reloj sin hacer nada; se utilizará como "nano-pausa" (un ciclo de reloj).

// Patillaje.
const byte din = 5;  // Número de pin de la entrada de datos series provenientes de la FPGA. (Registro de desplazamiento con la información de los pulsos del encoder óptico. 32 bits)
const byte clk = 6;  // Número de pin de la señal de pulso para el registro de desplazamiento en la FPGA. (idem)
const byte ld  = 7;  // Número de pin de la señal para cargar el contador de pulsos al registro de desplazamiento en la FPGA. (idem)

// Variable general.
int  cnt = 0;                        // Contador general para el bucle For-Next.

// Acumulador de pulsos.
long pulsos = 0;                     // Contador de pulsos.
long aux    = (2^32)-1;              // Variables auxiliar para comparar si hay cambios. Cargamos al valor máximo para que imprima el valor desde el comienzo y no salga la pantalla vacía.

void setup()
{  
  Serial.begin(115200);              // Configuración del puerto serie virtual.
  
  pinMode(din, INPUT);               // din  como entrada. Estos son los tres pines para la lectura del registro de desplazamiento en la FPGA. (pin 5)
  pinMode(clk, OUTPUT);              // clk  como salida. (pin 6)
  pinMode(ld,  OUTPUT);              // ld   como salida. (pin 7)
  digitalWrite(clk, LOW);            // Esas dos salidas se incian con cero.
  digitalWrite(ld,  LOW);
}

void loop()
{
    digitalWrite(ld,  HIGH);          // Habilita la carga el contador de pulsos en el registro de desplazamiento en la FPGA.
    digitalWrite(clk, HIGH);          // Se necesita poner a 1 la patilla "ld" (Load) y después un flanco de subida en clk (clock) para hacer la carga.
    digitalWrite(ld,  LOW);           // Hecho esto, ambas patillas vuelven a cero.
    digitalWrite(clk, LOW);
    
    pulsos=0;                         // Ponemos a cero la variable pulsos; luego en el bucle "for" se irán poniendo a 1 los bits correspondientes.
    for (cnt = 0; cnt < 32; cnt++)    // Lectura del registro de desplazamiento.
    {
      if (digitalRead(din) == 1) { bitSet(pulsos, cnt); }  // Inicialmente todos los bits de la variable "pulsos" están a cero. Aquí va poniendo a 1 los bits correspondientes.
      
      digitalWrite(clk, HIGH);        // Flanco de subida de clk para pasar al siguiente bit del registro de desplazamiento de la FPGA.
      NOP;                            // Un pequeño delay porque no se debe (en teoría) poner una instrucción seguida de otra en la que cambia el estado el mismo pin; en este caso es clk.
      digitalWrite(clk, LOW);         // Se pone a cero la señal clk para completar el pulso.
    }

    if (aux != pulsos)                // Si se produce algún cambio de contaje se muestra por el puerto serie.
    {
      Serial.println(pulsos);         
      aux = pulsos;                   // Igualamos para luego ver si hay cambios.
    }                                 
}


Lector_cuadratura_x4.ice
Lector_de_encoder_32bits.ino

Jose Pico

unread,
Apr 5, 2017, 6:08:49 AM4/5/17
to fpga-wars-explora...@googlegroups.com
Gracias!

Ya andaba yo Intentando probar ese circuito que pasaste! Jejjej
Me he liado intentando hacer también un medidor de pulso. De forma que con un único sensor que cuente las reboluciones también se puede estimar su velocidad midiendo el ancho del pulso que genera al dar la vuelta.
A mayor velocidad, menor pulso y viceversa.
Lo probaré!
Saludos 

--


Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.


Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.


Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.


Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.


Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.


Jose Pico

unread,
Apr 5, 2017, 6:40:06 AM4/5/17
to FPGAwars: explorando el lado libre
Hola!
Lo has probado con un encoder real?
yo tengo un motor con el encoder HDES 9140 que a parte de las señales A y B en cuadratura tiene la posibilidad de mostrar otra señal I  de inicio cada vez que da una vuelta (home). yo he probado simplemente contar vueltas metiendo la señal I ( alimentado a 3,3 lo hago directamente sobre una entrada de la FPGA ) y no he empleado resistencias de pull up ( parece que me lo hace bien), de todas forma pienso que siempre para proteger nuestra FPGA sería recomendable pasar por algún optocoplador de forma que nos aisle de los periféricos.
Adjunto Data Sheet del HDES 9140.

Por otra parte estoy interesado en añadir una UART tanto Rx ( he visto en otro hilo que las has realizado ) y TX para poder comunicarme con cualquier periférico externo
, sea Arduino, un PC .... y poder presentar valores internos de la FPGA. Quería adaptar los ejemplos de Obijuan a  Icestudio pero no he tenido tiempo de intentarlo siquiera.

Saludos y Gracias a todos
HDES 9140 Encoder.pdf

1138-4EB

unread,
Apr 5, 2017, 8:10:50 AM4/5/17
to FPGAwars: explorando el lado libre
Hola Democrito, ¿con qué frecuencia de reloj estás trabajando? ¿Ese clk son 12MHz?


El miércoles, 5 de abril de 2017, 11:53:59 (UTC+2), Democrito escribió:

Democrito

unread,
Apr 5, 2017, 10:38:52 AM4/5/17
to FPGAwars: explorando el lado libre
Hola Unai,

así es, el reloj es de 12 MHz.

Saludos!

Democrito

unread,
Apr 5, 2017, 10:52:51 AM4/5/17
to FPGAwars: explorando el lado libre

Hola de nuevo José,

El encoder utilizado es este (sin index) el típico que va acoplado a un motor de poca potencia.


Como el Arduino que manejo (Arduino Nano) es de 5V y la FPGA funciona a 3,3v, pongo el típico circuito que adapta las tensiones bidireccionalmente, como este:

3.3V 5V TTL 8 Channel Bi-directional Logic Level Converter Module

Saludos!

Democrito

unread,
Apr 5, 2017, 11:29:02 AM4/5/17
to FPGAwars: explorando el lado libre
Dejo un pequeño esquema general con las conexiones por si en el futuro alguien busca algo parecido, ahorrando la deducción de las conexiones.


El encoder es de 334 pulsos por revolución, pero como el lector de cuadratura multiplica por 4, queda como uno de 1336 pulsos por revolución.

Al parecer las FPGA que normalmente manejamos (Alhambra/Icestick) tienen histéresis en las entradas, por tanto no se necesita acondicionar las señales del encoder.

Jose Pico

unread,
Apr 5, 2017, 11:31:37 AM4/5/17
to fpga-wars-explora...@googlegroups.com
Ok Gracias

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.

Victor Morales Mora

unread,
May 12, 2017, 7:24:54 AM5/12/17
to FPGAwars: explorando el lado libre
Buenas, soy nuevo en esto y me interesa mucho implementar un PID en la FPGA. He realizado este codigo:

//-----------------------------------------------------------------------------
// PID.v
//-----------------------------------------------------------------------------
//- MakersUPV - 2017
//- Written by Victor Morales (VicMorMor)
//-----------------------------------------------------------------------------
//-- Componente PID
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//--  Modulo PID
//-----------------------------------------------------------------------------
module PID(input clk_in, output [7:0] uk, input [7:0] ek);

wire clk_in;
wire clk_out;


parameter q0 = 1;
parameter q1 = 1;
parameter q2 = 1;
parameter N = 1;

reg [7:0] uk = 0;
reg [7:0] ek1 = 0;
reg [7:0] ek2 = 0;
reg [7:0] uk1 = 0;

prescaler #(.N(N))
  Pres0(
   .clk_in(clk_in),
   .clk_out(clk_out)
  );


  always @(posedge(clk_out)) begin
 
  ek1  <= ek;
  ek2 <= ek1;
  uk1  <= uk;
  uk <= uk1 + ek2*q2 + ek*q0 + ek1*q1;   
 
  end


endmodule


No se hasta que punto tendrá errores, un profesor mio de automática lo ha visto por encima y dice que esta bien.

Entiendo que es solo la implementacion de las ecuaciones en diferencias, pero queria saber opinión de gente más experta.

Un saludo.



El viernes, 24 de marzo de 2017, 0:34:57 (UTC+1), Jose Pico escribió:
Hola:

Estoy intentando informarme un poco sobre un tema que me parece más que interesante.


La idea es:

   Como un circuito analógico se puede expresar como   H(s)   función de transferencia  expresada usando la transformada de Laplace  y esta a su vez se puede convertir a  H(z) su transformada z y a su vez esto se puede
   expresar como en sumas y diferencias, funciones del tipo  y(k) = -a1 y(k-1) -a2 y(k-2) + b1 u(k-1) + b2 u(k-2)

   Si una señal de entrada la muestreamos con un convertidor A/D y los datos digitales los introducimos a nuestro FPGA donde mediante la combinación de sumas de valores anteriores de entradas y salidas,
   podemos pues, obtener el resulado   de salida de un circuito ante una señal de entrada, que serán un conjunto de muestras digitales que si a su vez la extraemos de la FPGA a un convertidor D/A , podemos crear digitalmente el   funcionamiento    de   cualquier circuito analógico.

Bueno! esto dicho así parece muy fácil pero entiendo que tiene su miga.
Pero estas cosas me surgen al releer algún apunte de cuando era estudiante y me quedé frustado con una gran cantidad de formulaciones que nos daban sin sentido y que nunca llegabamos a comprender porque nunca se hacía nada práctico.
Ahora, con esto de las FPGAs libres estoy intentando  reordenar todas aquellas ideas que al final muchas de ellas seguro que con dos conceptos básicos y claros se pueden hacer maravillas.

Aquí os dejo un poco una hoja recuperada de unos apuntes de los cuales me he inspirado para iniciar este nuevo tema ( Por cierto, me acuerdo poco  o casi nada de estos temas matemáticos jejejej )


Si alguien sabe algo más del tema y conoce de ejemplo prácticos,etc


Saludos y Gracias




Democrito

unread,
May 12, 2017, 7:50:44 AM5/12/17
to FPGAwars: explorando el lado libre
Hola Víctor.

Hasta bien entrado en verano no creo que me pueda poner con este tema, a mí también me interesa mucho, al menos el probarlo y saber qué puedo conseguirlo.

Aunque en principio no es difícil, y esto lo digo porque con un Arduino y algo de experiencia se hace de forma relativamente sencilla, pese a todo esto, realizar uno bien hecho tiene sus complejidades.

Si no lo has leído, te recomiendo esta lectura porque es muy completa y está en castellano:

Verás que hay mucho por hacer. También es recomendable comenzar con un microcontrolador, empaparse bien sobre su funcionamiento y luego intentar extrapolarlo a una FPGA.

Saludos y suerte.

Unai Martinez

unread,
May 12, 2017, 9:02:45 AM5/12/17
to FPGA-WARS: explorando el lado libre
Buenas Víctor,

Como ha comentado tu profesor, está "bien". Es una aproximación al problema muy interesante, porque has descrito un PID como un FIR. Desde el punto de vista de la automática, esto permite "ver" que un PID no es más que un filtro más, como podría ser un Bessel, Chebyshev, etc. En otras palabras, en lugar de utilizar esta estructura:

https://i.stack.imgur.com/5pfIa.png

has utilizado esta:

https://es.wikipedia.org/wiki/FIR_(Finite_Impulse_Response)

Por lo tanto, la primera duda que me planteo: ¿sabes qué equivalencia hay entre los parámetros [P, I, D, Ts] y [q0, q1, q2]?

En segundo lugar, ¿sabes qué discretización estás utilizando para la derivación y/o integración? Al plantearlo así, has optado implícitamente por Euler, Backwards, o Tustin/Bilinear. ¿Cuál(es)?

Nótese que las preguntas anteriores son teóricas, y las expongo sólo por si quieres profundizar en la comprensión de la relación entre tu circuito y los múltiples modelos teóricos. En la práctica, ya va a funcionar "bien".

¿Por qué pongo todo el rato "bien" entre comillas? Porque no has tenido en cuenta que estás realizando aritmética en coma fija. Por un lado, todas tus señales son de 8 bits. Por otro, estás sumando cuatro de ellas "al mismo tiempo". La miga está aquí:


uk <= uk1 + ek2*q2 + ek*q0 + ek1*q1;

Tu mayor riesgo es el 'overflow', léase que el resultado de una suma o multiplicación no se pueda representar con el tamaño de palabra utilizado. Por ejemplo, si uk=64, ek2*q2=64, ek1*q1=64 y ek*q0=64, tendremos que uk=256. Como 256 no es representable en 8 bits, uk=0. Así, habrá un error aritmético, ya que la salida del controlador tendrá su valor mínimo, cuando debería tener el máximo.

Para solucionarlo, tienes dos posibilidades:
  • La fea: utilizar tamaños de palabra suficientemente grandes para garantizar que (con los datos recibidos) no habrá overflow. Además de ser una solución "pobre", como verás a continuación, no va a solucionar todos los problemas en este caso.
  • La elegante: aprovechar que los lenguajes HDL y las FPGAs nos permiten definir el tamaño de palabra de cada señal a medida, para implementar lo que se denomina arítmetica en coma fija variable, o formato de coma fija de tamaño variable.

Así, debes tener en cuenta estas dos condiciones para garantizar que no habrá overflow:

  • Al sumar dos números binarios, el resultado debe tener al menos un bit más que la señal con tamaño de palabra mayor de entre las entradas.
  • Al multiplicar dos númerios binarios, el resultado debe tener al menos tantos bits como la suma de los tamaños de palabra de las entradas.
En otras palabras, para sumar dos números de 8 bits necesitamos un registro de 9. Y para multiplicarlos, un registro de 16. Por lo tanto, podemos redefinir los tamaños de palabra de tu diseño:

Mantenemos 8 bits para la entrada 'ek', y utilizamos también 8 bits para los parámetros q0, q1 y q2. Por ello, ek1 y ek2 mantienen su tamaño y los resultados de las multiplicaciones deben tener 16 bits:

wire [15:0] ekq0;
wire [15:0] ekq1;
wire [15:0] ekq2;

reg [7:0] ek1 = 0;
reg [7:0] ek2 = 0;

Como no sabemos cómo se suman cuatro elementos al mismo tiempo, vamos a asumir que sólo podemos utilizar sumadores de dos elementos.

s0 <= ekq0;
s1 <= s0 + ekq1;
s2 <= s1 + ekq2;
uk <= s2 + uk1;

Así, los tamaños deberán ser:

wire [15:0] s0;
wire [16:0] s1;
wire [17:0] s2;
wire [18:0] uk;
reg [18:0] uk1 = 0;

Aún, habrá riesgo de overflow en las señales uk y uk1, porque conforman un acumulador. Más concretamente el que cumple las funciones de integrador (de la parte I del PID). Éste corre el riesgo de sufrir el efecto denominado windup: https://en.wikipedia.org/wiki/Integral_windup

La forma más sencilla de solucionarlo es añadir una saturación (esto es pseudocógido, no verilog):

ukraw <= s2 + uk1;
uk <= sign * ( abs(ukraw)>2^18-1 ? max : ukraw );

No obstante, sobre este aspecto en concreto tienes información en el enlace que ha puesto Democrito. Si quieres profundizar en ello después, hay otras soluciones complementarias para mitigar el efecto.

Ya está casi todo hecho. Pero todavía tenemos una incoherencia: la salida uk de tu diseño es de 8 bits, y la señal de la nueva propuesta de 18. Simplemente debemos truncar la señal, es decir, tomar los ocho bits más significativos. En la práctica, podemos querer coger ocho bits en medio de la palabra, no necesariamente los más significativos. En ese caso, deberemos añadir un saturador adicional. Puedes echar un vistazo a un mensaje anterior mío en este hilo, donde adjunto una figura con colores. Apreciarás ambos bloques de saturación.

Por último, debes tener en cuenta que tanto tu sumador de cuatro elementos como mi propuesta con 'wires' limitarán la frecuencia máxima de operación. Lo óptimo sería 'segmentar' las operaciones. A partir de mi propuesta, en principio lo único que deberías tener que hacer es sustituir los wire por registros y posiblemente añadir alguno auxiliar. Además, tendrás que revisar cómo afecta eso a la latencia del circuito.

Como bonus, entendido todo lo anterior, verás que no hay motivo para que q0, q1 y q2 tengan el mismo tamaño de palabra, por lo que puedes jugar con ello en función de la precisión que necesites para definir cada uno.

Ten en cuenta que he utilizado número enteros positivos en los ejemplos, pero funciona exactamente igual con complemento a 2 y con decimales.

Espero que te sirva para profundizar y no dudes en plantear las dudas concretas que te puedan surgir.

Un saludo


--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Victor Morales Mora

unread,
May 12, 2017, 12:04:56 PM5/12/17
to FPGAwars: explorando el lado libre
Buenas,

A nivel teorico no tengo problema, conozco las equivalencias entre los parametros y los metodos de discretización, no pretendía por ahora desarrollar el regulador como tal, solo queria saber que problemas podian surgir a la hora de la implementación en una FPGA.
Muchas gracias por todo revisaré y lo replantearé.

Democrito

unread,
May 29, 2018, 8:35:17 PM5/29/18
to FPGAwars: explorando el lado libre
Hola 1138-4EB,

Sólo sé moverme con Icestudio y el único Verilog que manejo es el de dentro de las cajitas, mis conocimientos de Verilog es bastante pobre (observando cómo hacen las cosas los demás, tutoriales y Google). Lo único que estoy haciendo es traducir un programa PID (para Arduino) a Icestudio.

Saludos.

Democrito

unread,
May 29, 2018, 8:40:43 PM5/29/18
to FPGAwars: explorando el lado libre
Sólo usaré sumas, restas y desplazamientos. Todo con números enteros. Es un intento... ya veremos qué sale...

Democrito

unread,
Jun 18, 2018, 4:46:37 PM6/18/18
to FPGAwars: explorando el lado libre
Sin más preámbulo dejo un vídeo. Al final de éste enfoco los 8 leds de la Alhambra y es importante observar que los dos del medio significa que está en la posición, y el resto de leds, tanto de la derecha como de la izquierda es el PWM en un sentido del motor. Si comento lo de los leds es para observar que no se queda un poco más acá o más allá, sino que siempre llega a la posición. 


Es un motor de impresora a 12,57v (lo medí) con un encoder de 334 pulsos por revolución, aunque el lector de encoder es x4. Matt hizo un encoder que me queda pendiente probar, parece mucho más simplificado.

Adjunto el ICE, pero es sólo un esbozo. Hay que corregir muchas cosas, como por ejemplo he de "secuenciar" los cálculos, porque los hace todos a la vez y eso es una inconsistencia (en un PID convencional esto no puede ser así), pese a que aparentemente parece que funcione bien. Para mí la cuestión es que funciones mejor o igual que con el proyecto que hice con Arduino, y me queda mucho por aprender.

He puesto una carga de medio kilo para arrastrar (sin engranajes, motor directo, tal cual como en el vídeo), con Arduino lo hacía perfecto, y tal como lo tengo diseñado en FPGA no pasa la prueba, existe oscilación en ese caso, no es que oscile todo el rato, pero pasa un tiempo hasta posicionarse.

Me apasiona este tema, así que cualquier cosa que vea o consiga en plan interesante, os daré la lata!

Un saludo.
pseudoPID.ice

Juanma Rico

unread,
Jun 18, 2018, 4:58:53 PM6/18/18
to fpga-wars-explora...@googlegroups.com
Puedes dar la lata todo lo que quieras...
¡Me encanta! 😜

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.

Jose Pico

unread,
Jun 18, 2018, 6:18:52 PM6/18/18
to FPGAwars: explorando el lado libre
Gracias.
Habrá que mirarlo con calma.

Acabo de pasar en otro hilo un codificador de cuadratura con un pequeño ejemplo, yo lo quiero usar también para intentar hacer un PID y controlar la velocidad.
Por si te puede valer, está basado en la página fpga4fun. 
Saludos

1138-4EB

unread,
Jun 18, 2018, 6:22:39 PM6/18/18
to FPGAwars: explorando el lado libre

Jose Pico

unread,
Jun 19, 2018, 3:23:19 AM6/19/18
to FPGAwars: explorando el lado libre
Muchas Gracias Unai.
Como siempre, tienes toda la información.

Saludos

Juan Gonzalez Gomez

unread,
Jun 19, 2018, 6:32:27 AM6/19/18
to FPGA-WARS: explorando el lado libre
Una pasada demócrito. Muchas gracias por compartir!  En cuanto pueda le hecho un vistazo más en detalle

Saludos, Obijuan

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.

Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Democrito

unread,
Jun 19, 2018, 7:55:14 AM6/19/18
to FPGAwars: explorando el lado libre
Todavía no está terminado y hay muchas cosas que explicar.

Por ejemplo:

1.) La recepción de datos se hace enviando desde el PC un long (32 bits) y de tal manera que cada byte representa un peso. Esto quiere decir que no se puede enviar directamente una cifra tal y como estamos acostumbrados. Puedo subir un programa de ejemplo, pero preferiría hacerlo cuando todo esté terminado de verdad, pero si alguien quiere el código lo subo.

2.) La entrada "st" (SapleTime, tiempo de muestreo) viene de un detector de pulsos que es una intención de hacer un circuito sincronizado y para explicar esa parte quería poner un circuito muy sencillo para que los que no tenemos mucha experiencia en Verilog y queramos sincronizar en Icestudio, nos sea mucho más sencillo y lógico.

3.) Por experiencia anteriores y siguiendo las recomendaciones de Brett Beauregard, en vez de utilizar el error en la parte diferencial se utiliza la diferencia entre un tiempo el siguiente del Input (el encoder en este caso), de esta forma mejora el comportamiento del sistema.

4.) El código verilog que tengo puesto en la cajita (lo primero que se ve) que es el control PID en sí, tiene muchas incosistencias. La primera de todas es que hace todos los cálculos de un golpe, aquí se necesita una jerarquía de cálculos (secuenciarlo) porque si no lo que está haciendo (y de hecho hace) es calcular del pasado en vez del presente. Otra incosistencia es que hago desplazamientos y como lo muevo hacia a la izquierda (hasta donde yo sé) para multiplicar en base 2 n veces el signo se pierde.

5.) Para el control integral, como necesitaba miniminarlo sin utilizar la división, se me ocurrió (sin saber bien si eso era correcto o no) que se ejecutase cada x ciclos del tiempo de muestreo. Por ejemplo, cada 25 veces se ejecuta una.

6.) En Arduino me dió muy buen resultado hacer esto para el control integral (no sé si ya estará inventado, pero en mi desesperación por eliminar el respingo del control integral, al hacer eso me llevé una grata sorpresa, porque no sólo desaparece el respingo sino que relantiza la llegada) :

[pongo cómo sería originalmente, no lo que hay en verilog]
if ((dInput == 0) || (error == 0))  ITerm <= ITerm + error;   else    ITerm <= ITerm - dInput;

7.) El módulo "ControlMotor" hago una cosa en apariencia muy extraña pero da muy buen resultado. Sólo utilizo la derecha e izquierda del valor de salida que da el control PID. Pero para parar el motor, es decir, decirle que ya está en la posición, utilizo el error proporcional. Esta parte funciona tan bien que cuando llega a la posición el motor se para por completo, no hay consumos residuales.

Si consigo terminarlo y hacerlo bien, explicaré todas las parte con detalle. De momento sólo vale (o eso creo) para encoders con bastante resolución, yo usé uno de 334 (luego es multiplicado por 4).

Gracias a todos por vuestros comentarios y sugencias, siempre las tengo presente!

Un saludo.

Democrito

unread,
Jun 19, 2018, 8:18:44 AM6/19/18
to FPGAwars: explorando el lado libre
Un detalle importante a comentar es que cuando buscamos las constantes KP, KI y KD, yo me preguntaba por qué había que seguir "las reglas del juego" (seguir el modelo tal cual que se plantea matemáticamente). Si de todas formas vamos a intentar ajustar esos parámetros, se podría eliminar cálculos innecesarios. Es cierto que hay modos de hallar esas constantes, pero en la realidad al final suele tener unos ajustes finales.

Así que por ejemplo, en el control diferencial originalmente tenemos esto:

ControlDiferencial = (error-lastErr)/timeChange;

Y luego más adelante se multiplica por la constante diferencial (KD). Pues elimino la parte del tiempo de muestreo y la misma KD ha de ser un número tal que se ajuste a ese propósito. Esto mismo para la parte integral.

En Arduino, el hacer eso y lo que comenté anteriormente de hacer dependiente la parte integral con la diferencial [ if (dInput == 0)...]  da un resultado muy bueno y todo está extremedamente simplificado.

Jose Pico

unread,
Jun 19, 2018, 6:06:01 PM6/19/18
to FPGAwars: explorando el lado libre
Hola:

Estoy pegando un vistazo por encima para intentar comprender un poco el proyecto.

El martes, 19 de junio de 2018, 13:55:14 (UTC+2), Democrito escribió:
Todavía no está terminado y hay muchas cosas que explicar.

Por ejemplo:

1.) La recepción de datos se hace enviando desde el PC un long (32 bits) y de tal manera que cada byte representa un peso. Esto quiere decir que no se puede enviar directamente una cifra tal y como estamos acostumbrados. Puedo subir un programa de ejemplo, pero preferiría hacerlo cuando todo esté terminado de verdad, pero si alguien quiere el código lo subo. Por lo que me parece, envías por puerto serie 4 bytes para indicar al sistema el SetPoint ( punto a donde quieres que se mueva el motor) y por lo que
veo se agrupan en una palabra de 32 bits pero no veo que por ejemplo indiques al sistema que ya tienes agrupados los 32 bits. ¿Esto no podría hacer que tu sistema
pueda coger valores de SetPoints erróneos? Supongo que está a lo mejor controlado por el periodo de muestreo que eliges de 500us. Pero quizás sería conveniente que
el sistema supiera cuando tiene los 32 bits válidos del Setpoint. 
 
2.) La entrada "st" (SapleTime, tiempo de muestreo) viene de un detector de pulsos que es una intención de hacer un circuito sincronizado y para explicar esa parte quería poner un circuito muy sencillo para que los que no tenemos mucha experiencia en Verilog y queramos sincronizar en Icestudio, nos sea mucho más sencillo y lógico.
   Entiendo que configuras ahí el periodo de muestreo con el cual se actualizan todos los datos del PID.
  Porqué eliges 500us?  

3.) Por experiencia anteriores y siguiendo las recomendaciones de Brett Beauregard, en vez de utilizar el error en la parte diferencial se utiliza la diferencia entre un tiempo el siguiente del Input (el encoder en este caso), de esta forma mejora el comportamiento del sistema.

4.) El código verilog que tengo puesto en la cajita (lo primero que se ve) que es el control PID en sí, tiene muchas incosistencias. La primera de todas es que hace todos los cálculos de un golpe, aquí se necesita una jerarquía de cálculos (secuenciarlo) porque si no lo que está haciendo (y de hecho hace) es calcular del pasado en vez del presente. Otra incosistencia es que hago desplazamientos y como lo muevo hacia a la izquierda (hasta donde yo sé) para multiplicar en base 2 n veces el signo se pierde.
   No lo he estudiado a fonfo pero por lo que veo si usas asignaciones del tipo <= estás haciendo que todo se realice de un golpe de reloj y habrá que tener en cuenta con que valores partes con los registros que creas ( por defecto 0 pero no veo que fuerces ninguno de ellos a 0 cuando los creas ), aquí no tendrás asignaciones secuenciales como en programación para eso creo que  deberías asignar usando  = solo sin <. 
Veo también que pones unos limites superiores e inferiores para limitar Ki. 

5.) Para el control integral, como necesitaba miniminarlo sin utilizar la división, se me ocurrió (sin saber bien si eso era correcto o no) que se ejecutase cada x ciclos del tiempo de muestreo. Por ejemplo, cada 25 veces se ejecuta una. Me parece buena idea como concepto de dividir aunque no sé muy bien si es correcto. 
   Cuando dices que necesitabas minimizarlo. ¿A que te refieres?.  Yo entendía un factor integral como un sumatorio de todos los errores que se acumulan a lo largo del tiempo. 

6.) En Arduino me dió muy buen resultado hacer esto para el control integral (no sé si ya estará inventado, pero en mi desesperación por eliminar el respingo del control integral, al hacer eso me llevé una grata sorpresa, porque no sólo desaparece el respingo sino que relantiza la llegada) :

[pongo cómo sería originalmente, no lo que hay en verilog]
if ((dInput == 0) || (error == 0))  ITerm <= ITerm + error;   else    ITerm <= ITerm - dInput;
   Yo esto lo entiendo como que si el error es 0 y además la variación entre la posición actual y anterior es 0 ( osea que no ha habido variación de posición ,entiendo que estaría parado en ese instante de tiempo, o pendiente =0 )  que entonces dejes el acumulado integral conforme está  y si no es así  que al sumatorio /histórico de errores que acumula parte integral le restes/sumes (en función si dInput es+ o -) no el valor del error sino el valor de la derivada ( o diferencia entre valor posición actual- posición anterior ).

Democrito

unread,
Jun 19, 2018, 9:11:48 PM6/19/18
to FPGAwars: explorando el lado libre
Hola José,
Te respondo directamente para evitar exceso de texto:

1.José.) Por lo que me parece, envías por puerto serie 4 bytes para indicar al sistema el SetPoint ( punto a donde quieres que se mueva el motor) y por lo que veo se agrupan en una palabra de 32 bits pero no veo que por ejemplo indiques al sistema que ya tienes agrupados los 32 bits. ¿Esto no podría hacer que tu sistema pueda coger valores de SetPoints erróneos? Supongo que está a lo mejor controlado por el periodo de muestreo que eliges de 500us. Pero quizás sería conveniente que el sistema supiera cuando tiene los 32 bits válidos del Setpoint.

1.Demo.) Tienes toda la razón, debería de haber un pin que validase, sin embargo, en este caso no es estrictamente necesario porque los 32 bits salen de golpe. Sin embargo, para otros casos sería bueno incluirlo.


2.José.) Entiendo que configuras ahí el periodo de muestreo con el cual se actualizan todos los datos del PID. Porqué eliges 500us?

2.Demo.) En Arduino trato de la misma forma el tiempo de muestreo que las constantes PID, en el sentido de que hay un tiempo de muestreo que es óptimo. Por ejemplo (y sigo con Arduino), para motores de mucha resolución (>=334) utilizaba tiempos de muestreo que rondaban entre los 50ms y los 20ms. Y para motores de muy poca resolución (4 pulsos por revolución) utilizaba 1 segundo de tiempo, manteniendo las mismas constantes PID en ambos casos. En la FPGA el tiempo de muestreo es muy rápido y me hubiera gustado que fuese más "lento", sin embargo el valor óptimo para este caso ronda los 500us.


4.José.) No lo he estudiado a fondo pero por lo que veo si usas asignaciones del tipo <= estás haciendo que todo se realice de un golpe de reloj y habrá que tener en cuenta con que valores partes con los registros que creas ( por defecto 0 pero no veo que fuerces ninguno de ellos a 0 cuando los creas ), aquí no tendrás asignaciones secuenciales como en programación para eso creo que deberías asignar usando = solo sin <. 
Veo también que pones unos limites superiores e inferiores para limitar Ki. 

4.Demo.) Según tengo entendido (puedo estar perfectamente equivocado) cuando hay un Always con un posedge (o negedge) ponemos un "<=", porque se refiere a un registro (hace referencia a "secuencia" de un ciclo al siguiente a través de un reloj). En los demás casos, cuando es lógica combinatoria es cuando pongo simplemente "=".
Por otra parte, ciertamente lo hace todo de un golpe y por ello es necesario secuenciar las operaciones.
El control integral ha de estar limitado a la resolución del PWM para evitar el "windup", luego se vuelve a hacer otra vez (acotar la salida) cuando que se suma todos los controles P, I, D.

5.José.) Me parece buena idea como concepto de dividir aunque no sé muy bien si es correcto. Cuando dices que necesitabas minimizarlo. ¿A que te refieres?. Yo entendía un factor integral como un sumatorio de todos los errores que se acumulan a lo largo del tiempo. 

5.Demo.) Literalmente lo que hice fue una chapuza que además no me resolvía mucha cosa (lo digo en pasado, luego te cuento). Las pruebas que hice en Arduino siempre me salía que lo óptimo era una KI muy pequeña, rondando los 0.05. Como es cero coma algo... para saltar los decimales es como dividir por su inverso, y me saqué de la manga que cuanto menos se ejecutase esa parte podría ser equivalente. Y aunque realmente no sea equivalente, lo cierto es que mejoró (sólo lo suficiente) el comportamiento del motor.


6.José.) Yo esto lo entiendo como que si el error es 0 y además la variación entre la posición actual y anterior es 0 ( osea que no ha habido variación de posición ,entiendo que estaría parado en ese instante de tiempo, o pendiente =0 ) que entonces dejes el acumulado integral conforme está y si no es así que al sumatorio /histórico de errores que acumula parte integral le restes/sumes (en función si dInput es+ o -) no el valor del error sino el valor de la derivada ( o diferencia entre valor posición actual- posición anterior ).

6.Demo.) Eso es!

=======================================

Pues esta noche he dado un pasito más y de momento, las pocas pruebas que he hecho, funciona muchísimo mejor y además he eliminado la constante KI. Ten en cuenta que no es un control PID convencional y es probable que sólo sea aplicable a motores con encoder de mediana y alta resolución (todavía no he probado con baja resolución). Si se puede aplicar a otros terrenos el tiempo me lo irá diciendo. Por eso de momento lo llamo "pseudo PID".

Adjunto la nueva versión, sólo cambia el código verilog del control PID. Si consigo sacar tiempo, para este fin de semana pongo nuevo vídeo y un mini-tutorial de todas las partes que lo compone.

Te adjunto el programa (en FreeBasic) para mandar un número cualquiera (la posición), y cómo el programa toma ese número y los separa en 4 bytes equivalentes.

Un saludo!
Enviar32bitsConSigno.bas
pseudoPIDv2.ice

Democrito

unread,
Jun 20, 2018, 3:52:17 AM6/20/18
to FPGAwars: explorando el lado libre
Explicación gráfica a la primera pregunta.



Democrito

unread,
Jun 20, 2018, 4:27:46 AM6/20/18
to FPGAwars: explorando el lado libre
Explicación más detallada a la pregunta 5, cuando hablo del inverso y dividir. Es algo que ya conoces, pero los expliqué tan por encima (era muy tarde para mí) que no me expliqué bien.

Por ejemplo, decimos:

x = error*KI

Pongamos que KI es "cero coma algo", por ejemplo, KI = 0.05
Como quiero evitar los decimales porque todavía no sé hacer ese tipo de cosas en una FPGA hacemos lo siguiente:

El valor de KI le hago su inverso: 1/KI, y ese inverso es 20.
Entonces ahora en vez de multiplicar dividimos por ese inverso, lo cual significa que el resultado es el mismo.

x = error / (el inverso de KI que ahora es 20)

Ambas operaciones tiene el mismo resultado.

La chapucilla está en que utilizaba en la primera versión de "pseudoPID" ese valor inverso como ciclos que no ha de hacer nada (cada 20 ciclos sólo se ejecuta 1), intentando minimizar y emular sin división ni multiplicación el equivalente a esa operación (utilizando el tiempo). Pese a que mejoraba la respuesta del motor, este planteamiento creo que es erróneo.


Jose Pico

unread,
Jun 20, 2018, 4:51:17 PM6/20/18
to FPGAwars: explorando el lado libre

Entendido!
Se podría usar Q2 como señal de validación ( Cuando Q2 =1 el dato está disponible)

Saludos y Gracias

Jose Pico

unread,
Jun 20, 2018, 5:06:56 PM6/20/18
to FPGAwars: explorando el lado libre
La chapucilla está en que utilizaba en la primera versión de "pseudoPID" ese valor inverso como ciclos que no ha de hacer nada (cada 20 ciclos sólo se ejecuta 1), intentando minimizar y emular sin división ni multiplicación el equivalente a esa operación (utilizando el tiempo). Pese a que mejoraba la respuesta del motor, este planteamiento creo que es erróneo. Entiendo que no es lo mismo dejar pasar 20 ciclos sin hacer nada que acumular los diferentes errores que se producen durante esos 20 ciclos. Si no haces nada durante 20 ciclos es como si ignorases esa parte integral durante 20 ciclos ( eso entiendo yo ).

   Se podría hacer ?

   100*x = 100*error*KI      multiplicar por 100 a ambos lados   

   Yo tampoco he trabajado con números decimales  pero en teoria se podría tratar como números en coma fija donde decides cuantos números son parte decimal y cuantos son 
 parte entera. Por ejemplo   16 bits para definir la parte entera y 8 para la parte decimal, creo que la operaciones se hacen igual pero tú debes saber y considerar donde está la
parte entera y la decimal.  No he probado hacer operaciones en la FPGA , intentaré probar algún ejemplo básico para enterarme bien como va.  Ya te cuento si hago alguna prueba.
Saludos
 
 

Jose Pico

unread,
Jun 20, 2018, 5:51:21 PM6/20/18
to FPGAwars: explorando el lado libre

 Puedes revisar este hilo:

  
  De todas formas un Ki=0.05 la verdad es que me parece casi despreciable ( entiendo que poco hará y quizás despreciarlo ).

   
  Saludos

Democrito

unread,
Jun 20, 2018, 6:56:02 PM6/20/18
to FPGAwars: explorando el lado libre
En la práctica, lo que notas con tus propios dedos si coges el eje del motor y trata de moverlo, es que la constante ki lo que hace es dar el último toque para llegar a la posición. Notas que se incrementa si lo frenas o lo desplazas hay una fuerza que se opone, y no es el perenne control proporcional (ahí no puede hacer nada), sino el control integral. Esa es su función.

Democrito

unread,
Jun 20, 2018, 7:10:40 PM6/20/18
to FPGAwars: explorando el lado libre
Comprender lo que hace el control derivativo e integral tiene su cosa. El control derivativo lo que hace es frenar el motor, si la constante es adecuada, lo frena justo a la posición que se desea. Esto es algo visual. Sin embargo el control integral, es algo que lo sientes en tus dedos. Es como si el PID dijese, no me dejas llegar? pues añado más fuerza para conseguirlo, y lo hace de forma incremental en el tiempo. Y esto se complica cuando además en control derivativo "se da cuenta" que al ser frenado y lo sueltas de golpe, ha de ponerse en marcha y frenarlo para llegar a la meta designada (son situaciones que se pueden dar). En fin, es una pequeña maravilla lo que hace un control PID.

Jose Pico

unread,
Jun 21, 2018, 1:41:48 PM6/21/18
to FPGAwars: explorando el lado libre

 Entiendo que el proporcional  si mantienes con un error constante te sigue proporcionando una fuerza ( PWM ) constante que no variaría, sin embargo el derivativo,integral seria:

 derivativo: 
      Si mueves el motor a una posición distinta de la querida y la mantienes ahí,  como digamos que  el error actual y anterior es 0  o casi 0 pq lo mantienes  ahí, la derivada de una pendiente  0 o casi 0 se anulará y no tendrá efecto sobre el PWM.
    El derivativo lo entiendo como que predice (futuro) como va y digamos que hace que acelere o decelere en  función de lo lejos o cerca que esté del objetivo, osea, si estoy muy lejos del objetivo hará que se acelere más y conforme se acerque irá como intentando controlar para no pasarse.

Integral:
      Si mueves el motor a una posición distinta de la querida y la mantienes ahí, como tienes un error constante al mantenerlo en esa posición, la suma de todos los errores ( sumatorio de todos los errores = historial ) se va incrementando y cada vez tendrá más valor por lo que irá haciendo que aumente tu valor de PWM notando si lo sostienes con la mano que cada vez empuja con más fuerza porque se empeña aún más en llegar. Es como que si va pasando el tiempo y no llega va dando más caña.

  Eso es más o menos lo que entiendo ( es probable que me haya equivocado....jejejeje .... pero intento razonarlo.....jejejej)

  Saludos y Gracias

Jose Pico

unread,
Jun 21, 2018, 2:07:22 PM6/21/18
to FPGAwars: explorando el lado libre

  Hola Democrito!

  Me gusta esto del pensamiento PID... jejejje... voy a intentar filosofear otra vez con lo que comentas.

  Entiendo que si has parado con al mano el motor en una posición, mas bien, digamos lejana de su objetivo, el integral se da cuenta e intenta e intenta darle mas fuerza porque
  su histórico de errores acumulados con el tiempo va aumentando y esto hará el PWM aumente para darle más chicha y el derivativo aquí no tendrá efecto practicamente.
 Ahora, si se suelta el motor, como el acumulativo del integral era grande saldrá disparado a toda leche (PWM estaría a tope ) y ahí es donde el derivativo actuará ya que ahora si  habrá una diferencia grande ( una gran pendiente ) entre el error actual y el del momento anterior por lo que el derivativo se pondrá en acción para intentar calcular lo mejor posible su valor y llevarlo a  la posición correcta intentando no pasarse, pero, si el integral acumulado era muy grande lo normal es que de primeras se pase y corrija en sentido contrario  para volver a recuperar lo que se ha pasado ( sobreoscilación ). 
 
 Saludos y Gracias


El jueves, 21 de junio de 2018, 1:10:40 (UTC+2), Democrito escribió

Democrito

unread,
Jun 21, 2018, 2:35:10 PM6/21/18
to FPGAwars: explorando el lado libre
Exactamente, o igual estamos los dos equivocados, jejeje (broma).

El control pie convencional tiene ese problemilla con el control integral, que suele haber siempre un "respingo" porque no le da tiempo a ponerse a cero. Mucha gente lo que hace es poner a cero el control integral cuando llega a la posición. Pese a ello, como el motor tiene una inercia, se sigue pasando un poco, pero mejora otro poco. El pid que propongo no hace eso, se clava en el punto indicado y si existe algo de movimiento es inapreciable. Este finde pondré una demostración.

Un saludo!

Javier Vicén

unread,
Jun 22, 2018, 8:22:24 AM6/22/18
to FPGAwars: explorando el lado libre
Hola a todos:

Yo llevaba mucho tiempo tratando de comprender lo que significa el control PID y este tutorial me ha ayudado mucho: http://roble.uno/control-pid-barra-y-bola-arduino/

Espero que resulte de utilidad y no sea un nivel demasiado básico para vosotros, a mí me aclaró muchas ideas.

Un saludo

Javier Vicén

Jose Pico

unread,
Jun 22, 2018, 8:27:23 AM6/22/18
to fpga-wars-explora...@googlegroups.com
Tiene muy buena pinta!

Muchas Gracias

--
Has recibido este mensaje porque estás suscrito a un tema del grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/fpga-wars-explorando-el-lado-libre/D1TdQdAvjIg/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Message has been deleted
Message has been deleted

Democrito

unread,
Jun 24, 2018, 2:39:32 PM6/24/18
to FPGAwars: explorando el lado libre
Hola!

El vídeo de esta versión: https://www.youtube.com/watch?v=iuU8rFkw0hk
Al final de este post está el ICE y en un zip los módulos (y alguna cosa más) que he utilizado.

Me ahorro las explicaciones que hice en este hilo. El paso siguiente era secuenciar los cálculos porque no estamos programando sino diseñando circuitos. He implementado un "secuenciador" y lo que hace es contar del 1 al 6. En realidad cuenta del 0 hasta 7, pero 0 es reposo (no hacer nada) y 7 es resetear el contador que lleva internamente ese módulo. Cada vez que se produce un flanco de subida del tiempo de muestreo, utiliza 8 ciclos del reloj del sistema (clk) para secuenciar; en cada ciclo/secuencia realiza unas operaciones concretas. Acabados esos ciclos de reloj, no hace absolutamente nada hasta el siguiente flanco ascendente del tiempo de muestreo.

Os comento un poco las secuencias y partes del circuito.

Ciclo 1:

El secuenciador le da un número del 1 al 6 al control PID, si es '1' (primer ciclo) entonces calcula la desviación proporcionar y derivativa, el resto del circuito no hace nada. Como no existe KP, equivale a ser KP = 1. Si alguien quisiera "amplificar" el control proporcional tendría que hacer lo siguiente:

error<=(sp-in)<<<KP;

Ciclo 2:



"Amplifica" (con potencia de 2, desplazamiento a la izquierda) el valor original del control derivativo (dInput). Existe dx1 y dx2, el segundo depende del primero y se calcula después.

Ciclo 3:

Ahora sí que calculamos la segunda "amplificación" del valor derivativo y se guarda en "dx2". Al mismo tiempo se calcula la desviación proporcional (ITerm) con la peculiaridad de que sólo actúa cuando detecta que "dInput" (desviación derivativa) es 0. Esta parte es muy importante porque le dará mucha suavidad en los últimos instantes de llegar a la meta.

Ciclo 4:

El siguiente paso es acotar el valor integral entre 255 y -255, ya que no debe superar el valor absoluto de la resolución del PWM. Técnicamente a esto se le llama "Anti-windup".

Ciclo 5:

Ahora se realiza la suma de todas las desviaciones que hemos calculado anteriormente. Observa que aquí tenemos un valor derivativo "dx2" que es la derivada más amplificada. Esto de usar dos valores derivativos se debe a que me fue imposible minimizar el registro ITerm (todavía no sé dividir con FPGA), entonces se juega con dos amplificaciones, uno poco amplificado en el control integral, y otro muy amplificado en la suma de todas las desviaciones.

Ciclo 6:


Y ya para terminar, hemos de acotar la salida al valor que necesita el PWM, que es de 8 bits, pero también conservamos su signo, por tanto son 9 bits en total. En el caso de superar los valores máximos (en positivo y en negativo) lo fija al valor máximo dado (ya sea positivo o negativo). Si no se supera esos valores entonces guardamos los 8 bits y el signo.

Hasta aquí la parte del control (pseudo) PID. Ahora paso a comentar partes del circuito y lo que hace.

La parte que corresponde al PWM se le ha de eliminar el signo. En el interior de ABS(x) verás que si el valor es positivo lo deja tal cual, pero si es negativo le hace el complemento a 2. Recordemos que si un número es negativo y le hacemos el complemento a 2, lo convertimos a positivo (y si un número es positivo y le hacemos el complemento a 2, lo convertimos a negativo).

La cajita de "ControlMotor", si haces doble clic puede parecer un poco lioso, pero no lo es tanto. Simplemente jerarquiza la información que le llega. Prioriza la señal "igual", y lo hace cuando la señal de "error" que se calculó en la parte proporcional, es 0. Es importante tomar este valor (el de "error"), y no el que calcula la suma de todas las desviaciones porque es el único que consigue parar el motor completamente, sin consumos residuales ni pitidos extraños. Cuando "error" vale 0, ha de priorizar sobre el resto de señales. Lo demás es sencillo, se fija en el signo, si es positivo hace girar el motor en un sentido (con su PWM correspondiente) y si es negativo ha de girar en sentido contrario (con su PWM correspondiente).

Os comento puntos que considero importantes o interesantes.

  • El tiempo de muestreo es igual de importante (al menos en el PID que os muestro) que las constantes KP, KI, KD de un PID convencional
  • Este diseño tiene sus peculiaridades: No tiene KP ni KI, se juega con el tiempo de muestreo y las dos constantes derivativas.
  • Este PID sólo lo he probado en motores con encoder incremental, no lo he probado en otra naturaleza de cosas.
  • La resolución de encoder que he utilizado es de 334 pulsos por revolución. Para encoders de más resolución no creo que haya ningún problema. Para encoders de más baja resolución hay que ajustar el tiempo de muestreo. Por ejemplo, hice pruebas con un encoder de 37 pulsos por revolución y le puse un tiempo de muestreo de 1ms (el original es de 500us). Lo ideal es utilizar encoder de mucha resolución porque cuanta más definición tiene, mejor se comporta.
  • Las dos constantes derivativas "kd1" y "kd2" siempre han de ser números menores de 8, y no sólo eso, si multiplicas ambas cifras, no ha de superar 8. Por ejemplo, estoy utilizando kd1=4 y kd2=2, pues 4x2=8, nunca ha de superar ese 8. Si lo superas tendrás comportamiento errantes o simplemente no funcionará.
  • Para controlar el puente en H me gusta que el PWM vaya a la salida que se activa (la de "mayor que" o "menor que"), esto significa que no utilizo el "enable" que tienen la mayoría de estos puentes. Es que hay otra manera de controlar el motor y es inyectando la señal PWM por ese "enable", pero como decía, prefiero hacerlo de modo más directo. Y es por esta razón por la que en el esquema veréis una salida llamada "enable" siempre a 1.
  • El diseño no está sincronizado y eso es un problema porque a la mínima que se hace algo raro, hace cosas igual de raras.
Aquí me despido y agradezco a todos/as los comentarios y aportaciones que habéis ido haciendo.

Feliz día de San Obijuan! (aquí en el Mediterráneo se celebra por todo lo alto, es como si fuese Año Nuevo pero en verano.)

pseudoPIDv3.ice
Modulos.zip

Juan Gonzalez Gomez

unread,
Jun 24, 2018, 3:00:18 PM6/24/18
to FPGA-WARS: explorando el lado libre
Woala! Cómo mola Demócrito! 😍😍 ¡Muchas gracias por compartirlo! 😃

Saludos, Obijuan

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.

Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

1138-4EB

unread,
Jun 24, 2018, 3:31:52 PM6/24/18
to FPGAwars: explorando el lado libre
Hola Democrito,

> Cada vez que se produce un flanco de subida del tiempo de muestreo, utiliza 8 ciclos del reloj del sistema (clk) para secuenciar; en cada ciclo/secuencia realiza unas operaciones concretas.

Puedes simplificar la lógica de control utilizando un registro de desplazamiento. Generas un pulso en el primero, y éste va avanzando, activando lo enables correspondientes hasta llegar a la salida. Te ahorras el contador y los comparadores.


> Al mismo tiempo se calcula la desviación proporcional (ITerm) con la peculiaridad de que sólo actúa cuando detecta que "dInput" (desviación derivativa) es 0.

Creo que aquí hay una pequeña errata: debería ser "desviación integral" en vez de "proporcional", ¿no?


> El siguiente paso es acotar el valor integral entre 255 y -255, ya que no debe superar el valor absoluto de la resolución del PWM.

Es una limitación sensata. Pero también podrías limitarlo a +-128, ya que al utilizar +-255 permites que el factor integral "se coma" toda la importancia del control.


> a que me fue imposible minimizar el registro ITerm (todavía no sé dividir con FPGA)

A priori "no se puede dividir" en FPGA. Poder se puede, pero no es tan directo como las sumas, restas y multiplicaciones: https://www.eetimes.com/author.asp?section_id=36&doc_id=1321047 Por eso, es recomendable que sigas el planteamiento que expusiste en algún mensaje anterior: precomputar Kd/Ts y Ki*Ts, y quedarte con los resultados como factor de multiplicación.

Un saludo y felicidades, tiene muy buena pinta

Democrito

unread,
Jun 24, 2018, 6:05:06 PM6/24/18
to FPGAwars: explorando el lado libre
Hola Unai, 

Unai: Puedes simplificar la lógica de control utilizando un registro de desplazamiento. Generas un pulso en el primero, y éste va avanzando, activando los enables correspondientes hasta llegar a la salida. Te ahorras el contador y los comparadores.

Demo: Suena interesante y lo tendré presente. Algo así vi cuando me informaba sobre las operaciones como multiplicar y dividir en las calculadoras, al menos antiguamente.

Unai: Creo que aquí hay una pequeña errata: debería ser "desviación integral" en vez de "proporcional", ¿no?

Demo: Ciertamente, es una errata.

Unai: Es una limitación sensata. Pero también podrías limitarlo a +-128, ya que al utilizar +-255 permites que el factor integral "se coma" toda la importancia del control.

Demo: Mira que le he dado vueltas a la cabeza y esa idea tan sencilla no se me había ocurrido. Mañana lo pruebo.

Gracias por las ideas y correcciones!

Democrito

unread,
Jun 25, 2018, 3:51:54 AM6/25/18
to FPGAwars: explorando el lado libre
Otra errata que acabo de encontrar es donde digo:

<<
El secuenciador le da un número del 1 al 6 al control PID, si es '1' (primer ciclo) entonces calcula la desviación proporcionar y derivativa, el resto del circuito no hace nada.
>>

En realidad es: "El secuenciador le da un número del 0 al 6 al control PID". No estoy seguro si en realidad llega hasta 7, sucede que al llegar a 7 se resetea el contador interno. Sea como fuere el circuito PID sólo se pone en marcha en las secuencias del 1 al 6; en 0 (y si llega el caso en 7) no actuaría.

Democrito

unread,
Jun 26, 2018, 6:39:59 AM6/26/18
to FPGAwars: explorando el lado libre
Cuaderno de bitácora de una noche de verano. (Sin Shakespeare.)

Anoche estuve haciendo pruebas de varias cosas, especialmente en una que sabía que no la estaba haciendo bien y sin embargo lo hacía funcionar "por fuerza bruta" (creando dos constantes derivativas e ir probado valores, amén del tiempo de muestreo).

Cuando comencé este proyecto, intenté conservar el signo de la desviación derivativa, pero no hacía mal (por ignorancia), y para no quedarme paralizado en esa parte, decidí seguir hacia adelante sin tener presente el susodicho signo.

Las dos versiones que he subido en este hilo de "pseudoControl PID" funcionan convencionalmente bien, pero si se les hace pruebas más exhautivas, y como tengo como referencia las pruebas que hice con Arduino y que funcionó perfectamente bien, en los diseños para FPGA no cumple esas expectativas. Esas pruebas las hago con un carro de impresora y le coloco peso para conseguir inercias y ver el comportamiento del motor. El objetivo es mover (arrastrado por el carro) 500 gr directamente por el motor. La última versión que subí podía mover sin problemas hasta 175 gr., pero un poco más de eso comenzaba a tener problemas para terminar de posicionarse. En realidad llega, pero está entre dos posiciones y no termina de decidirse, provocando el ruidillo que para mí ya es tan familiar.

Como decía, anoche estuve haciendo pruebas a parte para ver cómo hacer bien eso de conservar el signo cuando se realiza desplazamientos a la derecha (como potencias de 2) y finalmente di con la forma correcta de hacerlo; era mucho más sencillo de lo que parecía, a tal punto que no recuerdo por qué no lo hice bien la primera vez.

Hecho eso lo apliqué al pseudoPID, y tras trastear un poco, ahora ya sólo existe una constante derivativa. Pese a que ahora el funcionamiento es más coherente, el terminar de posicionarse es más ruidoso; y es evidente, hay demasiada "influencia" derivativa para intentar minimizar la "brusquedad" (por no poderlo minimizar matemáticamente) el control integral. O sea, que una cosa trata de contrarestar la otra y como ambas son muy elevadas, el ruido está presente.

Un error que cometí al explicar el funcionamiento y los problemas con la división es que siempre estaba diciendo que había que miniminar el "ITerm" (desviación integral). No es exactamente eso, sino que (tenemos esto) :

ITerm = ITerm + error
               y 
ITerm = ITerm - dInput

Lo que hay que conseguir es que ITerm en ambos casos se incremente más lentamente (no minimizando ITerm) y eso se consigue haciendo que "error" y "dInput" sean valores pequeños, y se conseguiría dividiendo ambas variables por un número dado (ese número dado en realidad es KI). Esta es la parte que hay que resolver para solucionar el problema.

Es por ello que si se acota ITerm (antiwindup, tal como expuse ambos circuitos) a un valor más pequeño de 255 (en positivo y negativo) el resultado no es óptimo, porque se le quita fuerza para terminar de posicionarse, careciendo de fuerza para posicionarse. (Comprobado en una nueva versión no publicada y que no subo por exceso de ruidillos.)

La opción de registro de desplazamiento me es muy atractiva, pero para este caso la veo muy compleja porque para cada control se necesitaría un registro de desplazamiento independiente (y con distintos números de registros) y en el caso del control integral, ha de cargar el valor final al comienzo del registro en cada iteración (cada ciclo del tiempo de muestreo).

Estaré un tiempo tratando de ver si consigo resolver estos problemas, de momento queda en "intentos de acercamientos". A parte de eso si sigo usando un ICE40 de 1K, estoy al límite de terminar los PLBs (?) y eso da poco margen de maniobra, pero estoy un poco empeñado en que quepa el proyecto final, el tiempo dirá si se puede o no.

Un saludo.

Jose Pico

unread,
Jun 27, 2018, 6:31:00 PM6/27/18
to FPGAwars: explorando el lado libre
Hola Demócrito:

Habrá que probarlo. jejejej

Por cierto, podrías usar  un CASE  (Ojo con default también) en lugar de tantos IF creo que te ahorrará algún recurso.

Saludos 

Democrito

unread,
Jun 29, 2018, 4:58:32 AM6/29/18
to FPGAwars: explorando el lado libre
Hola José,

Si, si veo que baja algún PLB o se mantiene pondré el CASE, se verá mejor estructurado. Por cierto, se me ocurrió una idea súper sencilla para el tema de los decimales y aplicarlo al pseudo PID, y esa idea me vino volviendo a ojear una página que pusiste, así que muchas gracias! Este finde me pondré a aplicarla, y si funciona os volveré a dar la lata!

Un saludo!

Jose Pico

unread,
Jun 29, 2018, 7:29:29 AM6/29/18
to FPGAwars: explorando el lado libre

Estaremos atentos a nuevos Upgrades.

Saludos

Democrito

unread,
Jul 1, 2018, 7:55:25 AM7/1/18
to FPGAwars: explorando el lado libre
"Del dicho al hecho hay un trecho" y eso es lo que me ha pasado con "la idea" que comentaba en el post anterior sobre la coma fija.

He hecho varias modificaciones. Os adjunto el ICE sin vídeo. Decir que esta nueva versión arrastra 500gr como con el Arduino, sin problemas. A veces, no lo hace siempre, tiene un pequeño respingo al llegar a la meta. Aunque sea a veces y que con reducción de engranajes sería inapreciable, no lo puedo dar por bueno o finalizado, porque no es igual o mejor que con Arduino.

Pongo brevemente los cambios realizados o puntos a tener presente:
  • El signo de la desviación derivativa ahora lo conserva en todas las partes del circuito.
  • Como anteriormente, sólo hay una constante (KD) y el tiempo de muestreo para ajustar el control. KD no lo he puesto fuera como cajita de parámetro porque me da una incoherencia, así que queda dentro del código Verilog y de momento se ha de modificar ahí.
  • Como no he encontrado la manera de incrementar la desviación integral más lentamente, lo que he hecho es que se incremente o decremente en 1. Va bastante bien y se aprecia como en los últimos instantes de llegar a la meta se acerca lentamente hasta posicionarse. Cuanto mayor sea la constante KD, más lentamente será ese acercamiento, y si se aumenta demasiado comenzará a ganar en ruido.
  • Hay dos registros (variables) para la desviación derivativa: "dInput" que es la desviación real, y "dx" que es la amplificada.
  • Tenía una errata (que por alguna razón me lo sintetizaba bien) entre la salida del secuenciador y la entrada "st". Además de estar corregida, he aumentado la posibilidad de secuenciar hasta 14, en vez de sólo 6.
  • Hice el intento de usar CASE para que se viese todo más claro, pero según me ha parecido en todos los ejemplos que he podido ver, esa instrucción sólo se puede utilizar para lógica combinacional.
Y de momento queda aparcado el proyecto en este punto.

Un saludo.

pseudoPIDv5.ice

Democrito

unread,
Jul 1, 2018, 8:09:42 AM7/1/18
to FPGAwars: explorando el lado libre
Os paso un vídeo para ver si os recuerda a algo...

Pongo la parte que me interesa, unos 18 segundos, el resto es opcional.

https://www.youtube.com/watch?v=sENgdSF8ppA&t=5m7s (experimentos sobre la Ley de Lenz)

Democrito

unread,
Jul 3, 2018, 3:38:57 PM7/3/18
to FPGAwars: explorando el lado libre
Aplicación veraniega de un control PID: https://www.youtube.com/watch?v=Jz_VzjZSOyg

Democrito

unread,
Oct 2, 2018, 4:56:33 AM10/2/18
to FPGAwars: explorando el lado libre
Estoy en la búsqueda de algún tipo de algoritmo/truco que podamos fácilmente dividir cualquier número por otro número (especialmente por los números 3, 5 y 7) para evitar crear una calculadora dentro de la FPGA. Si sabemos que siempre vamos a dividir por un número fijo, se trataría de hallar un método sencillo que lo hiciese, con sólo sumas, restas y desplazamientos (izquierda/derecha).

Hace algunas semanas me topé (sin buscar nada relacionado) con un vídeo muy curioso en el que se explica un truco para dividir entre 5 (y también se aplica fácilmente a dividir con potencias de 5). Resulta que la forma de hacerlo es exactamente lo que necesitaba. Todavía no sé manejarme con la coma decimal (o punto decimal) en electrónica digital, pero veo posibilidades a esta forma de proceder.


Mi pregunta es si vosotros conocéis procedimientos similares para hacerlo con los números 3 y 7 para tener todo el repertorio básico.

Saludos.
Message has been deleted

Democrito

unread,
Oct 2, 2018, 4:17:21 PM10/2/18
to FPGAwars: explorando el lado libre
Hola Unai

Cuando vi el vídeo, me dije "ya está!" (sólo para dividir por 5, como en el vídeo), pero al ponerme con lápiz y papel para plantear el problema de forma binaria, me di cuenta que eso de la coma (o punto) decimal, al intentar hacerlo en binario era "harina de otro costal".

Me tengo que poner primero con eso del punto o coma en binario, experimentar y comprender. Me va a venir muy bien el último enlace que pusiste, tiene muy buena pinta.

Saludos. 

Felipe Machado

unread,
Oct 2, 2018, 5:08:27 PM10/2/18
to FPGAwars: explorando el lado libre
Hola,

En el apartado 8.10 (p 171) del siguiente enlace tienes una manera poco eficiente de implementar la división.
La ventaja es que es fácil de entender porque imita nuestra manera de dividir y didácticamente puede ser interesante porque hay que implementar un circuito de control.
Pero no es eficiente ya que es secuencial y por tanto tarda varios ciclos en realizarla, y todavía más si quieres calcular decimales en vez de devolver el resto.


Un saludo

Cristóbal Contreras Rubio

unread,
Oct 2, 2018, 5:15:16 PM10/2/18
to fpga-wars-explora...@googlegroups.com
Perdón si igual lo que digo es una chorrada o ya lo has puesto y no lo he leído ¿Has probado a usar un desplazador de barril / barrel shifter?

--
Has recibido este mensaje porque estás suscrito al grupo "FPGAwars: explorando el lado libre" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explora...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Jose Pico

unread,
Oct 2, 2018, 6:47:23 PM10/2/18
to FPGAwars: explorando el lado libre
Hola:

Trucos no me sé ninguno, jejejeje (Algoritmo CORDIC sería lo ideal creo)

Pero si lo vemos a pelo,  dividir, al finar es restar sucesivamente:

 Ejemplo   19:3

 19-3 =16  --1
 16-3 = 13 --2
 13-3 = 10 -- 3
 10-3 = 7 --- 4
  7-3 = 4  -- 5
 4-3 =1    -- 6  y  resto 1    1 de 3 =  1/3    

 19:3 = 6.33

  Si sabes que divides por 3:

   restando ( suma + Ca2 ) , contando la veces que restas hasta que el resultado sea menor de 3 o 0 ( un comparador y un contador) podrás, del contador
  obtener el número entero  y  este concatenar  el resto que solo podrá ser 0, 1 o 2  en el caso que dividas números enteros ( 0-->0, 1-->0.33, 2-->0.66 ), si divides números decimales hay muchas mas combinaciones.

   Tendrás que definir con cuantos bits trabajas para la parte entera y cuantos para la decimal ( eso lo decides tú y lo debes tener en cuenta )

   para el ejemplo si usas por ejemplo 8 bits para la entera y 8 para la decimal sería:

   6.33     0000_0110.0101_0101

  Lo mismo valdría para dividir por 7 o por 5

   puedes truncar, redondear, etc en función de lo exigente que sea tu aplicación.

   Saludos

Democrito

unread,
Oct 3, 2018, 3:55:24 AM10/3/18
to FPGAwars: explorando el lado libre
Hola a todos!

Os agradezco las aportaciones y tiempo que habéis dedicado a darme pistas de cómo abordar este "problemilla"!

Gracias de nuevo!

Saludos.




It is loading more messages.
0 new messages