meta data for this page
LamaPLC: Arduino code collection
Modbus code collection
Convert 2 registers to float
call: [float] = modbus_2regs_2_float([1.register], [2.register])
float modbus_2regs_2_float(uint16_t a, uint16_t b) { uint32_t combined = ((uint32_t)a << 16) | b; float f; memcpy(&f, &combined, sizeof f); return f; }
call: [float] = modbus_2regs_2_float([first register])
float modbus_2regs_2_float(uint16_t addr) { uint16_t a = node.getResponseBuffer(addr); uint16_t b = node.getResponseBuffer(addr+1); uint32_t combined = ((uint32_t)a << 16) | b; float f; memcpy(&f, &combined, sizeof f); return f; }
Convert float 2 registers
def: int16_t regs[2];
call: modbus_set_float([float], regs);
back: register1: regs[1], register2: [regs[2]
void modbus_set_float(float f, uint16_t *dest) { uint32_t i = 0; memcpy(&i, &f, sizeof(uint32_t)); dest[0] = (uint16_t)i; dest[1] = (uint16_t)(i >> 16); }Source: https://docs.ros.org/en/melodic/api/libmodbus/html/modbus-data_8c.html
Convert 2 registers to int32
uint32_t make_32bit_word(uint16_t hi_word, uint16_t lo_word) { uint16_t words_16bit[2] = {hi_word, lo_word}; uint32_t word_32bit = 0; memcpy(&word_32bit, words_16bit, 4); return word_32bit; }
int32 convert direct to float by division by a thousand:
float make_float_32bit_word(uint16_t hi_word, uint16_t lo_word) { uint16_t words_16bit[2] = {hi_word, lo_word}; uint32_t word_32bit = 0; float back; memcpy(&word_32bit, words_16bit, 4); back = word_32bit / 1000.0; return back; }
call: [float] = make_float_32bit_word([first reg])
float make_float_32bit_word(uint16_t addr) { uint16_t words_16bit[2]; words_16bit[1] = node.getResponseBuffer(addr); words_16bit[0] = node.getResponseBuffer(addr+1); uint32_t word_32bit = 0; float back; memcpy(&word_32bit, words_16bit, 4); back = word_32bit / 1000.0; return back; }
Float to / from one register
Note: The maximum value of the int16 type is 32767, so in this format only the value range 0 .. 327.67 can be stored with 2 decimal places!
// float 2 reg holdingRegs[REG_HUM] = (int16_t)(Humidity * 100); // back one reg to float float Humidity = holdingRegs[REG_HUM] / 100.0;
Modbus #define conversions
#define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF) #define MODBUS_GET_LOW_BYTE(data) ((data) & 0xFF) #define MODBUS_GET_INT64_FROM_INT16(tab_int16, index) \ (((int64_t) tab_int16[(index)] << 48) | ((int64_t) tab_int16[(index) + 1] << 32) | \ ((int64_t) tab_int16[(index) + 2] << 16) | (int64_t) tab_int16[(index) + 3]) #define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) \ (((int32_t) tab_int16[(index)] << 16) | (int32_t) tab_int16[(index) + 1]) #define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) \ (((int16_t) tab_int8[(index)] << 8) | (int16_t) tab_int8[(index) + 1]) #define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \ do { \ ((int8_t *) (tab_int8))[(index)] = (int8_t) ((value) >> 8); \ ((int8_t *) (tab_int8))[(index) + 1] = (int8_t) (value); \ } while (0) #define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value) \ do { \ ((int16_t *) (tab_int16))[(index)] = (int16_t) ((value) >> 16); \ ((int16_t *) (tab_int16))[(index) + 1] = (int16_t) (value); \ } while (0) #define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) \ do { \ ((int16_t *) (tab_int16))[(index)] = (int16_t) ((value) >> 48); \ ((int16_t *) (tab_int16))[(index) + 1] = (int16_t) ((value) >> 32); \ ((int16_t *) (tab_int16))[(index) + 2] = (int16_t) ((value) >> 16); \ ((int16_t *) (tab_int16))[(index) + 3] = (int16_t) (value); \ } while (0)
Modbus messages
bool getResultMsg(uint8_t result) { String tmpstr2; switch (result) { case node.ku8MBSuccess: return true; break; case node.ku8MBIllegalFunction: tmpstr2 = "Illegal Function"; break; case node.ku8MBIllegalDataAddress: tmpstr2 = "Illegal Data Address"; break; case node.ku8MBIllegalDataValue: tmpstr2 = "Illegal Data Value"; break; case node.ku8MBSlaveDeviceFailure: tmpstr2 = "Slave Device Failure"; break; case node.ku8MBInvalidSlaveID: tmpstr2 = "Invalid Slave ID"; break; case node.ku8MBInvalidFunction: tmpstr2 = "Invalid Function"; break; case node.ku8MBResponseTimedOut: tmpstr2 = "Response Timed Out"; break; case node.ku8MBInvalidCRC: tmpstr2 = "Invalid CRC"; break; default: tmpstr2 = "Unknown error: " + String(result); break; } Serial.println(tmpstr2); return false; }
General code collection
MAC random generator
Generate random MAC using pseudo random generator, bytes 0, 1 and 2 are static (MAC_START), bytes 3, 4 and 5 are generated randomly
void generateMac() { // Marsaglia algorithm from https://github.com/RobTillaart/randomHelpers seed1 = 36969L * (seed1 & 65535L) + (seed1 >> 16); seed2 = 18000L * (seed2 & 65535L) + (seed2 >> 16); uint32_t randomBuffer = (seed1 << 16) + seed2; /* 32-bit random */ memcpy(data.mac, MAC_START, 3); // set first 3 bytes for (byte i = 0; i < 3; i++) { data.mac[i + 3] = randomBuffer & 0xFF; // random last 3 bytes randomBuffer >>= 8; } }