简体   繁体   中英

Modbus calls returning same frame over and over again

I'm having a dickens of an issue with this one.

I have a remote installation with a raspberry pi installed in it (specifically a Kunbus RevPi connect) that is hooked up to an RS485 Modbus network with a total of 6 sensors on it. 4 Of these sensors are Dat3018 devices which serve to digitize thermocouples and make their values available over the network.

I wrote a C program that performs the following:

  • Sends a sync command (specified in the data sheet) to the dat3018 which causes them all to read values into their internal memory
  • Perform some other stuff
  • Read the saved values in to the raspberry pi over Modbus.

All is well and good, and I'm able to talk to each of the devices, no issues as far as I can tell on the physical communication link. The issue appears when I actually run the software and observe the Modbus request and response.

The first loop of the program runs normally, the sync command goes out, a request and response is received from each of the target slaves on the network. Starting with the second run of the loop each request results in the program receiving the exact same frame it did during the first run of the loop even through there should be at least some values changing. This continues for however long the program runs, always sending the same request from the server and always receiving the same values back.

As per the data sheet for the Modbus devices the following command is sent:

  [FF][06][00][00][00][0A][1C][13]

I verified with the company that makes the device that this was the right call to request the device to sync. I also verified that calling this again will cause new values to be read into the synced value registers, meaning that when I read them again there is a very low chance that they are all exactly the same.

I send the following modbus command with the following code:

int read_tempature_synced_values(modbus_t *RTU_context, int slave_addr, uint16_t output[]){
    modbus_set_slave(RTU_context, slave_addr);
    return modbus_read_registers(RTU_context, _temp_sync_tempatures_start_addr-1, 8, output); //Decrement to account for the inherient +1 from the library
}

For slave # 20:
[14][03][00][16][00][08][A7][0D]

Restarting the program pulls in new values for the first run of the loop before having the same issue.

I wrote a python script to call the sync command and pull in all the measurements from the same registers and that script gives me changing values as I make more calls. That would seem to indicate to me that the issue is somewhere in the Modbus code.

The part of the code that calls the above function looks like this:

//Read in the temperature measurements
    for (int i = 0; op_args->settings_instance->tempatureSlaveAddr[i] != -1; ++i){
        uint16_t *raw_measures = malloc(8 * sizeof(uint16_t));
        read_tempature_synced_values(op_args->modbus_instance, op_args->settings_instance->tempatureSlaveAddr[i], raw_measures);
        usleep(op_args->settings_instance->delay_ms);
        for (int u = 0; u <= 7; ++u){
            if(valid_sensors[i][u] == FALSE){ //Check that there is a valid sensor for this measurement
                measurements[measurements_taken].TYPE = TEMPATURE_MEASUREMENT_TYPE;
                measurements[measurements_taken].bankNumber = i;
                measurements[measurements_taken].sensorNumber = u;
                measurements[measurements_taken].measurementTime = sync_time;
                measurements[measurements_taken].tempatueReading = ((float)raw_measures[u])/10;
                measurements_taken += 1;
            }
        }
        free(raw_measures);
        modbus_flush(op_args->modbus_instance);
    }

It seems to me that there is something that is remembering what the responses to the calls were and then bouncing them back to me. I can't see any way that the code I have wrote could be doing this.

One other strange thing:

When running my code on the raspberry pi (and only on the pi) my program will randomly print out the two following lines at the start and then at seemingly random times:

ERROR Connection timed out: select
ERROR Connection timed out: select

This happens before the loading/connection to the serial port or sqlite database that I am using. Googling this issue did not appear to give me anything that makes sense in the context of where it is occuring.

Any help would be greatly appreciated

Edit -> The sync command is run at the start of every loop

I verified with the company that makes the device that this was the right call to request the device to sync. I also verified that calling this again will cause new values to be read into the synced value registers, meaning that when I read them again there is a very low chance that they are all exactly the same.

That's how the device works. The SYNC command tells the device(s) to latch the values into a register.

When you do the read, the devices return the latched value and not the "current" value.

From https://www.datexel.com/datexel-user-guides/dat3018-thermocouple-input-to-rs485-modbus.pdf we have:

SYNCHRONISM The Synchronism function is performed by a command sent to all devices connected on the net. When the devices receive the Sync command, all input states are saved in the relative register, to be read after time. Doing this, it is possible to read the value of all inputs at the Sync command time. To send the synchronism command, write the value 10 in the “Test” register (40001) at the address 255. NOTE: The sync values are not saved in EPROM.

So, for every new value you want you have to send a new SYNC command:

while (1) {
    send SYNC command
    for (x in all_devices)
       read(x)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM