PJON - Multi-master, multi-media network protocol stack

GioBlu:
Hi Paolo! I would be able to maintain only one version of PJON for 0.x 1.x and 1.6x!
I would merge your contribution but I am not sure if I want to have digital write fast and PJON in the same arc directory! And also I can t get the sense of having the src directory! Generally is used in repos where u can / have to compile or maybe I am ignorant :slight_smile:

La struttura della libreria tra 0.x, 1.x e 1.6.x è notevolmente cambiata.
La nuova struttura prevede che il codice della libreria si all'interno di una cartella "src", gli esempi nella cartella "examples", eventuali altri file come doc, pdf, schemi ecc nella cartella "extra" (che viene ignorata dall'IDE).
Nella directory principale andranno i file keyword, json e property. Questi file servono all'IDE per gestire la libreria sia nell'editor (colorazione delle funzioni e dei metodi) si per il library manager. (introdotto dalla versione IDE 1.6.4.
Le versioni 1.0.x ricercano i file anche nelle sottodirectory delle librerie per cui anche l'architettura nuova è utilizzabile.
Con le versioni 0.x invece c'è incompatibilità, ma sinceramente credo si possa smettere sviluppare librerie per una versione alpha dell'IDE continuando ad includere il Wcostant.h.

Quindi ecco perché ho messo tutto nella cartella src e creato i vari file di proprietà per l'IDE 1.6.x.

Una volta convertita la libreria nel formato 1.5.x si può chiede l'inclusione nel library manager.
--> Library Manager FAQ · arduino/Arduino Wiki · GitHub

In particolare:

How can I add my library to Library Manager?

Ensure your library is complaint with 1.5 format
Tag it and push the tag, or create a release with github "releases"
Open an issue on Arduino's github, specifying the git repo (or github url) from where to download your library

Ciao Paolo!! Grazie mille del tuo supporto! Ho iniziato con una diecimila 7anni fa quindi forse sono un po' legato ai vecchi strumenti :slight_smile:

Oggi creo una branch dove tu possa inviare la pull request!! Oki?

Ci vorrebbe più gente attiva come te nella community!! :slight_smile:

La pull l'ho già inviata. Da gitHub puoi fare il merge sul branch invece che sul master.

Ciao Paolo, non ho ancora accettato la tua pull request perche' devo ancora testare come viene compilato il codice con la 1.5. Ho notato che tutto il codice compilato con 0.x occupa decisamente piu spazio ma la cosa piu assurda e' che ci sia una netta differenza nel tempo di esecuzione del codice. Intendo dello stesso codice, compilato con una o l' altra versione. Infatti, lo stesso sketch di test di velocita' di PJON nella 0.x raggiunge quasi 4kB/s, nella 1.x 3kB/s questo credo, perche' e' cambiato il tempo di attuazione di tutte le funzioni base. Infatti come puoi vedere nella master attuale ho dovuto ricalibrare condizionalmente i delay di lettura tra la versione 0.x e la versione 1.x

A questo punto porterei la tua versione a master con alcune modifiche che intatto ho fatto sulla attuale master, e creerei una branch dedicata alle versione 0.x e 1.x pre 1.5

cosi' da retrocompatibilizzare qualsiasi sketch che usi PJON

Per la velocità non so che dirti.
Riguardo lo spazio è possibile che la nuova toolchain Atmel integrata nelle ultime versioni dell'IDE sia meno esosa di risorse.

posso fare una domanda? sarei interessato nell'applicazione di questa libreria a network però di arduino collegati tramite bluetooth secondo voi è adattabile?

Ho adattato il layer fisico di PJON per funzionare con le coppie di rx e tx 433 mhz da 3 dollari e ho ottenuto 200 metri di range in ambiente cittadino (tra i palazzi). Quindi credo che si possa fare ma non conosco il mondo del bluetooth per darti una risposta affidabile, qui trovi il link della libreria con layer fisico radio:

Fammi sapere come va!

Grazie Paolo per la pull request, l'ho accettata e ora ci lavoro un po' grazie ancora

Ho scambiato qualche battuta con Christian Maglie. Ho capito che sbagliavo a voler inserire la libreria nella sotto cartella SRC. Quella serve solo se si vuole creare una libreria esclusivamente per la nuova versione. Da 1.5.x in poi.
Se si vuole una libreria retrocompatibile, basta aggiungere semplicemente il file library.properties per il Library Manager e mettere gli esempi come file .ino.
Con la retrocompatibilità si perde la compilazione ricorsiva delle sottocartelle.
Inoltre devo ancora controllare la funzione della sottocartella UTILITY al posto della tua "include".
Non è necessario neanche il file .json che serve solo per i pacchetti del core.

Ho fatto una PR con le estensioni degli esempi aggiornate.

Ho fatto una prova e compila sia sulla 1.0.6 che sulla 1.6.5.

@gbm per interfacciarlo con il modulino hai dato come pin di trasmissione tx?

Ciao @Paolo, grazie per il tuo supporto!! Senti ma hai mai testato PJON?? Mi farebbe piacere sapere cosa ne pensi vedendolo funzionare!! In ogni caso, ho letto attentamente la tua risposta. Ho risposto su github alla tua ultima pull request, ma ti scrivo anche qui:

Cosa ne dici di includere in examples gli esempi per entrambe le versioni?
Tipo dir 0.x_blink_example con .pde e 1.x_blink_example con i .ino?

@simonenascivera ciao! Cosa intendi? La libreria si istanzia con il pin utilizzato per la comunicazione in entrambi i casi (ricevitore e trasmettitore). Ho provato soltanto in configurazione monodirezionale, e ho ottenuto range intorno ai 200 metri in environment cittadino (attraverso palazzi) con una quarter wavelength dipole antenna autocostruita da entrambi i lati.

Ecco una foto dell'impianto:

fa parte di una micro radiosonda meteorologica che sto costruendo:

(il grafico rappresenta l'esperimento con cui ho analizzato l'efficacia dell'isolamento termico della capsula, costruita in polistirolo e mylar militare)

In uno dei precedenti post che probabilmente ti è sfuggito, ti ho posto delle domande.

Te le riformulo:

  • al pacchetto di dati viene aggiunto un carattere di checksum?
  • è possibile trasmettere un messaggio a tutti i dispositivi della rete, senza doverlo ripetere per ciascun nodo?
  • come fai a garantire la ricezione di un dispositivo occupato?
  • come gestisci le collisioni in caso di multi master?

Ciao mi devi scusare, hai ragione, mi e' sfuggita la tua risposta.

  1. Al pacchetto viene aggiunto il CRC, (1 byte xor based)

  2. Per trasmettere un messaggio a tutti i devices connessi puoi usare la costante BROADCAST al posto dell'id
    che vuoi contattare

  3. La ricezione non e' garantita, cio' che e' garantito e' che chi invia sia sicuro se o no il ricevente ha ricevuto correttamente grazie all'implementazione dell' ACK o acknowledge e del CRC precedentemente descritto.

  4. Prima di trasmettere qualsiasi device ascolta il canale per un determinato periodo per capire se c'e' una trasmissione in corso oppure il canale e' occupato.

Ti consiglio di dare un occhio al readme della libreria che ho cercato di migliorare molto, e che e' stato di certo molto migliorato da chi ha contribuito al repository :slight_smile:

Spero farai un test :slight_smile:

gbm:
A questo punto porterei la tua versione a master con alcune modifiche che intatto ho fatto sulla attuale master, e creerei una branch dedicata alle versione 0.x e 1.x pre 1.5

cosi' da retrocompatibilizzare qualsiasi sketch che usi PJON

La 1.0.6 è deprecata ma ancora utilizzata, la 0.23 e precedenti sono semplicemente preistoriche. Io non perderei tempo con la retrocompatibilità per questa versione (0.23).

@PaoloP ok considero il tuo consiglio, probabilmente hai ragione!!

In una branch locale sto provando un nuovo approccio possibile al reaction manager e volevo chiedervi quale implementazione preferite:

Attualmente il sistema funziona cosi': l'utente puo' inviare un comando (prendo per esempio lo short_command che manda a un determinato device un paccketto composto dalla costante CMD che determina che sia un comando e di un singolo byte (il tutto controllato con CRC) e aspetta l'acknowledge del ricevitore)

network.send_short_command(44, 'B');

Cosi' sto inviando alla board con ID 44 il carattere B.

Dall'altra parte e' possibile configurare una reazione a un determinato comando:

network.insert_reaction('B', blink_function);

void blink_function() {
  // Cicla i dati ricevuti
  for(int i = 0; i < max_package_length; i++)
    Serial.print(network.data[i]);
  Serial.println();

  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
}

In questo modo e' possibile per esempio nel mio sistema di home automation, definire che T e' un simbolo che rappresenta la temperatura e che ogni board nelle varie stanze invia T, il proprio id seguito dalla temperatura cosi' che il master possa aggiungere i dati in un database tramite POST su un server web.

Il nuovo approccio a cui ho pensato:

Definisco un puntatore a una funzione che venga chiamata quando qualsiasi messaggio e' ricevuto correttamente:

typedef void (*receiver)(int length, char *payload);

L'utente puo' gestire il routing e la reazione ai messaggi nel ricevitore in un unica funzione che riceve come parametri la lunghezza del paccketto e il contenuto, questi parametri verranno passati automaticamente dal sistema quando un messaggio verra' ricevuto, l'unica accortezza dell'utente e' quella di dover dichiarare la funzione come segue:

network.set_receiver(message_received);

receiver message_received(int length, char *payload) {
  // Ciclo i dati ricevuti
  for(int i = 0; i < lenght; i++)
    Serial.print(*payload[i]);

  Serial.println();

  if(payload[0] == 'B') {  // Stessa funzionalita' della reazione
    digitalwRITE(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
  }
    
}

Quale soluzione pensate sia piu' sensata? Quale pensate che sia piu' comoda e semplice nell'uso per un utente anche meno esperto?

Ciao,
anche io alle prese con la domotica per casa mia, mentre stavo cercando informazioni sulle tecniche migliori per evitare le collisioni di pacchetti mi sono imbattuto in questa tua liberia.

Lato software ad una prima occhiata mi è sembrata fatta molto bene.

Personalmente ho preferito seguire la strada di implementare le funzioni aggiuntive (criptazione, controllo collisioni ecc) su protocolli noti, semplicemente per avere una egevole estendibilità della rete e avere almeno in parte la strada pronta per la coesistenza di oggetti di terze parti sullo stesso bus (conscio ovviamente che integrarli non sarà comunque una passeggiata).

Dal lato "Hardware" però ho serie perplessità. Mi pare di capire che in casa hai collegato direttamente gli Arduino, giusto? I microcontrollori si "parlano" passando in decine di metri di cavo e ti sei fidato solo delle protezioni onboard del microcontrollore?

E' questo che mi lascia molto perplesso. I miei prototipi hanno più componenti per la sezione di ingresso e filtraggio che in tutto il resto dalla board :slight_smile:

Sarà anche che io ho a che fare con l'apertura della porta di casa e la gestione di antifurto e tapparelle, e sicuramente sarà che io non sono ottimista :slight_smile: Ma arrivare a casa e non riuscire ad entrare perché il frigo si è attaccato nel momento sbagliato, o vedersi chiudere le tapparelle mentre si è sul balcone, mi spaventa non poco.
Ho perso davvero molto più tempo a studiare i possibili malfunzionamenti e a prevenire danni che a studiare il caso d'uso in cui tutto funziona.

Non dico di optoisolare tutto quanto ma secondo me dovresti almeno passare ad una RS485 come livello fisico (su cui potrai tranquillamente mantenere il tuo protocollo logico) e proteggere la linea con dei TVS, altrimenti al primo fulmine potresti avere sgradevoli sorprese.

Hai fatto un gran lavoro, ti manca davvero poco a trasfomarlo in qualcosa che abbia sapore di professionale e affidabile :wink:

Eh sei in una situazione non proprio tradizionale, per quello hai risultati così buoni.

Dalla tua parte hai la relativa lentezza della comunicazione e la banda (intesa come tempo nel quale il bus è in comunicazione rispetto a quanto è a riposo) bassa, cose che sicuramente giovano al riconoscere correttamente i livelli logici ed avere margini per una eventuale ritrasmissione del pacchetto senza sovrapporre i flussi dati.

Ma la cosa più importante è l'alimentazione che è veramente poco influenzata dalle spurie di rete. Non tutti possono contare su un sitema del genere. Magari hai pure la fortuna di non abitare a ridosso di industrie...

Il cavo di rete immagino sia STP (schermato) o comunque molto ben fatto perché sei in una situazione ancor più roesea di cosa potessi immaginare.

Il fatto che il cavo sia attorcigliato aiuta, ma l'effetto di protezione sarebbe decisamente migliore se al suo interno passasse una connessione bilanciata (come lo sono le connessioni Ethernet, RS485 ecc).

Visto come hai fatto la rete fisica, non avrai problemi a fare un upgrade ad un sistema bilanciato quando noterai errori di comunicazione.

Fossi in te metterei però almeno uno zener in ingresso di ciascun modulo per evitare che qualche spuria ti faccia fuori l'intera rete. Sono facilmente reperibili, costano pochissimo, e non fanno certo miracoli, ma un minimo di protezione la danno, per lo meno riesci a circoscrivere l'area danneggiata.

Se un domani dovessi decidere per aumentare la velocità del bus, con quella rete potresti trovarti errori dovuti alle riflessioni. In tal caso dovrai sperimentare inserendo dei terminatori (resistenze a massa) come si faceva sulle vecchie reti a stella con cavo coassiale.

Sarò ciecato, ma non ho visto cenni alla resistenza nel readme che c'è su GitHub, per quello ti dicevo di metterla.

Lo zener impedisce allla linea di andare oltre una certa tensione. Se hai un bus a 5V e metti uno zener di valore superiore, di norma non interviene mai. Ma se qualche condizione esterna porta ad avere più di 5 volt sulla connessione, lo zener trasforma in calore questa energia in eccesso.
Ha solo il difetto di essere un po' lento e quindi si preferisce il TVS (comportamento simile ma più rapido).
In sostanza lo scopo è di non far fuori la porta del micro a causa di extratensioni in arrivo dall'esterno.
Il microcontrollore ha già di suo un po' di protezioni, ma sono per forza di cosa minime, quindi è meglio averne di esterne.

Se un fulmine colpisce in pieno l'impianto non c'è nulla da fare, quindi i fusibili da soli farebbero pocco. Hai fatto bene comunque a metterli perché è sempre meglio avere dei circuiti di sicurezza (es, proteggere da cortocircuiti accidentali)
Quello da cui guardarti è il caso di un fulmine non troppo distante, in quel caso potresti avere picchi di tensione di qualche decina di volta per pochi millisecondi, sufficienti a distruggere le porte del micro (ma niente incendi o cose di questo genere), in quel caso un semplice TVS ti salva la porta del mocrocontrollore.

Hai ragione, la delucidazione riguardo le pull down c'e' solo nei commenti nel codice :slight_smile:
Grazie della segnalazione :slight_smile:

Ciao a tutti, ciao Paolo! :slight_smile:
Come puoi vedere ho accettato la tua pull request e modificato estensivamente la libreria. Attualmente in master sono finalmente presenti le modifiche a cui stavo lavorando in locale da tempo. Finalmente esiste un readme decente e degli esempi funzionanti. Grazie per il tuo supporto.

Posso dire di essere vicino alla release della 1.0 :o :o

Cosa ne pensate???