modbus starting address question

B

Thread Starter

barramundi9

Hi,

I am really new to modbus and trying to get information out of the meter mp-84dh which is modbus compliant.

Below is the code I found on the internet:
http://jalla.org/~stig/modbus/<pre>
int modbus_read_holding_registers(unsigned char slave_id,
unsigned int start_address, unsigned int num_registers,
unsigned short * modbus_registers)
{
unsigned char transmit[255];

transmit[0] = slave_id;
transmit[1] = MB_READ_HOLDING_REGISTERS;
transmit[2] = start_address >> 8;
transmit[3] = start_address & 0xFF;
transmit[4] = num_registers >> 8;
transmit[5] = num_registers & 0xFF;
short crc = CRC16(transmit, 6);
transmit[6] = crc;
transmit[7] = crc >> 8;

if (write(fd, transmit, 8) == -1) {
perror("Unable to write to serial device");
mb_datagram_status = MB_ERROR;
return -1;
}


mb_waiting_for_reply = 1;

struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += 1;


/* Time out here if no bytes have been received within the time out period */
if (pthread_cond_timedwait(&datagram_start_receiving,
&waiting_for_reply, &time) == ETIMEDOUT) {
mb_datagram_status = MB_TIMEOUT;
timeout_error_count++;

return -1;
}


pthread_cond_wait(&datagram_finished_receiving, &waiting_for_reply);
mb_waiting_for_reply = 0;

if (mb_datagram_status == MB_OK) {

unsigned char byte_count = modbus_read_num_bytes(datagram);
mb_datagram_status = MB_OK;

unsigned char * datagram_data = datagram + 3;

int i;
for(i = 0; i < byte_count / 2; i++) {
modbus_registers = datagram_data[i * 2] << 8 | datagram_data[i * 2 + 1];
}
return byte_count / 2;

} else {
return mb_datagram_status;
}

}</pre>

And the spec on MP-84DH mentions the following:<pre>
Modbus Register Address
Address word item code
0000H 2 Watt Hour 03H
0002H 1 Watt 03H
0003H 1 Voltage 03H
0004H 1 Current 03H</pre>

I wrote:<pre>
readState = modbus_read_holding_registers(2, 0, 1, mbusRegisters);
printf("readState : %d\n", readState);</pre>
and readState returns -1 because it died at the block:<pre>
if (pthread_cond_timedwait(&datagram_start_receiving, &waiting_for_reply, &time) == ETIMEDOUT) {
mb_datagram_status = MB_TIMEOUT;
timeout_error_count++;

return -1;
}</pre>
Have I given it the wrong starting address, according to spec, it looks like the starting address is 0, or am I misunderstanding something here?

Any help will be appreciated.

Thanks.
barramundi9
 
Hello,

It seems that you need swap bytes of CRC. The high byte should be first.

Also you may try to build and send this request a manually from Advanced Serial Port Monitor. It is possible the device returns an error code.
 
B
Hi Helen,

thanks for the reply, I know it's been a month ...

I tried swapping the crc bytes, but it still dies in

if (pthread_cond_timedwait(&datagram_start_receiving, &waiting_for_reply, &time) == ETIMEDOUT) {

and returns -1

I used some modbus testing software and it does return the values I want.

Any ideas?

Thanks
 
Hello,

Try connect to modbus slave simulator like Modsim to see the frame is send from application and compare this with the frame which is send from Modbus test application (like Modbus Tester from www.modbus.pl).

Regards,
Andrzej
 
Top