interfacing to libmodbus is fairly straightforward. i'm leaving out the error checking and what not, since the whole code is on github
opening a connection
modbus_t *ctx = modbus_new_rtu ( "COM1", 9600, 1,8 ,1);
if ( ctx) {
if(modbus_connect ( ctx ) == -1 ) {
modbus_free ( ctx );
ctx = NULL;
}
}
set as slave
if ( modbus_set_slave ( ctx, 1 ) == -1 ) {
// error
}
read a register
if ( modbus_read_registers ( ctx, status_monitor_2_addr, 1, ( uint16_t* ) &status_monitor_2 ) == -1 ) {
//error
}
write a register
if ( modbus_write_register ( ctx, run_stop_addr, 1 ) == -1 ) {
//error
}
that is more or less it.
a modbus RTU message looks like this
// 01 10 09 1b 00 02 04 02 58 00 01 5a 66
// breakdown
// 01 node address
// 10 command (write registers)
// 09 1b register to write to 9.26
// 00 02 number of registers to write, consecutive
// 04 amount of data to write
// 02 58 00 01 data to send 0258 to 9.26 and 0001 to 9.27
// 5a 66 crc
from the VFD's manual it has the following info
/*
Status Monitor 2 - Memory Address h2101
Address Bit(s) Val AC Drive Status
Bit(s) Binary(Dec)
------- ------ ---------------
0 and 1 00 (0) Drive operation stopped(STOP)
01 (1) Run to Stop transition
10 (2) Standby
11 (3) Drive operation running(RUN)
2 1 (4) JOG active
3 and 4 00 (0) Rotational direction forward(FWD)
01 (8) REV to FWD transition
10 (16) FWD to REV transition
11 (24) Rotational direction reverse(REV)
5 ~7 N/A Reserved
8 1 (32) Source of frequency determined by serial comm interface (P4.00 = 5)
9 1 (64) Source of frequency determined by AI terminal(P4.00 = 2, 3, 4 or 6)
10 1 (128) Source of operation determined by serial comm interface (P3.00 = 3 or 4)
11 1 (256) Parameters have been locked (P9.07 = 1)
12 N/A Copy command eable(sp?)
*/
a quick bitfield, being wary of how compilers pack bitfiles and differences in systems.
typedef struct statusMonitor2_tag {
uint16_t drive_state : 2;
uint16_t jog_active : 1;
uint16_t direction : 2;
uint16_t reserved_1 : 3;
uint16_t freq_src_1 : 1;
uint16_t freq_src_2 : 1;
uint16_t freq_src_3 : 1;
uint16_t params_locked : 1;
uint16_t reserved_2 : 1;
} statusMonitor2;
statusMonitor2 status_monitor_2;
and the VFD manual again to get the registers, hackaday has some issues with colouring.
Modbus is strange (to me anyway) that the decimal is in a range, may map to a memory address so you have to know which range the register is in, then add the register value to that range. For the status monitors, seems to be 40000 + they're indexed at 1, versus 0, so it is +1, therefore Status Monitor 1 is 0x2100, which to get the decimal address is 40000+0x2100+1 = 48449
Octal and Hex are just the address.
Durapulse GS3 status registers form CH5 of manual
Name Hex Dec Oct Mode
Status Monitor 1 2100 48449 20400 RO
Status Monitor 2 2101 48450 20401 RO
Frequency Command F 2102 48451 20402 RO
Output Frequency H 2103 48452 20403 RO
Output Current A 2104 48453 20404 RO
DC Bus Voltage d 2105 48454 20405 RO
Output Voltage U 2106 48455 20406 RO
Motor RPM 2107 48456 20407 RO
Scale Frequency(Low Word) 2108 48457 20410 RO
Scale Frequency(High Word) 2109 48458 20411 RO
Power Factor Angle 210A 48459 20412 RO
% Load 210B 48460 20413 RO
PID Setpoint 210C 48461 20414 RO
PID Feedback Signal(PV) 210D 48462 20415 RO
Firmware Version 2110 48465 20420 RO
quick macro
#define MODBUS_CMD(maj,minor) ((uint16_t)(maj<<8)+minor)
some enums for commands i'm using. // commands for GS3 DuraPulse VFD
enum modbuscmds {
hz_addr = MODBUS_CMD ( 9, 26 ),
run_stop_addr = MODBUS_CMD ( 9, 27 ),
control_freq_addr = MODBUS_CMD ( 4, 0 ),
control_drive_addr = MODBUS_CMD ( 3, 0 ),
status_monitor_2_addr = MODBUS_CMD ( 0x21, 01 ) //(BD42)
} ;
so if we do if ( modbus_read_registers ( ctx, status_monitor_2_addr, 1, ( uint16_t* ) &status_monitor_2 ) == -1 ) {
}
and it goes well , status_monitor_2.drive_state will be the state of the drive. enum {
DRIVE_STOPPED,
DRIVE_RUN_TO_STOP,
DRIVE_STANDBY,
DRIVE_RUNNING
};
turning the motor on and off is just 0 for off, 1 for on to be passed into the last argument if ( modbus_write_register ( ctx, run_stop_addr, 1 ) == -1 ) {
}
and that is pretty much it.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
[this comment has been deleted]
as noted it's all on github, the parity is dependent on the vf+interface so you have to match whatever you set it at.
Are you sure? yes | no