Controllo sketch

Ciao a tutti dopo un po di prove a tanto aiuto da parte vostra ho scritto questo piccolo sketch che comunicando con u raspberry tramite python riesce a leggere scrivere e impostare i pin su arduino a seconda di quello che viene ricevuto, però non essendo un mago della programmazione vorrei se potete farvelo controllare e nel caso migliorarlo, da considerare che fa tutto quello che deve fare ed è anche molto stabile e veloce.
Per comodità di lettura oltre a metterlo tra i tag code lo allego anche.

Grazie

#include <OneWire.h>
#include <DallasTemperature.h>

#define TIMEOUT 30000
#define SET_MODE 0xc8
#define LETTURA_DIGITALI 0xc9
#define LETTURA_ANALOGICI 0xca
#define SCRITTURA_DIGITALI 0xcb
#define SCRITTURA_ANALOGICI 0xcc
#define SONDA_TEMPERATURA_1_VASCA 45
#define SONDA_TEMPERATURA_2_VASCA 46
#define SONDA_TEMPERATURA_3_VASCA 47
#define SONDA_TEMPERATURA_SERBATOIO 48

char arduinoId[9] = "c3d1e@9=";//identificatvo arduino verso python
char pythonId[9] = "Db5i42uk";//identificativo python verso arduino
char confermaId[9] = "bB0gP1Zw";//conferma di ricezione id da arduino verso python
char inizioInvio[9] = "j9W6KKLK";//codice per indicare ad arduino dell'inizio della trasmissione dei dati
char fineInvio[9] = "cRoG4WT9";//codice per indicare ad arduino della fine della trasmissione dei dati
char confermaRx[9] = "l9b85tpl";//codice di conferma della ricezione che arduino invia a python
bool statoConnessione = false;
bool statoRicezione = false;
unsigned long inizioConteggio;
byte indice=0x00;
String rxData01;
byte buffer[3];
/*I dati del buffer seguono questa logica:
 * 0) Funzione da eseguire
 * 1) Numero del pin da controllare
 * 2) Valore del pin nel caso di scrittura sul pin o del setttaggio del tipo
 */

OneWire sensore1(SONDA_TEMPERATURA_1_VASCA);
OneWire sensore2(SONDA_TEMPERATURA_2_VASCA);
OneWire sensore3(SONDA_TEMPERATURA_3_VASCA);
OneWire sensore4(SONDA_TEMPERATURA_SERBATOIO);
DallasTemperature sonda1(&sensore1);
DallasTemperature sonda2(&sensore2);
DallasTemperature sonda3(&sensore3);
DallasTemperature sonda4(&sensore4);

bool connessione(bool stato,char tokenId01[9],char tokenId02[9],char tokenConferma[9],int tokenChar=8)
/*La funzione serve per iniziare la comunicazione seriale tra arduino e python,
 * arduino invia in loop il suo id, quando python lo riceve risponde col suo 
 * quando arduino riceve l'id di python riposnde con la conferma di ricezione
 * e quindi si stabilisce la connessione e si esce dalla funzione ritornado true
 */
{
  int i=0;
  String rxData;
  char data;

  while (!stato){
    if (Serial.available()){
      delay(50);
      data = Serial.read();
      if (data != '\n'){
        rxData += data;
        i++;
      }
      else if (data == '\n'){
        if (rxData == tokenId02 && i == tokenChar){
          stato = true;
          i=0;
          rxData = "";
        }
        else{
          i=0;
          rxData = "";
        }
      }
    }
    else{
      /*Se la connessione non va a buon fine arduino attende 3 secondi e poi renivia 
       * il suo id
       */
       delay(3000);
      Serial.write(tokenId01);
    }
  }
  /*se la connessione ha esito positivo python invia la conferma e ritorna true*/
  Serial.write(tokenConferma);
  inizioConteggio = millis();
  return true;
}


bool inviaRicevi(char tokenId01[9],char tokenId02[9],char tokenConferma[9],int tokenChar=8,int maxBuffer=3)
/*La funzione riceve i dati inviati da python che debbono essere elaborati
 * per essere sicuro di non lasciare dati per starda ho preferito inviare un codice
 * di inizio invio e uno di fine invio, mentre i dati saranno una serie di byte
 * che andranno a popolare il buffer
 */
{
  char data;
  byte data01;

  if (Serial.available()){
    inizioConteggio = millis();
    data = Serial.read();
    if (data != '\n'){
      rxData01 += data;
      indice++;
    }
    else if (data == '\n' && indice == tokenChar){
      if (rxData01 == tokenId01){
        indice=0;
        rxData01 = "";
        memset(buffer,0,sizeof(buffer));
        delay(15);
        while (Serial.available()){
          data01 = Serial.read();
          if (data01 != '|'){
            buffer[indice] = data01;
            indice++;
          }
          else if (data01 == '|'){
            if (indice>1 && indice<=maxBuffer){
              indice=0;
              delay(15);
              while (Serial.available()){
                data = Serial.read();
                if (data != '\n'){
                  rxData01 += data;
                  indice++;
                }
                else if (data == '\n' && indice == tokenChar){
                  if (rxData01 == tokenId02){
                    indice=0;
                    rxData01= "";
                    Serial.write(tokenConferma);
                    return true;
                  }
                  else if (rxData01 != tokenId02){
                    indice=0;
                    rxData01 = "";
                  }
                }
                else if (data == '\n' && indice != tokenChar){
                  indice=0;
                  rxData01 = "";
                }
              }
            }
            else{
              indice=0;
              rxData01 = "";
            }
          }
        }
      }
      else if (rxData01 != tokenId01){
        indice=0;
        rxData01 = "";
      }
    }
    else if (data == '\n' && indice != tokenChar){
      indice=0;
      rxData01 = "";
    }
  }
  return false;
}

void _setMode(byte pinNum, byte pinValue)
/*Funzione per settare i pin come Input o come Output*/
{
#define IN 0x00
#define OUT 0x01

  if (pinValue == IN){
    pinMode(pinNum,INPUT_PULLUP);
  }
  else if (pinValue == OUT){
    pinMode(pinNum,OUTPUT);
  }
}

void _letturaDigitali(byte pinNum)
/*Funzione che legge dai pin di Input Digitali, se poi il pin corrisponde
 * ad uno dei pin dei sensori di temperatura legge da quelli, e in entrabi 
 * i casi invia alla seriale il valore del pin letto
 */
{
	if (pinNum == SONDA_TEMPERATURA_1_VASCA){
	  sonda1.requestTemperatures();
	  Serial.println(sonda1.getTempCByIndex(0));
	}
	else if (pinNum == SONDA_TEMPERATURA_2_VASCA){
	  sonda2.requestTemperatures();
	  Serial.println(sonda2.getTempCByIndex(0));
	}
	else if (pinNum == SONDA_TEMPERATURA_3_VASCA){
	  sonda3.requestTemperatures();
	  Serial.println(sonda3.getTempCByIndex(0));
	}
	else if (pinNum == SONDA_TEMPERATURA_SERBATOIO){
	  sonda4.requestTemperatures();
	  Serial.println(sonda4.getTempCByIndex(0));
	}
	else{
	  Serial.write(digitalRead(pinNum));
	}
}

void _letturaAnalogici(byte pinNum)
/*La funzione legge il valore dei pin di input ananlogici e invia 
 * la lettura alla seriale
 */
{
  Serial.println(analogRead(pinNum));
}

void _scritturaDigitali(byte pinNum, byte pinValue)
/*La funzione imposta i pin di Output nello stato High o Low*/
{
#define LOW_VALUE 0x00
#define HIGH_VALUE 0xff

  if (pinValue == LOW_VALUE){
    digitalWrite(pinNum,LOW);
  }
  else if (pinValue == HIGH_VALUE){
    digitalWrite(pinNum,HIGH);
  }
}

void _scritturaAnalogici(byte pinNum, byte pinValue)
/*La funzione imposta il valore dei pin PWM da 0 a 255, che però ho mappato
 * da 0 a 100
 */
{
  analogWrite(pinNum, map(pinValue,0,100,0,255));
}

void _connect()
{
  statoConnessione = connessione(statoConnessione,arduinoId,pythonId,confermaId);
}

void _ricezione()
{
  statoRicezione = inviaRicevi(inizioInvio,fineInvio,confermaRx);
}

void setup()
{
  /*Inizializzo la seriale*/
  Serial.begin(115200);
}

void loop()
{
  /*Finchè statoConnessione è falso esegui _connect, quindi eseguo fino a true la funzione 
   * di connessioneIniziale
   */
  if (!statoConnessione){
    _connect();
  }
  
  /*Finchè statoricezione è falso esegui _ricezione, quindi esegue inviaRicevi fino al true*/
  if (!statoRicezione){
    _ricezione();
  }

  /*Quando statoRicezione diventa true, cioè ho ricevuto tutti i dati da python elaboro
   * i dati ricevuti
   */
  if (statoRicezione){
    if (buffer[0] == SET_MODE){
      _setMode(buffer[1],buffer[2]);
    }
    else if (buffer[0] == LETTURA_DIGITALI){
      _letturaDigitali(buffer[1]);
    }
    else if (buffer[0] == LETTURA_ANALOGICI){
      _letturaAnalogici(buffer[1]);
    }
    else if (buffer[0] == SCRITTURA_DIGITALI){
      _scritturaDigitali(buffer[1],buffer[2]);
    }
    else if (buffer[0] == SCRITTURA_ANALOGICI){
      _scritturaAnalogici(buffer[1],buffer[2]);
    }
    inizioConteggio = millis();
  }

  statoRicezione = false;

  if ((millis() - inizioConteggio) >= TIMEOUT){
    statoConnessione = false;
    inizioConteggio += TIMEOUT;
  }
}

sketch01.ino (8.17 KB)

ciao vinny74,

qualcuno disse: sono più le volte che uno script viene letto che quelle che viene eseguito.

se funziona ed è veloce...e se, compatibilmente con la realtà, hai testato tutte le possibili casistiche e risponde come previsto...va bene così...ma questa è una mia personalissima opinione.

ORSO2001:
ciao vinny74,

qualcuno disse: sono più le volte che uno script viene letto che quelle che viene eseguito.

se funziona ed è veloce…e se, compatibilmente con la realtà, hai testato tutte le possibili casistiche e risponde come previsto…va bene così…ma questa è una mia personalissima opinione.

é giusto quello che dici, ma se a qualcuno va di dargli un’occhiata io non mi offendo.

Grazie

Solo consigli "estetici" ^-^ 1. anche se alcune define le usi solo in una funzione, almeno per me, è meglio metterle ad inizio assieme alle altre (almeno che non ti crei una libreria con parte delle funzioni) 2. anche il carattere di fine msg e il carattere separatore potresti dichiararlo all'inizio con define, se un giorno tu volessi cambiarlo/i sarebbe più facile

define K_SEP '|'

define K_EOM '\n'

... if (data01 != K_SEP) { // invece di '|'

  1. le graffe sarebbe bene metterle sempre su nuova riga. Ormai tutti li IDE evidenziano la graffa aperta con la sua chiusa, se sono incolonnate è più semplice leggerle.
  if( test)
  { if (test2)
    { ..
    }
  }

nid69ita: Solo consigli "estetici" ^-^ 1. anche se alcune define le usi solo in una funzione, almeno per me, è meglio metterle ad inizio assieme alle altre (almeno che non ti crei una libreria con parte delle funzioni) 2. anche il carattere di fine msg e il carattere separatore potresti dichiararlo all'inizio con define, se un giorno tu volessi cambiarlo/i sarebbe più facile

define K_SEP '|'

define K_EOM '\n'

... if (data01 != K_SEP) { // invece di '|'

  1. le graffe sarebbe bene metterle sempre su nuova riga. Ormai tutti li IDE evidenziano la graffa aperta con la sua chiusa, se sono incolonnate è più semplice leggerle.
  if( test)
  { if (test2)
    { ..
    }
  }

A parte questo, che sicuramente adesso vado a sistemare, pensi che ci sia possibilità di snellire il codice o che sia troppo macchinoso?

Grazie