Newsgroup: it.hobby.elettronica.digitale
Titolo: Autodetect slaves su bus RS485 master-slave

E' una cosa a cui penso di tanto in tanto: può essere implementato 
sul master un meccanismo di autodetect/discovery degli slave 
presenti sul bus?
 
Il problema si divide nettamente in due: gli slave sono *identici*, 
oppure si differenziano per un ID (numero di serie, MAC address, ...).
 
Consideriamo il secondo caso che è sicuramente più semplice: ogni 
slave ha lo stesso firmware, ma un serial number (SN) diverso.  Il
problema si riduce a scoprire quali SN sono presenti sul bus.
 
Ho fatto qualche ricerca ed effettivamente ci sono alcune idee
interessanti, ma ognuna con pro e contro, e non saprei quale 
effettivamente iniziare ad implementare.  In tutti i casi, il master
deve essere in grado di rilevare collisioni (pacchetti malformati,
CRC errata, errori di framing...).
 
Un approccio semplice può essere questo (consideriamo SN a 32 bit):
 
- il master invia un messaggio broadcast chiedendo se esistono 
  slave con un SN all'interno di un certo range (inizialmente 
  0x00000000-0xFFFFFFFF);
- tutti gli slave con un SN in quel range rispondono con un messaggio
  che contiene il proprio SN.
 
Possono succedere 3 situazioni:
 
1 esistono N>0 slave in quel range che rispondono in tempi diversi
  con risposte che non si sovrappongono, quindi il master rileva 
  N risposte corrette (memorizza gli N slave, comunica loro di zittire
  fino alla fine della procedura di discovery e va avanti con altri 
  eventuali range);
2 non esiste alcuno slave in quel range (il master va avanti con
  altri eventuali range);
3 ci sono N>0 slave in quel range che rispondono con messaggi
  sovrapposti, quindi il master rileva collisioni/errori, quindi
  dimezza il range in due intervalli (0x00000000-0x7FFFFFFF e 
  0x80000000-0xFFFFFFFF) e continua così.
 
Esiste però un caso particolare del caso 3 che mi sembra pericoloso
e che apparirebbe al master come caso 1.
Se due o più slave rispondono esattamente nello stesso istante 
(oppure con ritardi trascurabili rispetto al baudrate)?
E' probabile che lo slave più vicino oppure quello con il driver 
più forte possa nascondere l'altro o gli altri slave, senza che il 
master se ne accorga (sperando che due bit diversi messi sul bus
non creino altri problemi).
Ovviamente è possibile implementare il classico ritardo di risposta
calcolato in base all'SN, ma c'è comunque la probabilità che due o
più slave con differenti SN abbiano lo stesso delay.
 
Una soluzione potrebbe essere quella di ritardare la risposta di un
tempo *casuale* e ripetere (solo per il caso 1) più volte la 
procedura di discovery in un certo intervallo, se siamo nel caso 1.  
Se i risultati sono tutti uguali (il master vede sempre il caso 1)
ok, altrimenti procede con la divisione dell'intervallo.
Probabilmente basterebbe un algortimo di numeri pseudo-casuali 
inizializzato con un numero calcolato dall'SN che è sicuramente 
diverso da slave a slave.
 
Un'altra idea è quella di usare una RS485 alla maniera di una rete
1-wire che ha già un metodo di discovery degli slave collaudato.
Non bisognerebbe usare più la UART, ma i GPIO del micro collegati
ai pin RX, TX e DE (driver enable) del transceiver RS485.
Per trasmettere 0, TX va messo a zero e il driver va abilitato. Per
trasmettere 1, il driver va disabilitato. In caso di collisioni,
sul bus viene visto un AND di tutti i bit trasmessi in quell'istante.
In pratica si dovrebbe implementare a tutti gli effetti il
protocollo 1-wire, cosa che potrebbe non essere semplice.
 
Un'altra possibilità che evita il detect delle collisioni (che 
potrebbe non essere semplice e affidabile), è quella mista 
UART/GPIO.
Alla solita richiesta del master, gli slave interrogati rispondono
con una condizione di break (mettono a 0 il bus per un certo
tempo, usando il pin TX e DE del transceiver).
Il master dovrebbe effettuare una ricerca binaria fino a ridurre
l'intervallo ad un solo SN e per il quale viene ricevuto un break: 
lo slave con quel SN esiste veramente.
Se più slave hanno un SN nello stesso intervallo, generano lo stesso
impulso di break, ma anche se sono sovrapposti ciò non crea problemi.
 
 
L'altro prolema è quello di un discovery avendo slave perfettamente
identici, quindi senza un SN che li distingua.  E' possibile
trovare una soluzione anche in questo caso?
Si potrebbe pensare ad un SN calcolato come un numero casuale,
sperando che due slave non ricavino lo stesso SN (con un numero a
32 bit ed un distribuzione sufficientemente uniforme su tutti i
numeri, questa probabilità è veramente minima).
Ma questo fa nascere un altro problema a cui non ho mai pensato:
come creare in modo affidabile numeri casuali in una piattaforma
embedded?

 embedded?
 
Soluzione semplice: campioni il rumore sugli ingressi analogici del micro
(o se il micro non ha ingressi analogici generi del rumore bianco con un
transistor e lo campioni con un I/O) e usi queste informazioni come seme
iniziale per uno dei "soliti" algoritmi di generazione di numeri
pseudocasuali. Questa soluzione è accettabile per la maggior parte delle
applicazioni, se invece devi fare cose più serie (crittografia ecc..)
allora ti servono metodi più sofisticati.
 
-- 
Fletto i muscoli e sono nel vuoto.

 Soluzione semplice: campioni il rumore sugli ingressi analogici del micro
 
E dove collego questi ingressi analogici?  Li lascio flottanti?  Oppure 
parli dei bit meno significativi che normalmente sono affetti da rumore?


 trovare una soluzione anche in questo caso?
E' possibile, se lo slave è progettato per ricevere anche quello che
trasmette (possibilita' di agire su RxEna e OutEna in modo indipendente).
Si usa un approccio tipo CSMA/CD (Carrier Sense, Multiple access,
Collision detect).
Su un messaggio broadcast, gli slave prima di trasmettere l' eventuale
risposta, ascoltano per un tempo 'random' X che la linea sia libera,
poi iniziano a trasmettere un preambolo (0x55555555): se lo ricevono 
correttamente, iniziano a trasmettere il proprio messaggio, monitorando 
che sia inviato senza errore: in caso di errore, delay di un tempo
generato in modo random (oppure in tempo pari a N caratteri) e poi 
quando la linea e' libera , diciamo per il tempo di X caratteri,
riprovano. Questo metodo non e' originale, ma funziona piuttosto
bene anche se ha qualche criticità nella messa a punto dei tempi.
 
Con una 485 classica (senza potere controllare il carattere trasmesso)
sarebbe possibile usare il solo ascolto della linea e se libera
iniziare una trasmissione di un messaggio di 'impegno', che inibisce
tutti gli altri slave: se Ok, il master risponde con un messaggio
per continuare, al temine del colloquio, il master rimanda un messaggio
broadcast a cui possono rispondere tutti gli altri slave, ma non
quello che ha gia' risposto...
Il tutto e' parecchio piu' critico, non potendo rilevare il trasmittente
la collisione, ma se si ussano messaggi e tempi adeguati, e' possibile
gestire i broadcast per configurare la rete.
Tenendo condo che una rete 485 potra' difficilmente avere piu' di
una 60-ina di nodi, la cosa dovrebbe essere gestibile ...
 
Naturalmente usando una rete CAN questi problemi spariscono :-)
 
AA.
 
 

 Yes :-)
 
tutto molto interessante,grazie ,spero che con Settembre il ng riprenda un 
pò di attività
ciao 
 
 

 parli dei bit meno significativi che normalmente sono affetti da rumore?
 
Esatto!


 anche questi ultimi si sono pressoch� estinti in favore degli switch.
Non e' proprio cosi' :-) Anche la 1000base-t (Gigabit) rimane un
protocollo CSMA/CD (con lo slolt time di 64byte allungato a 512byte per 
compensare la maggior velocita' - questa e' la parte di 'collisione').
Non si hanno collisioni solo quando si va in full-duplex, ma questo
dipende dalla negoziazione dei due punti. Se per qualsiasi motivo la
linea funziona in half-duplex, le collisioni saranno sempre presenti.
AA.
 
 

 AA.
 
Che è appunto ciò che ho scritto: a parte per l'auto negoziazione, le
schede vanno in modalità half-duplex solo quando sono connesse attraverso
hub.


 hub.
Non proprio , Sembrava quasi che l' ethernet non funzionasse piu' come
da specifica:
 >Probabilmente comunque le schede di rete moderne supportano tutt'ora il
 >CSMA/CD e l'exponential backoff, per prevedere la presenza di hub. Ma 
 >ormai anche questi ultimi si sono pressoché estinti in favore degli
 >switch.
il probabilmente e' di troppo, tutto li :-)
AA

 presenti sul bus?
 
Come ti han detto si pu� fare, ma a me pare una pessima idea.
 
Gi� di suo la 485 non � tanto veloce, se ci metti pure il CSMA/CD a 
quanto la fai andare? E tieni presente che con la vecchia Ethernet 
coassiale pi� PC c'erano e peggio andava: il rallentamento era 
percettibile con 5 PC connessi, e oltre gli 8-9 PC su uno stesso cavo 
invecchiavi davanti al monitor... le prestazioni crollavano letteralmente.
 
Seconda obiezione, in modalit� master/slave classica la 485 � un bus 
deterministico, cio� sei certo che il tuo slave sar� interrogato entro 
un tempo finito e noto a priori (vedi Profibus). Con queste modifiche, 
tanti saluti al determinismo. Non puoi pi� sapere entro quanto uno slave 
risponder�, e non ti puoi pi� permettere di usarla per cablare impianti 
e controlli che necessitano di prestazioni realtime.


Le tue obiezioni sono corrette, anche se molto dipende dall'applicazione 
(real-time o meno, velocit�, banda dei dati, ...).
 
Ad ogni modo questi meccanismi che rallentano il bus servirebbero solo 
durante la fase di autodetect che, almeno per come la vedo io, � 
assistita dall'utente e avviene molto saltuariamente (aggiunta o 
rimozione di slave).
 
Sicuramente non stavo pensando ad un autodetect plug&play, anche se 
ammetto sarebbe molto carino.
 
 

 rimozione di slave).
 
Anche cos�... assistita per assistita, tanto vale che sia l'utente a 
dare al master i dati del nuovo slave da pollare :-D
 
Vabb�, sarebbe sicuramente pi� semplice per l'utente non configurare 
niente e lasciare che sia il sistema a fare tutto, cos� basta che dice 
al master "cerca uno slave nuovo" e poi che se la vedano tra macchine.
 
Diciamo che il master manda un messaggio broadcast di "ricerca slave" e 
tutti gli slave presenti devono comunicare entro XXX secondi dalla 
ricezione (che supponiamo contemporanea alla trasmissione, per 
comodit�). Ci sarebbe da vedere che fare con gli slave di tipo normale, 
non autodetect, ma quello � un problema che al momento non credo 
t'interessi :-)
 
UHM... per l'autodetect plug&play mi viene un'altra idea: rilevare 
eventuali nuove connessioni al cavo in modo elettrico e non logico. Cio� 
mandare una sinusoide ad alta frequenza (debole, per carit�) lungo il 
cavo e "sentire" quante riflessioni e quanti disadattamenti subisce. 
Misurare il ROS, insomma.
Se il ROS misurato � diverso da quello all'ultima accensione, vuol dire 
che c'� un nuovo dispositivo collegato da qualche parte e bisogna fare 
un ciclo di autodetect.