Problema con pausa random()

Buona sera a tutti, sto cercando aiuto per quando riguarda la costruzione di un dissuasore per uccelli nocivi alle coltivazioni.... il progetto è stato fatto con un Arduino Uno e un DfPlayerMini mp3.... nella scheda sd ho inserito 8 tracce mp3 che devono essere attivati in maniera Random e con una pausa Random l'una dall'altra.... il problema è che ho fatto un array di millis corrispondenti a minuti che vanno da 1 a 15 minuti, ma quando arduino sceglie i millis non sceglie quelli che ho impostato io, ma numeri a caso.... per quando riguarda i canti li sceglie a caso ma spesso si ripete il numero di traccia scelto il passaggio prima.

Qualcuno mi può aiutare a venirne a capo?
Vi ringrazio anticipatamente.

Ps. allego sketch



#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"

#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266))  // Using a soft serial port
#include <SoftwareSerial.h>
SoftwareSerial softSerial(/*rx =*/6, /*tx =*/7);
#define FPSerial softSerial
#else
#define FPSerial Serial1
#endif

DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

// Definisci un array con i numeri desiderati
int canti[] = { 1, 2, 3, 4, 5, 6, 7, 8 };                                                                                         // 8 canti nella sd
int pausa[] = { 60000, 120000, 180000, 240000, 300000, 420000, 480000, 540000, 600000, 660000, 720000, 780000, 840000, 900000 };  // Pause tra una traccia ed un'altra da 1 a 15 Minuti

// Numero di elementi nell'array
int cantiElements = sizeof(canti) / sizeof(canti[0]);
int pausaElements = sizeof(pausa) / sizeof(pausa[0]);

void setup() {
#if (defined ESP32)
  FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
  FPSerial.begin(9600);
#endif

  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(FPSerial, /*isACK = */ true, /*doReset = */ true)) {  //Use serial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0);  // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
  myDFPlayer.play(1);     //Play the first mp3

  randomSeed(analogRead(0));
  randomSeed(analogRead(1));
}

void loop() {

  int randomIndex = random(cantiElements);
  int randomCanti = canti[randomIndex];

  int randomIndexPausa = random(pausaElements);
  int randomPausa = pausa[randomIndexPausa];

  

  static unsigned long timer = millis();

  if (millis() - timer > 15000) {
  Serial.println(randomCanti);
  Serial.println(randomPausa);
    
    myDFPlayer.play(randomCanti); 
  
    timer = millis();
  }
 

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read());  //Print the detail message from DFPlayer to handle different errors and states.
  }
}

void printDetail(uint8_t type, int value) {
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

  1. random su solo 8 numeri è possibilissimo che ti ripeta il precedente estratto.
  2. tu calcoli "randomPausa" ma poi... a parte stamparlo ... mica lo usi
    ...edit... forse quel tuo "vedo tempi a caso" è riferito a quello che ti dice Guglielmo qui sotto.
1 Like

Tu sai che su Arduino UNO R3 gli 'int' sono a 16 bit e che possono andare da un minimo di -32768 ad un massimo di +32767 ?

I tuoi valori sono molto più grandi e millis() richiede variabili di tipo 'unsigned long' (che, su Arduino UNO R3, è un tipo dato a 32 bit non segnati).

Guglielmo

1 Like

Avete ragione!!! :rofl: :rofl:
Ho cambiato delle cose nello sketch e adesso pare funzionare...



#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"

#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266))  // Using a soft serial port
#include <SoftwareSerial.h>
SoftwareSerial softSerial(/*rx =*/6, /*tx =*/7);
#define FPSerial softSerial
#else
#define FPSerial Serial1
#endif

DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

// Definisci un array con i numeri desiderati
int canti[] = { 1, 2, 3, 4, 5, 6, 7, 8 };                                                                                         // 8 canti nella sd
unsigned long pausa[] = { 60000, 120000, 180000, 240000, 300000, 420000, 480000, 540000, 600000, 660000, 720000, 780000, 840000, 900000 };  // Pause tra una traccia ed un'altra da 1 a 15 Minuti

// Numero di elementi nell'array
int cantiElements = sizeof(canti) / sizeof(canti[0]);
int pausaElements = sizeof(pausa) / sizeof(pausa[0]);

void setup() {
#if (defined ESP32)
  FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
  FPSerial.begin(9600);
#endif

  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(FPSerial, /*isACK = */ true, /*doReset = */ true)) {  //Use serial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0);  // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
  myDFPlayer.play(1);     //Play the first mp3

  randomSeed(analogRead(0));
  randomSeed(analogRead(1));
}

void loop() {

  int randomIndex = random(cantiElements);
  int randomCanti = canti[randomIndex];

  unsigned long randomIndexPausa = random(pausaElements);
  unsigned long randomPausa = pausa[randomIndexPausa];


  static unsigned long timer = millis();

  if (millis() - timer > randomPausa) {
  Serial.println(randomCanti);
  Serial.println(randomPausa);
    
    myDFPlayer.play(randomCanti); 
  
    timer = millis();
  }
 

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read());  //Print the detail message from DFPlayer to handle different errors and states.
  }
}

void printDetail(uint8_t type, int value) {
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

Ma il problema sta nel fatto che le tracce variano a random, per le pause mi prende sempre 60000.

vedi Monitor seriale:

DFRobot DFPlayer Mini Demo

Initializing DFPlayer ... (May take 3~5 seconds)

DFPlayer Mini online.

Time Out!

Number:1 Play Finished!

DFRobot DFPlayer Mini Demo

Initializing DFPlayer ... (May take 3~5 seconds)

DFPlayer Mini online.

Time Out!

Number:1 Play Finished!

60000

Number:6 Play Finished!

1

60000

Number:1 Play Finished!

7

60000

Number:7 Play Finished!

6

60000

Number:6 Play Finished!

Beh intanto diciamo che è la logica in generale del codice che non mi è proprio del tutto chiara...

Per dire, ad esempio:

  randomSeed(analogRead(0));
  randomSeed(analogRead(1));

A cosa serve fare due volte randomSeed()? Una volta impostato un "seed" se chiami quella funzione una seconda volta stai semplicemente cambiando "seed".
Tra l'altro anche se è il metodo consigliato per inizializzare il seed, dato che la analogRead() restituisce valori tra 0 e 1023 (e in realtà non è una distribuzione lineare...) avrai al massimo 1024 diverse sequenze random. Per questo scopo non è necessario, ma in genere io uso un metodo che calcola un "unsigned long" combinando tra loro più letture analogRead(). Ma quest'ultima cosa puoi trascurarla nel tuo caso.

Poi:

// Pause tra una traccia ed un'altra da 1 a 15 Minuti
unsigned long pausa[] = { 60000, 120000, 180000, 240000, 300000, 420000, 480000, 540000, 600000, 660000, 720000, 780000, 840000, 900000 };  

Se la pausa è un valore random in minuti, perché fare un array di unsigned long invece di limitarti a generare un intero tra 1 e 15 e moltiplicarlo per 60.000 e usarlo per impostare la pausa?

Infine questo:

  static unsigned long timer = millis();

  if (millis() - timer > randomPausa) {

Prima cosa, praticamente qui sei nel loop, dove ad ogni iterazione generi un valore di pausa casuale: a che serve farlo migliaia di volte al secondo? Devi farlo solo una volta quando c'è la riproduzione e poi aspettare solo la pausa (confesso che non ho esaminato tutto il codice, ma non mi è chiaro se debba essere solo alla fine della riproduzione o partendo dall'inizio ma non è così importante).

Poi la variabile "timer" contiene il valore corrente di millis(): tu pensi che l'espressione "millis() - timer" possa mai essere maggiore della pausa? Sarà spesso zero o si e no qualche millisecondo, per cui temo che questa versione non possa funzionare correttamente...

Prova a fare qualche correzione, fai qualche test, e posta qui il tuo nuovo codice. Se poi non riesci, allora appena avrò tempo (forse stasera...) proverò a modificarti lo sketch per proporti le mie modifiche.

Buon giorno....

Hai ragione in questo modo non faccio altro che impostare due volte il SEED.... cosa conviene che ne tolga uno o c'è un altro metodo migliore??

Hai nuovamente ragione.... posso mettere i minuti e poi moltiplicarli per 60000....

Questo invece non mi è chiaro... non capisco come dovrei impostarlo! :thinking: :thinking:

Per il tuo obiettivo non è essenziale che le sequenze siano più casuali possibile, quindi basta lasciarne uno solo.
Tra l'altro devi usare "A0" e non "0", perché il simbolo predefinito A0 è il numero della porta analogica (che di fatto è 14).
Quindi randomSeed(analogRead(A0));.

Beh qui mi devo scusare io, mi era sfuggito che quella variabile fosse "static". Come hai fatto va bene, perché la variabile "timer" essendo statica viene inizializzata alla sua attivazione, quindi conterrà il valore di millis() della prima attivazione, e poi viene reimpostata solo nel momento in cui parte il brano successivo. Puoi ignorare quel mio commento.

1 Like

Salve a tutti, ho fatto le modifiche che mi avete suggerito e funziona quasi tutto.... l'unico problema è che le tracce vengono prese in maniera random, ma il tempo di pausa prende sempre 1 minuto.... non capisco cosa ci sia di sbagliato.



#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"

#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266))  // Using a soft serial port
#include <SoftwareSerial.h>
SoftwareSerial softSerial(/*rx =*/6, /*tx =*/7);
#define FPSerial softSerial
#else
#define FPSerial Serial1
#endif

DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

// Definisci un array con i numeri desiderati
int canti[] = { 1, 2, 3, 4, 5, 6, 7, 8 };                                                                                         // 8 canti nella sd
int pausa[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};  // Pause tra una traccia ed un'altra da 1 a 15 Minuti

// Numero di elementi nell'array
int cantiElements = sizeof(canti) / sizeof(canti[0]);
int pausaElements = sizeof(pausa) / sizeof(pausa[0]);

void setup() {
#if (defined ESP32)
  FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
  FPSerial.begin(9600);
#endif

  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(FPSerial, /*isACK = */ true, /*doReset = */ true)) {  //Use serial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0);  // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
  myDFPlayer.play(1);     //Play the first mp3

  randomSeed(analogRead(A0));
  
}

void loop() {

  int randomIndex = random(cantiElements);
  int randomCanti = canti[randomIndex];

  int randomIndexPausa = random(pausaElements);
  int randomPausa = pausa[randomIndexPausa];


  static unsigned long timer = millis();

  if (millis() - timer > (randomPausa*60000)) {
  Serial.println(randomCanti);
  Serial.println(randomPausa);
    
    myDFPlayer.play(randomCanti); 
  
    timer = millis();
  }
 

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read());  //Print the detail message from DFPlayer to handle different errors and states.
  }
}

void printDetail(uint8_t type, int value) {
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

C'è qualcuno che riesce a capire il problema?
Grazie anticipatamente... :pensive: :pensive:

Prova con:

if (millis() - timer > (randomPausa*60000UL)) {

Ciao.

1 Like

Purtroppo va a cadenza sempre di un minuto.... mi sta facendo impazzire... :face_with_spiral_eyes: :face_with_spiral_eyes: :face_with_spiral_eyes: :face_with_spiral_eyes:

DFRobot DFPlayer Mini Demo

Initializing DFPlayer ... (May take 3~5 seconds)

DFPlayer Mini online.

Time Out!

DFRobot DFPlayer Mini Demo

Initializing DFPlayer ... (May take 3~5 seconds)

DFPlayer Mini online.

Time Out!

Number:1 Play Finished!

2

1

Number:2 Play Finished!

4

1

Number:4 Play Finished!

2

1

Number:2 Play Finished!

3

1

Number:3 Play Finished!

8

1

Number:8 Play Finished!

Errore mio, scusa:

if (millis() - timer > ((uint32_t)randomPausa*60000UL)) {

Ciao.

1 Like

Mi dispiace ma non cambia niente..... sempre pause di un minutoooo.... :sob:

timer=millis(); deve stare subito dopo l'apertura della parentesi graffa dell'if!

Poi puoi farla tranquillamente globale e se la chiami t_ripetizione o altro nome che inizia con t_ è più chiaro che è un salvataggio di millis() per una temporizzazione.

1 Like

Cura l'indentazione, prima ancora di imparare a programmare.

  int randomIndex = random(cantiElements);
  int randomCanti = canti[randomIndex];

  int randomIndexPausa = random(pausaElements);
  int randomPausa = pausa[randomIndexPausa];

Questa porzione di codice è priva di alcuna condizione, ciò significa
che viene eseguita ogni volta che la funzione loop() ricomincia.

// Ogni elemento dell'array contiene un byte 0÷255 il tipo byte o uint8_t sono sufficienti.

// Dichiara e inizializza array con i numeri desiderati
// 8 canti nella sd
byte canti[] = { 1, 2, 3, 4, 5, 6, 7, 8 };   
// Pause tra una traccia ed un'altra da 1 a 15 Minuti
byte pause[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

Nota sono canti e pause al plurale.
Dichiara globali canto e pausa al singolare

byte canto;
uint32_t pausa;

Nel setup()

void setup() {
#if (defined ESP32)
  FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
  FPSerial.begin(9600);
#endif

  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(FPSerial, /*isACK = */ true, /*doReset = */ true)) {  //Use serial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0);  // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
  myDFPlayer.play(1);     //Play the first mp3

  randomSeed(analogRead(A0));
  // queste quattro righe sono candidate ad essere funzioni
  byte idxCanti = random(sizeof(canti)); 
  canto = canti[idxCanti];
  byte idxPause = random(sizeof(pause)) ;
  pausa = (uint32_t)pause[idxPause] * 60000UL;
  
}

Funzione loop()

void loop() {

  static unsigned long timer = millis();
  if ( millis() - timer > pausa ) {
       
    myDFPlayer.play(canto); 
  
    timer = millis();
    byte idxCanti = random(sizeof(canti)); 
    canto = canti[idxCanti];
    byte idxPause = random(sizeof(pause)) ;
    pausa = (uint32_t)pause[idxPause] * 60000UL;
    
  }  
  if (myDFPlayer.available()) {
    //Print the detail message from DFPlayer to handle different errors and states.
    printDetail(myDFPlayer.readType(), myDFPlayer.read());  
  }
}

Non sono sicuro, ho scritto sul forum direttamente, quindi controlla
errori di battitura e indentazione ecc.

Ciao.

1 Like

:face_with_spiral_eyes: :face_with_spiral_eyes: :face_with_spiral_eyes: :face_with_spiral_eyes: :face_with_spiral_eyes: :face_with_spiral_eyes:
mi sono CONFUSOOOO....

se dichiaro globali questi due l'ide mi dice che vanno in conflitto con

questi messi al singolare.... mi da tantissimi errori.... devo capire bene le modifiche da te proposte....

Mi sono spiegato male. Un array contiene degli elementi, nel caso della lista dei canti (plurale) il nome dell'array è canti.
La lista delle pause per quale motivo dovrebbe chiamarsi pausa, per cui il nome dell'array è pause (plurale).

Dalla lista dei canti (pl.) selezioni un canto (.sing).
Dalla lista delle pause (.pl) selezioni una pausa (.sing).

Comunque io non conosco la libreria DFPlayer e non so se myDFPlayer.play(canto);
ha un comportamento bloccante, io l'ho considerata bloccante, solo per semplificare, serve verificare.

Ciao.

1 Like

Oltretutto ci sono tante voci al singolare e plurale e mi sto perdendo...

Comunque questo secondo me è bloccante, visto che il programma riparte alla fine della traccia.

Ma qui non capisco, devo inserire tutte e due le dichiarazioni e mettere al singolare il nome dell'array?

e perchè nell'array sono tutti e due byte e nella dichiarazione globale mi dici di mettere canto in byte e pausa in uint32_t??

Scusa, ma ho fatto tantissimi progetti ma in queste cose mi perdo facilmente... :pensive:

Il simulatore online wokwi lo puoi usare (serve iscrizione)?
Puoi modificare questo sketch su wokwi ma non puoi salvarlo se non sei iscritto:

La variabile pausa contiene il tempo calcolato in millesimi di secondo, vedi:

if ( millis() - timer > pausa ) {
//                       ^

Ciao.

1 Like

Ma io ho l'arduino già montato... a cosa mi serve questo simulatore? non l'ho capito

Ti (mi) serve per capire cosa fa il codice suggerito dagli utenti.
Ad esempio scrivi il tuo sketch in wokwi e lo condividi, io prendo il tuo sketch lo modifico e lo condivido e tu apporti le modifiche al tuo.
Il tutto con rapidità e senza dovere scrivere nella flash di arduino.
Ancora un esempio potevi condividere lo sketch modificato che ti dava errore e io potevo eseguirlo e capire dove si trova l'errore e correggerlo.

Ciao.

1 Like