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

Ciao Astro. Scusami, ho probabilmente frainteso la tua opinione.
In ogni caso credo che anche tu abbia frainteso il contenuto di questa libreria, perche' non e' soltanto un protocollo di comunicazione, ma contiene anche un packet manager che si occupa della gestione dei pacchetti in background senza nessun effort dell utente e di un reaction manager che ti permette di correlare delle funzioni da eseguire quando viene ricevuto un determinato simbolo (o serie di simboli) definito dall'utente. Questo significa che in molti casi puo' agire da main scheduler di task.

In ogni caso sarei felice se dedicassi 10 minuti a leggere il readme e a dare un occhio al codice perche' ammiro la tua esperienza e le tue conoscenze e sono certo tu possa darmi ottimi spunti a cui io non ho pensato.

La libreria sta ottenendo un discreto successo all'estero.
Mi stanno tempestando di messaggi e pull request.

Ecco un video di uno dei test:

Qualche domanda:

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?

Ho convertito la libreria per l'IDE 1.6.5 aggiungendo i file json e property. Stasera, tempo permettendo, faccio la pull request per l'integrazione.
Visto che però non sarà più compatibile con la versione 1.0.x e 00.x, forse è il caso di fare una nuova branch. Che dici?

Ciao GioBlu,
se crei una nuova branch per la versione 1.5.x, faccio una pull-request con le modifiche.

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?