Vai al contenuto
PLC Forum


Ricorsione


claudio

Messaggi consigliati

Gentili utenti del forum

Ho un dubbio che vorrei sottoporvi.

Vorrei implementare su un PLC S7-1500 un algoritmo minimax che mi servirebbe per realizzare il programma del tris, ovvero giocare a tris contro il PLC.

Si tratterebbe di un'applicazione a uso didattico.

Solo che l'algoritmo minimax sfrutta la ricorsività; io ho il sospetto che non si possano implementare algoritmi ricorsivi nei PLC e anche le prime prove che ho fatto, scrivendo il codice in SCL, porterebbero alla conferma di questa ipotesi.

Chiederei a voi, molto più esperti di me, se poteste confermare questa ipotesi.

Vi ringrazio per il tempo che potrete dedicarmi

Cordiali saluti

Claudio

Link al commento
Condividi su altri siti


34 minuti fa, claudio scrisse:

io ho il sospetto che non si possano implementare algoritmi ricorsivi nei PLC

 

E perchè mai?

 

Si sono sempre fatti. Non conosco SCL ma con AWL è abbastanza semplice: deconti un contatore e fai il confronto, se il contatore è >0 salti all'inizio del loop, altrimenti esci.

Link al commento
Condividi su altri siti

se per ricorsione intendi cicli tipo 
WHILE-DO oppure FOR-NEXT oppure IF-THEN oppure tutto quello previsto dalle norme IEC 61131-3 il linguaggio SCL è proprio quello che devi usare.

Link al commento
Condividi su altri siti

Vi ringrazio per le risposte che mi avete dato e proverò ad attuare il suggerimento di Livio, anche se sono un po' dubbioso

Sicuramente non mi sono spiegato bene.

Il mio problema è che l'algoritmo minimax è codificato come una funzione e all'interno della medesima funzione viene nuovamente richiamato il minimax, insomma viene effettuata una chiamata alla stessa funzione.

Ho provato a scrivere il codice relativo in SCL e il compilatore mi segnala errore sulla chiamata interna: però, a onor del vero, non ci ho ancora dedicato un tempo sufficiente a studiare bene la questione, cosa che spero riuscirò a fare già stasera.

Ancora grazie

Claudio

 

Link al commento
Condividi su altri siti

9 minuti fa, claudio scrisse:

Il mio problema è che l'algoritmo minimax è codificato come una funzione e all'interno della medesima funzione viene nuovamente richiamato il minimax, insomma viene effettuata una chiamata alla stessa funzione.

 

Forse sono io che non ho capito bene, ma non è possibile, indipendentemente dal linguaggio, chiamare una funzione all'interno della stessa funzione, tra l'altro non ha senso.

 

Prova a scrivere la funzione in simil "C" così si può capire meglio quello che vuoi fare.

Link al commento
Condividi su altri siti

Grazie Livio, non vorrei farti perdere troppo tempo ...

Di seguito riporto la codifica del minimax in C++ applicata al tris; sinceramente al momento non mi sono preoccupato di comprenderne il funzionamento perchè prima vorrei capire se è una roba che posso implementare su un PLC.

La funzione fa parte di un software un po' più complesso, ma non di molto; ho però lanciato l'eseguibile che era associato al sorgente e il tutto funziona.

Finora ho riscritto buona parte del programma in SCL in TIA Portal, solo che il problema ce l'ho quando mi trovo sulla riga evidenziata in grassetto: più tardi controllerò meglio, ma mi sembra che il compilatore non mi permetta di richiamare la funzione minimax dal suo interno, comunicandomi l'errore "nome di funzione non valido".

Quello che sospetto è che in un PLC la ricorsione di funzioni sia un processo "osteggiato" perchè potrebbe portare, se non controllato nella sua profondità, all'entrata in funzione del watch-dog del PLC, con gli effetti collaterali conseguenti

Però mi riservo di farci altre prove .

Ancora grazie

Buona serata

Claudio

 

 

//Funzione minimax, i giocatori sono indicati con 1 e -1
int minimax(int giocatore)
{
    int valore;
    //Se la situazione è valutabile ritorna il valore
    //1 vince il giocatore 1
    //-1 vince il giocatore -1
    //0 pareggio
    if ((valore = controlla_vittoria()) != 2)
        return valore;
    int mossa_migliore;
    int i,j;
    mossa c;
    //Inizializzo la mossa migliore con un valore che è sicuramente
    //perdente per entrambi, in modo che venga sostituito da valori
    //migliori
    mossa_migliore = (giocatore == 1) ? -2 : 2;
    //Provo tutte le mosse
    for ( i = 0; i < 3; i++)
        for ( j = 0; j < 3; j++)
        {
            //Se qualche casella è già occupata non viene provata
            if (mossa_corretta(i+1,j+1))
            {
                //Segno la mossa che sto provando
                tris[j] = giocatore;
                //Calcolo ricorsivamente il valore della posizione
                //chiamandola sull'altro giocatore
                valore = minimax(cambio_turno(giocatore));
                //Se sono il giocatore 1 cerco di massimizzare
                if (giocatore == 1 && valore > mossa_migliore)
                {
                    c.riga = i;
                    c.colonna = j;
                    mossa_migliore = valore;
                }
                //Se sono il giocatore -1 cerco di minimizzare
                if (giocatore == -1 && valore < mossa_migliore)
                {
                    c.riga = i;
                    c.colonna = j;
                    mossa_migliore = valore;
                }
                //Faccio backtracking
                tris[j] = 0;
            }
        }
   //Segno nella variabile globale la mossa da fare
   da_fare = c;
   //Ritorno il valore della posizione
   return mossa_migliore;
}

Link al commento
Condividi su altri siti

9 ore fa, claudio scrisse:

Quello che sospetto è che in un PLC la ricorsione di funzioni sia un processo "osteggiato" perchè potrebbe portare, se non controllato nella sua profondità, all'entrata in funzione del watch-dog del PLC, con gli effetti collaterali conseguenti 

 

Io credo che questo tipo di ricorsività non sia ammesso da molti compilatori proprio per le considerazioni che hai fatto tu.

Il rischio reale è di entrare in un loop infinito.

Queste "porcate"  sono sempre sconsigliate anche se alcuni linguaggi le permettono.

Se lo scrivi in AWL riesci a farlo senza problemi, così come con un micro lo si fa tranquillamente in asm.

Link al commento
Condividi su altri siti

Ancora una volta grazie, Livio.

Purtroppo l'AWL non lo conosco: magari vorrà dire che sarà l'occasione buona per studiarlo ...

Magari ti terrò informato se avrò fatto progressi significativi nel minimax !

Link al commento
Condividi su altri siti

Io comunque ripenserei all'organizzazione della funzione in modo da evitare di doverla richiamare al suo interno.

In certe situazioni rivaluto linguaggi come il Pascal che pur essendo noiosissimo (fu progettato da un professore svizzero tedesco) è veramente propedeutico perchè impedisce qualsisasi porcata. Non per niente il professore lo progettò come linguaggio didattico per studenti di informatica.

 

Il linguaggio AWL è una sorta di ASM per i PLC siemens; è un linguaggio 1 a 1, però ti permette di avere il contatto diretto con registri e risorse fisiche.

Link al commento
Condividi su altri siti

In effetti credo che SCL derivi dal Pascal e questo potrebbe confermare l'impossibilità di effettuare ricorsioni.

Tuttavia voglio andare a ricontrollare, più che altro per sfizio, alcuni listati che sottoponevo ai miei studenti una trentina di anni fa: questa discussione mi ha fatto venire in mente che allora implementavo il calcolo del fattoriale, funzione assolutamente ricorsiva, solo che non ricordo se usavo il Pascal o il C.

Qui la cosa si fa interessante, soprattutto visto il tuo suggerimento di ripensare alla funzione in modo di non doverla richiamare al suo interno: devo pensarci su ...

 

Link al commento
Condividi su altri siti

La ricorsione, cioè una funzione che richiama se stessa, è una tecnica comunemente usata nei più comuni linguaggi di programmazione (C, C++, C#, VB, ecc.) ed è utile in molti casi, esempio tipico sono vari algoritmi di ordinamento.

Sinceramente non so se con SCL mamma Siemens potrebbe darti problemi ma, teoricamente è possibile in tutti i linguaggi che danno la possibilità di utilizzare funzioni.

Naturalmente, lavorando su un plc, occorrerà fare molta attenzione per non saturare il tempo ciclo, cioè assicurare un punto di uscita ragionevolmente veloce e sicuro.

 

Link al commento
Condividi su altri siti

Facendo ricerche in rete ho trovato che a partire da TIA Portal 14 Siemens ha introdotto la possibilità di effettuare chiamate a blocchi ricorsivi.

Non so se è consentito, quindi prima lo chiedo: potrebbe essere di interesse che pubblichi il link alla pagina di Siemens dove si parla di questo e dalla quale è possibile scaricare un esempio ?

Buona giornata

 

Link al commento
Condividi su altri siti

14 ore fa, lucios scrisse:

La ricorsione, cioè una funzione che richiama se stessa, è una tecnica comunemente usata nei più comuni linguaggi di programmazione (C, C++, C#, VB, ecc.) ed è utile in molti casi, esempio tipico sono vari algoritmi di ordinamento.

 

QUesti linguaggi prevedono anche il "goto" però chi programma bene non lo usa.

Organizzando bene la funzione si può costruirla evitando il sempre pericoloso autorichiamo.

Link al commento
Condividi su altri siti

Sperando di non infrangere alcun regolamento del forum, riporto di seguito il link del quale avevo precedentemente scritto.

https://support.industry.siemens.com/tf/WW/en/posts/step-7-v14-simple-sample-recursive-block-calls/162015?page=0&pageSize=10

 

Ce n'è anche un altro che ho appena trovato che mi pare interessante ma non l'ho letto con attenzione

 

https://support.industry.siemens.com/tf/WW/en/posts/recursive-algorithm-with-plc-s7-1200/159279?page=0&pageSize=10

Link al commento
Condividi su altri siti

Quote

QUesti linguaggi prevedono anche il "goto" però chi programma bene non lo usa.

Organizzando bene la funzione si può costruirla evitando il sempre pericoloso autorichiamo.

Livio, stavolta non sono completamente d'accordo con te (benevomente beninteso...😉)

 

Il GOTO non è più così deprecato come in passato dai guru della programmazione, anche se a me personalmente non piace.

 

La ricorsione ti permette di risolvere in modo molto elegante e compatto situazioni che altrimenti ti costringerebbero a scrivere molte più righe di codice.

Immagina di dover implementare una funzione che deve fare qualcosa (ad es. cambiare le dimensioni di tutti i controlli label all'interno di controlli contenitore) e di volerla riutilizzare per diverse situazioni senza sapere a priori come sono organizzati i controlli stessi. Usando la ricorsione puoi iterare tutti i controlli all'interno dei contenitori anche se gli stessi sono contenuti in altri contenitori padri ecc.

Oppure di dover inserire testi nei menù a tendina di un'applicazione (ad es. per cambiare lingua), i quali menù hanno dei sottomenù con altri sottomenù. Con una semplice funzione ricorsiva di poche righe puoi farlo, altrimenti dovresti sapere a priori come sono organizzati i menù di ogni finestra ed in ogni caso non potresti applicarla genericamente ad ogni diversa finestra.

 

Link al commento
Condividi su altri siti

Concordo con Lucios, in informatica la ricorsione è usata in molte situazioni ed è un metodo elegante per risolvere problemi in maniera compatta e semplice, al contrario con i metodi iterattivi, anche se più efficienti, la risoluzione di alcuni problemi richiederebbe la scrittura di molto codice e in maniera complessa.

Link al commento
Condividi su altri siti

3 ore fa, lucios scrisse:

Il GOTO non è più così deprecato come in passato dai guru della programmazione, anche se a me personalmente non piace.

 

I così detti guru, quasi semrpe, è gente che fa solo teoria.

Io provengo dal Fortran, che è un classico "spaghetti like" proprio per le linee tracciate sui listati, linee necessarie per comprenderne i salti.

Poi imparai il PL1, che è un po' l'antenato di tutti gli strutturati e, finalmente compresi come si deve programmare per avere programmi ben comprensibili, facilmente debuggabili e... "riciclabili".

Un'ulteriore spinta verso l'ordine e lam razionalità mi venne dal Pascal.

Di porcate ne ho fatte tante con l'asm, anche del tipo di non ritornare da una sub dal punto di chiamata, ma effetturre il ritorno ad un indirizzo che è funzione del risultato di una certa operazione.

Però non ho mai avuto bisogno di richiamare una funzione all'interno della stessa.

Se la funzione la organizzi bene riesci a farla compatta e senza autorichiami.

Oltre 30 anni fa scrissi la mia prima ed unica funzione in Pascal per calcolare il fattoriale e proprio non ci fu bisogno dell'autorichiamo, anche perchè, se non ricordo male, il Pascal non lo permette.

 

Poi ognuno fa quello che ritiene meglio, secondo necessità, storia e cultura.

Non sono certo io quello che invoca il rogo per chi usca "goto" in "C" o scrive una funzione che si richiama (non mi piace il termine "ricorsivo" per questo tipo di lavoro).

Link al commento
Condividi su altri siti

Alle superiori (itis informatica) gran parte della teoria verniva studiata utilizzando come linguaggio di programmazione il Pascal, ricordo che la ricorsione fu un capito interessante e l'avevamo sperimentata, oltre classico calcolo dei fattoriali, anche per risolvere ad esempio il gioco della torre di Hanoi, oppure per trattare i frattali.

Ad esempio, anche in java si può far ricorso alla ricorsione, nonostante sia un linguaggio sicuro e robusto che non permette di effettuare, come dice Livio, alcune "porcate".

Link al commento
Condividi su altri siti

Sicuramente ci sono problemi che si risolvono meglio sfruttando la ricorsione, ma l'esempio del calcolo del fattoriale, secondo me, non è tra questi.
Risulta molto più semplice con un banale ciclo FOR.

Link al commento
Condividi su altri siti

2 ore fa, batta scrisse:

Risulta molto più semplice con un banale ciclo FOR

 

Certamente, ma anche altri problemi che sembrano risolvibili solo usando una funzione che richiama se stessa, se ben organizzati si possono risolvere differentemente, spesso usando funzioni di secondo livello o, magari coroutines. Alla fine l'algoritmo risulta più semplice ed ottimizzato ed è più facilmente riciclabile.

Almeno questa è la mia esperienza; poi, ripeto, ognuno ha le sue preferenze.

Link al commento
Condividi su altri siti

Ciao a tutti

Ho qualche novità sul mio esperimento di far giocare a tris il PLC usando un algoritmo ricorsivo.

Intanto confermo che con TIA Portal 14 si può scrivere codice ricorsivo.

Solo che, simulandolo, mi sono immediatamente accorto che l'algoritmo minimax restituisce si il codice di posizione corretto (mi sono per ora limitato a far fare la prima mossa al PLC, quindi avendo la griglia libera non è che poi si deve sforzare tanto...), ma lo fa in un tempo che va ben oltre il ciclo di scansione (ci mette diversi secondi).

Può certamente essere che abbia tradotto male dal C all'SCL il codice minimax e adesso ci guarderò meglio, tuttavia mi sa che il problema rimarrà.

Mi chiedo (e vi chiederei) se esiste una qualche istruzione che consente di ricaricare il watchdog da programma, perchè in un caso come questo ptrebbe essere utile poterla inserire dentro al codice ricorsivo e quindi annullare l'effetto, in questo caso nefasto, della ricorsione sul tempo di ciclo.

Vi ringrazio per il tempo che potrete dedicarmi

 

Link al commento
Condividi su altri siti

4 minuti fa, claudio scrisse:

se esiste una qualche istruzione che consente di ricaricare il watchdog da programma, perchè in un caso come questo ptrebbe essere utile poterla inserire dentro al codice ricorsivo e quindi annullare l'effetto, in questo caso nefasto, della ricorsione sul tempo di ciclo.

 

A parer mio il watch dog ha senso se è impostabile solo in sede di caricamento del programma.

Su alcuni processori è resettabile a livello di esecuzione di programma.

Comun que visto che sei ben conscio del pericolo di entrare in un loop infinito puoi escludere il watch dog alla partenza, quando carichi il progrmma.

Link al commento
Condividi su altri siti

Certo, non ci avevo pensato. Dal momento che non ho particolari sensori collegati da tenere sotto controllo (si tratta di un'applicazione a uso scolastico), penso che farò così.

Grazie mille, Livio

 

Link al commento
Condividi su altri siti

Ospite
Questa discussione è chiusa alle risposte.
×
×
  • Crea nuovo/a...