03-04-2024 11:23 PM
Good day,
I am (still) trying to record a modbus conversation. There are some values sent intermittend only, sometimes its sent for about 15 s once or twice per second. Then its been sent every 2-3s, and then its not sent at all over minutes /hours. The plan is to record the conversation, once per second. How can I then filter out that intermittend value? Best idea so far is a latch that when the value is been sent, it keeps it for 10 cycles, then falls back. To deal with a not sent value I record 65535. Then I just have to delete all 65535 in my table.
Recorded into SQL that is, simplest I could figure is send some array, then some value has to be in every spot, hence the 65535. This will never be sent in my application, so I know its a placeholder.
For sure there are better ideas, any help?
Thanks,
Steffen
03-05-2024 09:32 AM
It is not clear what you want and what you mean by "filter", because it seems you want to interpolate more values.
I assume you know when new data arrives. You can keep the previous data in a shift register until new data arrives.
You can also only record a value if it differs from the previous value.
Please be more clear in your description. What is "some array"? What is "every spot"? What is a "conversation"?
03-05-2024 02:34 PM
I records into a database every 1 seconds. There some values that arrive constantly. But on top of that there are values that only arrive occasionally. The empty fields would be ' ' in SQL, but its hard to send this in an array. So I fill the empties with 65535.
The entire conversation is on modbus and not at regular intervalls. The values that appear regularly can be held in shift registers until the next one arrives. But the last one I need a timestamp as well as to when it arrives. So I cannot just hold it in a shift register until the next one arrives and populate the others with the same value. 1-4 are readings, 5 is a write command and I need to know what time it has been sent.
03-06-2024 12:21 AM
It's still not entirely clear what you want, but I'm going to assume your code is the Modbus master and is the one sending the read and write commands and that's what you want to log.
I don't know the details of your system, but I expect what I would do is to change the structure of the table and rather than having a column for every value and a row for every logged value, you could have a table with a column for identifying the value, a column with the time and a column with the measured value. That way, you can write to the table only when a value changes (you might want to implement some kind of deadband or a running average, so that changes which are smaller than the resolution you care about don't fill up the table).
You can then select from the table to get the data you want.
If you still want to record the number of values, you could add a count column, where you increment the count if you read a new value and it hasn't changed.
Or you could keep your current table and add a new table just for the values which update less frequently.
Ultimately, the decision on which design works for you depends on your needs and your own preferences.
03-06-2024 01:05 AM - edited 03-06-2024 01:07 AM
ok, need to explain a bit more.
I am listening in on a modbus conversation. There is a modbus sniffer that sends data via UDP into my application and I untangle the commands, from scratch. Following the modbus protocol.
Most of the communication is always the same, bulk read the exact same registers, slave responds the content of them. This already happens at irregular time intervals, but several times per second. Means constant flow of data, easy, shift register, log once per second, I know what the slave is up to.
The other part is, occasionally the master sends a write command to a certain register. This can happen just any given time, or maybe not for hours. So to log that one does not send anything I fill the corresponding cell in my database with 65535.
So there is a loop that listens to UDP, runs quite fast so as not to miss anything. The loop that logs into SQL runs once per second. So off course if there comes a write signal once, then next iteration is write signal for a few seconds, then the SQL loop may just pick that interval of the UDP loop where 65535 is passed on. In short the conversation is
my recording is
I figured it is sthe easiest if I send an array of 16 bit numbers to SQL, then off cource I have to put something into the time where the master is not sending a write. And thne later replace 65535 with a blank.
03-06-2024 01:14 AM
Hi Steffen,
@Steffen01 wrote:
The other part is, occasionally the master sends a write command to a certain register. This can happen just any given time, or maybe not for hours. So to log that one does not send anything I fill the corresponding cell in my database with 65535.
So there is a loop that listens to UDP, runs quite fast so as not to miss anything. The loop that logs into SQL runs once per second.
What happens when the master sends more than one write command within your "one second SQL interval"?
03-06-2024 01:28 AM
then my chances increase to capture one write. By the look of it it sends one every 0.8s when it does. So I need to hold that value for 1s max. for the SQL loop to capture it. The signal is for instance 1, clear fault, and it keeps sending it, until the fault cleared, then it stops. I do not need to know if sent it twice per second. Just, when it started sending until it stopped. Then I can line up to the readings which one triggered the "clear fault" write. Its for debugging, so I can only listen in but not actually send things myself.
03-06-2024 01:40 AM
Hi Steffen,
@Steffen01 wrote:
I do not need to know if sent it twice per second.
Use an intermediate step to handle the data:
03-06-2024 01:57 AM
to make it more interesting there are 4 different send events happening. But I can handle them individually, then build the array and send to SQL,
Or try a latch that keeps a value for a fwe cycles, until the next write, or if nothing happens, it empties
03-06-2024 09:43 AM
Whenever you receive data, keep the timestamp in a shift register and fill that same timestamp in that column. If there is no new data, write the last received timestamp from the shift register.