Ho passato 2 giorni di prove prima di decidere a scrivere qui, ho letto guide e post ma senza trovarne la soluzione, il problema è tanto banale che ho finito le armi... oltre ad essere alle prime armi naturalmente.
Se eseguo uno scrip analogo a questo su ArduinoUnoR3 programmandolo dall'IDE offline funziona tutto come mi immagino.
Una volta che lo porto sul coud di arduino e su una MKRWiFi1010 invece si comporta in modo anomalo.
Sicuramente sto sbagliando qualcosa di banale ma fondamentale ma prima di continuare a scervellarmi provo a chiedervi un aiuto visto che sono alle prime armi e ho già perso 2giorni con la funzione scheduler scoprendo poi che era colpa di un bug.
Lo scopo di tutto questo?
Quando attivo il selettore "Manuale" allora "Stato" si deve attivare (true) per 1 minuto e poi spegnersi(false).
Ora il valore di millisecondi nel wile l'ho messo a caso, è una delle tante prove, ma non riesco a farlo funzionare con nessun valore.
In realtà i millis li avrei confrontati con time_now+intervallo . Intervallo avrei settato il 1minuto di attesa.
"Abilitato" serviva ad altro come si vede dal codice, l'ho usato solo per questo esempio per resettare il "var" che ho inserito nel programma solo per visualizzare cosa succedeva alla variabile "time_now"
void onAbilitatoChange() {
if (abilitato == true) {
stato = true;
var = 0; //only for test
}
if (abilitato == false) {
stato = false;
}
}
void onManualeChange() {
if (manuale == true) {
timer_now = millis();
var = timer_now; //only for test
while (millis() < 40000) {
stato = true;
}
stato = false;
manuale = false;
}
if (manuale == false) {
stato = false;
}
Grazie a chiunque mi dia un qualche consiglio
Ciao
Hai ragione, mi sembra fosse troppo dispersivo, rimedio subito:
/*
Sketch generated by the Arduino IoT Cloud Thing "Untitled"
https://create.arduino.cc/cloud/things/3a098327-9bd4-451c-a93e-6c01f50ae8c5
Arduino IoT Cloud Variables description
The following variables are automatically generated and updated when changes are made to the Thing
float humidity;
float pressure;
float temperature;
float vaso1;
CloudSchedule prog;
bool abilitato;
bool manuale;
bool stato;
CloudTime time_read;
Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
which are called when their values are changed from the Dashboard.
These functions are generated with the Thing and added at the end of this sketch.
*/
#include "thingProperties.h"
#include <Arduino_MKRENV.h> //rs aggiunta per led integrato
//rs variabili interne
const int intervallo = 5000; // Tempo in millisecondi accensione manuale
unsigned long timer_now = 0;
void setup() {
// Initializza serial
Serial.begin(9600);
// lasciare il tempo che si connetta
delay(1500);
// vedi thingProperties.h
initProperties();
// Connetti IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
//ENV
if (!ENV.begin()) {
Serial.println("Failed to initialize MKR ENV shield!");
while (1);
}
stato = false; //spegne stato nel caso fosse rimasto acceso
var = 0; //solo per test
//definizione del led rgb integrato
WiFiDrv::pinMode(25, OUTPUT); //define red pin
WiFiDrv::pinMode(26, OUTPUT); //define green pin
WiFiDrv::pinMode(27, OUTPUT); //define blue pin
}
void loop() {
ArduinoCloud.update();
if (ArduinoCloud.connected()) {
time_read = ArduinoCloud.getLocalTime();
}
// leggi valori dei sensori
temperature = ENV.readTemperature();
humidity = ENV.readHumidity();
pressure = ENV.readPressure();
//leggi valori pin analogici
vaso1 = analogRead(A1);
}
void onAbilitatoChange() {
if (abilitato == true) {
stato = true;
var = 0; //only for test
}
if (abilitato == false) {
stato = false;
}
}
void onManualeChange() {
if (manuale == true) {
timer_now = millis();
var = timer_now; //only for test
while (millis() < 40000) {
stato = true;
}
stato = false;
manuale = false;
}
if (manuale == false) {
stato = false;
}
}
void onProgChange() {
if (prog.isActive()) {
stato = true;
} else {
stato = false;
}
if (ArduinoCloud.connected()) {
time_read = ArduinoCloud.getLocalTime();
}
}
void onStatoChange() {
//niente
}
void onTimeReadChange() {
//niente
}
Ero partito da questo che su l'arduino UNO funzionava bene:
stato_pulsante=digitalRead(pulsante);
if (stato_pulsante==HIGH){
timer_now=millis();
do {
digitalWrite(LEDR, HIGH);
} while (millis()<timer_now+intervallo);
digitalWrite(LEDR, LOW);
Ma nel cloud non sono riuscito a farlo funzionare,
stato_pulsante=digitalRead(pulsante);
if (manuale == true){
timer_now=millis();
do {
stato = true;
} while (millis()<timer_now+intervallo);
stato = false;
cosi ho ripiegato su un while più semplice, ma evidentemente continuo a sbagliare qualcosa...
Non ha senso. Se vedi il codice che tu stesso hai postato come punto di partenza vedi che quando si lavora con millis() si fa sempre verificando una differenza tra valore attuale di millis() e un valore precedente. Millis() < 40000 non ha molto senso. Appena accendi Arduino per un pò millis() è sotto 40000 ma dopo 40 secondi... millis() supera quel valore.
OK, questa è la definizione di un ciclo while Quello che intendevo era assicurarmi che capisci che non stai testando una durata con
while (millis() < 40000) { stato = true; }
Stai dicendo di aspettare fino a 40 secondi dopo l'avvio di Arduino e di mantenere lo stato a true durante quel periodo (quando una volta sarebbe sufficiente).
•••
unsigned long tempoCambioManuale;
•••
void onManualeChange() {
if (manuale) { // l'utente ha attivato la modalità manuale
tempoCambioManuale = millis();
}
}
void loop() {
•••
if (manuale && (millis() - tempoCambioManuale >= 60000ul)) manuale = false;
•••
}
Se cambiate manuale a true nel vostro codice e volete anche lo spegnimento automatico dopo 60 secondi, allora ricordatevi di registrare millis() anche in tempoCambioManuale affinché il loop possa tenerne conto.
Grazie a tutti per le risposte, ho fatto varie prove ed il ciclo while quando parte blocca la lettura di tutti i sensori finchè non termina, giustamente, quindi forse meglio usare un if.
Ma evidentemente il mio problema con i millis() è più grave del previsto =) ...
void loop() {
....blablabla....
if (stato == true) {
if (millis() - tempo_accensione < tempo_on)
stato = false;
manuale = false;
delay(200);
}
....
}
void onManualeChange() {
if (manuale == true) {
tempo_accensione = millis();
delay(200);
stato = true;
}
Quando si attiva il selettore "manuale" lo stato deve diventare true per il tempo "tempo_on" e poi tornare false.
Quello che intendo è che se manuale cambia solo attraverso l'interfaccia cloud, l'approccio di attivare il timeout durante la sua modifica e verificare se il tempo è trascorso nel ciclo dovrebbe funzionare.
Ho provato ad inserire una sorta di log e non è molto incoraggiante.
Il programma allo start manda subito il primo messaggio, ma questo ci potrebbe anche stare forse è il funzionamento stesso del tasto "cloud" normalmente spento (false) quando viene letto la prima volta.
tempo_on= 10000;
void loop() {
ArduinoCloud.update();
if (stato == true) {
if (millis() - tempo_accensione < tempo_on)
stato = false;
manuale = false;
var = "è passato il tempo_on quindi stato&manuale=false";
}
}
void onManualeChange() {
if (manuale == true) {
var = "onManualeChange: manuale true (1)";
tempo_accensione = millis();
delay(200);
stato = true;
var = "onManualeChange: manuale true (2)";
}
if (manuale == false) {
var = "onManualeChange: manuale false";
stato = false;
}
}