#include <Wire.h>
#define servo 2
int conC=0;
int conD=0;
int conU=0;
int ren[]={27,14,12,13}; //pines para los renglones
int colum[]={32,33,25,26};//pines para las columnas
int esp=20;
int angulo=0;
int posi=0;
byte johnson;
byte tecla;
byte col=0x0f;
byte PCF_addr=0x27; //direccion para la lcd
byte uni=0;
byte dec=0;
byte cen=0;
bool teclaActiva=0;
bool rw=0; //lcd
bool rs;//lcd
bool LED=1;//lcd
char conf []={3, 3, 3, 2, 2, 8, 0, 14, 0, 1, 0, 6}; //configuración para la lcd
char tiempos []={15, 5, 1, 1, 1, 1, 1, 1};
char msj1[] = {"Ang.Deseado= "}; //para la lcd
char msj2[] = {"Ang.Real= "}; //para lcd
hw_timer_t*timer= NULL; //inicializador del timer para el contador johnnson
void setup(){
pinMode(servo, OUTPUT);
Serial.begin(9600);
for (byte i=0;i<=3;i++){
pinMode(ren[i],OUTPUT);
pinMode(colum[i],INPUT_PULLUP);
}
//Poner el contador johnson en su valor inicial
johnson=0xfe;
timer=timerBegin(0,80,true);
timerAttachInterrupt(timer,cnt_johnson,true);
timerAlarmWrite(timer,20000,true);
timerAlarmEnable(timer);
//Configuración de LCD
Wire.begin();
rs=0;
for(byte i=0; i<=11; i++){
delay(tiempos[i]);
send_Nibble(conf[i],LED,rs,rw);
}
//Configuración de mensaje 1 PARA LA LCD
rs=1;
for(byte i=0; i<=13; i++){
send_byte(msj1[i]);
}
//Configuración de mensaje 2 y posicionar LCD en segunda linea
rs=0;
send_byte(0xc0);
rs=1;
for(byte i=0; i<=10; i++){
send_byte(msj2[i]);
}
}
//funcion para detectar teclados
void cnt_johnson(){
col=(digitalRead(colum[3])<<3)|(digitalRead(colum[2])<<2)|(digitalRead(colum[1])<<1)|(digitalRead(colum[0]));
if (col == 0x0f){
byte m,j,i;
teclaActiva = 0;
johnson= (johnson << 1)| 0x01;
//Regresar el contador johnson a su valor inicial
if(johnson == 0xef)
johnson= 0xfe;
m= 3;
for(i=0; i <=3 ; i++){
j=pow(2,m);
digitalWrite(ren[i],(johnson & j));
m--;
}
}
}
//funcion para enviar los nibbles para lcd
void send_byte(char N){
byte carac= N >> 4;
send_Nibble(carac, LED, rw, rs);
send_Nibble(N, LED, rw, rs);
}
//para la lecd
void send_Nibble(byte N, byte L, byte W, byte S) {
byte dato=(N << 4) | (L << 3) | 0x04 | (W << 2) | S;
Wire.beginTransmission(PCF_addr);
Wire.write(dato);
Wire.endTransmission();
delay(10);
dato= dato & 0xfb;
Wire.beginTransmission(PCF_addr);
Wire.write(dato);
Wire.endTransmission();
}
//para el movimiento del servo
void movi(int pin, int an){
float pul;
pul=an * 1800.0/180.0 + 500;
digitalWrite(pin, HIGH);
delayMicroseconds(pul);
digitalWrite(pin, LOW);
}
void loop(){
if(col != 0x09){ // bandera
//No repetir el número si la tecla sigue presionada
if(teclaActiva == 0){
teclaActiva=1;
//Recorrer los 4 bits utilizables del contador johnson y agregar los de las columnas para iniciar el switch
byte rengcol=(johnson << 4) | col;
switch(rengcol){
//La letra A funciona como nuestro boton de enter
case 0b11101110: //la letra A
//Juntamos centenas, decenas y unidades en una variable para tenerlos como un solo número
angulo=cen*100+dec*10+uni;
//Empezar con el incremento del contador para cuando se ponga un número mas grande que el anterior
if(angulo>=posi){
for(int i=posi;i<=angulo;i++){
movi(servo, i);
delay(esp);
rs=0;
send_byte(0xcc);
rs=1;
if (conC == 0){
send_byte(0x20);
}
else{
send_byte(0x30 | conC);
}
if ((conC == 0) && (conD == 0)){
send_byte(0x20);
}
else{
send_byte(0x30 | conD);
}
send_byte(0x30 | conU);
conU++;
//Cuando las unidades lleguen a 9 se regresan a 0 y comienza el incremento de una decena
if(conU > 9){
conD++;
conU=0;
}
//Cuando las decenas lleguen a 9 se regresan a 0 y comienza el incremento de las centenas
if(conD > 9){
conC++;
conD=0;
}
}
}
//Empezar con el decremento del contador para cuando se ponga un número mas chico que el anterior
if(angulo<=posi) {
for(int i = posi; i >= angulo; i--) {
movi(servo, i);
delay(esp);
rs=0;
send_byte(0xcc);
rs=1;
if(conC == 0){
send_byte(0x20);
}
else{
send_byte(0x30 | conC);
}
if ((conC == 0) && (conD == 0)){
send_byte(0x20);
}
else{
send_byte(0x30 | conD);
}
send_byte(0x30 | conU);
conU--;
//Cuando las unidades lleguen a 0 se le da el valor de 9 y las decenas decrementan un numero
if (conU < 0) {
conD--;
conU = 9;
}
//Cuando las decenas lleguen a cero
if (conD < 0) {
conC--;
conD = 9;
}
}
}
posi=angulo;
break;
case 0b11101101: //numero 3
cen=dec;
dec=uni;
uni=0x03;
break;
case 0b11101011: //para el numero 2
cen=dec;
dec=uni;
uni=0x02;
break;
case 0b11100111: //numero 1
cen=dec;
dec=uni;
uni=0x01;
break;
case 0b11011110: //letra B
tecla=0x0b;
break;
case 0b11011101: //Par numero 6
cen=dec;
dec=uni;
uni=0x06;
break;
case 0b11011011: // para el numero 5
cen=dec;
dec=uni;
uni=0x05;
break;
case 0b11010111: //para el numero 4
cen=dec;
dec=uni;
uni=0x04;
break;
//Cuando se presiona la tecla C se borran los datos
case 0b10111110:
cen=0;
dec=0;
uni=0;
break;
case 0b10111101: //para el numero 9
cen=dec;
dec=uni;
uni=0x09;
break;
case 0b10111011: // para el numero 8
cen=dec;
dec=uni;
uni=0x08;
break;
case 0b10110111: // para el numero 7
cen=dec;
dec=uni;
uni=0x07;
break;
case 0b01111110: //Para La letra D
tecla=0x0d;
break;
case 0b01111101: //para el #
tecla=0x0f;
break;
case 0b01111011: //para el numero cero
cen=dec;
dec=uni;
uni=0x00;
break;
case 0b01110111: //para el *
tecla=0x0e;
break;
}
}
}
// logica para mover ceros y unos, decenas y unidades segun lo indicadp-----------------------------
rs=0;
send_byte(0x8c);
rs=1;
//Si las centenas son cero dejar un espacio
if(cen==0){
send_byte(0x20);
}
else{
send_byte(0x30|cen);
}
//Si las centenas y decenas son cero dejar un espacio
if((cen==0) && (dec==0)){
send_byte(0x20);
}
else{
send_byte(0x30|dec);
}
send_byte(0x30|uni);
send_byte(0b11011111);
//-------------------------------------------------------------------------------------------------------
}