/*
Pong is a two-dimensional sports game that simulates table tennis.
by Anderson Costa with ❤ for the Wokwi community
Visit https://wokwi.com to learn about the Wokwi Simulator
*/
// https://sourceforge.net/p/arduino-tvout/wiki/FDcomplete/
//
// https://real2electronics.blogspot.com/2010/11/libreria-tvout.html
//
// https://www.instructables.com/TV-Out-with-Arduino/
//
//https://sourceforge.net/p/arduino-tvout/wiki/FDcomplete/
//
//https://github.com/Avamander/arduino-tvout
//
//
#include <Wire.h>
#include <LowPower.h>
#include <TVout.h>
//#include <TVoutfonts/font4x6.h>
#include "logo.h"
#include "font4x6.h"
#include "font6x8.h"
#include "font8x8.h"
#include "font8x8ext.h"
//#include <TimerOne.h>
// Entradas Y Salidas Ultrasonico
const int Trigger = 6; // Pin digital 6 para el Trigger del sensor
int Echo_Sensor[6] = {A0, A1, A2, A3, A4, A5};
int Lectura_Sensor[6] = {0, 0, 0, 0, 0, 0};
int nivel_min[6] = {25, 25, 25, 25, 25, 25};
int nivel_max[6] = {5, 5, 5, 5, 5, 5};
int porcentaje_nivel[6] = {0, 0, 0, 0, 0, 0};
bool alarma[6] = {false, false, false, false, false, false};
const int ancho_casilla = 40;
const int largo_casilla = 48;
// Constante velocidad sonido
const float VelSon = 34314.00; // Velocidad sonido en cm/s
//const float VelSon = 343140.00; // Velocidad sonido en mm/s
// Entradas menu
#define BOTON_MENU 3
#define BOTON_NEXT 4
bool Pulsacion_LargaA = false;
bool Pulsacion_CortaA = false;
bool PulsadoA = false;
bool Pulsacion_LargaB = false;
bool Pulsacion_CortaB = false;
bool PulsadoB = false;
volatile bool ModoCalib = false;
int segundos_salir = 0;
bool salir_calib = false;
unsigned long Inicio_pulsacionA = 0;
unsigned long duracionA = 0;
unsigned long Inicio_pulsacionB = 0;
unsigned long duracionB = 0;
bool a = false;
bool b = false;
#define buzzerPin 2 //buzzer name and pin
//int Do = 262; // do
//int Re = 294; // re
//int Mi = 330; // mi
//int Fa = 349; // fa
//int Sol = 392; // sol
//int Lya = 440; // la
//int Si = 494; // si
int pitido = 1000; //
int cnt_pitido = 0;
volatile bool alarmaON = false;
bool parpadeo1 = false;
unsigned long tiempo1 = 0;
int Antirrebote = 250;
#define SCREEN_WIDTH 120
#define SCREEN_HEIGHT 96
////borrar esta variable
int ccnt_nivel = 0;
bool bajar = false;
TVout TV;
void setup() {
TV.begin(_PAL, SCREEN_WIDTH, SCREEN_HEIGHT);
attachInterrupt(digitalPinToInterrupt(BOTON_MENU), Despertar, FALLING);
Serial.begin(9600);
pinMode(BOTON_MENU, INPUT_PULLUP);
pinMode(BOTON_NEXT, INPUT_PULLUP);
pinMode(Trigger, OUTPUT); //pin como salida
for (int k = 0; k <= 5; k++) {
pinMode(Echo_Sensor[k], INPUT);
delay(10);
}
digitalWrite(Trigger, LOW);//Inicializamos el pin con 0
//Conficguracion interrupcion cada segundo Si USO TIMER 0
//Timer1.initialize(1000000); //Configura el TIMER en 1 Segundo
//Timer1.attachInterrupt(Interrupcion) ; //Configura la interrupción del Timer 1
TV.clear_screen();
Pantalla_vacia();
//Lectura_niveles();
Pintar_niveles();
delay(100);
}
void loop() {
//Pantalla_vacia();
//Lectura_niveles();
Lectura_niveles2();
//Serial.println("leer");
Pintar_niveles();
//Serial.println("PINTAR");
alerta_nivel_bajo();
sonido_alarma();
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_ON);
Serial.println("A MIMIR");
delay(50);
}
void Despertar() {
ModoCalib = true;
}
void Lectura_niveles2() {
for (int ii = 0; ii <= 5; ii++) {
porcentaje_nivel[ii] = ccnt_nivel;
}
if ((ccnt_nivel <= 100) && (bajar == false)) {
ccnt_nivel ++;
}
else if ((ccnt_nivel == 100) && (bajar == false)) {
bajar = true;
}
else if ((ccnt_nivel <= 100) && (bajar == true)) {
ccnt_nivel --;
}
else if ((ccnt_nivel == 0) && (bajar == true)) {
bajar = false;
}
}
int calibracion_nivel(int indice, int x, int y, String titulo, int nivel_calib) {
int lectura = 0;
while ((Pulsacion_CortaB == false) && (salir_calib == false)) {
leerbotones() ;
if (millis() > tiempo1 + 700) {
tiempo1 = millis();
parpadeo1 = !parpadeo1;
if (parpadeo1 == true) {
TV.draw_rect(x + 1, y + 1, 38, 47, 0);
}
else if ((parpadeo1 == false)) {
dibujar_tanque_vacio(x, y, ancho_casilla, largo_casilla, titulo);
Pintar_nivel_tanque(x, y, ancho_casilla, largo_casilla, nivel_calib);
}
}
lectura = Leer_Sensor(indice);
}
dibujar_tanque_vacio(x, y, ancho_casilla, largo_casilla, titulo);
Pintar_nivel_tanque(x, y, ancho_casilla, largo_casilla, nivel_calib);
delay(250);
return lectura;
}
void leerbotones() {
segundos_salir = 0;
duracionA = 0;
duracionB = 0;
Pulsacion_LargaA = false;
Pulsacion_CortaA = false;
Pulsacion_LargaB = false;
Pulsacion_CortaB = false;
delay(5);
a = digitalRead(BOTON_MENU); // pin donde miras la señal digital
if ((a == LOW) && (PulsadoA == false)) { // si hay flanco 0 a 1 entonces
Inicio_pulsacionA = millis();
PulsadoA = true;
// Serial.print("Inicio_pulsacionA = ");
// Serial.println(Inicio_pulsacionA);
}
if ((a == HIGH) && (PulsadoA == true)) { // si el flanco es 1 a 0, entonces detengo la cuenta
duracionA = millis() - Inicio_pulsacionA; // en milisegundos
// Serial.print("duracionA = ");
// Serial.println(duracionA);
}
if ((duracionA >= 150) && (duracionA < 3000)) {
Serial.println("Pulsacion Corta A");
Pulsacion_CortaA = true;
PulsadoA = false;
}
if (duracionA >= 3000) {
Serial.println("Pulsacion Larga A");
Pulsacion_LargaA = true;
PulsadoA = false;
}
b = digitalRead(BOTON_NEXT); // pin donde miras la señal digital
if ((b == LOW) && (PulsadoB == false)) { // si hay flanco 0 a 1 entonces
Inicio_pulsacionB = millis();
PulsadoB = true;
// Serial.print("Inicio_pulsacionB = ");
// Serial.println(Inicio_pulsacionB);
}
if ((b == HIGH) && (PulsadoB == true)) { // si el flanco es 1 a 0, entonces detengo la cuenta
duracionB = millis() - Inicio_pulsacionB; // en milisegundos
// Serial.print("duracionB = ");
// Serial.println(duracionB);
}
if ((duracionB >= 1000) && (duracionB < 2000)) {
Serial.println("Pulsacion Corta B");
Pulsacion_CortaB = true;
PulsadoB = false;
}
if (duracionB >= 2000) {
Serial.println("Pulsacion Larga B");
Pulsacion_LargaB = true;
PulsadoB = false;
}
delay(5);
}
void Pantalla_vacia() {
marcos();
dibujar_tanque_vacio(0, 0, ancho_casilla, largo_casilla, "SOL A1");
dibujar_tanque_vacio(ancho_casilla, 0, ancho_casilla, largo_casilla, "SOL B1");
dibujar_tanque_vacio(2 * ancho_casilla, 0, ancho_casilla, largo_casilla, "BAJ PH");
dibujar_tanque_vacio(0, largo_casilla, ancho_casilla, largo_casilla, "SOL A2");
dibujar_tanque_vacio(ancho_casilla, largo_casilla, ancho_casilla, largo_casilla, "SOL B2");
dibujar_tanque_vacio(2 * ancho_casilla, largo_casilla, ancho_casilla, largo_casilla, "BAJ PH");
}
void dibujar_tanque_vacio(int x, int y, int tam_x, int tam_y, String texto) {
// x coordenada hotizontal,
// y coordenada vertical
// tam_x dimension en horizontal
// tam_x dimension en vertical
// dibujar titulo de tanque
TV.select_font(font4x6);
TV.set_cursor((x + 4), (y + 3));
for (int i = 0; i < texto.length(); i++) {
TV.print(texto.charAt(i));
}
//dibujar origen de recuadro
//tft.drawLine(x, y, x, y, ILI9341_RED);
int margen_x = 5;
int margen_x_d = 15;
int margen_y = 5;
int margen_y_sup = 10;
// dibujar lineas de tanque
int x1 = (x + margen_x);
int y1 = (y + margen_y_sup);
int x2 = x1;
int y2 = y + (tam_y - margen_y);
int x3 = x + (tam_x - margen_x_d);
int y3 = y2;
int x4 = x + (tam_x - margen_x_d);
int y4 = y1;
TV.draw_line(x1, y1, x2, y2, 1);
TV.draw_line(x2, y2, x3, y3, 1);
TV.draw_line(x3, y3, x4, y4, 1);
// Marcas llenado
TV.draw_line(x4, y1 + 3, x4 + 3, y1 + 3, 1); //100%
TV.draw_line(x4, y1 + 10, x4 + 2, y1 + 10, 1); //75%
TV.draw_line(x4, y1 + 16, x4 + 3, y1 + 16, 1); //50%
TV.draw_line(x4, y1 + 24, x4 + 2, y1 + 24, 1); //50%
TV.draw_line(x4, y2 - 2, x4 + 3, y2 - 2, 1); //0%
// TEXTOS NIVEL
TV.select_font(font4x6);
TV.set_cursor(x4 + 4, y1);
TV.print("F");
TV.set_cursor(x4 + 4, y1 + 13);
TV.print("M");
TV.set_cursor(x4 + 4, y1 + 28);
TV.print("V");
}
void Pintar_niveles() {
Pintar_nivel_tanque(0, 0, ancho_casilla, largo_casilla, porcentaje_nivel[0]);
Pintar_nivel_tanque(ancho_casilla, 0, ancho_casilla, largo_casilla, porcentaje_nivel[1]);
Pintar_nivel_tanque(2 * ancho_casilla, 0, ancho_casilla, largo_casilla, porcentaje_nivel[2]);
Pintar_nivel_tanque(0, largo_casilla, ancho_casilla, largo_casilla, porcentaje_nivel[3]);
Pintar_nivel_tanque(ancho_casilla, largo_casilla, ancho_casilla, largo_casilla, porcentaje_nivel[4]);
Pintar_nivel_tanque(2 * ancho_casilla, largo_casilla, ancho_casilla, largo_casilla, porcentaje_nivel[5]);
}
void Lectura_niveles() {
for (int i = 0; i <= 5; i++) {
Lectura_Sensor[i] = Leer_Sensor(i);
delay(5);
// Calculo de porcenaje
porcentaje_nivel[i] = map(Lectura_Sensor[i], nivel_min[i], nivel_max[i], 0, 100);
delay(350);
}
for (int ii = 0; ii <= 5; ii++) {
if (porcentaje_nivel[ii] >= 100) {
porcentaje_nivel[ii] = 100;
}
if (porcentaje_nivel[ii] <= 0) {
porcentaje_nivel[ii] = 0;
}
Serial.print(porcentaje_nivel[ii]);
Serial.print(",");
}
Serial.println(" ");
}
int Leer_Sensor(int indice) {
int muestras = 5; // numero de muestras
float suma = 0;
float media = 0;
unsigned long t = 0; //timepo que demora en llegar el eco
float d = 0; //distancia en centimetros
suma = 0;
delay(5);
for (int j = 0; j < muestras; j++) {
digitalWrite(Trigger, LOW);
delayMicroseconds (5);
digitalWrite(Trigger, HIGH);
delayMicroseconds(10); //Enviamos un pulso de 10us
digitalWrite(Trigger, LOW);
t = pulseIn(Echo_Sensor[indice], HIGH); //obtenemos el ancho del pulso
// d = t / 59;
// Obtenemos la distancia en cm, hay que convertir el tiempo en segudos ya que está en microsegundos
// por eso se multiplica por 0.000001
// Si queremos precision mm/s tenemos que desmarcar la opcion VelSon en mm/s y comentar la cm/s
d = t * 0.000001 * VelSon / 2.0;
suma = suma + d;
delay(70);
}
media = suma / muestras;
return media;
}
void alerta_nivel_bajo() {
// Serial.println("mirandoooo");
for (int i = 0; i < 6; i++) {
// Serial.print(porcentaje_nivel[i]);
// Serial.print(",");
if (porcentaje_nivel[i] <= 10) {
alarma[i] = true;
}
else {
alarma[i] = false;
}
delay(1);
}
// Serial.println(" ");
//recuento alarmas
int n_alarma = 0;
for (int i = 0; i < 6; i++) {
// Serial.print(alarma[i]);
// Serial.print(",");
if (alarma[i] == true) {
n_alarma ++;
}
delay(1);
}
// Serial.println(" ");
// comprobamos si hay alarmas
if (n_alarma >= 1) {
alarmaON = true;
}
else if (n_alarma == 0) {
alarmaON = false;
}
//Serial.println(n_alarma);
// Serial.println(alarmaON);
//llamamos a la rutina de alarma
//sonido_alarma();
}
void sonido_alarma() {
// Serial.println("ENTRAMOSSSSA SONIDO ");
// Activate the buzzer (produce sound)
if ((alarmaON == true) && (ModoCalib == false)) {
// Serial.println("alarma");
for (int h = 0; h < 3; h++) {
for (int hh = 0; hh < 3; hh++) {
// Serial.println("PITIDO");
tone(buzzerPin, pitido); // You can adjust the f
delay(333);
noTone(buzzerPin); // You can adjust the f
delay(333);
}
delay(500);
}
alarmaON = false;
}
}
void Pintar_nivel_tanque(int x, int y, int tam_x, int tam_y, int num) {
int margen_x = 5;
int margen_x_d = 15;
int margen_y = 5;
int margen_y_sup = 10;
int l0 = 0;
int l100 = tam_y - (margen_y + margen_y_sup + 5);
int level = map(num, 0, 100, l0, l100);
// dibujar lineas de tanque
int x1 = (x + margen_x) + 2;
int y1 = y + (tam_y - margen_y) - 2;
int x2 = (tam_x - (margen_x_d + margen_x)) - 4;
int y2 = - level;
//BORRAR ANTIGUO
TV.draw_rect(x1, y1, x2, -l100, 0);
//pINTAR NUEVO
for (int h = l0; h <= level; h++) {
TV.draw_rect(x1, y1, x2, -h, 1);
//delay(1);
}
}
void marcos() {
int largo = 6;
TV.draw_rect(0, 0, 119, 95, 1);
TV.draw_line(0, 47, largo, 47, 1);
TV.draw_line(119 - largo, 47, 119, 47, 1);
TV.draw_line(39, 0, 39, largo, 1);
TV.draw_line(39, 95 - largo, 39, 95, 1);
TV.draw_line(79, 0, 79, largo, 1);
TV.draw_line(79, 95 - largo, 79, 95, 1);
TV.draw_line(39 - (largo - 4), 47, 39 + (largo - 3), 47, 1);
TV.draw_line(39, 47 - (largo - 3), 39, 47 + (largo - 3), 1);
TV.draw_line(79 - (largo - 4), 47, 79 + (largo - 3), 47, 1);
TV.draw_line(79, 47 - (largo - 3), 79, 47 + (largo - 3), 1);
}
BTN MENU
BTN NEXT
SOL. B1
SOL. A2
SOL. A1
SOL B2
PH- 1
PH- 2