I have the following setup:
A: 1 x Coordinator connected via USB dongle (sparkfun) to a Windows 10 IoT device - Serial communication
B: 1 x Router connected to an Arduino Fio
C: 1 x Router connected via USB dongle (sparkfun) to Windows 10 to XCTU
All above are API mode 1.
My scenario is as follows:
I send at each 5 seconds a 6 byte message from A to B and C.
B is instructed to reply to that message with another one of the same size.
After some time, typically 40 - 50 minutes, A no longer receives messages from B.
Reads from Serial port are working (Transmit Status messages are received for each message Sent by A).
C receives messages as seen in XCTU.
If nothing changes A will never hear from B again.
However if (by some internal logic) B sends a message to A (other than the reply) or if C sends a 6 byte message (same as the one A sends to B and C) to B, suddenly A starts receiving messages from B.
Does anyone know why is this happening?
It was the arduino library that we misused.
It only works in API Mode 2 and we have the module configured for API Mode 1.
(does anyone know why the library has not yet been updated to be used with API Mode 1?)
It was happening only after a while since we have an incremental counter in our message and at some point, that counter reached a value that contained a special character from API Mode 2 perspective.
From XCTU was always running since there was no incremental logic in there.
Many thanks to #tomlogic for his suggestion. Helped a lot!
Related
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)
}
I'd like to get the states of the relays on the board from the relay, but I can get only ACK back.
I have two XBee modules, one is connected to a computer with USB, and acts as a Serial device, the other is connected to a TOSR0X-T relay. I am planning to add more XBee modules to the network with more relays later, so I am using API mode, not the simple AT mode, because I need to address them separately.
I am sending TX frames with 64bit address to the remote XBee to open or close relays. That works fine, I get the ACK response frames properly. However if I send a message to get the relay states by sending 0x5B, I get back an ACK only, and I can find no way to get the actual data back indicating the relay states.
I am using node-serialport and the X-CTU software, but could not read the data, and the only example I found used both XBees connected to the same machine - that way an RX appeared on the destination XBee - but I need to get that remotely somehow.
TOSR0X-T documentation here only tells me about talking to it via TX messages, so I have no clue if I can achieve anything with commands (and how to do that).
The ACK you're seeing is likely the network-layer ACK, telling you that the remote XBee module received your packet. You need to use "AT mode" on the XBee connected to the TOSR0X-T, and address your TX API frames correctly for that mode (cluster 0x0011 of endpoint 0xE8).
If you've configured the XBee on your computer as the coordinator, the default settings of 0 for DH and DL on the relay's XBee module will result in all received serial bytes getting relayed back to the XBee on your computer, and coming through as RX frames.
After some experiments I could solve my problem.
Considering the CH (Channel) and ID (PAN ID) are matching - that is a requirement to be able to set up the network, I set up my XBees like this:
The Coordinator XBee (the one attached to the computer):
CE = 1 (for being coordinator)
MY = 0001
DH = 0
DL = 0
AP = 1 (in API mode)
The first End Point (the one attached to the TOSR0X-T):
CE = 0 (for being an endpoint)
MY = 000A (whatever you want), use FFFF for 64 bit responses
DH = 0
DL = 0001 (This is one I missed. It should be the Coordinator's MY)
AP = 0 (in AP mode)
So basically I did everything right, except the DH/DL addressing. For the Endpoint the DL must be set to the MY of the Coordinator. I read some articles where using FFFF and FFFE and things like that to set broadcasting, and I think I was confused by those informations.
I have tried to run the example programs from arduino-xbee library. I need to send some data to a node from a node and at the same time need to be ready to read the data available to the sending node itself. Assuming X sends a data to Y. When Y receives data it sends an acknowledgement back to X.But if Z sends data to X or if Z sends a broadcast will I be able to read the data from Z at X and read the acknowledgement from Y to X.
So any pointers to send and receive at the same time using arduino-xbee would be very helpful.
Thanks in advance.
If arduino-xbee uses "API mode" for the XBee modules, you'll receive separate frames of data. Each frame will have headers to identify the source of the data, and to match responses to requests (for AT commands).
An XBee module in "AT mode" or "Transparent mode" will just stream data out of the serial port that was received over the network on a specific endpoint and cluster. You won't know who sent it, and you need to enter "command mode" to read or write parameters using AT commands.
This is for educational purpose (University assignment).
I need to write a client-server programs in C for Linux. (I already have that part. A client connects to the server, it sends and receive files without a problem...).
When a client connects to the server, it sends the server a list of files on the client. So the server has a list of all the files on it's clients.
A client A can request from the server a file "test.txt", the server knows that the file is on client B, and the file should be transferred from B to A. I'm trying to think about the best way of doing this.
recv from B into a buffer, and immediatly send() the buffer to A?
recv() the whole file from B and save it on server ,then send it
to A?
My programs should support this behavior:
if A asks a file from B, and then C asks a file from B, C should NOT wait until the transfer A<-->B will end. And this is where I get stuck.
Thank you very much!!
Edit: My server is using threads: whenever a new client is connecting, a new thread is opened to serve it. My client, at this moment, does not use threads (this can be changed).
If you want to do several transfers at once using sockets you have two options:
Blocking sockets and threads
This is the way you've written your server. The problem with threads is that they can lead to bugs that are rather hard to debug. Combine that with network bugs that in themselves can be rather hard to debug and you have a potential nightmarish debugging session on your hands.
Non-blocking sockets and select()
This way doesn't need threads, instead it uses select() to see which sockets have data waiting to be read. Combine that with some loops and you can transfer several files concurrently. Setting sockets to be non-blocking is easy, using correct can be slightly trickier but weighted against the potential for thread + network bugs this is the way I personally prefer to write network code.
Regarding your actual problem; I would suggest something like this:
Client A connects to server S. You need to bind the local side for the next step.
A also opens another socket for data transfer on the next port upwards.
S sends file list to A. How you build up the file list I leave to you.
A requests file F from S.
S checks which client has F.
S sends "send F to A on port X" to B. You can check which remote port is used, and then you know which port to send the file on.
B recieves and executes the command.
You have to connect 2 sockets per client, so you gonna have 4 sockets like this :
1 A <-> C
2 B <-> C
3 A <-> C <-> B 4
So you will have to use socket 1 and 2 to transfer file just between client A and Server C (socket1) and between client B and Server C (socket 2).
Then you will have to developp a bridge in server C using socket 3 and 4 to transfer data from A to B.
A multithreading solution should work, I guess !
What I've got so far:
Server is running only with select().
Client has a socket in listen() mode- call it dataSocket (on top of it's regular socket).
If a client A want a file, it tells the server the file name. The server finds the user with the file, and making a connet() to the dataSocket. (I managed to implement that).
Small files are transferred without a problem. Big files fails.
I think it's because something is wrong with my client.
I've implemented the client with a select() function, and if it finds some one doing a connect() it opens a new thread and serves the request. But something there is wrong..
The code is like this:
FD_SET(globalSocket,&origin);
FD_SET(dataSocket,&origin);
FD_SET(STDIN,&origin); //#define STDIN 0
while(1)
{
readfds=origin;
select(fdmax+1,&readfds,NULL,NULL,NULL);
for(i=0;...)
{
if(FD_ISSET(i,&readfds)
{
if(i==STDIN)
// get user input
if(i==dataSocket)
{
printf("someone wants a file from me");
pthread_create(...);
}
}
}
}
One problem that I saw is when I do my first request of the file, it prints the line "someone want a file from me" 2 or 3 times, but only one thread is created.
And when I try to send a large file, I do get some of it, but then a "Connection reset by peer" pops out...
I hope somebody here will be able to answer my not-so-good-explained question.
Thank you.
I want to setup an xBee network with four serial 1 modules. Any two of them can communicate with each other in two-way. The transmitted data is string other than a single byte.
My original design is to setup a nonbeacon (with coordinator) network: One module is configured as coordinator. The left three modules is configured as end devices. The coordinator broadcasts the data from end devices.
The communication workflow is: If end device 1 want to send data to end device 2, it sends data to coordinator first. Then the coordinator broadcasts the data received from end device 1. End device 2 can receive the broadcast data. The communication workflow finishes.
I want the received string to be atomic. If end device 1 and end device 3 send out the data in the same time, there would be conflict. The two strings would combined together. And the end device 2 can't distinguish which byte is from which device. That is, end device 1 sends out string "{AAAA}" (quotes aren't included). In the meanwhile, end device 3 sends out string "<2222>". The end device 2 may receive the string like "{A<22AA2A2}>", which isn't what I want. My expected string is "{AAAA}<2222>" or "<2222>{AAAA}".
How do I setup the network to meet my requirements?
There are two ways to achieve atomic transmissions using Digi's XBee modules. The method varies depending on if API-mode (AP parameter > 0) is in use or not.
If API mode is not in use (AP = 0) then the atomicity of data can be encouraged by setting the RO time to be greater than the number of characters of the longest string you are going to send from one of your nodes. This will make the XBee buffer wait the specified number of character times (the time it takes to send a character at a particular baud rate) before starting the over-the-air transmission. Note: you'll have to ensure that you send your entire string all at once to the radio in order for this scheme to work.
If API mode is being used (AP > 0) then it is very easy to get the behavior you want. You'll simply use the Tx Request frame (API frame type 0x1) and specify the string data you want to send. The data will always be sent atomically.
If API mode is being used on the on the receiving node (i.e. in this case, the coordinator) then the frame data will always arrive atomically as well.
Please refer to the Digi XBee 802.15.4 product support page for more information on how to use API mode and search the Internet for the many wonderful XBee libraries which allow you to use Digi XBee modules in API mode easily.