modbus communication

I am implementing a control panel using a 2560mega board, using the modbus_slave library to manage the communication protocol requirements. Physical communication is via USB (115K baud, even parity). For testing, the controller program reads 4 holding registers and writes 1 register in a 1/2 second loop. Approximately half the times I start the controller program, I get garbage data reported in the read registers, plus communication timeout errors on every pass through the controller loop. When the program does start properly, it will run for days without error. Has anyone seen similar behavior and found a fix?

thanks

lloyd

It's hard to say without any background information. May I see your code used for polling?

here’s the master:

#include “modbus_rtu.h”
#include “…/hurco.h”
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

// #define COMM_PORT “/dev/ttyUSB0”
#define COMM_PORT “/dev/ttyACM0”

#define COMM_PARITY “even”

/* Modbus RTU common parameters, the Slave MUST use the same parameters /
enum {
COMM_BPS = 115200,
MB_SLAVE = 1, /
modbus slave id */
};

int main(int argc, char *argv)
{
int err = 0;
int val = 0;
int inregs[MB_REGS];
int fd = set_up_comms(COMM_PORT, COMM_BPS, COMM_PARITY);
int lite = 1;
int lite_count = 0;
int i;
// testing, let everything settle
sleep(1);

/* turn off leds */
preset_single_register(MB_SLAVE,(MB_IND+1), val, fd);

while(1){

err = read_holding_registers( MB_SLAVE, (MB_COUNT + 1), MB_REGS, inregs, MB_REGS,fd);
for( i = 0; i < MB_REGS; i++){
inregs ^= 0xffff;

  • fprintf(stderr, “%d: %0x\n”, i, inregs[ i]);*

  • }*
    fflush(stderr);

  • preset_single_register(MB_SLAVE,(MB_IND+1), lite, fd);*

  • lite <<= 1;*

  • if( ++lite_count >= LIGHT_COUNT){*

  • lite =1;*

  • lite_count = 0;*

  • }*

  • usleep( 500000);*

  • // sleep(2);*

  • }*
    }
    ---------------------------------------------------------------------------------
    and the arduino sketch:
    ----------------------------------------------------------------------------------
    #include <ModbusSlave.h>
    #include “hurco.h”
    _ /*_

  • Hurco 3*

  • sketch to scan a machine tool control panel, report the state,*

  • control associated indicator lights*

  • 1st iteration 4/20/11 ldw*

  • 4/30/11 ldw fold in the modbus comm package*

  • 6/12/11 ldw testing indicators, integrated .h file*

  • 6/26/11 ldw add encoder handling*
    */
    // for testing lights
    #define LIGHT_DLY 3 // X 50 msec → 5 sec cycle
    ModbusSlave mbs;
    //global/static variables
    enum PinAssignments {

  • encoderPinA = 2, // interrupt 0*

  • encoderPinB = 3, // interrupt 1*
    // encoderPinA = 20, // interrupt 3
    // encoderPinB = 21, // interrupt 2

  • clearButton = 8 // not used in hurco*
    };
    volatile unsigned int encoderPos = 0;
    unsigned int lastReportedPos = 1;
    boolean A_set = false;
    boolean B_set = false;
    unsigned int modbus_regs[MB_REGS];
    unsigned int last_regs[MB_REGS];
    int row = SCAN_ROWS;
    int heart = 0;
    // for testing lights
    int light_count = LIGHT_DLY;
    int light_idx;
    SCAN_STRUCT scan_set[] =
    { 22, &modbus_regs[MB_SWITCH1],0,

  • 23, &modbus_regs[MB_SWITCH1],1,*

  • 24, &modbus_regs[MB_SWITCH2],0,*

  • 25, &modbus_regs[MB_SWITCH2],1};*
    LIGHT_STRUCT lights[] =
    { AUTO, 53,

  • MAN, 52,*

  • MDI, 51,*

  • CW, 50,*

  • CCW, 10,*

  • BRAKE, 11,*

  • MACH_ON, 12,*

  • ESTOP, 13,*

  • MIST, 14,*

  • FLOOD, 15};*
    // array of i/o pins used for leds
    //int indicators[] = {
    // 10, 11, 12, 13, 50, 51, 52, 53};
    void setup(){

  • int i;*
    //clear output registers

  • for (i=0; i < MB_REGS; i++){*
    modbus_regs =0;
    last_regs = 0;
    * }*
    //setup scan pins
    pinMode( 22, OUTPUT);digitalWrite(22,HIGH);
    pinMode( 23, OUTPUT);digitalWrite(23,HIGH);
    pinMode( 24, OUTPUT);digitalWrite(24,HIGH);
    pinMode( 25, OUTPUT);digitalWrite(25,HIGH);
    //setup led pins
    for( i= 0; i < LIGHT_COUNT; i++){
    * pinMode( lights[ i].port_pin, OUTPUT);
    digitalWrite( lights.port_pin, LOW);
    _}
    // and turn on the relay providing power to the lights*

    pinMode( LIGHT_RELAY, OUTPUT);
    digitalWrite( LIGHT_RELAY, LOW);
    //configure column port as 8 bits in, with pullups
    //corresponds to pins 37 (bit 0) to 30 (bit 7)
    DDRC=0;
    PORTC=B11111111;
    // setup modbus communications
    mbs.configure( MB_ADDR, BAUD, PARITY, TXENPIN);
    // setup encoder handling
    * pinMode(encoderPinA, INPUT);
    pinMode(encoderPinB, INPUT);
    pinMode(clearButton, INPUT);
    digitalWrite(encoderPinA, HIGH); // turn on pullup resistor*

    * digitalWrite(encoderPinB, HIGH); // turn on pullup resistor*
    * digitalWrite(clearButton, HIGH);
    // encoder pin on interrupt 0 (pin 2)
    attachInterrupt(0, doEncoderA, CHANGE);
    // encoder pin on interrupt 1 (pin 3)
    attachInterrupt(1, doEncoderB, CHANGE);
    }
    void loop(){_

    if(++row >= SCAN_ROWS){
    check_modbus();
    _ row = 0;
    }
    scan_row( row);
    delay(50);
    }
    void check_modbus(){
    int i;
    int ind_mask = 1;
    //noInterrupts();
    modbus_regs[MB_COUNT] = encoderPos;
    encoderPos = 0;
    //interrupts();_

    mbs.update( (int )modbus_regs, MB_REGS);
    for( i = 0; i < LIGHT_COUNT; i++){
    // if(modbus_regs[ MB_IND] & ind_mask)

    * digitalWrite( lights[ i].port_pin, (modbus_regs[ MB_IND] & ind_mask));
    _// else*
    // digitalWrite( lights[ i].port_pin, LOW);
    * ind_mask <<= 1;*
    * }
    }
    void scan_row( int row){
    unsigned int temp;_

    digitalWrite( scan_set[ row].row_pin, LOW);
    _ delay(5);
    temp=PINC;_

    if( scan_set[row].shift){
    scan_set[row].reg &=HIGH_MASK;
    scan_set[row].reg |= temp<<8;
    _ }

    else{
    *scan_set[row].reg &=LOW_MASK;
    *scan_set[row].reg |=temp;
    }_

    digitalWrite( scan_set[ row].row_pin, HIGH);
    _}
    // interrups; one for each channel*

    // Interrupt on A changing state
    void doEncoderA(){
    * // Test transition*
    * A_set = digitalRead(encoderPinA) == HIGH;*
    * // and adjust counter + if A leads B*
    * encoderPos += (A_set != B_set) ? +1 : -1;*
    }
    // Interrupt on B changing state
    void doEncoderB(){
    * // Test transition*
    * B_set = digitalRead(encoderPinB) == HIGH;*
    * // and adjust counter + if B follows A*
    * encoderPos += (A_set == B_set) ? +1 : -1;*
    }
    -----------------------------------------------------------------------------------------
    both programs compile with no warnings_

If you don’t mind could you format your code with the # button on the submit toolbar? It would allow for easier review.