reading negative value from registers
Here is the output of reading the registers of a motor driver:
0,0 0,0
9,6543 517,65015
19,6533 1751,63776
29,6523 3701,61819
39,6513 6369,59146
50,6503 9750,55761
60,6493 13839,51667
70,6483 18640,46860
80,6473 24156,41340
Code is:
std::cout<<controller.lm_vel<<","<<controller.rm_vel<<"\t"<<controller.lm_pos<<","<<controller.rm_pos<<std::endl;
...
void Controller::read_vel(int nb) {
rc = modbus_read_registers(ctx, LM_READ_VEL_REG, nb, tab_rp_registers); // Actual velocity left
lm_vel = tab_rp_registers[0] * 0.1;
rc = modbus_read_registers(ctx, RM_READ_VEL_REG, 2, tab_rp_registers);
rm_vel = tab_rp_registers[0] * 0.1;
}
Here as in the output, instead of -19 6543 is comming and so on. This is the motor driver i'm trying to control from the linux computer with modbus library.
Guessing tab_rp_registers data type, you may want something like the following
rm_vel = ((short int)tab_rp_registers[0]) * 0.1;
not only missing the type of tab_rp_registers (should be unsigned 16 bit word type of your compiler), also missing the idea behind the 2 in modbus_read_registers(ctx, RM_READ_VEL_REG, 2, tab_rp_registers), and then only taking 1 in rm_vel = tab_rp_registers[0] * 0.1 ... how about tab_rp_registers[1] here?
If it is a 32 bit number, assuming endianness is ok, it may be rm_vel = (*((int32_t *)&tab_rp_registers[0])) * 0.1;
Assume that the value of a certain PLC register is -12
USHORT *usNRegs = new USHORT[nRegNums]; memset(usNRegs, 0, nRegNums * sizeof(USHORT));
modbus_set_slave(g_MBMMaster, nSlaveId); modbus_read_registers(g_MBMMaster, nRegAddr, nRegNums, usNRegs);
int negativeValue = static_cast
??
basically right, but some mini flaws and some Micro$oft C++ specific terms.
You already used C++98 stuff, how about preventing VC++ keywords and using bit more recent (year 2011) code, not creating a memory leak, btw ;-)
#include <cstdint>
#include <limits>
#include <vector>
#include <iostream>
...
const int nRegAddr = 0x2000; // just for example, 1st address of the 11 registers
const size_t nRegNums = 11; // just f.i.
std::vector<uint16_t> vuiRegs(nRegNums); // creates a 11-element vector holding {0, 0, ..., 0}
modbus_set_slave(g_MBMMaster, nSlaveId);
modbus_read_registers(g_MBMMaster, nRegAddr, vuiRegs.size(), &vuiRegs[0]);
for(auto unsigVal : vuiRegs) {
signed int negativeValue = static_cast<signed int>(unsigVal) - numeric_limits<uint16_t>::max();
signed int16_t easyValue = static_cast<int16_t>(unsigVal);
std::cout << "signed of " << unsigVal << "=" << negativeValue << ", but " << easyValue << " is also okay." << std::endl;
}
;-)