From cfb6a0c291eaddfc68dc6578e3faeeee65685f1f Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Thu, 28 Oct 2021 19:23:03 +0200 Subject: [PATCH] Bozza metodo scrittura modbus (da testare da ufficio) --- IOB-WIN-NEXT/IobModbusTCP.cs | 367 ++++++++++++----------------------- 1 file changed, 129 insertions(+), 238 deletions(-) diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index 5330dc05..22c4281d 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -133,7 +133,7 @@ namespace IOB_WIN_NEXT /// /// /// - private static double convertVal(int[] listInt, int size, plcDataType tipoMem) + private static double convertFromReg(int[] listInt, int size, plcDataType tipoMem) { double valore = 0; //verifico se sia INT o real x convertire... @@ -165,6 +165,58 @@ namespace IOB_WIN_NEXT return valore; } + /// + /// Converte valore reale nel tipo desiderato in forma di int[] adatti a scrivere nei registri + /// + /// + /// + /// + /// + private static int[] convertToReg(object origVal, int size, plcDataType tipoMem) + { + int[] answ = new int[2]; + //verifico se sia INT o real x convertire... + switch (tipoMem) + { + case plcDataType.Real: + if (size == 4) + { + answ = ModbusClient.ConvertDoubleToRegisters((double)origVal); + } + else if (size == 2) + { + answ = ModbusClient.ConvertFloatToRegisters((float)origVal); + } + break; + + case plcDataType.Int: + default: + if (size == 4) + { + answ = ModbusClient.ConvertLongToRegisters((long)origVal); + } + else if (size == 2) + { + answ = ModbusClient.ConvertIntToRegisters((int)origVal); + } + break; + } + return answ; + } + + private static double getScaledDouble(dataConf currMem) + { + double valDouble; + // prima faccio eventuale fattore di scala... + double.TryParse(currMem.value, out valDouble); + if (currMem.factor > 1) + { + valDouble = valDouble * (double)currMem.factor; + } + + return valDouble; + } + private static int getScaledInt(dataConf currMem) { int valInt; @@ -219,13 +271,13 @@ namespace IOB_WIN_NEXT case modBusAddrType.InputRegister: listInt = readInputReg(item.Value.index, item.Value.size); - valore = convertVal(listInt, item.Value.size, item.Value.tipoMem); + valore = convertFromReg(listInt, item.Value.size, item.Value.tipoMem); break; case modBusAddrType.HoldingRegister: listInt = readHoldReg(item.Value.index - 1, item.Value.size); - valore = convertVal(listInt, item.Value.size, item.Value.tipoMem); + valore = convertFromReg(listInt, item.Value.size, item.Value.tipoMem); break; default: @@ -307,10 +359,9 @@ namespace IOB_WIN_NEXT /// protected override void plcWriteParams(ref List updatedPar) { -#if false dataConf currMem = null; int byteSize = 0; - byte[] MemBlock = new byte[1]; + int[] CurrVal = new int[1]; string memAddrWrite = ""; bool fatto = false; string serObj = ""; @@ -324,6 +375,7 @@ namespace IOB_WIN_NEXT memAddrWrite = ""; int valInt = 0; uint valUInt = 0; + double valDouble = 0; // cerco in area memMapWrite... if (memMap.mMapWrite.ContainsKey(item.uid)) { @@ -331,7 +383,7 @@ namespace IOB_WIN_NEXT currMem = memMap.mMapWrite[item.uid]; byteSize = currMem.size; memAddrWrite = currMem.memAddr; - MemBlock = new byte[byteSize]; + CurrVal = new int[byteSize]; // faccio preliminarmente upsertKey... upsertKey(currMem.name, currMem.value); serObj = JsonConvert.SerializeObject(item, Formatting.Indented); @@ -345,45 +397,47 @@ namespace IOB_WIN_NEXT case plcDataType.Int: valInt = getScaledInt(currMem); - saveIntOnMemBlock(ref MemBlock, 0, valInt.ToString()); + CurrVal = convertToReg(valInt, 2, plcDataType.Int); + fatto = writeInputReg(currMem.index, CurrVal); break; case plcDataType.DInt: - valInt = getScaledInt(currMem); - saveDIntOnMemBlock(ref MemBlock, 0, valInt.ToString()); + valUInt = getScaledUInt(currMem); + CurrVal = convertToReg(valInt, 4, plcDataType.Int); + fatto = writeInputReg(currMem.index, CurrVal); break; - case plcDataType.Word: - valUInt = getScaledUInt(currMem); - saveWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); - break; + //case plcDataType.Word: + // valUInt = getScaledUInt(currMem); + // saveWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); + // break; - case plcDataType.DWord: - valUInt = getScaledUInt(currMem); - saveDWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); - break; + //case plcDataType.DWord: + // valUInt = getScaledUInt(currMem); + // saveDWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); + // break; case plcDataType.Real: - saveRealOnMemBlock(ref MemBlock, 0, currMem.value); + valDouble = getScaledDouble(currMem); + CurrVal = convertToReg(valInt, 2, plcDataType.Real); + fatto = writeInputReg(currMem.index, CurrVal); break; - case plcDataType.String: - // se ho writePre --> "allungo" di 2 la dimensione della stringa x MemBlock... - if (writePre) - { - MemBlock = new byte[byteSize + 2]; - } - saveStringOnMemBlock(ref MemBlock, 0, currMem.size, currMem.value); - break; + //case plcDataType.String: + // // se ho writePre --> "allungo" di 2 la dimensione della stringa x MemBlock... + // if (writePre) + // { + // MemBlock = new byte[byteSize + 2]; + // } + // saveStringOnMemBlock(ref MemBlock, 0, currMem.size, currMem.value); + // break; default: break; } - lgInfo($"---------------MemBlock data---------------{Environment.NewLine}{BitConverter.ToString(MemBlock)}{Environment.NewLine}--------------- END data ---------------"); + lgInfo($"---------------MemBlock data---------------{Environment.NewLine}CurrVal: {CurrVal}{Environment.NewLine}--------------- END data ---------------"); if (!string.IsNullOrEmpty(memAddrWrite)) { - // scrivo su ModBusTCP - fatto = S7WriteBB(ref MemBlock, memAddrWrite); // se fatto --> aggiorno! if (fatto) { @@ -391,6 +445,7 @@ namespace IOB_WIN_NEXT item.reqValue = ""; item.lastRead = DateTime.Now; } +#if false // se configurato faccio verifica write... if (getOptPar("WRITE_CHECK") == "TRUE") { @@ -406,6 +461,7 @@ namespace IOB_WIN_NEXT lgInfo($"Scrittura corretta: {BitConverter.ToString(MemBlockRead)}"); } } +#endif } else { @@ -423,7 +479,6 @@ namespace IOB_WIN_NEXT } } } -#endif } /// @@ -849,214 +904,6 @@ namespace IOB_WIN_NEXT } } -#if false - /// - /// wrapper chiamata LETTURA in blocco MULTI BYTE dell'area read DI DEFAULT... - /// - /// - /// - public bool S7ReadBB(ref byte[] Value) - { - return S7ReadBB(ref Value, parametri.memAddrRead, parametri.memSizeRead); - } - - /// - /// wrapper chiamata LETTURA in blocco MULTI BYTE... - /// - /// MATRICE valori letti - /// Area memoria da leggere... - /// Numero byte da leggere - /// - public bool S7ReadBB(ref byte[] Value, string memAddrRead, int numByte) - { - bool answ = false; - if (Value != null) - { - sw.Restart(); - parentForm.commPlcActive = true; - parentForm.commPlcActive = false; - sw.Stop(); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("{0}|{1}", parametri.memAddrRead, numByte), sw.ElapsedTicks); - } - } - return answ; - } - - /// - /// wrapper chiamata LETTURA in blocco MULTI BYTE... default size a parametri.memSizeRead - /// - /// - /// Area memoria da leggere... - /// - public bool S7ReadBB(ref byte[] Value, string memAddrRead) - { - bool answ = false; - answ = S7ReadBB(ref Value, memAddrRead, parametri.memSizeRead); - return answ; - } - - /// - /// wrapper chiamata SCRITTURA in blocco MULTI BYTE, DI DEFAULT su area configurata x scrittura CONTINUA... - /// - /// - /// - public bool S7WriteBB(ref byte[] Value) - { - return S7WriteBB(ref Value, parametri.memAddrWrite); - } - - /// - /// Override scrittura in area DBB - /// - /// - /// - /// - public bool S7WriteBB(ref byte[] Value, string memAddrWrite) - { - bool answ = false; - if (Value == null) - { - lgError($"Errore in S7WriteBB: Value è null"); - } - else - { - if (string.IsNullOrEmpty(memAddrWrite)) - { - lgError($"Errore in S7WriteBB: memAddrWrite è vuoto"); - } - else - { - sw.Restart(); - sw.Stop(); - } - } - return answ; - } - - /// - /// Override scrittura in area DBB - /// - /// Valore byte[] da scrivere - /// Numero del DB (es 700 per DB700) - /// Indice interno al datablock del byte da cui partire - /// - public bool S7WriteBB(ref byte[] Value, int DbNum, int IndiceMem) - { - bool answ = false; - if (Value == null) - { - lgError($"Errore in S7WriteBB: Value è null"); - } - else - { - if (DbNum < 0 || IndiceMem < 0) - { - lgError($"Errore in S7WriteBB | DbNum: {DbNum} | IndiceMem: {IndiceMem}"); - } - else - { - sw.Restart(); - sw.Stop(); - } - } - return answ; - } -#endif - - /// - /// Salvo in memblock il valore Int indicato con formattazione ModBus TCP - /// - /// Blocco memoria come byte[] dove scrivere - /// Posizione inizio scrittura - /// valore da scrivere - public void saveIntOnMemBlock(ref byte[] MemBlock, int startPos, string valore) - { - try - { - short valInt = 0; - short.TryParse(valore, out valInt); - byte[] strByte = S7.Net.Types.Int.ToByteArray(valInt); - int byteLen = 2; - Buffer.BlockCopy(strByte, 0, MemBlock, startPos, byteLen); - //var verifica = S7.Net.Types.String.FromByteArray(MemBlock); - } - catch (Exception exc) - { - lgError($"Errore in gestione scrittura INT {valore} alla posizione {startPos} byte{Environment.NewLine}{exc}"); - } - } - - /// - /// Salvo in memblock il valore Int indicato con formattazione ModBus TCP - /// - /// Blocco memoria come byte[] dove scrivere - /// Nome del parametro da recuperare da prodData x scrivere - /// Posizione inizio scrittura - public void saveIntOnMemBlock(ref byte[] MemBlock, string stringKey, int startPos) - { - if (currProdData.ContainsKey(stringKey)) - { - try - { - string valore = currProdData[stringKey]; - saveIntOnMemBlock(ref MemBlock, startPos, valore); - } - catch (Exception exc) - { - lgError($"Errore in gestione scrittura INT {stringKey}{Environment.NewLine}{exc}"); - } - } - } - - /// - /// Salvo in memblock il valore stringa indicato con formattazione ModBus TCP - /// - /// Blocco memoria come byte[] dove scrivere - /// Posizione inizio scrittura - /// Valore scrivere - public void saveRealOnMemBlock(ref byte[] MemBlock, int startPos, string valore) - { - try - { - byte[] stringPar = new byte[2]; - - double valReal = 0; - double.TryParse(valore, out valReal); - byte[] strByte = S7.Net.Types.Double.ToByteArray(valReal); - int byteLen = 4; - Buffer.BlockCopy(strByte, 0, MemBlock, startPos, byteLen); - //var verifica = S7.Net.Types.String.FromByteArray(MemBlock); - } - catch (Exception exc) - { - lgError($"Errore in gestione scrittura REAL {valore} alla posizione {startPos} byte{Environment.NewLine}{exc}"); - } - } - - /// - /// Salvo in memblock il valore stringa indicato con formattazione ModBus TCP - /// - /// Blocco memoria come byte[] dove scrivere - /// Valore scrivere - /// Posizione inizio scrittura - public void saveRealOnMemBlock(ref byte[] MemBlock, string stringKey, int startPos) - { - if (currProdData.ContainsKey(stringKey)) - { - try - { - string valore = currProdData[stringKey]; - saveRealOnMemBlock(ref MemBlock, startPos, valore); - } - catch (Exception exc) - { - lgError($"Errore in gestione scrittura REAL {stringKey}{Environment.NewLine}{exc}"); - } - } - } - /// /// Effettua salvataggio in LUT del valore ricevuto (double) /// @@ -1181,6 +1028,50 @@ namespace IOB_WIN_NEXT } } + /// + /// Scrittura di un singolo valore COIL (1...) + /// + /// + /// + /// + public bool writeCoil(int startAddr, bool currValue) + { + bool answ = false; + if (currPLC.Connected) + { + try + { + currPLC.WriteSingleCoil(startAddr, currValue); + answ = true; + } + catch + { } + } + return answ; + } + + /// + /// Scrittura di un valore Input Register (4...) + /// + /// + /// Valore in formato INT da registri + /// + public bool writeInputReg(int startAddr, int[] currRegVal) + { + bool answ = false; + if (currPLC.Connected) + { + try + { + currPLC.WriteMultipleRegisters(startAddr, currRegVal); + answ = true; + } + catch + { } + } + return answ; + } + #endregion Public Methods } } \ No newline at end of file