I miei PLC sono connessi al Web tramite il Wifi di Wemos. Per accoppiare il Wemos alla rete Wifi ho sempre usato il pulsante WPS presenti nei nuovi router.
Ma (c'è sempre un MA) non tutti i router ce l'hanno.
Ecco quindi che quelle poche volte dovrei sparare dal Touch screen al PLC dei caratteri ASCII che poi leggerò dal Wemos in modo che lui si "accoppi" con la rete Wifi.
Nessun problema, a quello poi ci penso io.
Però il PLC usa delle word da 16bit.
E il numero che leggo non ha senso, o almeno questo pensavo...
Cioè, se lo converto in BIN il senso ce lo ha:
se scrivo A mi risponde
01000001
se scrivo AA mi risponde
0100000101000001
se scrivo AAA mi risponde
0100000101000001
01000001
(ho messo gli zeri davanti per migliorare la lettura ma l'output non ha il primo ZERO se questo non è un 1).
Tutto chiaro: se inserisco un carattere usa i primi 8 bit, se ne inserisco due usa tutti i 16 bit e se ne inserisco tre passa alla word successiva e questo lo farà per 30 word (cioè 60 caratteri alfanumerici ma posso anche leggerne di meno, vedrò quanto può essere lunga una password di un router...).
Se non scrivo nessun carattere la word da 0.
Il primo problema è SPEZZARE la word in due byte (però solo se è maggiore di un byte)
il secondo problema è convertire il byte in un carattere ASCII (spero che siano standard...).
Chi è quell'anima pia che puo' darmi un suggerimento?
Scusa 01000001 se lo scrivi come due nibble da 4 bit è 0100 0001 ovvero ... esattamente 0x41 che è la lettera 'A' in ASCII ... già ti sta trasmettendo i caratteri in ASCII, non devi convertire nulla ...
Ecco perché ho pensato alla conversione in bytes, la suddivisione in due byte e la conversione.
Sbaglio qualcosa o c'è un modo più rapido e/o sintetico?
... t'ho già detto, bisogna che ricevi byte a byte e metti in un char array, quando la trasmissione è finita metti uno 0x00 e ti trovi già tutto in ASCII nell'array ... dove è la difficoltà ???
Ma la trasmissione è seriale? o che trasmissione è dal PLC ?
Forse no, lui dice "se inserisco un carattere usa i primi 8 bit, se ne inserisco due usa tutti i 16 bit e se ne inserisco tre passa alla word successiva" e " il PLC usa delle word da 16bit".
In tal caso è più complesso perché riceve sempre word da 16 bit più o meno popolate.
Quindi, per essere certi di questo, cosa risponde il PLC con A AB ABC ABCD, includendo anche tutti gli zeri non significativi fino a 16 bit?
... e capirai che difficoltà ... se trasmette sempre 16 bit si tratta di capire solo se, nel caso gli bastino 8 bit, usa solo la parte più significativa o la parte meno significativa ... in ogni caso cambia poco.
Quello che invece io ancora non ho capito è come vengo trasmessi i dati ... su porta seriale? ... su un I2C? ... in un pacchetto TCP? ... in che cosa e come???
La trasmissione non è un problema dato che i dati già li sto leggendo sul monitor seriale del Wemos. Comunque, per soddisfare la tua curiosità, ho il PLC in slave quindi lo interrogo da Wemos su RS-485, in qualsiasi momento con
for (i = 0; i < 30; i++) {
ret = node.readHoldingRegisters (i + 430, 1); // read da D430 a D459
delay (del);
if (ret == node.ku8MBSuccess) {
nn = node.getResponseBuffer (0); // e' una Word da 16 bit.
Serial.print (nn); Serial.print (" ");Serial.print(nn, BIN);Serial.print (" ");Serial.println (nn, HEX);
}
e poi nn lo metto dove mi serve.
Certo, nn è a 16 bit quindi se è un solo carattere i primi 8 bit saranno ZERO (quelli a sinistra) e i successivi 8 bit saranno il carattere.
Non ricevo byte a byte (allora non disturbavo), ma ricevo una word da 16 bit, cioè due byte.
dove il primo numero è un DEC, di seguito il BIN e poi (per non farci mancare nulla) il HEX.
Siccome sarò bravo con PLC, HMI e hardware ma se si tratta di programmazione un po' più "spinta" sono una frana, se mi date un paio di righe le provo e vi faccio sapere.
for (i = 0; i < 30; i++) {
ret = node.readHoldingRegisters (i + 430, 1); // read da D430 a D459
delay (del);
if (ret == node.ku8MBSuccess) {
nn = node.getResponseBuffer (0); // e' una Word da 16 bit.
char var1 = (nn >> 8);
char var = (nn & 0x00FF);
Serial.print (var); Serial.print (" ");Serial.print(var1);Serial.print (" ");Serial.println (nn, BIN);
}
A B 100001001000001
C D 100010001000011
a b 110001001100001
c d 110010001100011
1 2 11001000110001
3 4 11010000110011
Come passo successivo mi manca di farne una stringa da passare al router
WiFi.mode(WIFI_STA);
//WiFi.begin(WiFi.SSID().c_str(), WiFi.psk().c_str()); // reading data from EPROM, last saved credentials
WiFi.begin("nomerete", "password"); // ------------- Se non possibile WPS, password manuale --------
SI, occhio, che ho visto programmi non andare più se portati su ESP (o su SAMD21) ...
... meglio, in testa al programma, includere sempre:
#include <stdint.h>
e poi definire le variabili con uint8_t, int8_t, uint16_t, int16_t, ecc. ecc., così le lunghezze sono ben chiare e non cambiano da architettura ad architettura.
password = "";
for (i = 0; i < 30; i++) {
ret = node.readHoldingRegisters (i + 430, 1); // read da D430 a D459
delay (del);
if (ret == node.ku8MBSuccess) {
nn = node.getResponseBuffer (0); // e' una Word da 16 bit.
char var = (nn & 0x00FF);
password += var;
char var1 = (nn >> 8);
password += var1;
Serial.print (var); Serial.print (" "); Serial.print(var1); Serial.print (" "); Serial.println (password);
}
Domanda (prima di verificarlo):
La stringa è piena anche di "spazi" se legge tutte le 30 locazioni di cui solo le prime sono occupate da caratteri oppure il valore ZERO non è inteso come carattere e la stringa rimane "pulita"?
Vabbé, dai, ogni tanto mettevano dietro la lavagna anche me.
Un po' lazzarone dell'ultimo banco lo sono, poi è sabato, fuori piove (e già è raro), il mare è grosso e fuori ci sono "solo" 18 gradi...
Allora ho "sintetizzato". E ho usato solo una var per risparmiare...
for (i = 0; i < 30; i++) {
ret = node.readHoldingRegisters (i + 430, 1); // read da D430 a D459
delay (del);
if (ret == node.ku8MBSuccess) {
nn = node.getResponseBuffer (0); // e' una Word da 16 bit.
char var = lowByte (nn);
password += var;
var = highByte (nn);
password += var;
}