CP versão 11.2 - 17/06/24

 /* Marelli - GTS - R&D - Testing Engineering

 * Wilson R Bueno 07/06/2024
 
 * >>>> Atenção: funciona no Arduino 2.3.2 <<<<<< * Projeto Medidor Contrapressão
 * >>>> Editar usando o adm do computador para evitar travamentos no Arduino <<<<
 * (*) A gravação na EEPROM é limita a 100.000 - continuação do projeto é colocar um cartão de EEPROM externo

  * V0.0 - base * V0.1 - retirando cartão ultrasson * V0.2 - gravando no cartão * V0.3 - Mesclando com o programa Enxugamento v13 NV * V1.0 - Funcional Base Enxugamento V13 NV * V2 - Adicionando teclado do programa Controle de Acesso * V2.1 - Condicionais
  * V2.1.1 - Simplificando para testar condicionais * V2.2 - Adicionando SwitchCase - Funcional * V2.2.1 - Limpando - Funcional * V2.2.2 - Iniciando gravação * V3 - Reformulando menus - unido com projeto Menu Básico para CP V0 https://www.youtube.com/watch?v=Swr2Q1IFiBM&ab_channel=WRKits
  * V3.1 - adicionando e mesclando * V3.1.1 - funcional * V3.1.2 / V3.1.3 - progressivo * V3.1.4 - retirada o menu de seleção básico da WR Kits - funcional * V3.1.5 - executar tarefas - progressivo * V3.1.6 - progressivo - menu OK - faltam os submenus * V3.1.7 - formatando submenus  
  * V3.1.8 - falta submenu - colocando função RESET soft * V4 - retirando menus WR Kits e colocando menu do Lacerda: MENU COM TRÊS BOTÕES ABRAÃO LACERDA - ACESSE O LINK https://www.youtube.com/channel/UCn_SRCloMrZ5y9XOHSIUFUQ
  * V4.1 / 4.2 / 4.2.1 - progressivo * V5 - inclusão módulos de temperatura * V5.1 - acelerando a gravação  file.close() ?? * V6.2 - retorno à ordem dos menus * V6.3 - retirando Menus do loop * V6.4 - inicializando submenus, zerando variáveis
  * V6.5 - progressivo * V6.6 - progressivo * V6.7 - inclusão do segundo submenu * V6.8 - problema * V6.9 - incluindo submenus - ok. Falta acertar sub sub menu calibração * V6.10 - incluindo Switch Case no sub sub menu calibração - não funcional
  * V6.11 - usando leitor de cartão externo * V6.12 -inserindo leitor umidade e temperatura - falta submenus * V7.0 - Incluindo timers diferentes para cada aquisição SD, serial, LCD e usando um timer confiável
  * https://josecintra.com/blog/arduino-controlando-intervalos-tempo/ * V7.1 - progressivo e alterando frequÊncia de gravação * V7.2 - Ampliação dos submenus * V7.3.1 - progressivo - subsub menu não funcional
  * V7.4, V7.5 - não funcional * V7.6 - retirando WRKits e alterando submenus * V7.6.7 - resolvendo reset e colocando submenus - funcional * V7.7 - zerar os canais e aplicar ganho
  * V7.8 - otimização * V7.8.1 - adicionando submenu de ganho e média móvel para canal analógico WRKits#108 https://www.youtube.com/watch?v=cxPQ0AMQ5bo&ab_channel=WRKits
  * V7.8.2 - funcional * V7.8.2.1 - verificar falha no acesso dos menus - não funcional * média móvel = deixou o programa muito lento. Avaliando custo benefício
  * V7.8.4 ref: 0=0 - submenus usando case, para eliminar o problema de travamento no submenu, base  https://www.youtube.com/watch?v=Swr2Q1IFiBM&ab_channel=WRKits
  * V7.8.4.1 - inclusão da aquisição via Excel PLX e troca do Timing por timers separados - não funcional * V7.8.5 / V7.8.6 / V7.8.7 - progressivo e uso do return; - funcional
  * V7.9 - alteração menus - funcional * V7.9.1 - otimização e inclusão de subsubmenus * V7.10 - zero e ganho nos canais * V7.10.1 - descartar * V7.10.2 - incluir conversor 4-20mA - progressivo
  * V7.11 V7.11.1 V7.12 - progressivo * V7.13 - alteração submenus -ok * V7.14 - simplificando os menus * V7.14.1 a 4 - travando no Arduino e W11 - problema com a biblioteca do RTC - usar RTCLib by NeiroN
  * V7.15 - funcional * V7.15.1 - progressivo menus * V7.16 - progressivo menus * V8 / V9 - mescla com StrinToIntv13: /https://www.luisllamas.es/en/converting-text-to-number-on-arduino/ / progressivo
  * V9.1 - progressivo - MENU ZERO * V9.11 / V9.2 / V9.3 / V9.4 / V9.5 / V9.6 - TESTE MENU CASE
  * V10 / V10.1 / V10.2 - alteração menu calibração com map * V10.3 - simplificando * V11 - gravando o ganho de cada canal na EEPROM - problema com endereço - ok
  * V11.1 - progressivo - ok * V11.2 - progressivo - ok
  * V11.2 - progressivo
  */

// --- Bibliotecas Auxiliares ---
#include <LiquidCrystal_I2C.h>
#include <Wire.h>            //biblioteca I2C
#include <RTClib.h>          // funciona no W11 - RTCLib by NeiroN // #include "RTClib.h" //biblioteca do RTC // com pau no W11
#include <SPI.h>             // biblioteca comunicação serial
#include <SD.h>              // biblioteca cartão SD
#include <Keypad.h>          // Biblioteca para controle do teclado de matrizes
#include "max6675.h"         // biblioteca do shield max6675
#include <Adafruit_AHT10.h>  // biblioteca sensor umidade e temperatura
#include <EEPROM.h>          // para gravação e leitura na EEPROM do valor de ganho

//Timers
unsigned long Tgrava = 0;

const int lederroPin = 14;
const int record = 13;
int freqgrav = 1000;  //record frequency
int a = 0;            // constante para gravação única do cabeçalho
int z = 0;            // constante para gravação //Serial
int d = 0;            // constante para mudar menu no LCD: CP ou temperatura
int tela = 1;         //variável para controlar a mudança de tela principal no menu

//Para o teclado
const byte LINHAS = 4;                         // Linhas do teclado
const byte COLUNAS = 5;                        // Colunas do teclado
const char TECLAS_MATRIZ[LINHAS][COLUNAS] = {  // Matriz de caracteres (mapeamento do teclado)
  { '7', '8', '9', 'U', 'C' },
  { '4', '5', '6', 'D', 'S' },
  { '1', '2', '3', 'O', 'F' },
  { '*', '0', 'E', 'P', 'R' }
};
const byte PINOS_LINHAS[LINHAS] = { 23, 25, 27, 29 };        // Pinos de conexao com as linhas do teclado
const byte PINOS_COLUNAS[COLUNAS] = { 31, 33, 35, 37, 39 };  // Pinos de conexao com as colunas do teclado

Keypad teclado_personalizado = Keypad(makeKeymap(TECLAS_MATRIZ), PINOS_LINHAS, PINOS_COLUNAS, LINHAS, COLUNAS);  // Inicia teclado

// --- Funções Auxiliares ---
void fileopen();              // SD card file openAbertura arquivo
void menuP();                 // Main menu
void subMenu();               // Submenu - second menu
void resetando();             // General reset
void gravacao();              // Record file SD card file
void temperatures();          // Record temperatures
void (*resetFunc)(void) = 0;  // create a standard reset function
void inicio();                // Novo menu case - vai usar?
void subMenuGain();           // Submenu - third menu - gain
void entradaDados();          // Entrada de dados
void gravaEEPROM();           // Gravação na EEPROM
void leituraEEPROM();         // Leitura na EEPROM

//Inicializa o display no endereco 0x27
LiquidCrystal_I2C lcd(0x27, 16, 2);

//Relógio
DS1307 rtc;
//char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

//Open file on SD card
File logfile;
int pinoCS = 49;  // Pin CS Turn on

//Utilidade desconhecida
void error(char *str) {
  Serial.print(F("error: "));
  Serial.println(str);
  while (1);
}

//Variáveis cpi = valor tabelado mínimo, cpm = valor tabelado máximo, cpp = resultado contrapressão, cpz = zerar, cp = leitura canais analógicos, cpg = ganho
int cpm1 = 0;int cpp1 = 0;int cpz1 = 0;float cp1 = A0;
int cpm2 = 0;int cpp2 = 0;int cpz2 = 0;float cp2 = A1;
int cpm3 = 0;int cpp3 = 0;int cpz3 = 0;float cp3 = A2;
int cpm4 = 0;int cpp4 = 0;int cpz4 = 0;float cp4 = A3;
int cpm5 = 0;int cpp5 = 0;int cpz5 = 0;float cp5 = A4;

//Thermocouples modules max6675
//1st thermocouple
int so1Pin = 22;   // SO=Serial Out do shield termopar
int cs1Pin = 24;   // CS = chip select CS pin do shield termopar
int sck1Pin = 26;  // SCK = Serial Clock pin do shield termopar
//2nd thermocouple
int so2Pin = 28;   // SO=Serial Out do shield termopar
int cs2Pin = 30;   // CS = chip select CS pin do shield termopar
int sck2Pin = 32;  // SCK = Serial Clock pin do shield termopar
//3rd thermocouple
int so3Pin = 34;   // SO=Serial Out do shield termopar
int cs3Pin = 36;   // CS = chip select CS pin do shield termopar
int sck3Pin = 38;  // SCK = Serial Clock pin do shield termopar
//4th thermocouple
int so4Pin = 40;   // SO=Serial Out do shield termopar
int cs4Pin = 42;   // CS = chip select CS pin do shield termopar
int sck4Pin = 44;  // SCK = Serial Clock pin do shield termopar
//5th thermocouple
int so5Pin = 46;   // SO=Serial Out do shield termopar
int cs5Pin = 48;   // CS = chip select CS pin do shield termopar
int sck5Pin = 12;  // SCK = Serial Clock pin do shield termopar

//MAX6675 instance
MAX6675 robojax1(sck1Pin, cs1Pin, so1Pin);
MAX6675 robojax2(sck2Pin, cs2Pin, so2Pin);
MAX6675 robojax3(sck3Pin, cs3Pin, so3Pin);
MAX6675 robojax4(sck4Pin, cs4Pin, so4Pin);
MAX6675 robojax5(sck5Pin, cs5Pin, so5Pin);

//AHT10 card umidity and temperature
Adafruit_AHT10 aht;
//Degree simbol character
byte grau[8] = {
  B00001100,
  B00010010,
  B00010010,
  B00001100,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
};

//Input keyboard data
String inputdata = "";


void setup()  /////////////////////////////////////////////////
{
  Serial.begin(9600);  // Serial starting
  Serial.print(F("Marelli GTS Amparo -- "));
  Serial.println(F("Project: Contrapressão V9"));
  Serial.println(F("Initializing ..."));

  pinMode(lederroPin, OUTPUT);  // Error LED indication
  pinMode(record, OUTPUT);      // Record SDCard LED

  //Initialize AHT10 card umidity and temperature
  if (!aht.begin()) {
    Serial.println(F("Could not find AHT10? Check wiring"));
    while (1) delay(10);
  }
  Serial.println(F("AHT10 Card Ok"));
  //Cria o caractere customizado com o simbolo do grau
  lcd.createChar(0, grau);

  //inicia o display 16x2
  lcd.init();
  lcd.backlight();
  lcd.begin(16, 2);

  //Inicialização do programa
  lcd.setCursor(0, 0);
  lcd.print(F(" MARELLI R&D-TE"));
  lcd.print(F(" "));
  lcd.setCursor(0, 1);
  lcd.print(F("Ver 10 - Junho24 "));
  delay(1000);

  //AHT10
  sensors_event_t humidity, temp;
  aht.getEvent(&humidity, &temp);  // Populate temp and humidity objects with fresh data
  lcd.setCursor(0, 1);
  lcd.print(temp.temperature);
  lcd.setCursor(4, 1);
  lcd.write((byte)0);  // Show degree symbol make by array
  lcd.print(F("C : "));
  lcd.setCursor(9, 1);
  lcd.print(humidity.relative_humidity);
  lcd.setCursor(13, 1);
  lcd.print(F("%HR  "));
  delay(1500);

  //Inicialização do cartão SD
  pinMode(pinoCS, OUTPUT);  // Declara pino CS como saída
  Serial.print(F("SD card "));
 
  if (!SD.begin(4)) {
    Serial.println(F("Initialization failed!"));
    digitalWrite(lederroPin, HIGH);  // turn the LED on (HIGH is the voltage level)
    lcd.clear();
    lcd.setBacklight(HIGH);
    lcd.setCursor(3, 0);
    lcd.print(F("* FAIL ON *"));
    lcd.setCursor(3, 1);
    lcd.print(F("* SD CARD *"));
    while (1);
  }
  Serial.println(F("Ok"));
  logfile.print(F("Temperature: "));
  logfile.print(temp.temperature);
  logfile.println(F(" degrees C"));
  logfile.print(F("Humidity: "));
  logfile.print(humidity.relative_humidity);
  logfile.println(F("% rH"));

  //Relógio RTC
  if (!rtc.begin()) {
    Serial.println(F("Couldn't find RTC"));
    lcd.clear();
    lcd.setBacklight(HIGH);
    lcd.setCursor(3, 0);
    lcd.print(F("* FAIL ON *"));
    lcd.setCursor(7, 1);
    lcd.print(F("* RTC *"));
    digitalWrite(lederroPin, HIGH);  // turn the LED on (HIGH is the voltage level)
    while (1);
  }

  if (!rtc.isrunning()) {
    Serial.println(F("RTC is NOT running!"));
    lcd.clear();
    lcd.setBacklight(HIGH);
    lcd.setCursor(3, 0);
    lcd.print(F("* FAIL ON *"));
    lcd.setCursor(7, 1);
    lcd.print(F("* RTC *"));
    digitalWrite(lederroPin, HIGH);  // turn the LED on (HIGH is the voltage level)
  }
  Serial.println(F("RTC is Ok"));

  // Ajuste data e hora - following line sets the RTC to the date & time this sketch was compiled
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
    //rtc.adjust(DateTime(2024, 6, 11, 14, 10, 0));

  logfile.print(F("Marelli GTS Amparo"));
  logfile.print(temp.temperature);
  logfile.println(F("Project: Contrapressão V9"));
  logfile.print(F("Temperature: "));
  logfile.print(temp.temperature);
  logfile.println(F(" °C"));
  logfile.print(F("Umidity: "));
  logfile.print(humidity.relative_humidity);
  logfile.println(F("% rH"));
  logfile.println(F("LABEL,Date,Time,Timer,TU1,TU2,TU3,TU4,TU5,TU6,TU7,TU8,TP1,TP2,TP3,TP4,TP5,TP6,TP7,TP8"));

  //Inicialização Menu Superior Excel PLX-DAQ
  Serial.println(F("CLEARDATA"));  // reset da comunicação //Serial
  Serial.println(F("LABEL,Date,Time,Timer,CP1,CP2,CP3,CP4,CP5,TP1,TP2,TP3,TP4,TP5"));

  leituraEEPROM(); // Leitura das variáveis de ganho para as CPs

}  ///////////////////////////////////////end setup


void loop()  ////////////////////////////// Start loop
{
   
  menuP();
 
}  //////////////////////////////////////// End loop


void menuP() {  /////////////////////////// Main Menu

  //Identify key press
  char leitura_teclas = teclado_personalizado.getKey();  // Atribui a variavel a leitura do teclado

  if (leitura_teclas) {

    if (leitura_teclas == 'R') {  // Se a tecla Reset foi pressionada
      lcd.clear();
      resetando();
    }
  }

  // === Main menu on display LCD === //
  digitalWrite(record, LOW);  //Show SD card record

  if (tela == 1) {  // Tela 1
    lcd.setCursor(0, 0);
    DateTime now = rtc.now();
    if (now.hour() < 10) lcd.print(F("0"));  // remains 2 digits
    lcd.print(now.hour());
    lcd.print(F(":"));
    if (now.minute() < 10) lcd.print(F("0"));
    lcd.print(now.minute());
    lcd.print(F(":"));
    if (now.second() < 10) lcd.print(F("0"));
    lcd.print(now.second());
    lcd.print(F("-"));
    lcd.print(now.day(), DEC);
    lcd.print('/');
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print((now.year() - 2000), DEC);
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Record"));
  }
  else if (tela == 2) {
    lcd.setCursor(0, 0);
    lcd.print(F(" CH CALIBRATION "));
    lcd.setCursor(0, 1);
    lcd.print(F(">> Press Enter <"));
  }
  else if (tela == 3) {
    lcd.setCursor(0, 0);
    lcd.print(F("> TEMPERATURES <"));
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Record<<"));
  }

  // === Down key - Menu moves=== //////////////
  if (leitura_teclas == 'D') {
    lcd.clear();
    if (tela == 1) tela = 2;
    else if (tela == 2) tela = 3;
    else if (tela == 3) tela = 1;
   
    //Submenu 2
    else if (tela == 21) tela = 22;
    else if (tela == 22) tela = 23;
    else if (tela == 23) tela = 24;
    else if (tela == 24) tela = 25;
    else if (tela == 25) tela = 26;
    else if (tela == 26) tela = 21;
   
    delay(30);  }  //Bounce efect - avoid repique

  // === Up key - Menu moves=== //   ////////////

  if (leitura_teclas == 'U') {
   
    lcd.clear();
    if (tela == 1) tela = 3;
    else if (tela == 2) tela = 1;
    else if (tela == 3) tela = 2;
   
    //Submenu 2
    else if (tela == 21) tela = 26;
    else if (tela == 26) tela = 25;
    else if (tela == 25) tela = 24;
    else if (tela == 24) tela = 23;
    else if (tela == 23) tela = 22;
    else if (tela == 22) tela = 21;
    delay(30);
  }

  if (leitura_teclas == 'S') {  // Stop and return to Submenu
    lcd.clear();
    if ((tela == 21) || (tela == 22) || (tela == 23) || (tela == 24) || (tela == 25) || (tela == 26))tela = 2;
    else if ((tela == 211) || (tela == 212) || (tela == 213) || (tela == 214) || (tela == 215) || (tela == 216)) tela = 21;
    return;  // finalmente retornou ao menu principal! :)
  }

  //////// Enter key: Main menu to Submenu
  if (leitura_teclas == 'O') {
    lcd.clear();
    if (tela == 1) tela = 10;
    else if (tela == 2) tela = 21;
    else if (tela == 3) tela = 30;
   
    else if (tela == 21) tela = 211;
    else if (tela == 22) tela = 212;
    else if (tela == 23) tela = 213;
    else if (tela == 24) tela = 214;
    else if (tela == 25) tela = 215;
    else if (tela == 26) tela = 216;

    delay(30);
  }

  subMenu(); // Fim Menu Principal
}


void subMenu()  /// Start subMenu
{

  // Tela de gravação CPs e temperaturas
  if (tela == 10) {
    fileopen();  // SD card file open
    logfile.flush(); // Renew data
    DateTime now = rtc.now();
    if (now.hour() < 10) lcd.print(F("0"));  // sempre 2 dígitos
    logfile.print(now.hour());
    logfile.print(F(":"));
    if (now.minute() < 10) lcd.print(F("0"));
    logfile.print(now.minute());
    logfile.print(F(":"));
    if (now.second() < 10) lcd.print(F("0"));
    logfile.println(now.second());
    gravacao();
  }

   /// Gains: Telas para colocar ganho nos canais
  if (tela == 21) {
    lcd.setCursor(0, 0);
    lcd.print(F("CHANNEL 01:"));
    lcd.setCursor(12, 0);
    lcd.print(cpp1);
    lcd.print(F(" <<<<<<<<"));
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Change<<"));
  }
  if (tela == 22) {
    lcd.setCursor(0, 0);
    lcd.print(F("CHANNEL 02:"));
    lcd.setCursor(12, 0);
    lcd.print(cpp2);
    lcd.print(F(" <<<<<<<<"));
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Change<<"));
  }
  if (tela == 23) {
    lcd.setCursor(0, 0);
    lcd.print(F("CHANNEL 03:"));
    lcd.setCursor(12, 0);
    lcd.print(cpp3);
    lcd.print(F(" <<<<<<<<"));
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Change<<"));
  }
  if (tela == 24) {
    lcd.setCursor(0, 0);
    lcd.print(F("CHANNEL 04:"));
    lcd.setCursor(12, 0);
    lcd.print(cpp4);
    lcd.print(F(" <<<<<<<<"));
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Change<<"));
  }
  if (tela == 25) {
    lcd.setCursor(0, 0);
    lcd.print(F("CHANNEL 05:"));
    lcd.setCursor(12, 0);
    lcd.print(cpp5);
    lcd.print(F(" <<<<<<<<"));
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Change<<"));
  }
  if (tela == 26) {
    lcd.setCursor(0, 0);
    lcd.print(F(" FINAL RECORD "));
    lcd.print(F(" <<<<<<<<"));
    lcd.setCursor(0, 1);
    lcd.print(F(">Enter to Apply<<"));
  }

  // Tela de gravação exclusiva temperatura
  if (tela == 30) {
    fileopen();  //Abertura de arquivo
    logfile.flush();
    //Data e hora abertura do arquivo
    DateTime now = rtc.now();
    if (now.hour() < 10) lcd.print(F("0"));  // sempre 2 dígitos
    logfile.print(now.hour());
    logfile.print(F(":"));
    if (now.minute() < 10) lcd.print(F("0"));
    logfile.print(now.minute());
    logfile.print(F(":"));
    if (now.second() < 10) lcd.print(F("0"));
    logfile.println(now.second());
    temperatures();
  }
  subMenuGain();

}  ////////////////////////////////////// End subMenuGain


void subMenuGain()  /////// Start Sub Menu Gain /////////
{

  //Leitura das CPs
  int cp1 = (analogRead(A0));
  int cp2 = (analogRead(A1));
  int cp3 = (analogRead(A2));
  int cp4 = (analogRead(A3));
  int cp5 = (analogRead(A4));

  //int cpp1 = cp1 * (670.0 / 1023.0);
  cpp1 = map(cp1, 0, 1023, 0, cpm1);
  cpp2 = map(cp2, 0, 1023, 0, cpm2);
  cpp3 = map(cp3, 0, 1023, 0, cpm3);
  cpp4 = map(cp4, 0, 1023, 0, cpm4);
  cpp5 = map(cp5, 0, 1023, 0, cpm5);


  if (tela == 211) {
    lcd.setCursor(0, 0);
    lcd.print(F("CAL CH01:           "));
    lcd.setCursor(11, 0);
    lcd.print(cpm1);  // Valor calibração atual do canal
    lcd.setCursor(5, 1);
    lcd.print(F("-> "));
    lcd.print(cpp1); // Resultado leitura do canal cp X ganho cpm
    lcd.print(F(" mbar          "));
    entradaDados();
  }
  if (tela == 212) {
    lcd.setCursor(0, 0);
    lcd.print(F("CAL CH02:           "));
    lcd.setCursor(11, 0);
    lcd.print(cpm2);  // Valor calibração atual do canal
    lcd.setCursor(5, 1);
    lcd.print(F("-> "));
    lcd.print(cpp2);
    lcd.print(F(" mbar          "));
    entradaDados();
  }
  if (tela == 213) {
    lcd.setCursor(0, 0);
    lcd.print(F("CAL CH03:           "));
    lcd.setCursor(11, 0);
    lcd.print(cpm3);  // Valor calibração atual do canal
    lcd.setCursor(5, 1);
    lcd.print(F("-> "));
    lcd.print(cpp3);
    lcd.print(F(" mbar          "));
    entradaDados();
  }
  if (tela == 214) {
    lcd.setCursor(0, 0);
    lcd.print(F("CAL CH04:           "));
    lcd.setCursor(11, 0);
    lcd.print(cpm4);  // Valor calibração atual do canal
    lcd.setCursor(5, 1);
    lcd.print(F("-> "));
    lcd.print(cpp4);
    lcd.print(F(" mbar          "));
    entradaDados();
  }
  if (tela == 215) {
    lcd.setCursor(0, 0);
    lcd.print(F("CAL CH05:           "));
    lcd.setCursor(11, 0);
    lcd.print(cpm5);  // Valor calibração atual do canal
    lcd.setCursor(5, 1);
    lcd.print(F("-> "));
    lcd.print(cpp5);
    lcd.print(F(" mbar          "));
    entradaDados();
  }
  if (tela == 216) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(F(">> RECORDING...."));
    lcd.setCursor(0, 1);
    lcd.print(F("-----------------"));
    gravaEEPROM(); // (*) See information on first line about EEPROM record
    lcd.setCursor(0, 1);
    lcd.print(F(">>>>> DONE <<<<<<"));
    lcd.clear();
    tela = 21;
  }


 }  //////////////////////////////////// End subMenuGain


void entradaDados()  /////// Entrada de dados para zerar e ganho dos canais /////////
{

  //Identificação tecla pressionada
  char leitura_teclas = teclado_personalizado.getKey();  // Atribui a variavel a leitura do teclado

  // Se alguma tecla foi pressionada
  if (leitura_teclas) {

    switch (leitura_teclas) {

        //caso a tecla CLEAR tenha sido pressionada
      case 'R':
        //limpa a variável que guarda a senha que está sendo digitada
        inputdata = "";
        if (tela == 211) cpm1 = 0;
        if (tela == 212) cpm2 = 0;
        if (tela == 213) cpm3 = 0;
        if (tela == 214) cpm4 = 0;
        if (tela == 215) cpm5 = 0;

        lcd.setCursor(0, 0);
        lcd.print(F(" RESTART OPTION -----"));
        lcd.print(F(" "));
        lcd.setCursor(0, 1);
        lcd.print(F("IN PROCESS ---->>>>>>"));
        delay(500);
        tela = 1;
        break;

        // Sem uso // case 'U': // case 'D': // case 'F':

      case 'S':
        Serial.println(F("Retorno menu"));
        lcd.clear();
        inputdata = "";
        if ((tela == 21) || (tela == 22) || (tela == 23) || (tela == 24) || (tela == 25)) tela = 2;
        //else if ((tela == 31) || (tela == 32) || (tela == 33) || (tela == 34) || (tela == 35)) tela = 3;
        else if ((tela == 211) || (tela == 212) || (tela == 213) || (tela == 214) || (tela == 215) || (tela == 216)) tela = 21;
        break;

      // Valores do teclado para a variável
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        //concatena o novo símbolo a senha que estamos digitando
        inputdata += leitura_teclas;
       
        lcd.setCursor(13, 0);
        if (tela == 211) lcd.print(cpm1);
        if (tela == 212) lcd.print(cpm2);
        if (tela == 213) lcd.print(cpm3);
        if (tela == 214) lcd.print(cpm4);
        if (tela == 215) lcd.print(cpm5);

        lcd.setCursor(1, 1);
        lcd.print(inputdata);
        delay(500);
        break;

      case 'O':

        // Transforma dados de caracter em número
        String text = inputdata; // transforma char em string
        long value; // para transformar em número inteiro
        value = text.toInt(); // transforma número inteiro

        Serial.print(F("Value: "));
        Serial.println(value);
       
        if (tela == 211) cpm1 = value;
        if (tela == 212) cpm2 = value;
        if (tela == 213) cpm3 = value;
        if (tela == 214) cpm4 = value;
        if (tela == 215) cpm5 = value;

        break;

        if (leitura_teclas == 'S') {  // //Teste tecla Parada para interromper a gravação e retornar ao menu 1
          Serial.println(F("Retorno menu"));
          lcd.clear();
          if ((tela == 21) || (tela == 22) || (tela == 23) || (tela == 24) || (tela == 25)) tela = 2;
          else if ((tela == 211) || (tela == 212) || (tela == 213) || (tela == 214) || (tela == 215) || (tela == 216)) tela = 21;
         
          inputdata = "";
          return;  // finalmente retornou ao menu principal!
        }

      default:
        break;
    }
  }
 
}  //////// Fim entrada de dados

void fileopen()  /// Star File open to record
{
  //Create a new file sequencial on SD card
  char filename[] = "LOGGE000.TXT";
  for (uint8_t i = 0; i < 1000; i++) {
    filename[5] = '0' + (i / 100) % 10;
    filename[6] = '0' + (i / 10) % 10;
    filename[7] = '0' + i % 10;
    if (!SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE);
      digitalWrite(lederroPin, LOW);  // turn the LED off by making the voltage LOW
      logfile.println(filename);

      //Data e hora abertura do arquivo
      DateTime now = rtc.now();
      logfile.print(now.day(), DEC);
      logfile.print('/');
      logfile.print(now.month(), DEC);
      logfile.print('/');
      logfile.println((now.year() - 2000), DEC);

      if (now.hour() < 10) lcd.print(F("0"));  // sempre 2 dígitos
      logfile.print(now.hour());
      logfile.print(F(":"));
      if (now.minute() < 10) lcd.print(F("0"));
      logfile.print(now.minute());
      logfile.print(F(":"));
      if (now.second() < 10) lcd.print(F("0"));
      logfile.print(now.second());
      logfile.print(F("-"));

      lcd.clear();
      lcd.setBacklight(HIGH);
      lcd.setCursor(0, 0);
      lcd.print(F("    FILE OPEN   "));
      lcd.print(F(" "));
      lcd.setCursor(0, 1);
      lcd.print(F("File:"));
      lcd.print(filename);
      delay(1000);

      break;  // leave the loop!
    }
  }
  if (!logfile) {
    error("couldnt create file");
    Serial.println(F("Fail to create file"));
    lcd.clear();
    lcd.setBacklight(HIGH);
    lcd.setCursor(3, 0);
    lcd.print(F("* FAIL ON *"));
    lcd.setCursor(3, 1);
    lcd.print(F("* SD CARD *"));
    digitalWrite(lederroPin, HIGH);  // turn the LED on (HIGH is the voltage level)
  }
  Serial.print(F("Logging to: "));
  Serial.println(filename);
  delay(1000);

}  //end fileopen


void gravacao()  ///// Star gravação = Recorder
{
  for (int k = 2; k > 1; k++)  //Para manter o loop da gravação
  {

    char leitura_teclas = teclado_personalizado.getKey();  // Atribui a variavel a leitura do teclado

    if (leitura_teclas == 'R') {  // Se a tecla Reset foi pressionada
      lcd.clear();
      resetando();
    }
    if (leitura_teclas == 'S') {  // //Teste tecla Parada para interromper a gravação e retornar ao menu 1
      Serial.println(F("Parada solicitada"));
      lcd.clear();
      tela = 1;
      return;  // Return to Main Menu
    }

    //Para troca de tela no LCD, quando gravando CPs e temperaturas
    if (leitura_teclas == 'U') {
      if (d == 0) d = 1;
      else if (d == 1) d = 0;
    }
    if (leitura_teclas == 'D') {
      if (d == 0) d = 1;
      else if (d == 1) d = 0;
    }

    unsigned long atual = millis();

    digitalWrite(record, LOW);  //Indica gravação no cartão
                               
    //Leitura das CPs
    int cp1 = (analogRead(A0));
    int cp2 = (analogRead(A1));
    int cp3 = (analogRead(A2));
    int cp4 = (analogRead(A3));
    int cp5 = (analogRead(A4));

    //int cpp1 = cp1 * (670.0 / 1023.0);
    cpp1 = map(cp1, 0, 1023, 0, cpm1);
    cpp2 = map(cp2, 0, 1023, 0, cpm2);
    cpp3 = map(cp3, 0, 1023, 0, cpm3);
    cpp4 = map(cp4, 0, 1023, 0, cpm4);
    cpp5 = map(cp5, 0, 1023, 0, cpm5);
   
    //Zeramento das entradas analógicas
    if (cpp1 < 4) cpp1 = 0;
    if (cpp2 < 4) cpp2 = 0;
    if (cpp3 < 4) cpp3 = 0;
    if (cpp4 < 4) cpp4 = 0;
    if (cpp5 < 4) cpp5 = 0;


    if (atual - Tgrava > 1000) {
      Serial.print((String) "DATA,DATE,TIME,TIMER,");  //Menu PLX-DAQ
      Serial.print(cpp1);
      Serial.print(F(","));
      Serial.print(cpp2);
      Serial.print(F(","));
      Serial.print(cpp3);
      Serial.print(F(","));
      Serial.print(cpp4);
      Serial.print(F(","));
      Serial.print(cpp5);
      Serial.print(F(","));

      Serial.print(F(","));
      Serial.print(robojax1.readCelsius(), 1);  // termopar 1
      Serial.print(F(","));
      Serial.print(robojax2.readCelsius(), 1);  // termopar 2
      Serial.print(F(","));
      Serial.print(robojax3.readCelsius(), 1);  // termopar 3
      Serial.print(F(","));
      Serial.print(robojax4.readCelsius(), 1);  // termopar 4
      Serial.print(F(","));
      Serial.print(robojax5.readCelsius(), 1);  // termopar 5
      Serial.println(F(","));

      if (d == 0) {
        //Saída LCD CPs
        lcd.setCursor(0, 0);
        lcd.print(cpp1);
        lcd.print(F("|"));
        lcd.print(cpp2);
        lcd.print(F("|"));
        lcd.print(cpp3);
        lcd.print(F(" mbar <<<<<<<"));

        lcd.setCursor(0, 1);
        //lcd.print(F("."));
        lcd.print(cpp4);
        lcd.print(F("|"));
        lcd.print(cpp5);
        lcd.print(F("|"));
        lcd.print(F("mbar <<<<<<<<"));
      }

      if (d == 1) {
        //Saída LCD temperaturas
        lcd.setCursor(0, 0);
        lcd.print(robojax1.readCelsius(), 0.1);
        lcd.print(F("|"));
        lcd.print(robojax2.readCelsius(), 0.1);
        lcd.print(F("|"));
        lcd.print(robojax3.readCelsius(), 0.1);
        lcd.print(F("   "));
        lcd.write((byte)0);  //Mostra o simbolo do grau formado pelo array
        lcd.print(F("C <<<<<<"));
        lcd.setCursor(0, 1);
        lcd.print(robojax4.readCelsius(), 0.1);
        lcd.print(F("|"));
        lcd.print(robojax5.readCelsius(), 0.1);
        lcd.print(F("   "));
        lcd.write((byte)0);  //Mostra o simbolo do grau formado pelo array
        lcd.print(F("C <<<<<<"));
        lcd.print(F("......."));
      }


      //SDCard record
      logfile.flush();
      DateTime now = rtc.now();
      if (a == 0) {
        logfile.println(F("Time,#,PT1,PT2,PT3,PT4,PT5,T1,T2,T3,T4,T5"));
        a++;
      }
      if (now.hour() < 10) logfile.print(F("0"));  // sempre 2 dígitos
      logfile.print(now.hour());
      logfile.print(F(":"));
      if (now.minute() < 10) logfile.print(F("0"));
      logfile.print(now.minute());
      logfile.print(F(":"));
      if (now.second() < 10) logfile.print(F("0"));
      logfile.print(now.second());
      logfile.print(F(" , "));
      logfile.print(z);
      logfile.print(F(" , "));
      logfile.print(cpp1);
      logfile.print(F(" , "));
      logfile.print(cpp2);
      logfile.print(F(" , "));
      logfile.print(cpp3);
      logfile.print(F(" , "));
      logfile.print(cpp4);
      logfile.print(F(" , "));
      logfile.print(cpp5);
      logfile.print(F(" , "));

      logfile.print(robojax1.readCelsius());  // termopar 1
      logfile.print(F(","));
      logfile.print(robojax2.readCelsius());  // termopar 2
      logfile.print(F(","));
      logfile.print(robojax3.readCelsius());  // termopar 3
      logfile.print(F(","));
      logfile.print(robojax4.readCelsius());  // termopar 4
      logfile.print(F(","));
      logfile.print(robojax5.readCelsius());  // termopar 5
      logfile.println(F(","));

      digitalWrite(record, HIGH);
      Tgrava = atual;
    }
  }
 
}  ///////////////////end gravacao()


void temperatures() {
  for (int k = 2; k > 1; k++)  // Maintains loop recorder
  {
    char leitura_teclas = teclado_personalizado.getKey();  // Atribui a variavel a leitura do teclado

    if (leitura_teclas == 'R') {  // Se a tecla Reset foi pressionada
      lcd.clear();
      resetando();
    }
    if (leitura_teclas == 'S') {  // //Teste tecla Parada para interromper a gravação e retornar ao menu 1
      Serial.println(F("Parada solicitada"));
      lcd.clear();
      tela = 1;
      return;  // finalmente retornou ao menu principal!
    }

    unsigned long atual = millis();  // Timing to record

    digitalWrite(record, LOW);  // Show record SD Card

   
    if (atual - Tgrava > 1000) {
      Serial.print((String) "DATA,DATE,TIME,TIMER,");  //Menu PLX-DAQ
      Serial.print(cpp1);
      Serial.print(F(","));
      Serial.print(cpp2);
      Serial.print(F(","));
      Serial.print(cpp3);
      Serial.print(F(","));
      Serial.print(cpp4);
      Serial.print(F(","));
      Serial.print(cpp5);
      Serial.print(F(","));

      Serial.print(F(","));
      Serial.print(robojax1.readCelsius(), 0.1);  // termopar 1
      Serial.print(F(","));
      Serial.print(robojax2.readCelsius(), 0.1);  // termopar 2
      Serial.print(F(","));
      Serial.print(robojax3.readCelsius(), 0.1);  // termopar 3
      Serial.print(F(","));
      Serial.print(robojax4.readCelsius(), 0.1);  // termopar 4
      Serial.print(F(","));
      Serial.print(robojax5.readCelsius(), 0.1);  // termopar 5
      Serial.println(F(","));


      //Saída LCD
      lcd.setCursor(0, 0);
      lcd.print(robojax1.readCelsius(), 0.1);
      lcd.print(F("."));
      lcd.print(robojax2.readCelsius(), 0.1);
      lcd.print(F("."));
      lcd.print(robojax3.readCelsius(), 0.1);
      lcd.print(F("."));
      lcd.print(robojax4.readCelsius(), 0.1);
      lcd.print(F("......."));
      lcd.setCursor(0, 1);
      lcd.print(F("."));
      lcd.print(robojax5.readCelsius(), 0.1);
      lcd.print(F("................."));

      //Saída Cartão SD
      logfile.flush();
      DateTime now = rtc.now();
      if (a == 0) {
        logfile.println(F("Time,#,PT1,PT2,PT3,PT4,PT5,PT6,PT7,PT8,T1,T2,T3,T4,T5"));  // Cabeçalho Excel
        a++;
      }
      if (now.hour() < 10) logfile.print(F("0"));  // sempre 2 dígitos
      logfile.print(now.hour());
      logfile.print(F(":"));
      if (now.minute() < 10) logfile.print(F("0"));
      logfile.print(now.minute());
      logfile.print(F(":"));
      if (now.second() < 10) logfile.print(F("0"));
      logfile.print(now.second());
      logfile.print(F(" , "));
      logfile.print(z);
      logfile.print(F(" , "));
      logfile.print(cpp1);
      logfile.print(F(" , "));
      logfile.print(cpp2);
      logfile.print(F(" , "));
      logfile.print(cpp3);
      logfile.print(F(" , "));
      logfile.print(cpp4);
      logfile.print(F(" , "));
      logfile.print(cpp5);
      logfile.print(F(" , "));

      logfile.print(robojax1.readCelsius());  // termopar 1
      logfile.print(F(","));
      logfile.print(robojax2.readCelsius());  // termopar 2
      logfile.print(F(","));
      logfile.print(robojax3.readCelsius());  // termopar 3
      logfile.print(F(","));
      logfile.print(robojax4.readCelsius());  // termopar 4
      logfile.print(F(","));
      logfile.print(robojax5.readCelsius());  // termopar 5
      logfile.println(F(","));

      digitalWrite(record, HIGH);
      Tgrava = atual;
    }
  }


}  ///////////////////end temperatures()


void resetando() {
  logfile.close();
  lcd.setCursor(0, 0);
  lcd.print(F("......RESET......"));
  lcd.setCursor(0, 1);
  lcd.print(F("----------------"));
  delay(1000);
  resetFunc();  // reset the Arduino via software function
}


void gravaEEPROM() {
 
  Serial.println(F("Gravando...."));
 
  Serial.println(cpm1);
    EEPROM.write(0, cpm1/256);
    EEPROM.write(1, cpm1%256);
    delay(2000);

  Serial.println(cpm2);
    EEPROM.write(6, cpm2/256);
    EEPROM.write(7, cpm2%256);
    delay(2000);

  Serial.println(cpm3);
    EEPROM.write(12, cpm3/256);
    EEPROM.write(13, cpm3%256);
    delay(2000);    
 
  Serial.println(cpm4);
    EEPROM.write(18, cpm4/256);
    EEPROM.write(19, cpm4%256);
    delay(2000);
 
  Serial.println(cpm5);
    EEPROM.write(24, cpm5/256);
    EEPROM.write(25, cpm5%256);
    delay(2000);

  return;
}

void leituraEEPROM()
{

  //Serial.println(F("Lendo cpm1 da memoria EEPROM... "));
  //Serial.print("Lendo parte 1 : ");
  int parte0 = EEPROM.read(0);
  //Serial.println(parte0);
  //Serial.print("Lendo parte 2 : ");  
  int parte1 = EEPROM.read(1);
  //Serial.println(parte1);
  Serial.print(F("Valor original1 : "));
  int valor_original1 = (parte0 * 256) + parte1;
  cpm1 = valor_original1;
  Serial.println(valor_original1);

 //Serial.println(F("Lendo cpm2 da memoria EEPROM... "));
  //Serial.print("Lendo parte 12 : ");
  int parte6 = EEPROM.read(6);
  //Serial.println(parte6);
  //Serial.print("Lendo parte 21 : ");  
  int parte7 = EEPROM.read(7);
  //Serial.println(parte7);
  Serial.print(F("Valor original2 : "));
  int valor_original2 = (parte6 * 256) + parte7;
  cpm2 = valor_original2;
  Serial.println(valor_original2);

  //Serial.println(F("Lendo cpm3 da memoria EEPROM... "));
  //Serial.print("Lendo parte 1 : ");
  int parte12 = EEPROM.read(12);
  //Serial.println(parte12);
  //Serial.print("Lendo parte 2 : ");  
  int parte13 = EEPROM.read(13);
  //Serial.println(parte13);
  Serial.print(F("Valor original3 : "));
  int valor_original3 = (parte12 * 256) + parte13;
  cpm3 = valor_original3;
  Serial.println(valor_original3);

  //Serial.println(F("Lendo cpm4 da memoria EEPROM... "));
  //Serial.print("Lendo parte 18 : ");
  int parte18 = EEPROM.read(18);
  //Serial.println(parte18);
  //Serial.print("Lendo parte 19 : ");  
  int parte19 = EEPROM.read(19);
  //Serial.println(parte19);
  Serial.print(F("Valor original4 : "));
  int valor_original4 = (parte18 * 256) + parte19;
  cpm4 = valor_original4;
  Serial.println(valor_original4);

  //Serial.println(F("Lendo cpm5 da memoria EEPROM... "));
  //Serial.print("Lendo parte 24 : ");
  int parte24 = EEPROM.read(24);
  //Serial.println(parte24);
  //Serial.print("Lendo parte 24 : ");  
  int parte25 = EEPROM.read(25);
  //Serial.println(parte25);
  Serial.print(F("Valor original5 : "));
  int valor_original5 = (parte24 * 256) + parte25;
  cpm5 = valor_original5;
  Serial.println(valor_original5);  

  //while(1) // Serve para parar quando colocado dentro do Loop
  //{}    

}

Comentários