Arduineces y otras hierbas (Monitorizar fugas de agua)

Todo cuanto tiene que ver con la obtención, almacenamiento y proceso de la información digital, sus aplicaciones y el software y hardware utilizado.
Responder
Mensaje
Autor
Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#361 Mensaje por Anilandro »

Con el Timer2, eligiendo el Prescaler 1024 podríamos generar frecuencias de 30,52 Hz, y con Prescaler 1 unos teóricos 7,969 Mhz, pero la realidad es mucho más limitada en este extremo alto, ya que para la mayoría de las acciones el microcontrolador necesita varios impulsos de reloj, y luego está el código interno de las funciones propias de Arduino, con lo cual, la máxima frecuencia real que consigue el programa anterior sólo alcanza los 47,6 Khz... (en la imagen, la base de tiempos del osciloscopio está a 5 uS/Div)

Imagen


...Eso puede parecer poco, pero debemos tener en cuenta que el Timer2 tiene que dispararse dos veces para crear cada ciclo, y de hecho el mayor retraso se produce en la rutina ISR, haciendo que con el Prescaler 1 (el más rápido) valores OCR2A inferiores a 160 ya no produzcan aumento de frecuencia.

Un límite lo establece la duración de la rutina de interrupción ISR, que debe ser lo más breve posible, ya que si dura más que el período del Timer, éste interrumpirá su propia rutina antes de que haya acabado, pudiendo incluso bloquear el microprocesador sin nosotros saber porqué se produce.

En este caso la frecuencia de salida podría aumentarse si en la rutina ISR sustituimos las órdenes de control del pin-13 "digitalWrite(13, LOW/HIGH)", que no son precisamente rápidas, por otras que actúen directamente sobre los registros que controlan el estado de los pines. Si al PORTB le asignamos el valor 0b00100000 para poner el Pin-13 en "HIGH" y 0b00000000 para "LOW"...

Imagen


...Podremos disminuir el valor de OCR2A de 160 a 45, y entonces la duración de la señal pasará de 21 uS a tan solo 6,4 uS, con lo que la frecuencia sube a 156,25 Khz manteniendo la señal simétrica... (en la imagen el osciloscopio está a 2 uS/div)...

Imagen


Continuará...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#362 Mensaje por Anilandro »

Y si no necesitamos que la señal sea forzosamente simétrica en tiempos "marca-espacio" podemos utilizar el Timer0 para que suba el flanco, mantenerlo arriba un breve tiempo con órdenes de retraso de bajo nivel y bajarlo seguidamente, con lo cual podemos conseguir que cada interrupción del Timer nos genere 1 ciclo de salida, y la frecuencia se duplicará respecto al sistema anterior. Con este nuevo código he obtenido señales de 3 uS (333,33 Khz)...

Imagen


Cada una de las órdenes _asm_("nop\n\t") causan la detención, y por tanto una espera, de 1 ciclo de reloj del microcontrolador... 1/16.000.000 = 62,5 nS

Imagen


Imagen


Continuará...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#363 Mensaje por Anilandro »

Ahora que ya sabemos un poco como va el Timer0, podemos crear con él una señal continua de control de servo, 20 mS a LOW y 1,5 mS a HIGH (para servo en posición media). El siguiente código nos tiene que dar estos valores...

Imagen


Para tiempos entre 20 mS y 1,5 mS, cambiaremos sólo el Prescaler TCCR2B y el registro comparador OCR2A. En la tabla vemos que para el Timer2 el mayor Prescaler de 1024 (código 7) sólo llega a 16,38 mS, así que será el valor que utilicemos, equivalente a OCR2A=255...

Imagen


De hecho, el tiempo a LOW de 20 mS no es crítico para la posición del servo. Podría variar entre 10 y 30 mS sin que el servo se diera cuenta. Lo que sí es importante es el tiempo entre 1 y 2 mS en HIGH, éste es el que determina la posición instantánea del eje. Sí 16,38 mS se da con un valor de OCR2A de 255, el valor para 1,5 mS será 255x1,5/16,38= 23, éste nos dará la posición media del servo, y los dos extremos serán 255x1/16,38 = 15 y 255x2/16,38= 31. Es decir, variando el OCR2A entre 15 y 31, el servo ser moverá de un lado a otro...

Con estos cálculos vemos que no vamos a tener demasiada resolución en la posición del servo, sólo valores enteros de OCR2A de 15 a 31, 17 posiciones únicas. Es el problema de que el Timer2 sea de 8 bits... pero de momento, sigamos, ya lo arreglaremos más adelante...

Continuará...

Un saludo
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#364 Mensaje por Anilandro »

...La rutina ISR lo único que hace es alternar asignaciones de 255 para generar el LOW en el pin-13, con asignaciones entre 15 y 31 (inicialmente 23) que guardamos en la variable "pServo", la cual si cambiáramos con código añadido en el "loop()", nos movería el servo a nuestro gusto.

Las formas de onda de control de servo obtenidas son:

- La señal completa, 20 mS a LOW y 1,5 mS a HIGH

Imagen


- Ampliación de señal HIGH, inicialmente a 1,5 mS. con valor pServo=23

Imagen


- La señal mínima de 1 mS con pServo=15

Imagen


- La señal máxima de 2 mS con pServo=31.

Imagen


Continuará...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#365 Mensaje por Anilandro »

La baja resolución al utilizar un Timer de 8 bits se puede solucionar con un bucle contador por software dentro de la rutina de interrupción ISR. En este programa he pasado de 23 pasos a un mínimo de 128, lo cual ya no está nada mal para controlar un servo...

Imagen


Continuará...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#366 Mensaje por Anilandro »

Afinando un poco el programa consigo aumentar la resolución al doble, a 255, que es el máximo que puede conseguirse con un Timer de 8 bits y es también la que tiene la librería "servo.h" de Arduino. Además una resolución mayor sería poco útil en un servo de calidad normal...

Imagen


En este programa, basado en tiempos máximos de disparo de Timer de 1,024 ms, primero ponemos el pin de salida a LOW y contamos 20 ciclos, con lo cual se generará la señal de "espacio" de 20 mS, luego ponemos el pin a HIGH y contamos un ciclo más, generando una señal "marca" de 1 ms. que correspondería al servo girado a un extremo. Y seguidamente, sin tocar la señal de HIGH, contamos otro ciclo, pero no entero como los anteriores, si no de 0-1 mS. dependiendo del valor 0-255 que establecerá proporcionalmente la posición del eje del servo, desde el extremo anterior, al extremo opuesto.

Este último programa "Servo_Timer2_mixHS_R255_01" se puede bajar de mi Drive con el enlace:
https://t.co/D2p4r4mqMK

Continuará...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#367 Mensaje por Anilandro »

Aprovechando el código del último programa, y apurando al máximo las posibilidades del Timer2, he ampliado su control simultáneo a 12 servos. Como sigue utilizando un Timer de 8 bits, la resolución se reduce a 5-255=250 pasos reales, con total estabilidad...

Imagen


Como ya he dicho, este programa controla entre 1 y 12 servos, dato que asignaremos a "nservos". La matriz "Servos[][]" guarda en [n][0] los pines de control de cada servo, y en [n][1], los valores de posición. Estos últimos datos podrán modificarse en el "loop()" para mover los servos...

La parte de configuración del Timer0 en el "setup()" no cambia demasiado, pero la rutina ISR es a la fuerza más compleja, y no sólo por tener que controlar 12 servos, si no porque al querer controlar un tiempo de 1-2 mS con la máxima resolución obliga a 2 ciclos para cada servo.

La ISR utiliza 20 ciclos de interrupción de 1 ms para crear los 20 mS de valor a LOW de todos los servos. Luego, para cada uno de los 12 servos, pone a HIGH y usa un primer ciclo fijo de 1 mS, seguido de un segundo variable entre 20 uS y 1 mS para mover el servo...

El problema es que esta ISR, por la complejidad a que obliga el Timer de 8 bits, ya no cumple la premisa de ser muy breve, con lo cual no se puede bajar del valor 4 en el OCR2A porque el ciclo deja de ser estable. Pero bueno, entre 5 y 255 controla los servos a la perfección...

Continuará...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#368 Mensaje por Anilandro »

Vale, esto como ejercicio está bien, pero para controlar servos es mucho más interesante utilizar el Timer1, cuya principal diferencia con el Timer0 es que es de 16 bits, y por tanto su contador va de 0 a 65.535, lo que nos simplificará el código y conseguiremos una mejor resolución.

Otra diferencia es que de forma incomprensible la configuración del Timer1 es distinta al 2. Tiene sólo 5 prescalers (1, 8, 64, 256 y 1024), y tanto la determinación de estos como la habilitación del modo CTC de comparación se efectúa en el mismo registro TCCR1B...

La habilitación del modo CTC se efectúa poniendo a 1 el 4º bit del registro TCCR1B, que en binario será 0b00001000, y en decimal 8, mientras que los "prescalers" ocupan los 3 primeros bits del registro. Los valores totales de configuración del TCCR1B (para el Timer1) son:

Imagen


Continuará...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#369 Mensaje por baldo »

Anilandro escribió:El problema es que esta ISR, por la complejidad a que obliga el Timer de 8 bits, ya no cumple la premisa de ser muy breve, con lo cual no se puede bajar del valor 4 en el OCR2A porque el ciclo deja de ser estable. Pero bueno, entre 5 y 255 controla los servos a la perfección...
El mayor retardo viene por usar matrices. para colmo de 2D. soluciones:

1º desbobla la matriz Servos[][], en ServosPin[] y ServosValor[], que equivalen a Servos[][0],Servos[][1],
esto alivia pero no cura.

2º llamar a cada cosa por su nombre, Servo1Pin=xxx, Servo2Valor=yy,,,,
sin duda metodo campeon en velocidad, pero intratable,

3º USAR VECTORES ! ! !
defines 2 matrices:
ServosPin[nservos] y ServosValor[nservos], como hiciste con la 2D.
y ahora como se hacia????,,,, ya no me acuerdo de nada,,, era algo asi,,,
se definen dos vectores:
volatile byte * ptrPin;
volatile byte * ptrValor;

reset de punteros:
ptrPin = &ServosPin; //con esto ptr apunta al 1º.

escribir en tal Servo = x://escribe en la matriz servoPin, tal equivale a tu indice.
*(ptrPin + tal) = x;

leer de tal Servo = x:
x = *(ptrPin + tal);

seguro que hay errores de sintaxis, pero la cosa va por ahi.

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Los servos (y los "Timers") con Arduino...

#370 Mensaje por Anilandro »

Gracias Baldo, pero cuando tienes muchas variables es mejor agruparlas en matrices que manejarlas individualmente, porque además harían falta muchas instrucciones condicionales "if()" o de selección "switch-case". Aquí el problema venía casi exclusivamente por usar un Timer de 8 bits, lo cual obligaba a florituras, contadores de soft, idas y venidas para manejar tiempos mayores y mantener una mínima resolución... Pero esto hace días que lo tengo solucionado con el Timer1 de 16 bits, aunque aún no lo había publicado. El código de control de 12 servos se simplificó mucho, especialmente en la ISR, y además la resolución ha pasado de 250 a 2.000 pasos...

Imagen


Este programa lo he probado con ocho servos simultáneamente, es totalmente estable y no se aprecia ningún desfase en el movimiento de los servos...

...Y los punteros de C, la verdad es que sin duda son un potente recurso, pero nunca me ha gustado usarlos, tal vez porque tengo poca experiencia con ellos y me confunden...

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 4 invitados