Uso de la placa IoT-02 como dispositivo ModBus-RTU esclavo
Salta a la navegació
Salta a la cerca
Puesta en marcha
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).
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
#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()
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;
}
