[Risolto]Come uscire da un loop bloccante dal Begin Blynk.

Salve, sto usando la libreria di Blynk ho messo la connessione al server in un loop che viene chiamato per la connessione ,vorrei che dopo un minuto verifico se non ha stabilito la connessione deve uscire.

[code]
#define BLYNK_PRINT Serial
#include <TinyGsmClient.h>
#include <BlynkSimpleTinyGSM.h>
#define SerialMon Serial
#define SerialAT Serial3
const char apn[]  = "internet.it";
const char user[] = "";
const char pass[] = "";
unsigned long  d_blynk , t_blynk ;
int sette = 1;
const char auth[] = "5GK3uWqWQKd";
const char gsm;
TinyGsm modem(SerialAT);
void setup()
{
  SerialMon.begin(9600);
  delay(10);
  SerialAT.begin(9600);
  delay(6000);
  SerialMon.println("Initializing modem...");
  modem.restart();
  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem Info: ");
  SerialMon.println(modemInfo);
}
void BLYNK() {
  //Se non riesce a connettersi al server rimane bloccato qui.
  Blynk.begin(auth, modem, apn, user, pass);
}
void loop()
{
  if (sette == 0) {
    Blynk.run();
  }
  d_blynk = millis() - t_blynk;
  if ( d_blynk > 10000  && Blynk.connected() == false) {
    BLYNK();
    sette = 0;
    t_blynk = millis();
  } 
}

[/code]

wingamesyun:

  //Se non riesce a connettersi al server rimane bloccato qui.

Blynk.begin(auth, modem, apn, user, pass);

Se il codice è questo allora è la funzione begin() ad essere bloccante. Vedi se c'è una variante non bloccante o un metodo di inizializzazione diverso.

Dalla documentazione Blynk: Documentation for Blynk, the most popular IoT platform for businesses.
non mi pare sia bloccante, ma tenta per molto tempo anche più di 30secondi.

What happens inside of Blynk.begin() function:

  1. Connection to the network (WiFi, Ethernet, …)
  2. Call of Blynk.config(...) to set Auth Token, Server Address, etc.
  3. Attempts to connect to the server once (can block for more than 30s)

La Blynk gsm non funziona con la config.

La config() viene chiamata dalla begin()
Qui pare hanno risolto, non usa begin() ma usa config():

Avevo già provato, mi dava un errore nella compilazione. Ora su tuo consiglio ci riprovo di nuovo.

Buongiorno, ho provato ma niente non ci riesco a risolvere.
Vorrei proseguire la strada dell'uscita del loop bloccato se non riesce a connettersi al server in un tempo prefissato.

wingamesyun:
Vorrei proseguire la strada dell'uscita del loop bloccato se non riesce a connettersi al server in un tempo prefissato.

Non puoi, a meno di non intervenire nel sorgente della libreria Blynk perché è il begin() ad essere bloccante. blynk-library/BlynkGsmClient.h at master · blynkkk/blynk-library · GitHub
Una possibile soluzione "esterna" (tutta da testare) è abilitare il watchdog con il relativo interrupt. Nella funzione associata all'interrupt a quel punto vai a salvare una variabile bool in EEPROM che al successivo riavvio sarà true, cosi salti a pie pari la funzione bloccante.
Poi da qualche parte vai a verificare se c'è connessione e in caso positivo provi di nuovo ad inizializzare Blynk.

Lo sketch completo ho già fatto una cosa del genere con la variabile salvata .
Faccio partire lo sketch senza blynk aspetto
Un minuto poi se le tre condizioni sono vere
Cioè tempo, verifica la connessione, la variabile
Salvata come attivazione tenta la connessione al server di blynk
A questo punto se rimane bloccato nella funzione Begin l utente può riavviare arduino e cambiare la variabile di attivazione con un minuto di tempo.
La mia idea era far partire un timer dopo if () se non riesce ad uscire dal void BLYNK () della connessione in tot tempo mi gira la variabile e riavvia il tutto .

Così metterei un altro if che dopo 10 minuti verifica la connessione al server se non si è connesso mi gira la variabile e mi ritenta la connessione tutto in automatico.

Direi che l'unico modo per uscire da quel punto del software è con un interrupt, timer o watchdog (che sempre un timer è) cambia poco.

... direi che la migliore cosa è un timer e ... lasciamo al watchdog fare il suo vero compito, anche perché ... sui nuovi chip AVR è stata tolta la possibilità al WD di sollvare un interrupt, lasciando solo quello che DEVE fare ... resettare la MCU :wink:

Così si impara direttamente ad usare i timers ed in futuro non si hanno brutte sorprese :smiley:

Guglielmo

Un piccolo esempio sulle interrupt a tempo.
Non vorrei usare watcthdog.

Guarda la libreria arduino-timer e vedi gli esempi li ... così eviti anche di dover mettere le mani a basso livello.

QUI su github con tutti i dettagli.

Guglielmo

gpb01:
sui nuovi chip AVR è stata tolta la possibilità al WD di sollvare un interrupt

Non ne ero a conoscenza.
Grazie Guglielmo, prezioso come sempre!

Come ho capito il tempo massimo che si può settare Watchdog e 8 secondi ?

wingamesyun:
Come ho capito il tempo massimo che si può settare Watchdog e 8 secondi ?

SI, ma ti ho detto di lasciar stare il WD che NON è fatto per queste cose ed usare i timers ... e ti ho anche dato i link alla libreria da usare.

Guglielmo

Ok ok.. ma wd era ottimo per quello che dovevo fare .
Provo a capire anche come funzionano i timers.

wingamesyun:
Ok ok.. ma wd era ottimo per quello che dovevo fare .

A si ... e perché? ... tu NON lo useresti com un WD, ma come un timer ... quindi? Usa un vero timer e lascia stare il WD, che serve a tutt'altro scopo e che, come ho già detto, nei nuovi AVR (es. Arduino Nano Every) neanche può più essere usato in quel modo !

Guglielmo

Mi funziona bene nel loop principale ma non così ,comunque non sono sicuro di aver capito bene come funzioni.

[code]
#include <arduino-timer.h>
#define TINY_GSM_MODEM_SIM900
#define BLYNK_PRINT Serial
#include <TinyGsmClient.h>
#include <BlynkSimpleTinyGSM.h>
#define SerialMon Serial
#define SerialAT Serial3
const char apn[]  = "internet.it";
const char user[] = "";
const char pass[] = "";
unsigned long  d_blynk , t_blynk ;
int sette = 1;
const char auth[] = "5GK3uW";
const char gsm;
TinyGsm modem(SerialAT);
auto timer = timer_create_default(); // create a timer with default settings
Timer<> default_timer; //

void setup()
{
  SerialMon.begin(9600);
  delay(10);
  SerialAT.begin(9600);
  delay(6000);
  SerialMon.println("Initializing modem...");
  modem.restart();
  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem Info: ");
  SerialMon.println(modemInfo);
  Serial.println("setup");

  auto task = timer.every(20000, print_message);

}
void BLYNK() {
  //Se non riesce a connettersi al server rimane bloccato qui.

  timer.tick();//qui attivo il timer se rimane bloccato qui fai...
  Serial.println("BLYNK");
  delay(5000);
  Blynk.begin(auth, modem, apn, user, pass);
  timer.cancel();

}
bool print_message(void *) {
  Serial.print("print_message: Called at: ");
  Serial.println(millis());
  //return true; // repeat? true
}
void loop()
{
  if (sette == 0) {
    Blynk.run();
    Serial.println("loop b");
  }

  Serial.println("loop");
  d_blynk = millis() - t_blynk;
  if ( d_blynk > 20000  && Blynk.connected() == false) {
    sette = 0;
    t_blynk = millis();
    Serial.println("if");
 BLYNK();
   
  }

}

[/code]

La libreria in questione non è adatta a risolvere il tuo problema, o meglio il problema di blynk.
Nella documentazione c'è scritto questo:

Currently only a software timer. Any blocking code delaying timer.tick() will prevent the timer from moving forward and calling any functions.

Mentre a te serve una lib che sfrutti un timer hardware.
Il wdt secondo me andrebbe bene configurato per resettare la mcu ogni tot secondi.
Devi solo disabilitarlo dopo l'istruzione bloccante.
Ciao.