Vai al contenuto
PLC Forum


Da Puntatori A Db


Frank681

Messaggi consigliati

Salve

Dovre spostare dei valori da un puntatore di 48 dw in memoria a delle struct composte da 48 dword in un db , tutto questo devo ripeterlo x 20 volte e' possibile fare un fb in scl ? Mi date un indizio che poi lo sviluppo..

Grazie mille

Link al commento
Condividi su altri siti


Puoi usare l'istruzione MOVE.

Questa istruzione non copia solo byte, word e dword, ma anche timer, counter, stringhe, array e strutture.

Unica cosa importante è che l'area sorgente e quella di destinazione devono essere identiche, ovvero non basta che abbiano la stessa dimensione, ma devono avere anche la stessa identica struttura.

Ora non ho ben capito cosa tu intenda con "memorizzare dei valori 48 dword di un puntatore in memoria" ma, se queste 48 dword possono essere dichiarate all'interno di una STRUCT, ti basta dichiarare come area di destinazione un array di 20 STRUCT identiche a quella sorgente.

Nell'istruzione MOVE, in uscita, puoi usare all'interno delle parentesi quadre una variabile (di tipo INT o DINT) con la quale vai ad indicare in quale struttura dell'array scrivere.

Modificato: da batta
Link al commento
Condividi su altri siti

Ciao STEU

Chiedo aiuto poiché e' la prima volta che lavoro con i puntatori

Leggo dei valori da degli strumenti modbus tcp ( ne ho 20 ) , ogni strumento mi restituisce i valori in un puntatore

P#M1000.0 DWROD 120 , vorrei alla fine della lettura spostare i valori delle variabili , in una struct di un db , parlo di 20 perché; ho 20 strumenti che mi restituiscono i valori nello stesso puntatore per cui prima di passare alla lettura successiva devo salvare i valori letti nel db .

Spero di essere stato chiaro , e mi scuso per la confusione

Link al commento
Condividi su altri siti

Scusami ma non ho capito moltissimo,

comunque esiste sfc 20 "Blockmove" , che ti copia il i valori dal parametro dove vuoi tu

CALL "BLKMOV"

SRCBLK :=P#M 100.0 DWORD 150

RET_VAL:=MW10

DSTBLK :=P#DB10.DBX 0.0 DWORD 150

la risposta mi sembra troppo facile per aver capito esattamente cosa vuoi.

Link al commento
Condividi su altri siti

Infatti
Amche nel 1200 esiste un bloc_move ma mi Sto arrivando! Diverso

Forse trovato usando poke_move , devo verificare esattamente i settaggi e gli offset fatte prove al volo su cpu di test ok , domani provo su cpu di progetto.

Modificato: da Frank681
Link al commento
Condividi su altri siti

Ciao Batta

Le variabile che leggo via modbus TCP , sono di tipo Real , ho provato a memorizzarle direttamente nel DB ma non mi funziona , per fare delle prove ho provato a leggere i dati con CAS modbus scanner e ho notato una cosa strana , leggo gli indirizzi 40001 ma il primo valore Real è nel registro 40002 , à normale ?

Chiedo poichè non ho mai letto direttamente le dword .

Può essere per questo che se provo a memorizzare i dati direttamente nell struct del db ho valori incomprensibili .

Ho paura che ci sia uno sfasamento nella lettura , domani provo a leggere il registro 40002 e vedere se i dati si allineano .

La cosa mi è poco chiara... :wallbash:

forse trovato usando poke_move devo verificare i settaggi da effettuare

Modificato: da Frank681
Link al commento
Condividi su altri siti

leggo gli indirizzi 40001 ma il primo valore Real è nel registro 40002 , à normale ?

I registri Modbus sono a 16 bit (2 byte).

Una REAL è composta da 4 byte.

Una REAL quindi occupa due registri. Forse devi scambiare tra loro i registri 40001 e 40002.

Per quanto riguarda poi la copia delle 48 variabili dall'area in cui vengono depositate dalla funzione MB_MASTER, devi solo procedere come ti ho indicato nel precedente post.

Per fare questo, devi apportare una piccola modifica: anziché depositare i registri letti nell'area di memoria M (P#M1000.0 DWROD 120), utilizzi un DB.

Il DB in questione deve essere "non ottimizzato" (tasto destro sul DB --> Proprietà --> Attributi --> Togli il segno di spunta da "accesso ottimizzato al blocco").

In questo DB crei una STRUCT con le tue 48 REAL.

Nel DB dove andrai a scrivere i dati di ogni singolo strumento crei un ARRAY di 20 STRUCT identiche (potresti anche creare un "Tipo di dati" da usare in entrambi i DB).

Poi ti basta usare l'istruzione MOVE, con un indice per indicare in quale struttura dell'array andare a scrivere.

In base al numero di nodo dal quale hai appena fatto la lettura dei registri, imposti questo indice ed hai già risolto, senza complicarti la vita con poke ed altro.

Link al commento
Condividi su altri siti

Grazie Batta

Provo e ti faccio sapere , infatti ho sperimentato la scrittura diretta in un DB partendo da 40002 e funziona ora devo solo capire la lunghezza da leggere che dipende dagli strumenti.

Grazie mille :thumb_yello:

Link al commento
Condividi su altri siti

Ciao Batta

Ho provato ad usare un db , non ottimizzato con dentro le struct che mi servono

e la seguente procedura di lettura modbus

ma i dati nelle struct mi cambiano sempre ad ogni lettura .
Ho provato a cambiare MB_UNIT_ID del db di istanza per puntare ad ogni singolo slave TCP poiché ne ho piu' di uno con lo steppo indirizzo IP
uso il done e error per avanzare , il segnmento che vedi e' una lettura per ogni lettura cambio MB_UNIT_ID e struct dove scrivere , ma si influenzano ....
Dove sbaglio ? :wallbash:
Link al commento
Condividi su altri siti

A quanto vedo tu stai trasferendo 67 registri letti dallo strumento con indirizzo IP 192.168.1.110 in "MOD_TCP_PARK".GEN

Non capisco perché l'indirizzo IP sia fisso e non capisco perché tu vada a caricare un valore in "MB_CLIENT".MB_UNIT_ID.

Dalla guida in linea:

Un server Modbus TCP viene indirizzato dall'indirizzo IP. Per questo motivo il parametro MB_UNIT_ID non viene utilizzato per l'indirizzamento Modbus TCP.

Quindi per puntare ai diversi strumenti non devi modificare MB_UNIT_ID ma l'indirizzo IP (a meno che tu non stia usando un qualche gateway per comunicare in MODBUS RTU).

Per quanto riguarda il DB non ottimizzato (e qui penso di aver detto una cavolata, perché sono quasi sicuro che potrebbe anche essere ottimizzato) mi riferivo al DB dove vai ad appoggiare i dati letti, ovvero "MOD_TCP_PARK".GEN

In questo DB, GEN dovrebbe essere una struttura di dimensioni adatte a contenere il numero più alto di registri letti da uno strumento (non so se leggi lo stesso numero di registri da ogni strumento. Se torniamo al discorso delle 48 REAL, i registri dovrebbero essere 96).

Poi dovrai fare un altro DB (ma potrebbe anche essere lo stesso DB) con un array di 20 strutture identiche a GEN.

A seconda del ciclo di lettura MODBUS completato, copierai i dati parcheggiati in "MOD_TCP_PARK".GEN nell'area definitiva impostando opportunamente l'indice dell'array.

Link al commento
Condividi su altri siti

Ciao Batta

In effetti il GAVAZZI VMUC-EM è un accentratore concentratore gateway , a cui sono collegati gli strumenti in RTU , lo "SCATOLOTTO" me li rende disponibili in TCP , per cui ho piu' slave TCP da leggere tramite un unico IP , cambiando il valore MB_UNIT_ID , trovato nel manuale di sistema del 1200 pag 759.

Mi permane il problema che mi cambiano tutti i dati .

Fatto prove assegnando ad ogni MB_UNIT_ID un MB_CLIENT con db di istanza diversa e un CONNECT_ID diverso , ora tutto funziona , ma se faccio cosi' per 20 strumenti saturo le connessioni del PLC.

qualche suggerimento

Usando un gateway , devo programmare in modo diverso ?

Link al commento
Condividi su altri siti

Mi permane il problema che mi cambiano tutti i dati .

Non capisco cosa intendi.

Cambiando il numero di nodo (MB_UNIT_ID) dovresti leggere i dati dallo strumento interessato. Questi dati vengono scritti dalla funzione MB_CLIENT in "MOD_TCP_PARK".GEN.

Ovviamente, ad ogni ciclo di lettura in "MOD_TCP_PARK".GEN troverai dati diversi perché è cambiato lo strumento dal quale sono stati letti.

Alla fine della lettura, prima di iniziare la lettura successiva, dovrai copiare i dati dall'area di "parcheggio" "MOD_TCP_PARK".GEN nell'area definitiva utilizzando l'istruzione MOVE.

Oppure, se devi leggere valori da strumenti con numero di nodo da 1 a 20 potresti creare un DB con un array di 20 strutture (array[1..20]of struct) con le variabili di cui hai bisogno.

I dati letti da MB_CLIENT li potresti scrivere direttamente nella struttura desiderata, collegando al parametro MD_DATA_PTR la struttura con tanto di indice dell'array (esempio: "DB_ProvaModbus".Strumento[#id]).

Non ti serve nemmeno usare l'istruzione MOVE.

Il DB credo debba essere di tipo "non ottimizzato", ma non ne sono del tutto sicuro.

Link al commento
Condividi su altri siti

Ciao Batta

Confermo il db non vuole ottimizzato

il mio problema e che anche se copio i dati con il move dalla struct di parcheggio alla struct del DB definitivo con il done della lettura , alla lettura sucessiva con MB|_UNIT_ID divers oi dati mi cambiano tutti nel db definitivo non so come far si che i dati vengano copiati una sola volta dalla zona di parcheggio al db definitivo .

per ogni diverso MV_UNIT_ID nel db definitivo mi cambiano tutti i dati

Link al commento
Condividi su altri siti

Per darti indicazioni dovrei vedere tutto il codice.

Comunque, puoi sempre eseguire il MOVE su un fronte di salita.

Link al commento
Condividi su altri siti

Ciao BAtta

Provato niente da fare , se vuoi posso fare upload del codice che mi da problemi , lo sto testando anche su una cpu di scorta

Link al commento
Condividi su altri siti

il problema e ' che stai sovrascrivendo i dati ad ogni ciclo

O usi dei fronti di salita per fare le operazioni solo una volta sola oppure usi dei bit di memoria tipo macchina a stati finiti per tenere traccia di cosa stai facendo e di cosa devi fare Se la comunicazione e' asincrona basta che guardi bene cosa fai quando leggi i dati e dove li metti , se invece e' sincrona puo darsi che mentre stai salvando i dati da qualche parte , la comunicazione te li sovrascrive .Ma comunque queste comunicazioni sono del tipo asincrono per cui usa dei bit per tenere traccia delle operazioni da fare e per sincronizzare un po il tutto

Per i puntatori ne puoi usare migliaia , asta che siano varaibili DWORD , l'accesso e' piu lento rispetto ai registri della cpu dedicati ma non importa .Puoi copiare quindi il contenuto di un puntatore su variabili globali , usane altri e poi ripescarli

Modificato: da walterword
Link al commento
Condividi su altri siti

Ciao walterword

Le operazioni le faccio solo se ho un indice che vado ad incrementare quando ho il done della lettura , ma niente da fare , quando ho il done faccio il move della struct dal db di parcheggio a quello definitivo ma niente da fare..

non so dove sbaglio

Link al commento
Condividi su altri siti

Per ora ho dato solo un'occhiata veloce al codice che mi hai inviato.

Ho subito notato un piccolo errore: la struttura dove vai a scrivere i dati è formata da 34 REAL, ma tu leggi solo 67 registri (che sono da 16 bit). Ne manca uno.

Non è comunque questo il problema.

Mi lascia molto perplesso piuttosto il fatto che a REQ hai linkato un TRUE.

Praticamente cambi al volo il nodo, senza mai interrompere un ciclo di lettura.

Non ne sono completamente sicuro ma, secondo me, potrebbe essere questa l'origine del problema.

Di certo è difficile capire quando il DONE è veritiero.

Non capisco poi come tu riesca ad incrementare l'indice dello strumento dal quale leggere i dati.

Io ho visto scritture in questa variabile solo se viene rilevato un errore, mai nel caso di lettura ok (DONE).

Domani o lunedì, se trovo un po' di tempo, provo a buttare giù un esempio di come farei io.

Link al commento
Condividi su altri siti

Ciao Batta

Hai ragione nel cancellare ho cancellato troppo , nel segmento 4 vi era anche il move dell'indice.

Il done va via da solo poichè quando ho il done cambio indice , all'inizio avevo provato anche il REQ con l'eguaglianza dell'indice ma il problema persiste..

Grazie mille

Link al commento
Condividi su altri siti

Giuseppe Signorella

Hai provato l'esempio che ti ho inviato?

Perchè non condividerlo sul forum, e due parole pse spiegarlo? ;)

Modificato: da Giuseppe Signorella
Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...