Como se maneja un encoder con el PIC?

Hola estebanfolcher.

Estuve mirando tu programa en assembler (encoder2.txt) y funciona correctamente, necesitaba cambiar la conexión de los pines del encoder de puerto por ejemplo al puerto B.
Como cada uno tiene su forma de programar y llevo un rato mirando como cambiarlo (no tiene que ser muy complicado) pero los cambios que he hecho solo me permiten incrementar un registro,gire tanto a la derecha como a la izquierda y no se que error debo de estar cometiendo.

Por otro lado queria saber si es necesario utilizar un puerto entero para conectar el encoder (utilizas el puerto A), no se si seria mejor utilizar un registro auxiliar y mover los bits activados del puerto A a ese registro y hacer las operaciones con el mismo.

He decidido no modifcar mucho tu programa para saber si me puedes dar alguna idea.

Te envío el código de lo que he modificado, es muy poco pero creo que por ahí van los tiros.

Creo que este codigo en ensamblador es el indicado para la aplicación de este tema.

Espero tu contestación.
 

Adjuntos

  • encoder2.txt
    2 KB · Visitas: 46
Hola. ¿Me pueden ayudar con estas practicas de un encoder para encender un led y apagarlo? Gracias.
 

Adjuntos

  • encoder pruebas.rar
    98.4 KB · Visitas: 6
Hola. Subo el código.
H
ace un parpadeo, es mal como lo planteé en el while.
Código:
#include <12f683.H>
#device ADC=10
#use delay(clock=4mhz)
#fuses intrc_io,nomclr,nowdt


int8   ciclo_activo=1;
//signed
#define A pin_A0
#define B pin_A1

void leer()
{

if ((input_state(A)==0)&&(input_state(B)==0)){
ciclo_activo++;
  if (ciclo_activo > 249) ciclo_activo = 249;   // No permitir que el ciclo activo suba de 249
      delay_ms(10);
}


if ((input_state(A)==0)&&(input_state(B)==1)){
ciclo_activo--;
       if (ciclo_activo <= 1) ciclo_activo = 2;
       delay_ms(10);
}


}


void main()
{  
   enable_interrupts(int_ext);
   ext_int_edge(0,L_TO_H);
   enable_interrupts(global);
 setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_4,249,1);  
 


while(True)
{
leer();

 set_pwm1_duty(ciclo_activo);

}
}
 
Gracias por el arduino, no lo conocía y resolví todo ahí, ahora conviene seguir con los pic o darle al arduino, con pic no hay muchos ejemplos y tenes que pedir por favor de rodillas una ayuda, no pude resolver con el pic lo del encoder una lástima
 
El encoder usa un sistema de cuadraturas.
No hace falta nada especial, solo entender el funcionamiento y de ahi hacen el codigo.
Yo lo hice para PIC y Atmel (Arduino).
Dejo un paper para leer
 

Adjuntos

  • Encoders-jvr-v01.pdf
    45.4 KB · Visitas: 14
Gracias por el arduino, no lo conocía y resolví todo ahí, ahora conviene seguir con los pic o darle al arduino, con pic no hay muchos ejemplos y tenes que pedir por favor de rodillas una ayuda, no pude resolver con el pic lo del encoder una lástima
1- Con PICs en Lenguaje Assembler, hay mucho ejemplo de casi todo, al detalle en el sitio del fabricante, lo que si debes manejar bien,es el ingles técnico para o comprender mal los detalles.
Con Assembler puedes hace todas las cosas que no puedes hacer con lenguaje C , de otro modo el fabricante, no se hubiera tomado tantas molestias en producirlo . ¿no le parece ? ;)
2- Los enconders en general son dispositivos de entrada para un procesador, ya que le proveen información posicional , sea esta lineal o angular, no la reciben.
Por ende, no son manejables, salvo mediante algún otro dispositivo externo lineal o angular que reposicione el encoder mediante SERVO por ejemplo.
:rolleyes:
 
Este código lo hice varios códigos que fui viendo, funciona bien en el attiny85, lo único que dudo es como guarda en la memoria eeprom con el pin al aire funciona bien, con una resistencia a vcc no guarda siempre, cual es la forma correcta de conectar if(digitalRead(m)==LOW cuando esta en bajo guarda, pero si siempre esta en estado bajo no esta guardando todo el tiempo?
Código:
#include "avr/interrupt.h";
#include <EEPROM.h>
int cont3;
int m = 7;
volatile int value;
volatile int lastEncoded = 0;


void energia (){
if(digitalRead(m)==LOW){
cont3++;
delay(1);
if (cont3 >5) {
 EEPROM.put(0,value);
delay(50);
cont3 = 0;
}
}
}
void setup()
{
    EEPROM.get(0, value);
  pinMode(0, OUTPUT);


 
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  pinMode(m, INPUT);


GIMSK = 0b00100000;       
PCMSK = 0b00011000;       
  
  
  sei();                   
}
 
void loop()
{
   energia ();
  analogWrite(0, value);
}
 

ISR(PCINT0_vect)
{
  int MSB = digitalRead(3);
  int LSB = digitalRead(4);
 
  int encoded = (MSB << 1) |LSB;
  int sum  = (lastEncoded << 2) | encoded;
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
    value++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
    value--;
 
  lastEncoded = encoded;
 
  if (value <= 0)
    value = 0;
  if (value >= 255)
    value = 255;
}
 
Este código lo hice varios códigos que fui viendo, funciona bien en el attiny85, lo único que dudo es como guarda en la memoria eeprom con el pin al aire funciona bien, con una resistencia a vcc no guarda siempre, cual es la forma correcta de conectar if(digitalRead(m)==LOW cuando esta en bajo guarda, pero si siempre esta en estado bajo no esta guardando todo el tiempo?
Código:
#include "avr/interrupt.h";
#include <EEPROM.h>
int cont3;
int m = 7;
volatile int value;
volatile int lastEncoded = 0;


void energia (){
if(digitalRead(m)==LOW){
cont3++;
delay(1);
if (cont3 >5) {
 EEPROM.put(0,value);
delay(50);
cont3 = 0;
}
}
}
void setup()
{
    EEPROM.get(0, value);
  pinMode(0, OUTPUT);


 
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  pinMode(m, INPUT);


GIMSK = 0b00100000;     
PCMSK = 0b00011000;     
 
 
  sei();                 
}
 
void loop()
{
   energia ();
  analogWrite(0, value);
}
 

ISR(PCINT0_vect)
{
  int MSB = digitalRead(3);
  int LSB = digitalRead(4);
 
  int encoded = (MSB << 1) |LSB;
  int sum  = (lastEncoded << 2) | encoded;
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
    value++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
    value--;
 
  lastEncoded = encoded;
 
  if (value <= 0)
    value = 0;
  if (value >= 255)
    value = 255;
}
Leyendo la letra chica del fabricante, se puede leer lo siguiente respecto a grabar / leer en la eeprom interna de ese dispositivo:

Reading EEPROM at low frequency may not work for frequencies below 900 kHz
Reading data from the EEPROM at low internal clock frequency may result in wrong data
read.
Problem Fix/Workaround
Avoid using the EEPROM at clock frequency below 900kHz.


De paso, le sugiero no abusar de la escritura en las EEPROM , trate que en su proyecto se la use solo para tomar referencias distanciadas en el tiempo, como por ejemplo , poner una referencia de calibración duradera o algo asi como un dato para conservar por largo tiempo.
Para decirlo fácil, si usted graba un dato a razón de, supongamos, uno dato por minuto, a las pocas semanas se quedará sin las funciones de EEPROM. No es una RAM y su principio de funcionamiento se basa en atrapar una partícula en un campo.

Espero le sirva
 
Última edición:
Leyendo la letra chica del fabricante, se puede leer lo siguiente respecto a grabar / leer en la eeprom interna de ese dispositivo:

Reading EEPROM at low frequency may not work for frequencies below 900 kHz
Reading data from the EEPROM at low internal clock frequency may result in wrong data
read.
Problem Fix/Workaround
Avoid using the EEPROM at clock frequency below 900kHz.


De paso, le sugiero no abusar de la escritura en las EEPROM , trate que en su proyecto se la use solo para tomar referencias distanciadas en el tiempo, como por ejemplo , poner una referencia de calibración duradera o algo asi como un dato para conservar por largo tiempo.
Para decirlo fácil, si usted graba un dato a razón de, supongamos, uno dato por minuto, a las pocas semanas se quedará sin las funciones de EEPROM. No es una RAM y su principio de funcionamiento se basa en atrapar una partícula en un campo.

Espero le sirva
Entiendo, voy a colocarle una resistencia 10k en el pin de lectura a vcc y que solo guarde si se corta la tensión de alimentación! Gracias por la data!
 
si se puede hacer por software
algo que puedes hacer cuando se te acaban los registros especiales o el hardware especial es que puedes emular todo lo que se te ocurra.
eso si gastas memoria y ciclos de reloj

aca te dejo un codigo que use , esta escrito en lenguaje C del PICC COMPILLER de CCS


PHP:
#include...
#Byte portb = 0xF81


   char   enc;  // Se almacenará el valor actual de RA0 y RA1, hasta la siguiente comparación.
   char   aux;  // Se almacenará el valor anterior de RA0 y RA1, hasta la siguiente comparación.
 
unsigned char ILIM;//incrementa o decrementa mi corriente maxima

while(1)
{

//--------AQUI SE LEE EL ENCODER -----------------------------------//
            aux=enc;               // Igualamos 'AUX' y 'ENC' para luego comparar cuando cambie 'ENC'.
            enc=portb & 3;         // Aislamos RA0 y RA1 como un número de 2 bits y se carga en la variable 'ENC'.
         
            if ((aux==2)&&(enc==3))// Si en la comparación hay flanco de subida,
            { 
               ILIM++;               // entonces incrementar una unidad el valor de X.
      
            }
         
            if ((aux==3)&&(enc==2))// Si en la comparación hay flanco de bajada,
            { 
               ILIM--;               // entonces decrementar una unidad el valor de X.
               if(ILIM<=1)
               {
                  ILIM=1;
               }
            }
        //--------------------SE DEJO DE LEER EL ENCODER---------//

/*
TU CODIGO
*/


}
Hola, no entiendo esta parte del codigo enc=portb & 3; // Aislamos RA0 y RA1 como un número de 2 bits y se carga en la variable 'ENC'.
como ailamos ra0 y ra1?
 
Hola, no entiendo esta parte del codigo enc=portb & 3; // Aislamos RA0 y RA1 como un número de 2 bits y se carga en la variable 'ENC'.
como ailamos ra0 y ra1?

Haciendo una operación lógica "AND" ("&") con el numero 3 (00000011 en binario) enmascaramos el dato leído para extraer solo los dos bits que nos interesa. Si se prefiere, esa instrucción lo que hace es poner a "0" todos los bit excepto los dos primero (bits 0 y 1, osea los dos de la derecha) que son los que representan el contenido del puerto RB1 y RB0 (Que por cierto esta mal escrita la descripción ya que no se lee sobre el puerto A sino sobre el B).

Una vez realizada la operación AND, "enc" solo podrá valer: 00000000(0), 00000001(1), 00000010(2) o 00000011(3).
 
Atrás
Arriba