kind3r / esp8266-xpressnet-lib

XpressNet library from Philipp Gahtow converted to run on ESP8266
5 stars 1 forks source link

Transmission issues #2

Open mytrain opened 6 years ago

mytrain commented 6 years ago

Hi,

First of all : great job to all the contributors !

I'm experimenting some transmission issues. Some requests are not answered by the command station (both a Lenz LZV100 ou a Lokmouse 2).

I track down the issue and it seems that the 80us time critical window to answer the normal inquiry (see Lenz specification 2.1.1) is not handle in the code. I'm working on a code modification to avoid sending request in XNetSend() if the transmission window has expired (and wait for the next).

Is this issue, something you get trough on your side ?

kind3r commented 6 years ago

Hi,

I was also experiencing some loss of commands between rocrail and the locos but I could not quite pinpoint it as it happend very rare. I thought it was due to to cables and I was waiting for my 4MB esp to arrive so I can embed the circuit inside the booster and do OTA as the whole process of updating the esp connected to the pc while debugging is a real pain.

I think this could also happen if you don't call XpressNet.receive() often enough. Unlike the original library in which the XpressNet.XNetget() was triggered by the serial port interrupt, which in turn triggered the sending of pending rs485 data, my port relies on XpressNet.receive() to call XNetget to fetch the incomming rs485 data buffered by the RS485SoftwareSerial library. So while rs485 data is read and buffered, if not interpreted often enough by the library it will indeed miss it's reply window.

Another option I tried was to call XNetget from inside the rs485 interrupt but that proved to be too much work to handle inside and interrupt and so packets were lost. This is due to the lack of a hardware 9bit serial on the esp.

You can also try to test with my esp8266-xpressnet-z21 sketch that combines all the libraries and has worked for me in my last tests.

So if you can find a solution you are more than welcome and thanks for pointing it out.

mytrain commented 6 years ago

@kind3r

Handling time critical activity on an ESP8266 is not simple. In fact the WiFi kernel is interrupting very often the Arduino loop. On the other hand, using in Arduino code a 'long' section of code in an ISR or inside a cli()/sei() section will get the WiFi down.

Instead of making the code 'real time', my approach consiste in checking if the normal inquiry window has expired before to send the request (and wait for the next window is the window has already expired).

Currently I added a timestamping (ESP.getCycleCount() ) support in RS485SoftwareSerial. In XNetSend I'm checking the duration between the byte reception cycle counand the current cycle count. If the duration is lower than 70us I'm sending the request otherwise I'm waiting for next callByte. The last point is to use a cli()/sei() section in between the moment I compute the duration and the moment first byte is sent in order to avoid the WiFi kernel to interrupt the Arduino code and delay the transmission of the request.

I'll perform some more intensive test (during this week) and I'll come back to you with the code modification if everything is OK.

kind3r commented 6 years ago

Sounds good, but I guess you would have to timestamp all bytes in the RS485SoftwareSerial buffer. This could increase memory usage but I think there is enough room in the esp for that.

Still, I think the issue of calling XpressNet.receive()/XNetget() often enough still remains it only reads one byte of data at a time. Perhaps it could be an ideea to make XNetget read all available data ?