Académique Documents
Professionnel Documents
Culture Documents
title=(1620-IELE3330-
TC)_Proyecto:_Pendulo_Invertido_Grupo_D
(1620-IELE3330-TC) Proyecto: Pendulo Invertido Grupo D
From CoffeeBrain-WikiControl
Contents
1Introduccin
3Variables a controlar
4Controladores
o 5.1Modelo Matemtico
5.1.1Linealizacin
5.1.3Funcin de transferencia
o 5.2Modelo en SimScape
6Diseo de controladores
o 6.1PID
6.1.1Sintonizacin
o 6.3Fuzzy Logic
8Implementacin
9Funcionamiento Inicial del montaje
10Protocolo de Pruebas
11Problemas en la implementacin
12Resultados
o 12.1PID
o 12.2Fuzzy Logic
13Videos de funcionamiento
o 13.1PID
o 13.2Fuzzy Logic
15Referencias
Introduccin
En el siguiente documento se presenta la implementacin y diseo a
nivel fsico de un pndulo invertido. En este se va a especificar el
estado de las actividades con respecto al cronograma presentado al
inicio del proyecto, el estado actual de la implementacin y la
asignacin de roles para concluir la implementacin en el plazo
establecido.
: Longitud.
: Masa.
Para el modelo, las variables de estado, es decir, las que van a ser
controladas van a ser la posicin del carro , y el ngulo del pndulo
con respecto al eje , para poder mantener la estabilidad de este.
Controladores
Teniendo en cuenta el objetivo del proyecto, para lograr la precisa
estabilizacin del pndulo invertido, es necesario aplicar un
controlador que sea capaz de actuar con rapidez y llevar al pndulo a
su punto de equilibrio de la manera ms eficiente posible,
independientemente de las perturbaciones que puedan afectar al
sistema. Para esto, se trabajar un controlador PID, un LQR y
finalmente un rechazo de perturbaciones que en conjunto permitirn
un control optimo del sistema.
Linealizacin
El control del pndulo invertido se lleva a cabo en el punto de
equilibrio superior, por lo que las ecuaciones se deben linealizar
utilizando el ngulo del pndulo respecto a la lnea vertical superior .
Este ngulo debe ser pequeo para que haya una estabilizacin del
sistema, por lo que:
Funcin de transferencia
Teniendo este modelo, se proceder a encontrar la funcin de
transferencia, que dar la posibilidad, al igual que la representacin en
espacio de estados, de manipular el sistema y llevar a cabo el control
deseado sobre la posicin y el ngulo del pndulo.
Modelo en SimScape
Para llevar a cabo el modelo mecnico del sistema en SimScape, se
utiliz como referencia, en primer lugar, el modelo de MathWorks [5].
Diseo de controladores
PID
Se van a implementar dos PID en Simulink para controlar la posicin
del carro y el ngulo del pndulo, teniendo en consideracin que es el
controlador ms utilizado en la industria y que por su flexibilidad, se
acopla a diferentes tipos de problemas.
Sintonizacin
Dado que para este sistema se busc controlar el ngulo del pndulo y
la posicin del carro que lo lleva, se obtuvieron las funciones de
transferencia respectivas, con los siguientes parmetros:
Masa del carro: 0.023 kg
Ahora bien, con el fin de poder sintonizar los PID, se verific en primer
lugar, que el sistema fuera controlable. Para esto, se encontraron las
matrices de representacin de estados, como se muestra a
continuacin:
Kp=0.6*1=0.6
Ti=0.5*0.937=0.4685
Td=0.125*0.937=0.1171
Donde,
Ahora bien, para el control de la posicin del carro no fue posible hallar
un valor Kp tal que se obtuvieran oscilaciones sostenidas en la salida.
Por lo cual, se sintoniz el PID por prueba y error. Tras bastantes
iteraciones, se obtuvo que era necesario una ganancia proporcional
negativa de -35 por la direccin de los ejes en el modelo en inventor, y
manteniendo Ki y Kd en cero, se obtuvo la siguiente respuesta:
Fig 18. Respuesta del sistema con Kp=-35, Ki=1, Kd=1.
Se puede ver que la respuesta an no es estable, por lo que se
modificaron los valores de las otras dos acciones de la siguiente
manera: Ki=-13 y K_d=0.15, para lo cual se obtuvo que:
Implementacin
Para empezar, se compraron los siguientes materiales para la
implementacin del sistema:
Compra de materiales.
Bloque de madera de
$15,000 Homecenter
2.5x8cm
$328,95
Total
0
Variable Magnitud
Ra=Va/Ia
Ke=V-I*Ra V/rad*seg
Kt (Nm/A)=Ke (V/rad*seg)
Jm=(Tm*Kt*Ke)/ Ra
Tm=Kt*Ia=b*Omega + Tf
Siendo Tf=Kt*Ia=0.05502*4.5454=0.25 s
Problemas en la implementacin
A la hora de implementar el sistema mecnico se presentaron
bastantes problemas. En primer lugar, se rompi el eje del motor por
lo que toc comprar uno nuevo.
Resultados
PID
Con las constantes encontradas para el PID despus de obtener la
funcin de transferencia experimental del sistema, se obtuvo el
comportamiento mostrado en la Figura 34 para la respuesta del ngulo
del pndulo ante varias perturbaciones.
Fuzzy Logic
Para el segundo controlador se implement fuzzy con una entrada y
una salida, se definieron 13 reglas y como mtodo de defuzzificacin
se utiliz Centroide. A contiacin se muestra la respuesta del sistema
ante perturbaciones.
Fig 35. Respuesta del sistema ante perturbaciones con Fuzzy
Videos de funcionamiento
PID
El siguiente video muestra un avance inicial del PID para mantener al
pndulo en su punto de equilibrio inestable:
Referencias
Category:
https://www.luisllamas.es/arduino-encoder-rotativo/
Medir el ngulo y sentido de giro con Arduino y encoder rotativo
Qu es un encoder rotativo?
Un encoder rotativo es un dispositivo genrico que permite determinar
la posicin y velocidad angular de un accionamiento, y registrar la
medicin desde un procesador o autmata como Arduino.
Precio
Los encoders son dispositivos baratos. Podemos encontrarlos en
mdulos preparados para conectar de forma sencilla a Arduino por
0,45 en vendedores internacionales de Ebay y Aliexpress.
Esquema de montaje
Para conectar el encoder a Arduino, necesitamos tres entradas
digitales, dos para la deteccin del encoder y una adicional si
queremos registrar la pulsacin de la palanca.
1 constintchannelPinA=9;
2 constintchannelPinB=10;
3
4 unsignedcharstateChannelA;
5 unsignedcharstateChannelB;
6 unsignedcharprevStateChannelA=0;
7
8 constintmaxSteps=255;
9 intprevValue;
1 intvalue;
0
1
constinttimeThreshold=5;
1
unsignedlongcurrentTime;
1
2 unsignedlongloopTime;
1
3
boolIsCW=true;
1
4
1 voidsetup(){
5 Serial.begin(9600);
1 pinMode(channelPinA,INPUT);
6
pinMode(channelPinB,INPUT);
1
7 currentTime=millis();
1 loopTime=currentTime;
8 value=0;
1
9 prevValue=0;
2 }
0
2
voidloop(){
1
currentTime=millis();
2
2 if(currentTime>=(loopTime+timeThreshold))
2 {
3
stateChannelA=digitalRead(channelPinA);
2
4 stateChannelB=digitalRead(channelPinB);
2 if(stateChannelA!=prevStateChannelA) // Para precision simple if((!
5 stateChannelA) && (prevStateChannelA))
2 {
6 if(stateChannelB)// B es HIGH, es CW
2 {
7
boolIsCW=true;
2
8 if(value+1<=maxSteps)value++;// Asegurar que no sobrepasamos
maxSteps
2
9 }
3 else // B es LOW, es CWW
0 {
3 boolIsCW=false;
1
if(value-1>=0)value=value--;// Asegurar que no tenemos negativos
3
2 }
3
3 }
3 prevStateChannelA=stateChannelA;// Guardar valores para
4 siguiente
3
5
// Si ha cambiado el valor, mostrarlo
3
6 if(prevValue!=value)
3 {
7
prevValue=value;
3
Serial.print(value);
8
3
9 }
4
0
loopTime=currentTime; // Actualizar tiempo
4
1 }
4 // Otras tareas
2 }
4
3
4
4
4
5
4
6
4
7
4
8
4
9
5
0
5
1
5
2
5
3
5
4
5
5
5
6
5
7
5
8
5
9
6
0
6
1
6
2
Precisin doble con una interrupcin
En este ejemplo cambiamos una de las entradas digitales por una
interrupcin, registrando flancos de subida y bajada, por lo que
tenemos precisin doble.
1 constintchannelPinA=2;
2 constintchannelPinB=10;
3
4 constinttimeThreshold=5;
5 longtimeCounter=0;
6
7 constintmaxSteps=255;
8 volatileintISRCounter=0;
9 intcounter=0;
10
11 boolIsCW=true;
12
13 voidsetup()
14 {
15 pinMode(channelPinA,INPUT_PULLUP);
16 Serial.begin(9600);
17 attachInterrupt(digitalPinToInterrupt(channelPinA),doEncode,CHANG
E);
18
}
19
20
voidloop()
21
{
22
if(counter!=ISRCounter)
23
{
24
counter=ISRCounter;
25
Serial.println(counter);
26
}
27
delay(100);
28
}
29
30
voiddoEncode()
31
{
32
if(millis()>timeCounter+timeThreshold)
33
{
34
if(digitalRead(channelPinA)==digitalRead(channelPinB))
35
{
36
IsCW=true;
37
if(ISRCounter+1<=maxSteps)ISRCounter++;
38
}
39
else
40
{
41
IsCW=false;
42
if(ISRCounter-1>0)ISRCounter--;
43
}
44
timeCounter=millis();
45
}
46
}
Precisin cudruple con dos interrupciones
En este ltimo ejemplo, empleamos interrupciones para ambos
canales, y en ambos flancos. Obtenemos precisin cudruple, pero a
cambio dejamos sin ms pines con interrupciones a la mayora de
modelos de Arduino.
1 constintchannelPinA=2;
2 constintchannelPinB=3;
3
4 constinttimeThreshold=5;
5 longtimeCounter=0;
6
7 constintmaxSteps=255;
8 volatileintISRCounter=0;
9 intcounter=0;
10
11 boolIsCW=true;
12
13 voidsetup()
14 {
15 pinMode(channelPinA,INPUT_PULLUP);
16 Serial.begin(9600);
17 attachInterrupt(digitalPinToInterrupt(channelPinA),doEncodeA,CHAN
GE);
18
attachInterrupt(digitalPinToInterrupt(channelPinB),doEncodeB,CHAN
19
GE);
20
}
21
22
voidloop()
23
{
24
if(counter!=ISRCounter)
25
{
26
counter=ISRCounter;
27
Serial.println(counter);
28
}
29
delay(100);
30
}
31
32
voiddoEncodeA()
33
{
34
35 if(millis()>timeCounter+timeThreshold)
36 {
37 if(digitalRead(channelPinA)==digitalRead(channelPinB))
38 {
39 IsCW=true;
40 if(ISRCounter+1<=maxSteps)ISRCounter++;
41 }
42 else
43 {
44 IsCW=false;
45 if(ISRCounter-1>0)ISRCounter--;
46 }
47 timeCounter=millis();
48 }
49 }
50
51 voiddoEncodeB()
52 {
53 if(millis()>timeCounter+timeThreshold)
54 {
55 if(digitalRead(channelPinA)!=digitalRead(channelPinB))
56 {
57 IsCW=true;
58 if(ISRCounter+1<=maxSteps)ISRCounter++;
59 }
60 else
61 {
62 IsCW=false;
if(ISRCounter-1>0)ISRCounter--;
63 }
64 timeCounter=millis();
65 }
}
https://www.luisllamas.es/que-son-y-como-usar-interrupciones-en-
arduino/
Qu son y cmo usar interrupciones en Arduino
Dentro de las interrupciones de hardware, que son las que nos ocupan
en esta entrada, Arduino es capaz de detectar los siguientes
eventos.
RISING, ocurre en el flanco de bajada de LOW a HIGH.
attachInterrupt(interrupt, ISR, mo
1 attachInterrupt(interrupt,ISR,mode);
Donde interrupt es el nmero de la interrupcin que estamos
definiendo, ISR la funcin de callback asociada, y mode una de las
opciones disponibles (Falling, Rising, Change y Low)
1 attachInterrupt(digitalPinToInterrupt(pin),ISR,mode);
Otras funcionas interesantes para la gestin de interrupciones son:
1 constintemuPin=10;
2
3 constintLEDPin=13;
4 constintintPin=2;
5 volatileintstate=LOW;
6
7 voidsetup(){
8 pinMode(emuPin,OUTPUT);
9 pinMode(LEDPin,OUTPUT);
10 pinMode(intPin,INPUT_PULLUP);
11 attachInterrupt(digitalPinToInterrupt(intPin),blink,CHANGE);
12 }
13
14 voidloop(){
15 //esta parte es para emular la salida
16 digitalWrite(emuPin,HIGH);
17 delay(150);
18 digitalWrite(emuPin,LOW);
19 delay(150);
20 }
21
22 voidblink(){
23 state=!state;
24 digitalWrite(LEDPin,state);
25 }
Contando disparos de una interrupcin
El siguiente cdigo empleamos el mismo pin digital para emular una
onda cuadrada, esta vez de intervalo 2s (1s ON y 1s OFF).
1 constintemuPin=10;
2
3 constintintPin=2;
4 volatileintISRCounter=0;
5 intcounter=0;
6
7
8 voidsetup()
9 {
10 pinMode(emuPin,OUTPUT);
11 pinMode(intPin,INPUT_PULLUP);
12 Serial.begin(9600);
13 attachInterrupt(digitalPinToInterrupt(intPin),interruptCount,LOW);
14 }
15
16 voidloop()
17
{
18
//esta parte es para emular la salida
19
digitalWrite(emuPin,HIGH);
20
delay(1000);
21
digitalWrite(emuPin,LOW);
22
delay(1000);
23
24
25
if(counter!=ISRCounter)
26
{
27
counter=ISRCounter;
28
Serial.println(counter);
29
}
30
}
31
32
voidinterruptCount()
33
{
34
ISRCounter++;
35
timeCounter=millis();
36
}
37
Lgicamente, nuestro objetivo es emplear interrupciones de hardware
no solo con otros dispositivos digitales, si no tambin con
dispositivos fsicos como pulsadores, sensores pticos
Qu es el debounce?
Los dispositivos electrnicos al cambiar de estado generan una seal
que, sin ser perfectamente cuadrada, en general es ms o menos
limpia. Veamos, por ejemplo, la seal que genera Arduino al
cambiar el estado de una salida digital de HIGH a LOW.
Sin embargo el mundo real no es tan bonito. Muchos dispositivos
fsicos habitualmente generan ruido en los flancos de seal. Como
ejemplo, veamos la variacin de tensin que ocurre cuando el cambio
de estado se genera por un pulsador.
Observar la cantidad de ruido ocurrido tras el flanco. En esencia, en el
rango de unos microsegundos la seal es puro ruido. Todos esos picos
pueden provocar disparos mltiples de una interrupcin.
PROBANDO EL REBOTE
Para probar el rebote, simplemente vamos a emplear un cable para
conectar el Pin 2 y Ground (tambin podis usar un pulsador o un
interruptor).
1 constintintPin=2;
2 volatileintISRCounter=0;
3 intcounter=0;
4
5
6 voidsetup()
7 {
8 pinMode(intPin,INPUT_PULLUP);
9 Serial.begin(9600);
10 attachInterrupt(digitalPinToInterrupt(intPin),debounceCount,LOW);
11 }
12
13 voidloop()
14 {
15 if(counter!=ISRCounter)
16 {
17 counter=ISRCounter;
18 Serial.println(counter);
19 }
20 }
21
22 voiddebounceCount()
23 {
24 ISRCounter++;
25 }
Al probar nuestro montaje y poner en contacto el PIN 2 a GROUND,
esperaramos que la variable se incrementara de uno en uno. Pero
veremos que en realidad salta varios nmeros cada vez (incluso
varias decenas).
Eliminando el rebote
Disponemos de dos formas de aplicar el debounce. Aadiendo
dispositivos electrnicos que filtren la seal (debounce por hardware) o
modificando nuestro cdigo para eliminar el rebote (debounce por
hardware).
1 constinttimeThreshold=150;
2 constintintPin=2;
3 volatileintISRCounter=0;
4 intcounter=0;
5 longtimeCounter=0;
6
7
8 voidsetup()
9 {
10 pinMode(intPin,INPUT_PULLUP);
11 Serial.begin(9600);
12 attachInterrupt(digitalPinToInterrupt(intPin),debounceCount,FALLIN
G);
13
}
14
15
voidloop()
16
{
17
if(counter!=ISRCounter)
18
{
19
counter=ISRCounter;
20
Serial.println(counter);
21
}
22
}
23
24
voiddebounceCount()
25
{
26
if(millis()>timeCounter+timeThreshold)
27
{
28
ISRCounter++;
29
timeCounter=millis();
30
}
31
}
Un tiempo de 100-200ms es correcto para un pulsador pero en otros
casos deberemos ajustar el tiempo de forma que eliminemos el rebote,
pero no ignoremos dos posibles eventos cercanos verdaderos.
https://www.luisllamas.es/referencia-lenguaje-arduino/
Referencia para el programador del lenguaje Arduino
Operadores y comparadores
Comparadores
//x igual a y
x == y
//x distinto de y
1 //x igual a y
2 x==y
3
4 //x distinto de y
5 x!=y
6
7 //x menor que y
8 x<y
9
10 //x mayor que y
11 x>y
12
13 //x menor o igual que y
14 x<=y
15
16 //x mayor o igual que y
17 x>=y
Operadores aritmticos
//operador de asignacin
a=b
//adicin
1 //operador de asignacin
2 a=b
3
4 //adicin
5 a+b
6
7 //substraccin
8 a-b
9
10 //multiplicacin
11 a*b
12
13 //divisin
14 a/b
15
16 //modulo
17 a%b
Operadores de bits
//and binario
a&b
//or binario
1 //and binario
2 a&b
3
4 //or binario
5 a|b
6
7 //xor binario
8 a^b
9
10 //not binario
11 a~b
12
13 //desplazamiento a izquierda
14 a<<b
15
16 //desplazamiento a derecha
17 a>>b
Operadores compuestos
//incremento
a++
//decremento
1 //incremento
2 a++
3
4 //decremento
5 a--
6
7 //adicin compuesta
8 a+=b
9
10 //substraccin compuesta
11 a-=b
12
13 //multiplicacin compuesta
14 a*=b
15
16 //divisin compuesta
17 a/=b
18
19 //and compuesto
20 a&=b
21
22 //or compuesto
23 a|=b
Operadores booleanos
//not
!a
//and
1 //not
2 !a
3
4 //and
5 a&&b
6
7 //or
8 a||b
Operadores de acceso
//operacion indireccin
*variable
//operacion direccin
1 //operacion indireccin
2 *variable
3
4 //operacion direccin
5 &variable
Declaracin y conversin de tipos de variables
//tipo vacio (solo para funciones
void
Booleanos
//booleano, false o true
boolean = false;
Enteros
//entero, 16 bits, de -32,768 a 3
int var = 100;
Coma flotante
//coma floante, 32 bits, de -3.40
float var = 1.117;
Bytes
//8 bits, de 0 a 255
byte var = B10010;
Caracteres
//8 bits, de -128 a 127
char var = 'A';
//convierte a byte
1 //convierte a char
2 char(variable);
3
4 //convierte a byte
5 byte(variable);
6
7 //convierte a int
8 int(variable);
9
10 //convierte a word
11 word(variable);
12
13 //convierte a long
14 long(variable);
15
16 //convierte a float
17 float(variable);
Cualificadores de variables
//STATIC
//Variables visibles nicamente
//y cuyo valor se mantiene entre
static int variable;
1 //STATIC
2 //Variables visibles nicamente en el interior de una funcin,
3 //y cuyo valor se mantiene entre llamadas a la misma.
4 staticint variable;
5
6 //CONST
7 //Variables cuyo valor no puede ser redefinido tras la inicializacin
8 constfloatpi=3.14;
9
10 //VOLATILE
11 //Variables en las que se indica al compilador que no guarde en los
registros
12
//del microprocesador, sino que fuerza la actualizacin en memoria.
13
Esto se
14
//hace cuando existe la posibilidad de que el valor de la variable
15 sea
16 //modificado por otro proceso que se ejecuta concurrentemente con
el actual
//(por ejemplo cuando se emplean hilos o interrupciones)
volatileintvariable=LOW;
Vectores
Creacin de vectores
//declarar vector
int miArray[5];
//iniciar vector
1 //declarar vector
2 intmiArray[5];
3
4 //iniciar vector
5 intmiArray[]={2,4,8,3,6};
6
7 //declarar e iniciar vector
8 intmiArray[5]={2,4,-8,3,2};
Manipulacin vectores
//asignar valor a elemento del ve
miArray[0] = 10;
1 condition?true:false;
Condicional IF
if (variable < 10)
{
// accion A
}
1 if(variable<10)
2 {
3 // accion A
4 }
5
6
7 if(variable<10)
8 {
9 // accion A
10 }
11 else
12 {
13 // accion B
14 }
15
16
17 if(variable<10)
18 {
19 // accion A
20 }
21 elseif(variable>=100)
22 {
23 // accion B
24 }
25 else
26 {
27 // accion C
28 }
1 switch(variable){
2 case1:
3 // accion A
4 break;
5 case2:
6 // accion B
7 break;
8 default:
9 // caso por defecto (opcional)
10 }
Bucles
Bucle FOR
for (int i=0; i <= 100; i++){
// accion
}
1 for(inti=0;i<=100;i++){
2 // accion
3 }
Bucle WHILE
variable = 0;
1 variable=0;
2
3 while(variable<100){
4 // accion
5 variable++;
6 }
Bucle DO WHILE
do
{
//accion
variable++;
1 do
2 {
3 //accion
4 variable++;
5 }while(variable<100);
Funciones matemticas
Funciones de rango
//devuelve mnimo entra a y b
min(a,b);
Potenciacin
//devuelve a^b (ambos tipo float
pow (a,b);
Nmeros aleatorios
//inicializa la semilla del generad
randomSeed(semilla);
Trigonometria
//devuelve el seno de a (a tipo f
sin(a);
Comparacin
//compara dos cadenas. Devue
//0 si son iguales, y -1 en caso
texto1.compareTo(texto2);
Subcadenas
//devuelve una subcadena de la
txtMsg.substring(3, 10);
Bsqueda y sustitucin
//devuelve el ndice de la primer
//a partir de la posicin offset
txtMsg.indexOf('A', offset);
int cambiar(){
option=4;
1 intoption=1;
2
3 intcambiar(){
4 option=4;
5 }
6
7 voidsetup(){
8 Serial.begin(9600);
9 }
10
11 voidloop(){
12 cambiar();
13 Serial.print(option); //muestra 4
14 delay(10000);
15 }
1 intcambiar(var){
2 var=4;
3 }
4
5 voidsetup(){
6 Serial.begin(9600);
7 }
8
9 voidloop(){
10 intoption=1;
11 cambiar(option);
12 Serial.print(option); //muestra 1
13 delay(10000);
14 }
1 intcambiar(int&var){
2 var=4;
3 }
4
5 voidsetup(){
6 Serial.begin(9600);
7 }
8
9 voidloop(){
10 intoption=1;
11 cambiar(option);
12 Serial.print(option); //muestra 4
13 delay(10000);
14 }
1 intcambiar(int*var){
2 *var=4;
3 }
4
5 voidsetup(){
6 Serial.begin(9600);
7 }
8
9 voidloop(){
10 intoption=1;
11 cambiar(&option);
12 Serial.print(option); //muestra 4
13 delay(10000);
14 }
Devolucin de valores
int cambiar(){
int var=4;
return var;
}
1 intcambiar(){
2 intvar=4;
3 returnvar;
4 }
5
6 voidsetup(){
7 Serial.begin(9600);
8 }
9
10 voidloop(){
11 intoption=1;
12 option=cambiar();
13 Serial.print(option); //muestra 4
14 delay(10000);
15 }
Tipos datos avanzados (Enum / Struct / Typedef)
Enumeraciones
//declaracion
enum miEnumeracion {
opcion1,
opcion2,
1 //declaracion
2 enummiEnumeracion{
3 opcion1,
4 opcion2,
5 opcion3
6 };
7
8 //ejemplo de uso
9 miEnumeracion variable=opcion2;
10
11 if(variable==opcion2){
12 //accion
13 }
Estructuras
//declaracion
struct miEstructura
{
int campo1;
1 //declaracion
2 structmiEstructura
3 {
4 int campo1;
5 int campo2;
6 charcampo3;
7 };
8
9 //ejemplo de uso
10 structmiEstructura variable;
11
12 variable.campo1=10;
1 //declaraciones
2 typedefintnuevotipo;
3 typedefenummiEnumeracion nuevotipo;
4 typedefstructmiEstructura nuevotipo;
5
6 //ejemplo de uso
7 nuevotipo variable;
Clases
Ejemplo de uso de clase
class MiRobot;
1 classMiRobot;
2
3 //definicion de clase ejemplo
4 classMiRobot
5 {
6 public:
7 voidsaludar();//muestra "Hola"
8 voidincCont();//incrementa contador
9 int getCont();//devuelve contador
10 voidsayCont();//muestra valor contador
11 voidsetCont(int);//inicializa contador a un valor
12 private:
13 intcont=0;//variable contador privada
14 };
15
16 //muestra "Hola"
17 voidMiRobot::saludar(){
18 Serial.println("Hola");
19 }
20
21 voidMiRobot::incCont(){
22 this->cont++;
23 }
24
25 //devuelve contador
26 voidMiRobot::getCont(){
27 returnthis->cont;
28 }
29
30 //muestra valor contador
31 voidMiRobot::sayCont(){
32 Serial.println(this->cont);
33 }
34
35 //inicializa contador a un valor
36 voidMiRobot::setCont(int_cont){
37 this->cont=_cont;
38 }
39
40 voidsetup(){
41 Serial.println("Iniciando");
42 Serial.begin(9600);
43 MiRobot robot;
44 robot.saludar();//se muestra hola
45 }
46
47 voidloop(){
48 robot.incCont();//se incrementa el contador
49 robot.sayCont();//muestra el valor
50 delay(1000);
51 }
https://javierloureiro.wordpress.com/2014/04/24/como-usar-un-
encoder-con-un-arduino/
Cmo usar un Encoder con un Arduino
Un encoder es muy parecido a un potencimetro por fuera, pero en
realidad son muy distintos. El potencimetro nos da un valor analgico
que tenemos que leer, pero el encoder nos enva informacin digital
que vamos leyendo segn la ruedecita gira. Un modelo comn es el
PEC11-4215F-S0024, que nos enva 24 pulsos en una vuelta
completa.
if ( read != enc_value )
{
enc_tests = 125; // 1 ms a 125khz
enc_value = read;
return;
}
if (enc_tests > 0)
{
-- enc_tests ;
return;
}
if ( enc_tests == 0 )
{
// comprobamos si estamos en un pulso
}
}
El cdigo es C puro, pero facilmente lo podris pasar al arduino.
Realmente q la interrupcin sea de 125Khz no es relevante. 1 ms es
suficiente para la mayoria de usos.
# define ENC_STEPS 24
if ( enc_tests == 0 )
{
if ( ENC_READ_AB == 0)
{
if ( enc_previ == 1 ) ENC_INDEX_INC ;
else if ( enc_previ == 2 ) ENC_INDEX_DEC ;
}
enc_previ = ENC_READ_AB ;
}
}
# define ENC_STEPS 20
if ( read != enc_value )
{
enc_tests = 125; // 1 milliseconds on 125khz timer (PEC11 datasheet
max debounce rate)
enc_value = read;
return;
}
if (enc_tests > 0)
{
-- enc_tests ;
return;
}
if ( enc_tests == 0 )
{
if ( ENC_READ_AB == 0)
{
if ( enc_previ == 1 ) ENC_INDEX_INC ;
else if ( enc_previ == 2 ) ENC_INDEX_DEC ;
}
enc_previ = ENC_READ_AB ;
if ( ENC_READ_BTN )
{
ClearBit (enc_index,6);
}
else
{
SetBit (enc_index,6);
}
}
}
Como ejercicio para el lector, queda poder medir la velocidad de giro,
contando los ticks que han pasado desde que dejan de estar ambos
pines a 1, hasta que vuelven a estar ambos pines a 1. Y si tienes
ganas, pasarlo a arduino para que la gente pueda usarlo rpidamente.
Por ahora funciona bien, si giras muy muy rpido puede perder algun
paso, sobre todo por el debouncer, pero no es relevante, ya que
personalmente voy a usar el encoder para controlar el men de una
pantalla, y es ms que suficiente.
http://www.leandroruiz.com/blog/arduino-encoder-rotativo/
Arduino + Encoder rotativo
En la entrada de hoy introduzco la utilizacin de un Encoder rotativo.
Estos encoders son ampliamente utilizados por ejemplo para el control
de volumen en radios de automviles. Mostraremos el resultado de
accionar este encoder en un display LCD de Nokia 5110. Nos
centraremos en la utilizacin del encoder rotativo, el manejo del
display podis verlo en este
1 #include "NokiaLCD.h"
2
3 // Setup del LCD
4 NokiaLCD NokiaLCD(3,4,5,6,7);// (SCK, MOSI, DC, RST, CS)
5 // Pines de lectura del encoder
6 int a =9;
7 int b =8;
8 // Valores de medida
9 int anterior =1;
10 int contador;
11 char texto[10];
12
13 void setup()
14 {
15 // Inicializamos el LCD
16 NokiaLCD.init();
17 NokiaLCD.clear();
18
19 // Inicializamos la lectura del encoder
20 pinMode(a, INPUT);
21 pinMode(b, INPUT);
22
23 // Inicializamos las variables
24 anterior =1;
25 contador =0;
26 escribir();
27 }
28
29 void loop()
30 {
31 // Lectura de A, si es 0, volvemos a medir para asegurar el valor
32 int actual = digitalRead(a);
33 if(actual ==0){
34 delay(10);
35 actual = digitalRead(a);
36 }
37
38 // Actuamos nicamente en el flanco descendente
39 if(anterior ==1&& actual ==0)
40 {
41 int valor_b = digitalRead(b);
42 if(valor_b ==1) contador++;// Si B = 1, aumentamos el contador
43 else contador--;// Si B = 0, reducimos el contador
44 escribir();// Escribimos el valor en pantalla
45 }
46 anterior = actual;
47 }
48
49 // Esta funcin escribe en el LCD el valor de
50 // la variable "contador"
51 void escribir()
52 {
53 String s = String(contador);// Convertimos el nmero en texto
54 s.toCharArray(texto, 10);// Convertimos el texto en un formato
55 compatible
56 NokiaLCD.clear();
57 NokiaLCD.setCursor(3,2);
58 NokiaLCD.print("Volumen:");
59 NokiaLCD.setCursor(64,2);
60 NokiaLCD.print(texto);
}
Finalmente, os dejo en breve vdeo del montaje realizado en
funcionamiento.
Especificaciones tcnicas:
Modelo: KY-040
Peso: 10g
Tamao: 32 x 19 x 30 mm
http://saber.patagoniatec.com/enconder-ky-040-arduino-argentina-
ptec/
Enconder KY 040
#include <Encoder.h>
void setup() {
Serial.begin(9600);
Serial.println(Basic Encoder Test:);
}
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
}
Materiales:
Arduino Uno.
Rotary encoder
http://bildr.org/2012/08/rotary-encoder-arduino/
Rotary Encoder + Arduino
One of the first things anyone does when they start working with the
Arduino is to connect it to a potentiometer and control the brightness
of and LED or move a servo. Well, a rotary encoder may look like a
potentiometer, but other than also having a knob, it is basically the
complete opposite.
A rotary encoder is a device that you can rotate infinitely. Simple ones
like this one I got from sparkfun have no real state like a pot does, so
when you start up, you wont be able to simply read from the encoder
where it is turned to. But because you can keep turning it it has no
beginning, middle or end anyways. However, if you keep track of that
rotation in code, you can use it as a knob input you can turn up or
down as much as you would like.
On most rotary encoders, when you rotate them, you will feel a bump.
These are known as steps, and most rotary encoders like this guy have
about 12 of these per rotation. But some have 200 or more. Basically
this step is the minimum amount you can rotate the encoder to
register any change.
Most simple encoders like this only make use of 3 pins, and one of
those is ground. Those other two pins change state and are always
either high or low, so they can only have a total of 4 combinations. 00,
01, 10, and 11. This is known as 2 bit gray code. So when you turn it,
the arduino can say Well you were at 01, and now you are at 00 so
you move this way. Or you were at 01, but now you are at 10 so you
must have moved the other way. You can see that this encoder has 5
pins, the other 2 are just a simple switch that is engaged when you
press down. (see the second illustration on the right)
It sounds super simple, and it kinda is, but what we can do is every
time a value changes we can check what direction it moved. Then if
we increment a value every time it turned one way, and deincrement it
when we move one step the other, we can keep track of how much it
has moved since we started. So if you want a knob that can turn up to
11, this is your guy. (there is a double pun in there I promise)
So, the really funky thing about a rotary encoder is for it to work, we
need to know every time those values change. This can be hard
because if the arduino is in the middle of doing something, like
delay(1000) or what have you, we will miss the change. So we need a
way to say to the arduino I dont care what you are doing, or when
you are doing it, if you see any of these two pins change state, you
drop everything and attend to them. To do this we need something
called interrupts.
Any global variables that are used inside these functions have a
special name. They are called volatile variables, and for good reason.
Their values can change at any time. So if you use a volatile twice in
your loop, it may not be the same value the second time if it was
change during an interrupt function.
Code
To keep track of the rotary encoder we are going to do something that
will look really weird, so bear with me. The encoder has 2 digital pins
that are either HIGH (1) or LOW (0) right? If we treat the pins as binary,
we read them as 00, 01, 10, or 11. The sequence the encoder outputs
while spinning clockwise is 00, 01, 11, 10 repeat. So if you have a
reading of 01, the next reading can either be 00 or 11 depending on
the direction the knob is turned. So by adding the previous encoded
value to the beginning of the current encoded value we get 1 of 8
possible numbers (0001, 0010, 0100, 0111, 1000, 1011, 1110 & 1101)
1101, 0100, 0010 & 1011 all mean cockwise movement. 1110, 0111,
0001 & 1000 are all counter-clockwise.
void setup(){
Serial.begin(9600);
pinMode(encoderPin1,INPUT);
pinMode(encoderPin2,INPUT);
void loop(){
//Do stuff here
Serial.println(encoderValue);
delay(1000);//just here to slow down the output, and show it will work
even during a delay
}
void updateEncoder(){
int MSB =digitalRead(encoderPin1);//MSB = most significant bit
int LSB =digitalRead(encoderPin2);//LSB = least significant bit
void setup(){
Serial.begin(9600);
pinMode(encoderPin1,INPUT);
pinMode(encoderPin2,INPUT);
pinMode(encoderSwitchPin,INPUT);
void loop(){
//Do stuff here
if(digitalRead(encoderSwitchPin2)){
//button is not being pushed
}else{
//button is being pushed
}
Serial.println(encoderValue);
delay(1000);//just here to slow down the output, and show it will work
even during a delay
}
void updateEncoder(){
int MSB =digitalRead(encoderPin1);//MSB = most significant bit
int LSB =digitalRead(encoderPin2);//LSB = least significant bit
http://www.instructables.com/id/Arduino-Rotary-Encoder-Simple-
Example-KY-040/
Step 1: Schematic Code & Parts List.
Parts List.
Good luck!
KY-040_ROTARY_ENCODER.ino
http://www.arduinoecia.com.br/2015/08/como-usar-encoder-rotativo-
ky-040-arduino.html
Como utilizar um encoder rotativo com Arduino
Conhece o encoder rotativo ? Por fora, ele um componente muito
parecido com um potencimetro, mas internamente funciona de uma
forma bem diferente, sendo um componente interessante para voc
utilizar com seus projetos para Arduino. Eu utilizei um mdulo encoder
KY-040 para criar um pequeno sistema de seleo com display LCD
20x4.