Hello everyone,
I am working with a RN171 module that adds Wi-Fi connectivity to an Arduino UNO board.
Everything works fine, and I can use the WiFlyHQ library (GitHub - harlequin-tech/WiFlyHQ: WiFly RN-XV Arduino Library) to connect to a server using wifly.open() and then some wifly.println() instructions to build a GET request.
The problem I am having now is that the loop is paused while the module fetches the response from the server (like when using a delay() instruction). I am quite sure the pause happens while fetching the response and not while parsing the incoming serial data because I made some prints to the serial monitor reading millis() between functions.
This can be a problem because it interferes with other code running on the loop (for example the fading of some LEDs): is there a way to avoid this delay and keep the loop stable? Any suggestions?
is there a way to avoid this delay and keep the loop stable? Any suggestions?
Probably not. Client/server communication is not asynchronous. That is, when you make the request, you don't come around later to see if a response has arrived. You wait for it.
Can you post a snippet of your code? That may help others debug your issue faster.
I've been working with the WiFly the past few days and I've also looked through the WiFlyHQ code. However I haven't gotten as far as you.
But I looked at the WiFly::read function you referred to. The function looks like it fetches 1 character per iteration of the loop, except on the case where it reads an asterisk character. Then it checks if the TCP connection is still open.
So maybe the delay you are experiencing is happening there. You mentioned a GET request, so that must mean you are using HTTP. I could be wrong, but I think HTTP closes its connection when it is finished with a request.
I'm not quite sure how you would get around this issue. But if you want to look into it more, look at the "checkStream" function. This is where the delay happens.
Thank you for the answers!
After the WiFly initialization on the setup() function like on the library examples, the loop() contains this quite simple snippet to make a new request every 30 seconds:
void loop() {
time = millis();
....
....
if ((time - prevTime) > 30000) { // update every 30 seconds
updateURL();
prevTime = time;
}
....
....
}
And here is the updateURL() function that makes the request:
In this way I am sending the HTTP request (is there a faster/lighter method?) to read a page on the server.
All other instructions on the loop rely on the time variable, so everything is non-blocking.
On the loop() I am also reading back from the buffer of the WiFly serial connection one char per loop (so this is non-blocking too), using some "if" statements to skip the HTTP headers and find the real value: this is not very elegant, but works just fine without complex string parsing etc: I am finding the sequence {"pattern": " to skip all other content.
if (wifly.available()) {
reading = wifly.read();
if ((reading == '{') and (count == 0)) {
count ++;
} else if ((reading == '"') and (count == 1))
count ++;
} else if ((reading == 'p') and (count == 2))
count ++;
} else if ((reading == 'a') and (count == 3))
count ++;
} else if ((reading == 't') and (count == 4))
count ++;
} else if ((reading == 't') and (count == 5))
count ++;
} else if ((reading == 'e') and (count == 6))
count ++;
} else if ((reading == 'r') and (count == 7))
count ++;
} else if ((reading == 'n') and (count == 8))
count ++;
} else if ((reading == '"') and (count == 9)) {
count ++;
} else if ((reading == ':') and (count == 10)) {
count ++;
} else if ((reading == ' ') and (count == 11)) {
count ++;
} else if ((reading == '"') and (count == 12)) {
count ++;
} else {
count = 0;
}
if (count == 13) {
pattern = wifly.read();
Serial.print("pattern: ");
Serial.println(pattern);
}
}
I agree, probably there is no way to avoid that delay, but maybe someone more expert than me can suggest a better approach...
I printed the millis() and it's the open() operation that is time-consuming. It usually takes an average of 600 millis (sometimes more) while the other parts of the instructions stay below 50-60 millis.
Gohn, I'll try to take a look at the functions inside the library to better understand the issue...
By the way, is there another way to avoid the problem? Maybe something more hardware-oriented? I am using a TLC5940 to drive some small LEDs in different ways, according to the reply of the server. So I'm thinking about something like an external "buffer" chip between the Arduino and the TLC5940 that keeps some instructions and constantly pushes them to the TLC5940 even when the Arduino is busy. Or maybe another "buffer" chip between the Arduino and the WiFi module. Is this a stupid or complex idea? Any suggestions?
Maybe you can use TCP, since that will give you a constant connection. There would be no need to keep reconnecting.
If you are getting data from a source you do not control, you could write a TCP server that grabs the data from that website and sends it your Arduino.
That way you only have to call open once. Although I'm not sure what happens in the case of disconnects.
Good approach gohn, I already experimented something similar with cron etc, but this is another path, cool. I will explore this, but first I have to find a hosting that allows TCP sockets, I prefer not to do this relying on a local setup...
So with the CRON are you using your WiFly as the HTTP server? That's a good idea. I would assume there would be no blocking in this case. How did that work for you?
I stopped with the CRON approach because it means dealing with port forwarding, dynamic IPs and so on. Quite simple to set up, but I preferred something more independent from the LAN environment: making requests as a client allows to only edit SSID and password on the sketch when changing WiFi network.
I saw the WebSocket example, and it seems a good solution. I made some experiments with Twitter stream APIs, but that was a bit too complex to manage. Thank you for pointing me to Pusher, free services are always welcome.
Wow... the Pusher service is really simple to setup and use, cool. I made some tests and it works fine!
The main problem is that at a certain point the socket is closed, because the sketch becomes unresponsive. I need to understand why... Any suggestions?
I think that my sketch is pushing the processor's limits: I don't know if it can bear both the WiFly and the LED animations with the TLC5940. I have to understand how to optimize the code.