B
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
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