There might be issues open in GitHub that touch on that. Make sure to report your findings there to to increase visibility of these issues.
If you don’t find a issue that fits good enough, file one yourself.
But to make sure similar issues haven’t been addressed and solved yours already try the latest version (0.8.0-rc.8).
Some explanation: I use a this NetworkSerialMuxer class to stream from either WiFi or Serial, whichever is available, with a preference for Serial.
To get it stable I had to:
Only look for a new TcpClient when the old one has dropped. I think there are some issues with how they are destroyed. TcpServer keeps a reference to the client. I think it should probably only create it and pass it on. Not keep a copy itself.
Don’t call Particle.connect() with no WiFi. It will trigger listening mode, unlike (WiFi.connect(WIFI_CONNECT_SKIP_LISTEN)). Listening mode sends messages over serial. This interferes with the application’s use of Serial! Holy shit, I missed this and it totally messed up the application’s Serial reliability.
So now the system accepts one TcpClient at a time and will only start looking for a new one if the client disconnects.
@Elco, agree with your strategy to check WiFi.connected() before calling Particle.connect(), this has worked well for me too!
I will have to digest your PiLink code and see if this will help. Note that my application is looking at serial and is also a TCP Client, not a TCP Server, so will have to see if your code can assist with this because your code is a TCP Server.
To reiterate, the issue happens when I purposely turn off the WiFi router, ie no WiFi. Is your (yet to be looked at) code helpful in this situation?
Asynchronous system functions do not block the application thread, even when the system thread is busy, so these can be used liberally without causing unexpected delays in the application. (Exception: when more than 20 asynchronous system functions are invoked, but not yet serviced by the application thread, the application will block for 5 seconds while attempting to put the function on the system thread queue.)
So, if you fire too many async functions and saturate the system thread, the main loop will be blocked.
WiFi.hasCredentials() is synchronous, I’m not sure whether this could cause problems. I have gone through so many iterations that it’s hard to remember what caused unreliability in the past. I’m just glad that I found something that works.
But perhaps it’s a good idea to remove the hasCredentials() call, because I think it is superfluous with SKIP_LISTEN.
@Elco, have neatened up the WiFi strategy code and moved it out to function which is now only called every 200 mS so as to overcome possibly overwhelming the system thread.
During this change, I added some extra logging lines which has shown that loop() is NOT being blocked as I had first thought. This is good news (but embarassing)!
Still left with the tricky situation of Serial1 (ie physical port) not receiving characters reliably. Which got me thinking… am now pretty sure that I have a hardware issue… I added test code which initiated a command with the device in play which elicits a serial response on a regular basis - no issue found, with or without WiFi…
I will confirm the hardware issue next week some time with my trusty logic analyser to confirm the serial traffic is ok theory.
Apologies to both you and @ScruffR for this wild goose chase…
Great, thanks for the update.
Depending on the baud rate and data rate you are using, you have to ensure that you are reading the serial port often enough. The serial buffer is small and easily overrun.
I have used this code as a quick and dirty USB to RS485 transceiver:
I can run it at 256000 baud rate.
If I print all of the output to a python terminal though, python cannot keep up and the data is lost there. It’s the printing to terminal that’s too slow. You have to make sure that you empty the buffers regularly. If they fill up, data is discarded. Even the USB buffer of the desktop is tiny.