Closed dreamfalcon closed 4 years ago
Hello Daniel, Sothing like:
mb.readIreg(1, 121, au16data, 2);
Inddeed It looks like sligtly more complex because of FCT_READLOADPROFILE is not standard Modbus function. As all Modbus magic is hidden inside the library code implementation of this processing function should be added to Modbus.h masterPDU()
.
This gives timeout.
void loop() {
//OTA
ArduinoOTA.handle();
//webSocket
webSocket.loop();
//LED
handleLedBlink();
//MQTT
if (!client.connected()) {
checkMqttConnection();
}
//MODBUS
//handleState();
if (!mb.slave()) {
mb.readIreg(1, 108, au16data, 2, cbWrite);
}
mb.task();
//yield();
}
FCT_READLOADPROFILE appears to be "READ_INPUT_REGISTER": / For FCT_READSINGLEREGISTER the u16RegAdd depends on which register you want to get. Check the documentation for more info. The u16CoilsNo is 1 as in one output. You should always use this configuration for FCT_READSINGLEREGISTER / / For FCT_READLOADPROFILE the u16RegAdd is 769 (00000011 00000001 in binary) That means values 0x0003 and 0x0001" in hexadecimal: 0x0003 for Measumerent ID indexes to retrieve (1st - Clock 2nd -AMR Status and 3rd - Active Energy Import (A+)) 0x0001 for quantity of entries (we only need the last) The u16CoilsNo is 0 as we don't need any more inputs. You should always use this configuration for FCT_READLOADPROFILE /
ModbusRtu.h:
/**
* @enum MB_FC
* @brief
* Modbus function codes summary.
* These are the implement function codes either for Master or for Slave.
*
* @see also fctsupported
* @see also modbus_t
*/
enum MB_FC
{
MB_FC_NONE = 0, /*!< null operator */
MB_FC_READ_COILS = 1, /*!< FCT=1 -> read coils or digital outputs */
MB_FC_READ_DISCRETE_INPUT = 2, /*!< FCT=2 -> read digital inputs */
MB_FC_READ_REGISTERS = 3, /*!< FCT=3 -> read registers or analog outputs */
MB_FC_READ_INPUT_REGISTER = 4, /*!< FCT=4 -> read analog inputs */
MB_FC_WRITE_COIL = 5, /*!< FCT=5 -> write single coil or output */
MB_FC_WRITE_REGISTER = 6, /*!< FCT=6 -> write single register */
MB_FC_WRITE_MULTIPLE_COILS = 15, /*!< FCT=15 -> write multiple coils or outputs */
MB_FC_WRITE_MULTIPLE_REGISTERS = 16 /*!< FCT=16 -> write multiple registers */
};
Timeout may be result of hardware/wiring problems of long delay in checkMqttConnection() if connection is permanently unsuccesseful.
Anyway it's not possible to use FCT_READLOADPROFILE function without the library code modification. Easiest way i see that should work is to redefine (in Modbus.h)
FC_READ_REGS = 68, // Redefine Read Holding Registers
and drop verifications (in ModbusRTU.h):
uint16_t ModbusRTU::readHreg(uint8_t slaveId, uint16_t offset, uint16_t* value, uint16_t numregs, cbTransaction cb) {
// if (numregs < 0x0001 || numregs > maxRegs) return false;
readSlave(offset, numregs, FC_READ_REGS);
return send(slaveId, HREG(offset), cb, value);
}
and (again in Modbus.h):
switch (fcode) {
case FC_READ_REGS:
case FC_READ_INPUT_REGS:
//field2 = numregs, frame[1] = data lenght, header len = 2
// if (frame[1] != 2 * field2) { //Check if data size matches
// _reply = EX_DATA_MISMACH;
// break;
// }
if (output) {
frame += 2;
while(field2) {
*((uint16_t*)output) = __bswap_16(*((uint16_t*)frame));
frame += 2;
output += 2;
field2--;
}
} else {
setMultipleWords((uint16_t*)(frame + 2), startreg, field2);
}
break;
Afrer that you can call
mb.readHreg(1, 769, &buffer, 0, cb);
as FCT_READLOADPROFILE (but for normal usage readHreg will be broken).
Hi,
I'm very new at this low level stuff, but managed to read some values from this setup: esp8266<->TTL to RS485 Converter<->Energy Counter
The code was based on this links that are using a old library, "Modbus-Master-Slave-for-Arduino": https://github.com/edphackathon/EDPIoTHackathon2017/blob/master/src/examples/EDPComm_example/EDPComm_example.ino https://github.com/edphackathon/EDPIoTHackathon2017/blob/master/src/EDPComm-Hackathon-2017/EDPComm.cpp
Special this part:
I was trying to convert to this library, but have some doubts: Where I have
Should be something like this?
Thx