Grazie per i consigli.
Quello che ho postato non è tutto lo sketch completo.
Sto adattando a pezzetti uno sketch funzionante per visualizzare su Lcd alcuni dati.
L'rtc funziona perché in questo momento è attiva la gestione dell'erogazione del cibo.
Proverò a modificare il programma completo inserendo a step le chiamate al LCD.
Ovviamente mi documento sulla sintassi dell'ISR su ESP.
Questo è lo sketch originale funzionante e attualmente operativo che io devo modificare per inserire le visualizzazioni su LCD.
Il motivo è togliere tutte le linee del programma che fanno riferimento a "uPanel" che non esiste più, che è cessato operativamente.
/******************** in test *******************************
* Derivato da Erogatore_v80_2xday_mod_test
* 6 marzo 2022
* editor: Arduino 1.8.16
* motore: NEMA 17HS19
* orologio: DS3231
* micro: Arduino NANO
* processore: ATmega328P (old bootloader)
* porta: /dev/cu.wchusbserial1410
* WiFi: SCF-01 e ADP-01 (miuPanel)
* step motor: IN1 D12(15), IN2 D11(14), IN3 D10(13), IN4 D9(12)
* i2C: SDA A4(23), SCL A5(24)
* interrupt: INT0 D2(5)
*
* Descrizione:
* Inserite 2 erogazioni giornaliere (8, 20)
* Massimo 32 erogazioni totali
* 3 led per visualizzare in locale le erogazioni
* Al restart dell'App ricarica la situazione precedente
*******************************************************************/
#include <Stepper.h>
#include <Wire.h>
#include <DS3231.h>
#define STEPS 400
#define decremento 3 // decremento normale = 3 per 32 erogazioni
#define DS3231_I2C_ID 0x68 //I2C indirizzo del RTC DS3231
Stepper stepper(STEPS, 12, 11, 10, 9);
int passi = 900; // passi alimentazione ruota 1/6 di giro
const byte interuptPin0 = 2; //D2 pin5
String Msg;
int Max = 100; // variabile per barra analogica
int Min = 0; // variabile per display a 7 segmenti
int v = 0; // variabile per display a 7 segmenti
int d1 = 0; // variabile per display a 7 segmenti
int d2 = 0; // variabile per display a 7 segmenti
volatile byte Ore = 0;
volatile byte Minuti = 0;
volatile byte orario = 0;
unsigned char led_L1G = 0; // led verde Automatico
unsigned char led_L2R = 0; // led rosso Riserva
unsigned char led_L35 = 0; // Led unità display
unsigned char led_L45 = 0; // led decine display
unsigned char led_L5Y = 0; // led giallo ore 8
unsigned char led_L7Y = 0; // led giallo ore 20
unsigned char led_L8R = 0; // led rosso Vuoto
volatile boolean alarmFlag = false;
volatile boolean Empty = true;
int ledVerde1 = 8; // led ore 8 (D8) pin 11
int ledVerde2 = 7; // led ore 20 (D7) pin 10
int ledRosso1 = 6; // led riserva (D6) pin 9
DS3231 clock;
void alarmISR(){
alarmFlag = true;
}
void setup(){
Serial.begin(57600);
delay(5000);
Serial.println("");
pinMode(interuptPin0,INPUT_PULLUP);
alarmFlag = false;
Wire.begin();
SendPanel();
stepper.setSpeed(100); // imposta la velocità del motore
digitalWrite(12,LOW);
digitalWrite(11,LOW);
digitalWrite(10,LOW);
digitalWrite(9,LOW);
pinMode(ledVerde1, OUTPUT);
pinMode(ledVerde2, OUTPUT);
pinMode(ledRosso1, OUTPUT);
digitalWrite(ledVerde1, LOW);
digitalWrite(ledVerde2, LOW);
digitalWrite(ledRosso1, LOW);
Allarme(); // attiva allarme su interrutp del RTC
}
void loop(){
int c;
while ((c = Serial.read()) > '\n') Msg += (char) c;
if (c == '\n')
{
if (Msg.substring(0,4).equals("#W01")) {Manuale();} // Manuale
else if (Msg.substring(0,4).equals("$RES")) {SendPanel();} // In caso di reset
Msg = ""; // Clean message string
}
if (alarmFlag == true){
readDate();
if (Ore == 8){
Eroga();
Serial.println("#L51"); // accende i led delle ore 8
led_L5Y = 1;
digitalWrite(ledVerde1, HIGH);
orario = 20;
}
else if (Ore == 20){
Eroga();
Serial.println("#L71"); // accende i led delle ore 20
led_L7Y = 1;
digitalWrite(ledVerde2, HIGH);
orario = 0;
}
else if (Ore == 0){
Aggiorna();
orario = 8;
digitalWrite(ledVerde1, LOW);
digitalWrite(ledVerde2, LOW);
}
alarmFlag = false;
clock.clearAlarm1();
}
}
/*************************** FUNZIONI *************************/
void SendPanel(){ // pannello principale
Serial.print("\n$P:D!06F;-0{%100,y6!06FTf*15d2:Erogatore v9.0_2xday - © EzioGi;}=//{-r30!228,114*15{T:Automatico;|L1G:1;_T:Riserva;|L2R:0;_T:Vuoto;|L8R:0;}");
Serial.print("|{^*10L35:0;&L45:0;_T:Erogazioni;}}//{T#FFF*15fa:Manuale;|*11W0G:0;}/10A1-*20-5r20!00F,DDD>:0:100:100:!00F;{T#FFF*15fa:% crocchette;}");
Serial.println("//{-r30!228,114*8{T#FFF*20fa:ore 8;|L5Y:0;|||T#FFF*20fa:ore 20;|L7Y:0;}}");
// Controlla lo stato di tutti gli oggetti del pannello
if (led_L1G == 1) Serial.println("#L11"); // automatico
if (led_L2R == 1) Serial.println("#L21"); // riserva
if (led_L5Y == 1) Serial.println("#L51"); // ore 8
if (led_L7Y == 1) Serial.println("#L71"); // ore 20
if (led_L8R == 1) Serial.println("#L81"); // vuoto
Serial.print("#L3"); Serial.println(d1,DEC);
Serial.print("#L4"); Serial.println(d2,DEC);
Serial.print("#A1:");
Serial.println(Max,DEC);
}
void Eroga(){ // ruota l'aletta di 1/6th per erogare le crocchette
if (Empty == true){ // se serbatoio ancora pieno
stepper.step(passi);
digitalWrite(12,LOW);
digitalWrite(11,LOW);
digitalWrite(10,LOW);
digitalWrite(9,LOW);
incrCont(); // Incrementa Contatore Erogazioni
decrBarraAn(); // Decrementa livello barra A1
}
}
void Aggiorna(){ // resetta i led ad eccezione del contatore numerico e della barra analogica
if (Empty == true){
Serial.println("#L11"); // Accende il led L1 "automatico"
}
Serial.println("#L20"); // Spegne il led L2 "riserva"
Serial.println("#L50"); // Spegne led5
Serial.println("#L70"); // Spegne led7
}
void incrCont(){ // incrementa contatori
v = v+1;
d1 = (v / 10) % 10; // Calcola la prima cifra LCD
d2 = v % 10; // Calcola la seconda cifra LCD
Serial.print("#L3"); Serial.println(d1,DEC); // Aggiorna la prima cifra LCD
Serial.print("#L4"); Serial.println(d2,DEC); // Aggiorna la seconda cifra LCD
}
void decrBarraAn(){ // decremento la barra analogica
Serial.print("#A1:");
Serial.println((Max -= decremento),DEC);
if ( Max <= 19 && Max > 1) // se contatore uguale o inferiore a 19 e contenitore non vuoto
{
Serial.println("#L21"); // Accende il led L2 "riserva"
digitalWrite(ledRosso1, HIGH);
}
else if (Max <= 1){ // se contatore uguale o inferiore a 1 il contenitore è vuoto
Max = 0;
Serial.print("#A1:");
Serial.println(Max,DEC);
Serial.println("#L10"); // Spegne il L1 "automatico"
Serial.println("#L20"); // Spegne il led L2 "riserva"
Serial.println("#L81"); // Accende il led L8 "vuoto"
Empty = false;
}
}
void Manuale(){
Serial.println("#W00"); // Accende lo Switch
if (Empty == true){ // se vera eroga, se falsa salta erogazione
Eroga(); // Eroga una porzione
}
Serial.println("#W01"); // Spegne lo Switch
}
void readDate(){
Wire.beginTransmission(DS3231_I2C_ID);
Wire.write(0x1);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ID, 2); // scarica 2 bytes
Minuti = bcd2dec (Wire.read() & 0b1111111);
Ore = bcd2dec (Wire.read() & 0b00111111);
}
byte bcd2dec(byte val){
return ((val / 16* 10) + (val % 16));
}
void Allarme(){
clock.begin();
// Interrupt abilitato, onda quadra disabilitata
clock.enableOutput(false);
clock.armAlarm1(false);
clock.clearAlarm1();
// Day, Ore, Minuti, Second, Mode, Armed = true)
// Set Alarm1 - il 10s in ogni minuto
//clock.setAlarm1(0, 0, 0, 10, DS3231_MATCH_S);
// Set Alarm1 - il 1m e 1s in ogni ora
clock.setAlarm1(0, 0, 1, 1, DS3231_MATCH_M_S);
attachInterrupt(digitalPinToInterrupt(interuptPin0), alarmISR, FALLING); // interrupt su fronte di discesa
}
Questa è la versione modificata che non funziona:
/******************** *******************************
* Derivato da Erogatore_v90_2xday_mod_test
* 31 marzo 2022
*
* editor: Arduino 1.8.13
* motore: NEMA 17HS19
* orologio: DS3231
* micro: Arduino NANO
* processore: ATmega328P (old bootloader)
* porta: /dev/cu.wchusbserial1410
* WiFi: SCF-01 e ADP-01 (miuPanel)
* step motor: IN1 D11(13), IN2 D10(13), IN3 D9(12), IN4 D8(11)
* i2C: SDA A4(23), SCL A5(24)
* interrupt: INT0 D2(5)
* erogazione manuale: Sw1 D12(15)
*
* Descrizione:
* Inserite 2 erogazioni giornaliere (8, 20)
* Massimo 32 erogazioni totali
* Al restart dell'App ricarica la situazione precedente
* Inserito visualizzazioni su LCD
*******************************************************************/
#include <Stepper.h>
#include <Wire.h>
#include <PCF8574_HD44780_I2C.h>
#include <DS3231.h>
#define STEPS 400
#define decremento 3 // decremento normale = 3 per 32 erogazioni
#define DS3231_I2C_ID 0x68 //I2C indirizzo del RTC DS3231
Stepper stepper(STEPS, 11, 10, 9, 8);
int passi = 900; // passi alimentazione ruota 1/6 di giro
const int ledpin = 13; // Led rosso/giallo
const byte interuptPin0 = 2; //D2 pin5
String Msg;
int Max = 100; // variabile per barra analogica
int Min = 0; // variabile per display a 7 segmenti
int v = 0; // variabile per display a 7 segmenti
int d1 = 0; // variabile per display a 7 segmenti
int d2 = 0; // variabile per display a 7 segmenti
volatile byte Ore = 0;
volatile byte Minuti = 0;
volatile byte orario = 0;
unsigned char led_L1G = 0; // led verde Automatico
unsigned char led_L2R = 0; // led rosso Riserva
unsigned char led_L35 = 0; // Led unità display
unsigned char led_L45 = 0; // led decine display
unsigned char led_L5Y = 0; // led giallo ore 8
unsigned char led_L6Y = 0; // led giallo ore 14
unsigned char led_L7Y = 0; // led giallo ore 20
unsigned char led_L8R = 0; // led rosso Vuoto
volatile boolean alarmFlag = false;
volatile boolean Empty = true;
volatile int flag = 0;
DS3231 clock;
PCF8574_HD44780_I2C lcd(0x27,16,2);
void alarmISR(){
alarmFlag = true;
}
void setup(){
Serial.begin(57600);
delay(5000);
Serial.println("");
pinMode(interuptPin0,INPUT_PULLUP);
alarmFlag = false;
Wire.begin();
SendPanel();
stepper.setSpeed(100); // imposta la velocità del motore
digitalWrite(11,LOW);
digitalWrite(10,LOW);
digitalWrite(9,LOW);
digitalWrite(8,LOW);
Allarme(); // attiva allarme su interrutp del RTC
readDate();
lcd.init();
lcd.backlight();
lcd.clear();
displayLCD(0);
displayLCD(1); // pagina di fondo
}
void loop(){
int c;
while ((c = Serial.read()) > '\n') Msg += (char) c;
if (c == '\n')
{
if (Msg.substring(0,4).equals("#W01")) {Manuale();} // Manuale
else if (Msg.substring(0,4).equals("$RES")) {SendPanel();} // In caso di reset
Msg = ""; // Clean message string
}
if (alarmFlag == true){
readDate();
if (Ore == 8){
Eroga();
Serial.println("#L51"); // accende il led delle ore 8
displayLCD(2);
orario = 20;
}
else if (Ore == 20){
Eroga();
Serial.println("#L71"); // accende il led delle ore 20
displayLCD(3);
orario = 0;
}
else if (Ore == 23){
Aggiorna();
displayLCD(4);
orario = 8;
}
alarmFlag = false;
clock.clearAlarm1();
}
}
/*************************** FUNZIONI *************************/
void SendPanel(){ // pannello principale
Serial.print("\n$P:D!06F;-0{%100,y6!06FTf*15d2:Erogatore v10.0-2xday - © EzioGi;}=//{-r30!228,114*15{T:Automatico;|L1G:1;_T:Riserva;|L2R:0;_T:Vuoto;|L8R:0;}");
Serial.print("|{^*10L35:0;&L45:0;_T:Erogazioni;}}//{T#FFF*15fa:Manuale;|*11W0G:0;}/10A1-*20-5r20!00F,DDD>:0:100:100:!00F;{T#FFF*15fa:% crocchette;}");
Serial.println("//{-r30!228,114*8{T#FFF*20fa:ore 8;|L5Y:0;|||T#FFF*20fa:ore 20;|L7Y:0;}}/{~1^%70,y10!06F#FFF{%50,y60M1*30fb:—:—;}");
// Controlla lo stato di tutti gli oggetti del pannello
if (led_L1G == 1) Serial.println("#L11"); // automatico
if (led_L2R == 1) Serial.println("#L21"); // riserva
if (led_L5Y == 1) Serial.println("#L51"); // ore 8
if (led_L7Y == 1) Serial.println("#L71"); // ore 20
if (led_L8R == 1) Serial.println("#L81"); // vuoto
Serial.print("#L3"); Serial.println(d1,DEC);
Serial.print("#L4"); Serial.println(d2,DEC);
Serial.print("#A1:");
Serial.println(Max,DEC);
}
void displayLCD(int flag){
switch (flag) {
case 0: // inizio
lcd.setCursor(1,0); // colonna, riga
lcd.print("Starting...");
lcd.setCursor(5,1); // colonna, riga
lcd.print(Ore);
lcd.print(":");
lcd.print(Minuti);
delay(3000);
lcd.clear();
lcd.home();
break;
case 1: // fondo stabile
lcd.setCursor(1,0); // colonna, riga
lcd.print("Dispenser ");
lcd.setCursor(11,0); // colonna, riga
lcd.print(Max);
lcd.print("%");
lcd.setCursor(1,1); // colonna, riga
lcd.print("Ore 8 ");
lcd.setCursor(12,1); // colonna, riga
lcd.print("20 ");
break;
case 2: // ore 8
lcd.setCursor(11,0); // colonna, riga
lcd.print(Max);
lcd.print("%");
lcd.setCursor(7,1); // colonna, riga
lcd.print("OK");
break;
case 3: // ore 20
lcd.setCursor(11,0); // colonna, riga
lcd.print(Max);
lcd.print("%");
lcd.setCursor(15,1); // colonna, riga
lcd.print("OK");
break;
case 4: // azzera OK
lcd.setCursor(7,1); // colonna, riga
lcd.print(" ");
lcd.setCursor(15,1); // colonna, riga
lcd.print(" ");
break;
case 5: // riserva
lcd.blink();
lcd.setCursor(11,0); // colonna, riga
lcd.print(Max);
lcd.print("%");
break;
case 6: // vuoto
lcd.blink();
lcd.setCursor(11,0); // colonna, riga
lcd.print(Max);
lcd.print("%");
lcd.setCursor(0,1); // colonna, riga
lcd.print(" ");
break;
}
}
void Eroga(){ // ruota l'aletta di 1/6th per erogare le crocchette
if (Empty == true){ // se serbatoio ancora pieno
stepper.step(passi);
digitalWrite(11,LOW);
digitalWrite(10,LOW);
digitalWrite(9,LOW);
digitalWrite(8,LOW);
incrCont(); // Incrementa Contatore Erogazioni
decrBarraAn(); // Decrementa livello barra A1
Serial.print("$CLOUD SEND:PUSH:Porzione erogata ore ");
Serial.println(Ore);
}
}
void Aggiorna(){ // resetta i led ad eccezione del contatore numerico e della barra analogica
if (Empty == true){
Serial.println("#L11"); // Accende il led L1 "automatico"
}
Serial.println("#L20"); // Spegne il led L2 "riserva"
Serial.println("#L50"); // Spegne led7
Serial.println("#L70"); // Spegne led21
}
void incrCont(){ // incrementa contatori
v = v+1;
d1 = (v / 10) % 10; // Calcola la prima cifra LCD
d2 = v % 10; // Calcola la seconda cifra LCD
Serial.print("#L3"); Serial.println(d1,DEC); // Aggiorna la prima cifra LCD
Serial.print("#L4"); Serial.println(d2,DEC); // Aggiorna la seconda cifra LCD
}
void decrBarraAn(){ // decremento la barra analogica
Serial.print("#A1:");
Serial.println((Max -= decremento),DEC);
if ( Max <= 19 && Max > 1) // se contatore uguale o inferiore a 19 e contenitore non vuoto
{
Serial.println("#L21"); // Accende il led L2 "riserva"
displayLCD(5);
}
else if (Max <= 1){ // se contatore uguale o inferiore a 1 il contenitore è vuoto
Max = 0;
Serial.print("#A1:");
Serial.println(Max,DEC);
Serial.println("#L10"); // Spegne il L1 "automatico"
Serial.println("#L20"); // Spegne il led L2 "riserva"
displayLCD(6);
Serial.println("#L81"); // Accende il led L8 "vuoto"
Empty = false;
}
else{
Serial.println("#L10"); // Spegne il led "automatico"
delay(1000);
Serial.println("#L11"); // Accende il led "automatico"
}
}
void Manuale(){
Serial.println("#W00"); // Accende lo Switch
if (Empty == true){ // se vera eroga, se falsa salta erogazione
Eroga(); // Eroga una porzione
}
Serial.println("#W01"); // Spegne lo Switch
}
void readDate(){
Wire.beginTransmission(DS3231_I2C_ID);
Wire.write(0x1);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ID, 2); // scarica 2 bytes
Minuti = bcd2dec (Wire.read() & 0b1111111);
Ore = bcd2dec (Wire.read() & 0b00111111);
}
byte bcd2dec(byte val){
return ((val / 16* 10) + (val % 16));
}
void Allarme(){
clock.begin();
// Interrupt abilitato, onda quadra disabilitata
clock.enableOutput(false);
clock.armAlarm1(false);
clock.clearAlarm1();
// Day, Ore, Minuti, Second, Mode, Armed = true)
// Set Alarm1 - il 10s in ogni minuto
//clock.setAlarm1(0, 0, 0, 10, DS3231_MATCH_S);
// Set Alarm1 - il 1m e 1s in ogni ora
clock.setAlarm1(0, 0, 1, 1, DS3231_MATCH_M_S);
attachInterrupt(digitalPinToInterrupt(interuptPin0), alarmISR, FALLING); // interrupt su fronte di discesa
}
Lo sketch l'ho solo testato con Arduino UNO senza collegato RTC.
Perché non ho la possibilità di provarlo al completo.
Potrebbe essere questo il malfunzionamento?
Lello