# Como se maneja un encoder con el PIC?



## ivan_mzr (Abr 7, 2009)

No entiendo como se debe de manejar un encoder con un microcontrolador, por ejemplo, tecnicamente no puedes usarlo como un switch por que cambia su estado en cada vuelta, por decirlo de una forma: esta en normalmente abierto al girarlo se cierra y queda en este estado, al girarlo un poco mas se abre y otra vez se queda en este estado. Como hay que manejar esto? alguien a visto algun ejemplo? de preferencia en asm. Si, es la primera vez que intento usar un encoder y estoy totalmente verde.


----------



## maurorgonzalez (Abr 8, 2009)

No puedo creer que tengas tanta suerte... justo acabo de realizar un programa para 16f84a y un compañero para el 18f4550. te dejo los dos para ayudarte. Claro uno en asm y el otro en C

ambos sirven.... el que yo hice es mas barato, solo eso...

PD: Lo hice para la facultad.


----------



## ivan_mzr (Abr 8, 2009)

Muchas gracias!, pues bajando y checando. Oye ya que te moleste, no podras postear tu squematico pa ver como lo utilizas? tambien utilizaste un encoder incremental? aqui dejo el link del fabricante lo olvide poner antes:
http://www3.alps.com/WebObjects/catalog.woa/E/HTML/Switch/Encoder/EC11J/EC11K1525401.shtml


----------



## maurorgonzalez (Abr 8, 2009)

en realidad estaba con poco tiempo, pero debo explicarte que hacen los programas.

emiten una señal para el driver de un motor paso a paso, siendo medido por el encoder.... pero que a su ves, la señal es recibida del pc. Osea... con la PC pido que de 1/16 vuelta, y el motro lo hace hasta que el encoder mide que se realizo eso.

los encoder trabajan con una señal defasada (90ª) en la señal A y B en relacion de si va hacia adelante o hacia atras, no estoy seguro que es lo que se te complica, porque no me lo aclaras muy bien. Pero te puedo asegurar que vos deberias trabajar con las interrupciones, para poder ver las señales (sincronizarlas con el pic).

siempre pensa en el hecho tambien de las frecuencias que se manejan, mi programa en ASM esta ideado para 20 khz de señales de entrada/salida maxima, aprox. (debido a la "DEMORA" que cree. y la cantidad de pasos que tiene). Pensando en que mi PIC trabaja a 4mhz. (en realidad la salida es la que sale lenta.)


----------



## ivan_mzr (Abr 8, 2009)

Lo que quiero hacer con este es lo siguiente: Tengo un reloj y para cambiar la hora(por ejemplo) utilizo dos switch uno para aumentar y otro para disminuirla, simplemente quiero quitar los interruptores y usar este encoder si gira para la izq disminuye y para la derecha aumenta.
 Viendo tu codigo se me ocurrio una forma, voy a intentar armar algo y lo pongo. 
Como puedes ver no voy a ser algo muy sofisticado.


----------



## maurorgonzalez (Abr 8, 2009)

mmmm... solo de curioso no mas....  crei que los encoder siempre eran cosas de alta precision, donde la mecanica no entra,( voy a tener que averiguar de eso... ) y tampoco son para lugares donde hay 2 posciones, incluso son para "MEDIR".         

Bueno me alegro que te halla servido, y sobre todo me alegro que te haya sido util mi programa.


----------



## ivan_mzr (Abr 8, 2009)

Bueno aqui hay una confusion mia, porque yo sabia que los encoder (en un topico mecanico) eran los que son discos perforados 
	

	
	
		
		

		
		
	


	




el detalle es que la mayoria de los aparatos nuevos de audio, que trabajan digitalmente utilizan una especie de potenciometro "digital" y al abrirlos puedes verlos, investigue un poco y al buscar al fabricante (ALPS http://www.alps.com/ ) este los llama encoders ò switch/encoder y trabajan internamente de forma mecanica, bueno este es el tipo de encoder que quiero utilizar,  espero no haber expresado mal mi primer post y haberte confundido.


----------



## ivan_mzr (May 13, 2009)

Hice un programilla pero es sin utilizar interrupciones para el tipo de uso que le pienzo dar creo que estara bien, aqui dejo el codigo y un video funcionando.



```
list	p = 12F675

	#include	P12F675.inc

	ERRORLEVEL -302

	__CONFIG	( _PWRTE_OFF & _BODEN_OFF & _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT  )
	

PDEL1    	EQU     0x20
PDEL2    	EQU     0x21	
PDEL3		EQU		0x22 
DEL1		EQU		0x23
DEL2		EQU		0x24

LFE			EQU		0x25
RFE			EQU		0x26
LFEC		EQU		0x27
RFEC		EQU		0x28

RETARDO		EQU		0x29


;-------------------------------------------------------------------

start
	ORG	0x00

	bcf 	STATUS,RP0 	;Bank 0
	bcf 	INTCON,GIE 	;Desabilita INTs 
	movlw 	07h 		; GP<2:0>  
	movwf 	CMCON 		;digital IO
	bsf 	STATUS,RP0 	;Bank 1
	clrf 	ANSEL 		;Digital I/O
	movlw 	B'00111000'	;GP<0,1,2> salidas GP<3,4,5> entradas
	movwf 	TRISIO 		;se carga la configuracion

	bcf 	STATUS,RP0 	;Bank 0

	clrf	GPIO		;limpia el puerto

	clrf	LFE
	clrf	RFE






INICIO
	call	ENCODER		;llama a checar el encoder
	call	REGRESA		;en regresa vuelve al estado normal
	goto	INICIO		;bucle


REGRESA
	bcf		GPIO,0		;apaga el led 
	bcf		GPIO,2		;apaga el led
	bsf		GPIO,1		;enciende el led de enmedio
		RETURN			;regresa


DER	bcf		GPIO,1		;apaga el led
	bcf		GPIO,0		;apaga el led
	bsf		GPIO,2		;enciende el led del pin 5
	call	DEMORA		;llama a un retardo
		RETURN			;regresa


IZQ	bcf		GPIO,1		;apaga el led
	bcf		GPIO,2		;apaga el led
	bsf		GPIO,0		;enciende el led del pin 7
	call	DEMORA		;llama un retardo
		RETURN			;regresa



ENCODER
	movfw	LFE			;el valor previo se carga a w
	movwf	LFEC		;y se guarda para compararlo
	movfw	RFE			;el valor previo se carga a w		
	movwf	RFEC		;y se guarda para compararlo
	

	bcf		RFE,0		;se pone en 0 el bit
	btfsc	GPIO,4		;si se detecta lo contrario se cambia
	bsf		RFE,0		;a uno


	bcf		LFE,0		;se pone en 0 el bit
	btfsc	GPIO,3		;si se detecta lo contrario se cambia
	bsf		LFE,0		;a uno
		
	movfw	RFE			;se carga a w el registro nuevo detectado
	xorwf	LFE,0		;se hace una operacion or exlusica buscando un cambio
	btfsc	STATUS,Z	;si esto no ocurre se regresa al llamado
		RETURN
	
	movfw	LFE			;si ocurre se carga a w el registro recien ingresado
	xorwf	LFEC,0		;y se compara con el anterior
	btfss	STATUS,Z	;si son diferentes llama a una funcion
	goto	IZQ			;en este caso IZQ
		
	movfw	RFE			;si ocurre se carga a w el registro recien ingresado
	xorwf	RFEC,0		;y se compara con el anterior
	btfss	STATUS,Z	;si son diferentes llama a una funcion
	goto	DER			;en este caso DER
		RETURN			
		



		


;-------------------------------------------------------------
;RETARDOS
;-------------------------------------------------------------

DEMORA  
 	movlw   .3				;Carga un numero para la DEMORA
 	movwf   PDEL3			;en este Registro
	movlw	.150 	     	;Obtiene el valor del retardo  
 	movwf   PDEL2			;en este Registro
 	movlw   .255			;Carga un numero para la DEMORA
 	movwf   PDEL1			;en este Registro
 	decfsz  PDEL1,1			;Decremente el segistro
 	goto    $-1				;hasta que llega a 0 y salta esta instruccion
	decfsz  PDEL2,1			;Decremente el registro
 	goto    $-5				;hasta que llega a 0 y salta esta instruccion
	decfsz  PDEL3,1			;Decremente el registro
 	goto    $-9				;hasta que llega a 0 y salta esta instruccion	
		RETURN	              

	



	END
```



YouTube - Encoder con PIC


----------



## felixls (May 14, 2009)

Aquí puedes encontrar lo que buscas:
http://www.mcmanis.com/chuck/robotics/projects/lab-x3/quadratrak.html

Implementé esta fuente de alimentación digital que utilizan estos conceptos con un encoder, en mi caso es mecánico:

http://sergiols.blogspot.com/

saludos.


----------



## Oceano (Jul 21, 2010)

Te pongo un PIC Encoder. Funciona perfectamente y está probado. Tienes el esquema, y dos versiones para programarlo, en *CCS* y en *Proton IDE.*

Funciona por la interrupción *RB0/INT.* Es la más rápida y realmente puede llegar a contar muy rápido. Lo probé poniéndolo en el eje de un motor de 3V y no pierde pulsos. Probar uno de los dos códigos sólo te llevará un momento.






*Código en CCS:*


```
#Include <16F876A.h>            // Usamos el PIC 16F876A.

#FUSES NOWDT, XT, PUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT

#Use Delay(clock=4000000)       // Usamos un cristal de 4MHz, por ejemplo. 

#ZERO_RAM                       // Variables a cero.

#byte porta = 0x05              // Asignamos PortA
#byte portb = 0x06              // Asignamos PortB
#byte portc = 0x07              // Asignamos PortC

// ------ Variables Globales ------
int8   x = 0;                   // Declaramos el valor de X como Byte, es decir, 8 bits.
                                // Esta variable ha de ser global porque su valor lo usaremos
                                // en la interrupción y en el programa principal.

// --------- Interrupción ---------
#INT_EXT                        // Interrupción: Decodificación de Encoder.
void IntRB0() 
{
   // CCS se encarga de desactiva automáticamente cualquier interrupción.
   // No hace falta guardar contextos de registros, al menos con el PIC 16F876A.

   if (bit_test(portb, 0))      // Si PortB.0 = 1,
   {  
       ext_int_edge(H_TO_L);    // entonces activar la siguiente interrupción para flanco de bajada. 
       if (bit_test(portb, 1))  // Si PortB.1 = 1,
       {
           x++;                 // entonces incrementar una unidad el valor de X.
       }
   }
   else                         // Si PortB.0 = 0, 
   {  
       ext_int_edge(L_TO_H);    // entonces activar la siguiente interrupción para flanco de subida.
       if (bit_test(portb, 1))  // Si PortB.1 = 1,
       {
           x--;                 // entonces decrementar una unidad el valor de X.
       }
   }
   // Al finalizar la interrupción CCS se encarga de volver a poner automáticamente
   // la badera INTF = 0 ---> borra la interrupción para poder permitir la siguiente;
   // no hemos de hacer nada por nuestra parte, al menos con el PIC 16F876A.
}

void main()                     // Inicio y configuración.
{
   port_b_pullups(FALSE);       // Configuración para el PIC 16F876A.
   setup_adc_ports(NO_ANALOGS); // Sin comparadores ni ADCs, todo digital, etc...
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   enable_interrupts(int_ext);  // Activar Interrupción Externa. 
   ext_int_edge(L_TO_H);        // Inicialmente detectar interrupción por flanco de subida. 
   enable_interrupts(GLOBAL);   // Interrupciones Generales Activadas. 

   set_tris_a(0b111111);        // Puerto A todo entradas (en este caso no usamos el Puerto A).
   set_tris_b(0b11111111);      // Puerto B todo entradas (sólo usamos las entradas RB0 y RB1).
   set_tris_c(0b00000000);      // Puerto C todo salidas  (8 bits que irán a los LEDs).

   // ---------- Programa Principial ----------

   While (True)
   {
          portc = x;            // El valor de X sale por el Puerto C a los 8 LED de salida. 
   }      
   
}
```

*Código en Proton IDE:*


```
Device=16F876A

REMINDERS = FALSE
     Config XT_OSC, PWRTE_ON, CPD_OFF, WDT_OFF, BODEN_OFF, LVP_OFF
REMINDERS = TRUE

Symbol INTF   = INTCON.1         ' RB0 External Interrupt Flag
Symbol INTE   = INTCON.4         ' RB0 External Interrupt Enable
Symbol GIE    = INTCON.7         ' Global Interrupt Enable
Symbol INTEDG = OPTION_REG.6     ' Flag = 0 int. por flanco bajada. Flag = 1 int. por flanco subida.

On_INTERRUPT GoTo Interrupcion   ' Interrupción por Hardware (es la más rápida).

GIE    = 1                       ' Activa interrupciones generales.
INTE   = 1                       ' Activa la interrupción externa RB0/INT.
INTEDG = 1                       ' Hace que inicialmente la interrupción se habilite
                                 ' para flanco de subida.

ALL_DIGITAL = TRUE               ' Todas las entradas y salidas son digitales.
                                                                              
TRISA  = %111111
TRISB  = %11111111               ' Puerto A y B todo entradas.
TRISC  = %00000000               ' Puerto C como salida para visualizar a través de los LED.
           
Dim x As  Byte                   ' Variable X ---> contador de posición actual con resolución 0..255


x=0                              
 
While 1=1                        ' |------ Programa Principal ------|
     
     PORTC = x                   ' El contenido de X se visualiza en el Puerto C a través de los LED.

Wend                             ' |--------------------------------|
             
End                              

    
Interrupcion:                 '-------- Decodificador de Encoder --------------
       
    Context SAVE              ' Salva en contexto de los registros antes de operar con la interrupción.
    
    If PORTB.0 = 1    Then    ' Si RB0 se ha puesto a 1 (flanco de subida),
       INTEDG  = 0            ' entonces activar la siguiente interrupción para flanco de bajada.
       If PORTB.1 = 1 Then    ' Si RB1 está a 1,
          Inc x               ' entonces incrementar el contador X.
       EndIf
    EndIf
    
    If PORTB.0 = 0    Then    ' Si RB0 se ha puesto a 0 (flanco de bajada),
       INTEDG  = 1            ' entonces activar la siguiente interrupción para flanco de subida.
       If PORTB.1 = 1 Then    ' Si RB1 está 1,
          Dec x               ' entonces decrementar el contador X.
       EndIf
    EndIf
     
    INTF = 0                  ' Borra el "flag" de la interrupción RB0/INT para poder permitir la   
                              ' siguiente interrupción cuando ocurra.
    Context Restore           ' Restablece el contexto de los registros tal como estaban antes de la
                              ' interrupción.
```

Más información aquí:
http://sites.google.com/site/proyectosroboticos/encoder/encoder-por-software


----------



## gmendozafiee (May 29, 2012)

yo compre un motor con encoder y me vino con 6 hilos que porque tantos hilos ?


----------



## estebanfolcher (Feb 27, 2013)

aqui te dejo dos uno para encoder rotativo de giro loco y el otro de auto posicionado
use un pic 16f84 en los pines ra0 y ra1 puse el encoder  ( pin A y B el comun  a 5V)
y en el puerto b 8 led. con esto podras ver el funcionamiento


PD: parti de este pdf


----------



## orlamarilla (Mar 28, 2014)

hola. estuve mirando sus ejemplos. Lo que yo necesito es un contador que incremente o decremente segun el giro de un encoder rotativo tipo potenciometro, este contador se visualiza en un display lcd de 16x2. Lo estoy trabajando con el pic 16f84 pero me parece que la forma de hacerlo es por interrupciones por cambio de estado de los pines RB4 a RB7. Estoy armando el código pero no se si debería hacerlo de esa manera o por interrupciones por RB0


----------



## orlamarilla (May 16, 2014)

nuevamente escribo por que no recibí respuesta alguna y la verdad sigo sin entender como plantear el código en assembler para incrementar o decrementar un contador leyendo un encoder rotativo. Me gustaría poner algún avance pero la verdad es que no se ni como empezar.Vi muchos ejemplos pero no los entiendo


----------



## Scooter (May 16, 2014)

De pics ni idea, hace mil años que no uso uno.
Hace poco hice el código con Arduino de lo mas sencillo.
Una de las señales a una interrupción, si al recibirla la otra es 0 es que gira en un sentido y si es 1 es que es el contrario. Dos líneas de código.


----------



## orlamarilla (May 16, 2014)

hola. estoy utilizando el pic16f84 y los pines de interrupciones por rb0 o de cambio de estado(rb4 a rb7) ya los tengo ocupados. Necesito un ejemplo de rutina que sea capaz de distinguir el sentido de giro

los ejemplos que vi no los llego a comprender bien por eso mi duda


----------



## Scooter (May 16, 2014)

Entonces está complicado, hay que detectar un flanco en uno de los pines y ver en ese momento como está el otro pin, eso consume mucha cpu


----------



## TRILO-BYTE (May 16, 2014)

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



```
#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
*/


}
```


----------



## orlamarilla (May 16, 2014)

gracias por las respuestas. voy a tratar de interpretar y pasar a assembler ese ejemplo


----------



## orlamarilla (May 26, 2014)

buenas. estuve tratando de interpretar el código en ccs pero no me queda bien en claro. Si no es molestia me vendría bien una mano para la interpretación y adaptación del código en lenguaje ensamblador. Muchas gracias.


----------



## Cristobal981 (Jul 27, 2014)

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.


----------



## callecuatro1976 (Jul 31, 2021)

Hola*. **¿M*e pueden ayudar con estas practicas de un encoder para encender un led y apagarlo*? G*racias*.*


----------



## callecuatro1976 (Ago 1, 2021)

Hola*. S*ubo el c*ó*digo*.
H*ace un parpadeo*,* es*tá* mal como lo plante*é* en el while.

```
#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);

}
}
```


----------



## callecuatro1976 (Ago 19, 2021)

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


----------



## DJ T3 (Ago 19, 2021)

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


----------



## unmonje (Ago 19, 2021)

callecuatro1976 dijo:


> 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.


----------



## callecuatro1976 (Ago 20, 2021)

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?

```
#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;
}
```


----------



## unmonje (Ago 20, 2021)

callecuatro1976 dijo:


> 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?
> 
> ```
> #include "avr/interrupt.h";
> ...


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


----------



## callecuatro1976 (Ago 20, 2021)

unmonje dijo:


> 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
> ...


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!


----------



## callecuatro1976 (Sep 16, 2021)

TRILO-BYTE dijo:


> 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
> 
> ...


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?


----------



## switchxxi (Sep 16, 2021)

callecuatro1976 dijo:


> 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).


----------



## callecuatro1976 (Sep 16, 2021)

Ahí esta, no entendía como estoy usando el puerto b y leo ra0 y ra 1, si lo quiero hacer en el puerto A es solo cambiar de puerto?


----------



## switchxxi (Sep 16, 2021)

Si, solo se cambia al puerto A. Solo hay que tener la precaución de que esos pines esten bien configurados como entradas digitales.


----------



## callecuatro1976 (Sep 16, 2021)

Que pic de 14 pines sería ideal con oscilador interno?


----------



## switchxxi (Sep 16, 2021)

callecuatro1976 dijo:


> Que pic de 14 pines sería ideal con oscilador interno?



Acá elegí el que mas quieras. (No se si es un token para mi y no las opciones de los filtros, de todas formas, si no aparece ya filtrado, seleccionas en los filtros las características que buscas y listo).


----------

