alla fiera degli Array un ascensore mio padre comprò........

Lo so che era un topolino ma non mi sono fatto un topolino (e purtroppo nemmeno una topa...) mi sono fatto l'ascensore, di nuovo. allora la situazione è che mi sono messo a provare di trasferire tra macchine "remote", se vogliamo possiamo dire Master/Slave, delle informazioni, oltre che dei comandi (cosa che avevo fatto nella stagine dei pin remoti, vedere qui https://forum.arduino.cc/index.php?topic=528445.msg3602457#msg3602457) Siccome squadra che vince non si cambia mi sono limitato ad aggiungere tre funzioni a quella libreria una legge e una scrive dal master un elemento di un array di byte inizializzato sulla macchina remota (slave) la terza funzione "scatena" sullo slave una funzione byte funzione (byte){} che si legge: funzione che accetta un solo argomento byte e ritorna un valore byte tale funzione deve venir preventivamente "caricata" in un array di puntatori a funzioni sulla macchina slave più o meno come avevo fatto qui: https://forum.arduino.cc/index.php?topic=537048.msg3661377#msg3661377 Quale maniera migliore per provarla che "remotare" (mi si passi il brutto neologismo) l'ascensore che avevo fatto qui: https://forum.arduino.cc/index.php?topic=542753.msg3699128#msg3699128 Sì insomma, ho messo un po' tutto assieme e ne ho fatto un concentrato... adesso vi spiego, nel prossimo post per non intasare e superare i 9000 caratteri

Perchè dico la fiera degli array?
perchè la maniera che ho usato per passare sia le informazioni che le funzioni da eseguire in remoto è passsare attravero l’indice di un array, indice che viana trasmesso all posto dell’informazione Pin nella mia precedente libreria di remotaggio
in buona sostanza la libreria è allegata qui, rispetto a quella di settimana scorsa gli ho tolto due bei bacherozzi:
mi ero sconfuso ad un certo punto tra indice e valore dello array, è una nera vergogna, ma lo avevo scritto subito che ero stanco
poi per un caso avevo sbagliato il carattere che trasmettevo per riconoscere il comando remoto, una semplice distrazione
sotto qui trovate la libreria aggiornata

keywords.txt (959 Bytes)

PinRemoti.h (19.9 KB)

Come si usano la nuove funzionalità?
semplice, spero:
per trasferire byte si fa dimensionare un array chiamato arraybyte
si fa dimensionare siglìnifica che lo dimensiona la libreria, basta, prima di includerla creare la macro ARRAYBYTE (notare il maiuscolo) con una #define, da calcoli miei il massimo indice utilizzabile è 78
non sono pochi come sembra, se avete da trasferire più di 78 variabili byte (o un numero corrispondente di variabili più ingombranti) c’è qualcosa che non va nella maniere di come avete “diviso i compiti” tra le varie macchine
la funzione
int remoteByteRead(char indirizzo, byte elemento) acctta come argomenti l’indirizzo della macchina remota e l’indice dell’elemento dell’array da leggere (va da se che sia minore o oguale a quanto grande avete dimensionato l’array)
invece la int remoteByteWrite(char indirizzo, byte elemento, byte valore)
scrive il valore nell’elemento dell’array, per il resto uguale è
se con la macro ARRAYFUNZIONI si fa dimensionare alla libreria un arrai di puntatori a funzioni (anche qui massimo 78 elementi, e se li usate tutti avete GROSSI problemi di divisione dei compiti)
create le funzioni
byte funzione (byte){} e usate il nome della funzione per popolare (modo di dire studiato che significa: scrivere dentro) l’array
la funzione int remoteFunBCall(char indirizzo, byte elemento, byte valore)
chiama sulla macchina remota la funzione puntata dall’elemento dell’array e ne riporta il risultato
due parole sui tipi
lo so’, c’è un po’ di confusione, in alcuni punti ho usato int dove basta (e anzi ho citato ) byte, metterò a posto
ma per ora così va e fa tutto quello che deve

il programma di esempio?
in allegato

allafieradellarray.ino (9.27 KB)

Rimane da spiegare come lavora
Prima parte, si dichiarano le funzioni da “caricare” nello array

byte funzione1(byte a)
{
    // mi limito a fare operazioni semplici ma riconoscibili
    Serial.println("E' stata chiamata la funzione 1");
    Serial.print("Che stampa il suo argomento: ");
    Serial.println(a);
    Serial.println("E restituisce il doppio");
    return a * 2;
}
byte funzione2(byte a)
{
    // mi limito a fare operazioni semplici ma riconoscibili
    Serial.println("E' stata chiamata la funzione 2");
    Serial.println("Che restituisce il numero 3");
    return 3;
}
byte funzione3(byte a)
{
    // mi limito a fare operazioni semplici ma riconoscibili
    Serial.println("E' stata chiamata la funzione 3");
    Serial.println("Che accende un led");
    pinMode(13, OUTPUT);
    digitalWrite(13, HIGH);
    Serial.println("Aspetta un decimo di secondo");
    delay(100);
    Serial.println("e lo spegne");
    digitalWrite(13, LOW);
    Serial.println("Ricordati che serve aumentare il timeout remoto,");
    Serial.println("bisogna dare alla funzione il tempo di terminare");
    return 4;
}

poi si richiamano le librerie necessarie
io ho usato la seriale software come canale di comuicazione e la scheda LED&KEY

// dichiarazione delle librerie
#include <SoftwareSerial.h>
SoftwareSerial canale(2, 3); // RX, TX
#include <TM1638lite.h>
TM1638lite tm(4, 7, 8); // strobe clock data

poi la libreria specifica di remotaggio, dichiarando prima gli array byte e funzioni

#define VETTOREBYTE 4
// per avere un vettore di byte da comandare da remoto
// se non scrivo la define non viene creato il vettore
#define VETTOREFUNZIONI 3
#include <PinRemoti.h>

nella setup, a seconda che il pin 9 sia ponticellato a massa oppure no la scheda arduino prende indirizzo A oppure B e si comporta da master o slave, pur se la libreria è simmetrica

void setup()
{
    remototimeout(80);
    porta = 1;
    Serial.begin(9600);
    canale.begin(1200);
    remotoflusso(&canale);
    pinMode(9, INPUT_PULLUP);

    if (digitalRead(9))
    {
        remotoindirizzo('B');
        Serial.print(F("Gestione pin remoti, unita': "));
        Serial.println(remotoindirizzo());
        Serial.println("ricevitore->ascensore");
        // carico lo array di funzioni
        vettorefunzioni[0] = funzione1;
        vettorefunzioni[1] = funzione2;
        vettorefunzioni[2] = funzione3;
        // notare lo scalato di uno per contare umanamente le funzioni
        // accendiamo la P
        tm.displayASCII(piano, 'P');
    }
    else
    {
        remotoindirizzo('A');
        Serial.print(F("Gestione pin remoti, unita': "));
        Serial.println(remotoindirizzo());
        Serial.println("ascensore->trasmettitore");
        // faccio accendere per un poco il led sull'altro arduino
        remotePinMode('B', 13, OUTPUT);

        if (remotoerrore())
        {
            Serial.print(remotoerrore());
            Serial.println("errore di comunicazione");
        }

        remoteDigitalWrite('B', 13, HIGH);

        if (remotoerrore())
        {
            Serial.print(remotoerrore());
            Serial.println("errore di comunicazione");
        }

        delay(500);
        remoteDigitalWrite('B', 13, LOW);

        if (remotoerrore())
        {
            Serial.print(remotoerrore());
            Serial.println("errore di comunicazione");
        }
    }
}

il bello viene al prossimo post

Allora, dicevo, adesso viene il bello: la loop

a seconda dell'indirizzo scelgo se la macchina è il master o lo slave se lo slave la storia è semplice

void loop()
{
    if (remotoindirizzo() == 'A')
    {
    


    // trasmettitore

.
.
.
    }
    else
    {
        // ricevitore
        // abilitiamo i comandi remoti
        remotaggio();
        // e poi facciamo comunque andare l'ascensore in locale
        ascensore();
    }
}

sempicemente si richiama la remotaggio() e tutto il resto che la macchine deve fare, nell'ordine che si preerisce la funzione ascensore() è semplicemente la loop() del vecchio ascensore, con un piccolo trucco che mostrero' dopo

invece se fosse il master:

void loop()
{
    if (remotoindirizzo() == 'A')
    {
        // trasmettitore
        if (Serial.available())
        {
            char cx = Serial.read();

            switch (cx)
            {
                case 'a':
                    remotePinMode('B', 13, OUTPUT);

                    if (remotoerrore())
                    {
                        Serial.print(remotoerrore());
                        Serial.println("errore di comunicazione");
                    }

                    remoteDigitalWrite('B', 13, HIGH);

                    if (remotoerrore())
                    {
                        Serial.print(remotoerrore());
                        Serial.println("errore di comunicazione");
                    }

                    Serial.println("Accensione Led");
                    break;

                case 's':
                    remotePinMode('B', 13, OUTPUT);

                    if (remotoerrore())
                    {
                        Serial.print(remotoerrore());
                        Serial.println("errore di comunicazione");
                    }

                    remoteDigitalWrite('B', 13, LOW);

                    if (remotoerrore())
                    {
                        Serial.print(remotoerrore());
                        Serial.println("errore di comunicazione");
                    }

                    Serial.println("Spegnimento Led");
                    Serial.print("Ascensore al piano: ");
                    Serial.println(remoteByteRead('B', 0));
                    break;

                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                    Serial.print("Ascensore al piano: ");
                    Serial.println(remoteByteRead('B', 0));
                    Serial.print("prenotiamo il piano: ");
                    remoteByteWrite('B', 1, cx - '0');
                    Serial.println(remoteByteRead('B', 1));
                    break;

                case '+':
                    // avviamo l'ascensore da remoto
                    Serial.print("Ascensore al piano: ");
                    Serial.println(remoteByteRead('B', 0));
                    Serial.print("Prenotato il piano: ");
                    Serial.println(remoteByteRead('B', 1));
                    remoteByteWrite('B', 2, 1);
                    Serial.println("Ascensore avviato, prego attendere il termine della manovra");
                    break;

                case 'q':
                    remototimeout(150);
                    // chiamiamo la prima funzione
                    Serial.print("Chiamo la prima funzione remota con argomento 2 e restituisce: ");
                    Serial.println(remoteFunBCall('B', 0, 2));
                    remototimeout(80);
                    break;

                case 'w':
                    remototimeout(150);
                    // chiamiamo la II funzione
                    Serial.print("Chiamo la II funzione remota con argomento 3 e restituisce: ");
                    Serial.println(remoteFunBCall('B', 1, 3));
                    remototimeout(80);
                    break;

                case 'e':
                    remototimeout(300);
                    // chiamiamo la IIi funzione
                    Serial.print("Chiamo la III funzione remota con argomento 25 e restituisce: ");
                    Serial.println(remoteFunBCall('B', 2, 25));
                    remototimeout(80);
                    break;

                default:
                    // ntd
                    Serial.println("comando non riconosciuto");
                    break;
            }
        }
    }
    else
    {
       .
.
.
.
    }
}

abbastanza semplicemente riceve dei comandi da seriale USB e dopo averli riconosciuti li fa eseguire alla macchina slave trucco: la macchina slave ha vita propria: funziona bene come ascensore autonomo basta semplicemente usare come nome delle variabili di controllo gli elementi dell'array "comandabile" dal master, e quindi, se il master scrive in quell'array la macchina controllata "crede" che siano stati premuti i pulsanti che "normalmente" la comandano scrivendo quelle variabili lo sporco trucco è stato quello di NON cambiare il programma, ma usare delle define per "taroccare i nomi" se andate a vedere la scensore() e la confrontate con la loop del suo programma originale vedete che sono uguali, il trucco è qui:

// per l'ascensore
//byte piano; // piano attuale dell'ascensore
#define piano vettorebyte[0]
// magata, il byte tele-comandabile viene usato come piano
//byte chiamato; // piano prenotato
#define chiamato vettorebyte[1]
//bool prenotato; // ascensore prenotato oppure no
#define prenotato vettorebyte[2]
//bool porta = 1; // 1 aperta, 0 chiusa
#define porta vettorebyte[3]

dov eio tarocco i nomi, tipicamente il piano attuale dell'ascensore, la variabile byte piano è ri-definita come il primo elemento dello array, e via così

da ultimo le funzioni remote nulla di particolare da dire, se non che bisogna dare alla macchina remota il tempo per eseguire la funzione, evitiamo quindi funzioni bloccanti o lunghe, evitare possibilmente anche le delay (io nell'esempio ne ho messa una) e trimmare bene il tempo di timeout della libreria nella parte di èrogramma dove uso le funzioni remote ho messo un esempio di regolazione del timeout

e con questo credo di potervi augurare buonanotte

PS sono nuovamente graditi gli applausi

o meglio le critiche costruttive

https://www.youtube.com/watch?v=Z8MqKfsLLxs

Bene, terminati i dovuti doveri vediamo un po' di ricapitombolare.

Si parte da lontane ex discussioni dell'ex utente docsavage, avevo scritto anche una mia versione.

E si arriba arriba alla PinRemoti (che ormai ha versioni sparse tra più post), che prima voleva solo controllare dei pin, poi poter leggere/scrivere degli array, ed infine attivare funzioni (in pratica un pico modbus).

Ci sono diverse cose che non mi sono chiare e devo approfondire (sui puntatori a funzioni, sullo Stream ecc).

Ma, partiamo dalla mirabolante affermazione: «servire a sviluppare qualunque cosa uno voglia»

Quindi subito due casi pratici reali...

  • Ci sono varie centraline che devono mostrare l'ora su un display, solo una di esse ha l'RTC a bordo e periodicamente deve informare le altre.
  • Ci sono varie centraline che possono avere diversi modi di funzionamento, facciamo per semplicità "giorno" e "notte", o "presenza" e "non presenza". Qualcuno deve segnalare il cambio a tutte quante. Come useresti la tua libreria per questi compiti (che fondamentalmente richiedono una sorta di broadcast)?

Se ho capito il funzionamento della libreria potrei banalmente usare la funzione di scrittura su array. Il master invia allo slave il comando di scrittura su un dato array (array mono elemento, contenente il modo di funzionamento). E aspetta conferma Lo slave, quando libero, chiama la remotaggio() che legge il segnale ricevuto, lo interpreta come messaggio per lo slave, lo decodifica e lo applica. E invia la risposta al master. Ora lo slave ha la variabile che gli identifica lo stato (normalmente presente nella sua programmazione) modificata, quindi cambia stato. Il master riceve risposta e passa allo slave successivo, ignorando questo.

In alternativa posso chiamare una funzione (preposta sullo slave) che modifichi quel parametro.

Ricordiamoci che NON può essere possibile che "lo slave non sappia di esserlo", in quanto deve avere installata la libreria. Visto questo mi pare una fantastica idea, che userò certamente

Io ho sempre ammesso, fin dal principio, che mi sono ispirato (e se vogliamo, ho pesantemente copiato) da cose trovate qui sul forum. Ho sempre pubblicato e commentato tutto, proprio perché il merito non è tutto mio, semmai del forum E poi la incriminata e rossa frase: sviluppare qualunque cosa uno voglia Era riferita al progettone col mio collega, non alla fiera degli array Hai ragione, mea culpa mea maxima culpa, dimenticai il broadcast

adesso sono le 16 e 51, il gastro ha chiuso i lavori e quindi il cerebro ha ripreso giri e rialzato la pressione
mi sono ricordato perchè non ho previsto il broadcast: non è possibile col broadcast ricevere la conferma di esecuzione, e a questa io davo molta importanza
per prevedere il broadcast avrei dovuto partire in maniera differente
(tradotto in italiano: ho copiato dalla pare sbagliata e adesso non saprei ripartire da capo)

Claudio_FF: https://www.youtube.com/watch?v=Z8MqKfsLLxs

Bene, terminati i dovuti doveri vediamo un po' di ricapitombolare. . . Ci sono diverse cose che non mi sono chiare e devo approfondire (sui puntatori a funzioni, sullo Stream ecc).

mi ero dimenticto di ringraziarti, scusami, non credevo di meritare tanto, io scheravo con gli applausi e poi, se ti serve un chiarimento, chiedi.....

Standardoil...non è per criticare,.....non è per essere polemico...non è per volerti prendere in giro e scherzare sulle problematiche dei malati mentali.

Ma ti volevo fare una domanda,ti 6 reso conto vero che su 10 risposte a questo Topic (a parte la mia che è la 11), le prime 6 volte ti stavi parlando da solo???? :o :o :o :o

Per fortuna dopo sono intervenuti Claudio_FF (il mio cliente Carta Oro) e Silente.

Ora con tutto il rispetto lo sai vero che ci sono cliniche e specialisti che provano a curare certe forme diciamo di visione fuori dagli schemi comuni???? tipo Psicologi che curano i disturbi ad esempio di chi parla da solo????? :confused: :confused: :confused: :confused:

:D :D :D :D :D :D :D :D :D :D :D Scusatemi ma non ho resistito

Tranquillo, lo sappiamo benissimo di avere sdoppiamento della personalità

:) :) :) ovviamente era solo una battuta....in realtà vi ammiro tanto..... :P :P :P :P

anch'io, tutti e due voi

due voi chi???? vedi anche la dislessia potrebbe essere curabile. :fearful: :fearful: :fearful:

OK…bello a volte fare anche battute…ora la smetto se no Guglielmo mi caccia fuori, comunque non ho letto quello che hai scritto,ma immagino che ci credi davvero(e questo è un sintomo).

A parte le battute

Ciao :slight_smile: :slight_smile: :slight_smile: :slight_smile:

scritto dove?
qui tutto pubblico è
io non uso PM o simili
uomo cristallino sono

Non ho finito di leggere i primi 6 Post dove di parlavi e rispondevi da solo e neppure gli altri due fino a 10...(dai basta se no mi cacciano per sempre) :drooling_face: :drooling_face: :drooling_face: :drooling_face: :drooling_face:

::) ::) ::) :P :P :P :P ;D ;D ;D ;D