/**
Arduino Electronic Safe
Copyright (C) 2020, Uri Shaked.
Released under the MIT License.
*/
#include <LiquidCrystal.h>
#include <Keypad.h>
#include "icons.h"
#include <math.h>
#include <ezBuzzer.h> // ezBuzzer library
/* Display */
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
// notes in the melody:
int melody[] = {
NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_G5, NOTE_C5, NOTE_D5,
NOTE_E5,
NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5,
NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_D5, NOTE_D5, NOTE_E5,
NOTE_D5, NOTE_G5
};
// note durations: 4 = quarter note, 8 = eighth note, etc, also called tempo:
int noteDurations[] = {
8, 8, 4,
8, 8, 4,
8, 8, 8, 8,
2,
8, 8, 8, 8,
8, 8, 8, 16, 16,
8, 8, 8, 8,
4, 4
};
String rotulosLista [] = {//Rotulos de donde
"BAS", //se elegiran los
"EOS", //mostrados
"LYM",
"POL",
"MET",
"MYE",
"NRBC",
"IG",
"NEUT",
"OTH"
};
String rotulosElegidos [9] = {
"xxx",
"BAS",
"EOS",
"MON",
"LYM",
"POL",
"MET",
"MYE",
"OTH"
};
typedef struct
{String Nombre;
unsigned int cuenta;
unsigned int posX;
unsigned int posY;
unsigned int porcentaje;
char tecla;
}Caja;
#define NUM_CAJAS 9
Caja cajas[NUM_CAJAS]={
{"xxx",10,12,2,8},
//alias ,inic,posx,posy,tecla
{"BAS",1 , 2, 0, 1},
{"EOS",1 , 9, 0, 2},
{"MON",0 , 2, 0, 3},
{"LYM",0 , 9, 0, 4},
{"POL",0 , 2, 0, 5},
{"MET",0 , 9, 0, 6},
{"MYE",0 , 2, 0, 7},
{"OTH",0 , 9, 0, 8}
};
char holdKey;
char key;
unsigned long t_hold;
char previousPressedKey;
boolean hasReleasedKey = false;
unsigned long tiempoDeC = 0;
const long TIEMPO_FUNCION_1 = 3000;
const long TIEMPO_FUNCION_2 = 6000;
unsigned long tiempoPresionado = 0;
unsigned long tiempoSoltado = 0;
unsigned long tiempoDiferencia = 0;
unsigned int totalCuentas = 0;
bool flagDeInicioDeCiclo = 0;
bool habilitaBlink = false;
bool habilitaResta = false;
bool muestraCantidades = false;
bool flagDeHoldC = false;
bool flagDeHoldD = false;
bool flagDeHold1 = false;
bool enTecladoFuncion1 = false;
byte paginaActual = 1;
int cantidadDePaginas = (NUM_CAJAS -1)/2;
int tecla = 0 ;
int pagina = 1 ;
String index;
//const byte pinBuzzer = 6;
const byte BUZZER_PIN = 6;
ezBuzzer buzzer(BUZZER_PIN); // create ezBuzzer object that attach to a pin;
/*
Keypad setup */
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
byte rowPins[KEYPAD_ROWS] = {5, 4, 3, 2};
byte colPins[KEYPAD_COLS] = {A3, A2, A1, A0};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
{'1','2','3','4'},
{'5','6','7','8'},
{'9','G','A','B'},
{'C','D','E','F'}
};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
void showStartupMessage() {
lcd.setCursor(0, 0);
lcd.print("BLOOD CELL COUNT ");
delay(100);
lcd.setCursor(2, 1);
String message = "version 1.3";
for (byte i = 0; i < message.length(); i++) {
lcd.print(message[i]);
delay(100);
}
lcd.blink();
//delay(1500);
}
void showWaitScreen(int delayMillis) {
lcd.setCursor(2, 1);
lcd.print("[..........]");
lcd.setCursor(3, 1);
for (byte i = 0; i < 10; i++) {
delay(delayMillis);
lcd.print("=");
}
}
void imprimeRotulos(int indice)
{ borraInicio();
imprimeSignos();
if (habilitaBlink) lcd.blink();
byte i = ((indice * 2)-1);
for (i ; i < ((indice * 2)+1) ; i++)
{
lcd.setCursor(cajas[i].posX,cajas[i].posY);
//lcd.print(cajas[i].Nombre);
lcd.print(rotulosElegidos[i]);
}
}
void imprimeCuentas()
{ for (byte i = 1; i < NUM_CAJAS; i++){
lcd.setCursor(cajas[i].posX,(cajas[i].posY)+1);
lcd.print(cajas[i].cuenta);
}
}
void imprimeLlaveMenor()
{ lcd.setCursor(0, 0);
lcd.print("<");
lcd.setCursor(0, 1);
lcd.print("<");
lcd.noBlink();
}
void borraLlaveMenor()
{ lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.noBlink();
}
void borraLlaveMayor()
{ lcd.setCursor(15, 0);
lcd.print(" ");
lcd.setCursor(15, 1);
lcd.print(" ");
lcd.noBlink();
}
void imprimeLlaveMayor()
{ lcd.setCursor(15, 0);
lcd.print(">");
lcd.setCursor(15, 1);
lcd.print(">");
lcd.noBlink();
}
void keypadLoop() {
int indice;
// Keypad related
char key = keypad.getKey();
if (key){
holdKey = key;
// Serial.println(key);
}
KeyState state = keypad.getState();
//cuando la tecla presionada supera el tiempo
//asociado al HOLD , hace la segunda funcion
if (keypad.getState() == HOLD ) {
if ((millis() - t_hold) > 1000 ) {
switch (holdKey) {
case 'C':
if (!flagDeHoldC) muestraCantidadesPorC(); //evita que al mantenerse presionado haga mas de una vez la funcion
flagDeHoldC = true;
Serial.println("Segunda funcion C");
break;
case 'D':
if (!flagDeHoldD) habilitaRestaPorD();
flagDeHoldD = true;
Serial.println("Segunda funcion D");
break;
case '1':
Serial.println("Segunda funcion 1");
if (!enTecladoFuncion1) tecladoFuncion1();
enTecladoFuncion1 = true;
}
t_hold = millis();
}
//Serial.println("C presionada: ");
//Serial.println(tiempoSoltado-tiempoPresionado);
}// hasta aqui llegaba el if pressed
if (state == PRESSED && key != NO_KEY) {
previousPressedKey = key;
hasReleasedKey = false;
tiempoPresionado = millis();
}// hasta aqui llegaba el if pressed
else if (state == RELEASED && !hasReleasedKey) {
// Multiple RELEASED events occur when there had not been HOLD
tiempoSoltado = millis();
/*Serial.print("released_");
Serial.println(previousPressedKey);
Serial.print("estado de 12: ");
Serial.println(keypad.key[12].kchar);
Serial.println(tiempoSoltado-tiempoPresionado);
*/
tiempoDiferencia= (tiempoSoltado-tiempoPresionado);
hasReleasedKey = true;
//}
if (previousPressedKey == '1')
{ indice = 1;
enTecladoFuncion1 = false;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == '2')
{ indice = 2;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == '3')
{ indice = 3;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == '4')
{ indice = 4;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == '5')
{ indice = 5;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == '6')
{ indice = 6;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == '7')
{ indice = 7;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == '8')
{ indice = 8;
habilitaBlink = true;
sumaCuentas(indice); }
else if(previousPressedKey == 'C')
{ previousPressedKey = 'R';
if (!flagDeHoldC) bajaPagina();
flagDeHoldC = false;
}
else if(previousPressedKey == 'D')
{ previousPressedKey = 'R';
if (!flagDeHoldD) subePagina();
flagDeHoldD = false;
}
Serial.println("saliendo de todos los else if");
previousPressedKey = 'R';
}
}
void tecladoFuncion1()
{ enTecladoFuncion1=true;
lcd.noBlink();
do
{
auto key = keypad.getKey();
index = String (key);
int indice = index.toInt();
lcd.setCursor (0,0);
lcd.print("Pos Actual Nuevo");
lcd.setCursor (0,1);
lcd.print(index);
if (indice !=0 ){
int indiceNuevo = indice;
key = keypad.getKey();
lcd.setCursor (4,1);
lcd.print(rotulosElegidos[indice]);
if (key == "C")
{ Serial.println("indiceNuevo ++");
indiceNuevo++;}
else if (key == 'D')
{ Serial.println("indiceNuevo --");
indiceNuevo--;}
Serial.println(indiceNuevo);
Serial.print("index ");
Serial.println(index);
lcd.setCursor (11,1);
lcd.print(rotulosLista[indiceNuevo]);
}
}while (index != "8");
}
void imprimeSignos()
{ if (habilitaResta)
{
lcd.setCursor (14,0);
lcd.print("-");
}
else
{
lcd.setCursor (14,0);
lcd.print("+");
}
}
void borraInicio()
{ lcd.setCursor (1,0);
lcd.print(" ");
lcd.setCursor (5,0);
lcd.print(" ");
lcd.setCursor (12,0);
lcd.print(" ");
lcd.setCursor (8,1);
lcd.print(" ");
}
void imprimeLlaves()
{
imprimeSignos();
switch (pagina)
{case 1:
borraLlaveMenor();
imprimeLlaveMayor();
break;
case 2:
imprimeLlaveMenor();
imprimeLlaveMayor();
break;
case 3:
imprimeLlaveMenor();
imprimeLlaveMayor();
break;
case 4:
borraLlaveMayor();
imprimeLlaveMenor();
}
}
void sumaCuentas(int indice)
{
//imprimeSignos();
if (habilitaResta && ((cajas[indice].cuenta) != 0 )){
cajas[indice].cuenta=cajas[indice].cuenta-1;
}
else if (!habilitaResta){
cajas[indice].cuenta=cajas[indice].cuenta+1;
}
float cociente = indice/1.98;//no usar numeros magicos!!!!!
int indicador = 0;
indicador =round(cociente);
pagina = indicador;
while (indicador != 0)
{ borraLlaveMenor();
borraLlaveMayor();
imprimeRotulos(indicador);
sumaTotal();
imprimePorcent(indicador);
indicador = 0;
//key = 0;
}
}
void sumaTotal(){
totalCuentas = 0;
for (byte i = 1; i < NUM_CAJAS; i++){
totalCuentas = totalCuentas + cajas[i].cuenta;
}
}
void imprimePorcent(int indice){
char outstr[15];
byte i = ((indice * 2)-1);
for (i ; i < ((indice * 2)+1) ; i++)
{ if (muestraCantidades == false)
{float porc;
lcd.setCursor(cajas[i].posX,(cajas[i].posY)+1);
if (totalCuentas >0)
{ porc=((cajas[i].cuenta)*100.00/(totalCuentas));
}
dtostrf(porc,1, 1, outstr);
//https://www.delftstack.com/howto/arduino/
//arduino-dtostrf/#:~:text=The%20dtostrf()
//%20function%20takes,digits%20after%20the%20decimal%20place.
lcd.print(outstr);
lcd.print("% ");
}
if (muestraCantidades == true)
{lcd.setCursor(cajas[i].posX,(cajas[i].posY)+1);
lcd.print(cajas[i].cuenta);
lcd.print("u ");
}
}
}
void habilitaRestaPorD()
{ habilitaResta = !habilitaResta;
/*
tone(pinBuzzer, 1000); // Send 1KHz sound signal...
delay(200); // ...for 1 sec
noTone(pinBuzzer); // Stop sound...
delay(200); // ...for 1sec
*/
imprimeRotulos(pagina);
imprimePorcent(pagina);
imprimeSignos();
imprimeLlaves();
}
void muestraCantidadesPorC()
{ //Serial.print(" en C con hold ");
//muestraCantidades = false ;
muestraCantidades = !muestraCantidades ;
//flagDeHoldC = true ;
/*tone(pinBuzzer, 500,500); // Send 1KHz sound signal...
noTone(pinBuzzer); // Stop sound...
delay(500); // ...for 1sec
tone(pinBuzzer, 500,500); // Send 1KHz sound signal...
delay(500); // ...for 1 sec
noTone(pinBuzzer);
*/
imprimeRotulos(pagina);
imprimePorcent(pagina);
imprimeLlaves();
}
void bajaPagina()
{
imprimeLlaves();
habilitaBlink = false;
imprimeRotulos(pagina);
imprimePorcent(pagina);
if (pagina >= 2)
{pagina = pagina - 1;
imprimeRotulos(pagina);
imprimePorcent(pagina);
imprimeLlaves();
}
}
void subePagina()
{ imprimeLlaves();
habilitaBlink = false;
if (pagina <= cantidadDePaginas-1)
{pagina = pagina + 1;
imprimeRotulos(pagina);
imprimePorcent(pagina);
imprimeLlaves();
}
}
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
init_icons(lcd);
showStartupMessage();
//lcd.clear();
keypad.setHoldTime(2500); // Default is 1000mS
//pinMode (pinBuzzer, OUTPUT); // Set buzzer - pin 6 as an output
}
void loop() {
//sumaTotal();
//leeTeclado();
//key = keypad.getKey();
keypadLoop();
buzzer.loop(); // MUST call the buzzer.loop() function in loop()
if (buzzer.getState() == BUZZER_IDLE) {
if (totalCuentas == 100)//si la cantidad de muestras , hace alarma
{
int length = sizeof(noteDurations) / sizeof(int);
buzzer.playMelody(melody, noteDurations, length); // playing
}
}
}