Uso de la placa IoT-02 como dispositivo ModBus-RTU esclavo

De binefa.com
Salta a la navegació Salta a la cerca

Puesta en marcha

Bibliotecas en Python necesarias para ejecutar el ejemplo de programa para leer y escribir a ModBus RTU

Código en Python para la lectura ModBus RTU (en GitHub) de la placa IoT-02 programada con un código ModBus RTU maestro (en GitHub).

ModBus

Código en Python

Ejecución:

./mb_IoT_00_windows.py COM3 4800

o

./mb_IoT_00.py /dev/ttyUSB1 4800

Puerto y velocidad como argumento

class ModBus():
	def __init__(self, parent=None):
		self.tipus = 0
		if len( sys.argv ) == 2 :
			szPort = sys.argv[1]
			nBauds = 115200
		else :
			if len( sys.argv ) == 3 :
				szPort = sys.argv[1]
				nBauds = int(sys.argv[2])
			else :
				szPort = "/dev/ttyUSB0"
				nBauds = 4800
		port = szPort
		baudrate = nBauds	
		print("Baudrate: %d at %s"%(baudrate,port))
		self.ser = 0
		self.t = 0	
		try: 	
			self.ser = serial.Serial(
				port,
				baudrate,
				timeout=0,
				parity=serial.PARITY_NONE,
				stopbits=serial.STOPBITS_TWO,
				bytesize=serial.EIGHTBITS
			)
			self.nSegonsTimer = 0.2
			self.t = Timer(self.nSegonsTimer,self.temporitzador)
			self.t.start()
			k = KeyGetter()
			self.bLoop = True
			while self.bLoop == True:
				if k.kbhit():
					cKey = repr(k.getch(False))
					self.processaTecla(cKey[1])
				sleep(0.1)
			self.bye()

Órdenes ModBus de escritura

	def writeCommand(self,command):
		hCRC = hexCRC(command)
		addedCRC="%c%c"%(hCRC>>8,hCRC&0xFF)
		command += addedCRC
		for cmd_byte in command:
			hex_byte = ("{0:02X}".format(ord(cmd_byte)))
			print (hex_byte,end=)
			self.ser.write(bytearray.fromhex(hex_byte))
		print("")

Órdenes ModBus de lectura

	def lecturaMB(self,q):
		# print("%s" % q)
		if q == 'relaySet':
			print("{\nSending: Relay SET")
			stMB = "%c%c%c%c%c%c"%(0x07,0x05,0x00,0x04,0xFF,0x00)
			self.writeCommand(stMB)
		if q == 'relayReset':
			print("{\nSending: Relay RESET")
			stMB = "%c%c%c%c%c%c"%(0x07,0x05,0x00,0x04,0x00,0x00)
			self.writeCommand(stMB)
		if q == 'input':
			print("{\nSending: Reading 4 coils")
			stMB = "%c%c%c%c%c%c"%(0x07,0x02,0x00,0x00,0x00,0x04)
			self.writeCommand(stMB)
		if q == 'temperature':
			print("{\nSending: Reading temperature")
			stMB = "%c%c%c%c%c%c"%(0x07,0x03,0x00,0x00,0x00,0x01)
			self.writeCommand(stMB)

Lectura de la respuesta ModBus del dispositivo

Lectura del puerto serie cada 200ms ( self.nSegonsTimer = 0.2 ):

	def temporitzador(self): 
		data = self.ser.read(1)
		n = self.ser.inWaiting()
		if n:
			n = 1 + n
			data = data + self.ser.read(n)
 		if len(data):
			self.processa(data,n)
			print("} ----")

Función principal

if __name__ == '__main__':
	print("s: Relay SET, r: Relay RESET, i: Read inputs, t: temperature, h: relative humidity, p: pressure, a: altitude, v: VOC and q: quit")
	mb = ModBus()

Código del ESP32 en el IDE de Arduino

IoT-02_11_modbus_bme280.ino en GitHub

#include "IoT-02_modbus.h"
HardwareSerial modbusData(2);
#define MODBUS_BAUD_RATE 4800

Parámetros ModBus en IoT-02_modbus.h

IoT-02_modbus.h en GitHub

#define MODULE_ADDRESS 0x07
#define COIL_RELAY_ADDRESS 0x0004
#define COIL_INPUTS_ADDRESS 0x0000
#define HOLDING_REGISTER_TEMEPRATURE_ADDRESS 0x0000
#define HOLDING_REGISTER_REL_HUMIDITY_ADDRESS 0x0001
#define HOLDING_REGISTER_PRESSURE_ADDRESS 0x0002
#define HOLDING_REGISTER_ALTITUDE_ADDRESS 0x0003
#define HOLDING_REGISTER_VOC_ADDRESS 0x0004

setup()

void setup() {
 Wire.begin(I2C_SDA, I2C_SCL);
 vSetupIO();
 vSetupScreen();
 vSetupModBus(MODBUS_BAUD_RATE);
 Serial.begin(115200);
 Serial.println(__FILE__);
 vSetupBME280();
}

Función vModBusReading() llamada en loop()

IoT-02_modbus.cpp en GitHub

void vModBusReading() {
 int i, nCmpt = 0;
 unsigned int uiCRC;
 byte uiCrcL, uiCrcH;
 unsigned char ucSt[N_MAX];
 while (modbusData.available() > 0) {
   ucSt[nCmpt] = (unsigned char)modbusData.read();
   nCmpt++;
   delay(2);
 }
 if (nCmpt) {
   Serial.print("He leído estos "); Serial.print(nCmpt); Serial.println(" bytes: ");
   for (i = 0; i < nCmpt; i++) {
     Serial.print(ucSt[i], HEX); Serial.print(" ");
   }
   Serial.println();
   uiCRC = uiModRTU_CRC(ucSt, nCmpt - 2);'
   if ((byte)(uiCRC >> 8) == ucSt[nCmpt - 1] && (byte)(uiCRC & 0xFF) == ucSt[nCmpt - 2]) {
     Serial.println("Trama con CRC correcto");
     vProcessa(ucSt, nCmpt);
   } else {
     Serial.println("Trama con CRC incorrecto");
   }
 }
 nCmpt = 0;
}