I am attempting to port a version of SimpleModbus from Arduino to Mbed. My Mbed device is acting as a slave and is connected to my PC via a MAX485 and a serial-USB converter. I am using ModbusPoll on my PC to simulate a master. Baud rate of 9600.

The system works for one function request then goes into error. The master sends a function request to the slave (Function 3 to read registers), this is all fine and passes checksum etc, my frame is filled from the buffer and a packet of data to be sent back is formulated. The packet is sent back and the register on my master is updated, it worked.

The problem now arises when the master attempts to poll the request again.. the slave reads a "phantom" byte almost. The buffer goes up to one and then stops receiving, this causes a corrupted packet because the buffer is not big enough and the slave rejects and tries again.

Now though its like everything in the frame has been shifted along, missing out the first bit of received packet and also adding the first bit of the next packet on to the end. So what should be:

3 3 0 0 0 2 197 233

Becomes:

3 0 0 02 197 233 3

Which causes a checksum error of course.

I have results on a serial print but due to this being my first post I'm struggling to post screenshots.

I am completely stumped as how to fix this, I've spent a fair bit of time researching Modbus protocol and I am pretty sure I have the correct timing intervals for 1.5 and 3.5.

I just don't see how it reads 1 buffer after the packet is sent back, no matter what delays or anything I put in. I'm pretty sure the problem is within how I send the packet data back to the master and maybe it is something to do with the Flush function? I'm unsure if this is even needed, but it was in the Arduino version.

I'm still only learning at University so any tips/advice and help will be hugely appreciated, thanks in advance.

CODE:

modbus_update(unsigned int *holdingRegs){

    slaveID = 3;
    holdingRegsSize = 2;

    unsigned char buffer = 0;
    unsigned char overflow = 0;

    if (MBPort.readable()) { // is there something to check?
        unsigned char overflowFlag = 0;
        buffer = 0;

        while (MBPort.readable()) {
            if (overflowFlag)
                MBPort.getc();
            else {
                if (buffer == BUFFER_SIZE)
                    overflowFlag = 1;

                frame[buffer] = MBPort.getc();
                buffer++;
                pc.printf("Buffer == %d\n", buffer);
            }
            wait_us(T1_5); //1718us intercharacter
        }    

    for (unsigned char i = 0; i < 8; i++) {
        pc.printf("Frame == %d\n", frame[i]);
    }
    if (overflow)
        return errorCount++;

    // The minimum request packet is 8 bytes for function 3 & 16
    if (buffer > 6) {
        unsigned char id = frame[0];
        //pc.printf("ID recieved == %d\n", id);
        //pc.printf("MBED ID == %d\n", slaveID);


//---------- carries on to the function selection part -------------


//---------- function to send the packet of data -------------------

sendPacket(unsigned char bufferSize){

    TxEnablePin = 1;

    for (unsigned char i = 0; i < bufferSize; i++) {
        MBPort.putc(frame[i]);
    }
    //flushSerialBuffer();

    // allow a frame delay to indicate end of transmission
    wait_us(T3_5); //4010us
    TxEnablePin = 0;
}

* EDIT *

I have stopped the slave from reading the "phantom" byte after sending back a packet. This was achieved by using the flushSerialBuffer function posted below.

HOWEVER, this has not stopped the problem of all data packets received afterwards being shifted along.

void Slave::flushSerialBuffer(void)
{
    char char1 = 0;
    while (MBPort.readable()) {
        char1 = MBPort.getc();
    }
    return;
}

0 Answers