I have a product that is running on 1.1.0 - it has a co-board with a MCP23017 using I2C that is used to read the status of buttons connected to the co-board (by a mechanism of polling each loop). All works well until the WAP the device is attached to has an outage (LED on photon is flashing green) this then blocks out the application thread (SYSTEM_THREAD(ENABLED) is being used). The impact of this is that the button presses can become unresponsive. I am looking for advice/options about how to ensure continued responsiveness to polling the buttons attached to the MCP23017. Wondering if the polling can be put on a dedicated thread with a high priority - how would the results be transmitted to the application thread and can the I2C bus be called to output values on the same MCP23017?
SYSTEM_MODE() are you using?
Have you tried
You have no option for interrupts?
All threads share the same set of globals. You may need to use thread sync mechanisms when accessing the shared variables tho’
Before using a dedicated thread, I’d also investigate Software Timers - they are also running in a separate thread.
Not sure what to make of that question tho’
As you sure know I2C is bidirectional, so not sure what you are after
SYSTEM_MODE(SEMI_AUTOMATIC); I like the fact that once setup the reconnection tries are then automatic. I could detect a WAP out of range and then turn off WiFi. Then the problem becomes when to turn it back on! Once you turn it on then there will be a short period of delay - can’t do that.
how would the results be transmitted to the application thread
My question could be better framed as - will I need to use thread sync mechanisms when accessing the shared variables? And how are these best implemented?
Software Timers - good idea, can the MCP23017 device (and I2C/Wire) be called from the timer handler routine? I know I can’t call Wire from an ISR and I thought Software Timer Handlers need to be very quick?
can the I2C bus be called to output values on the same MCP23017?
I will try to reframe that question - if I am calling Wire from say a Timer handler (to read the button status) can I also be calling Wire from the application loop to set the outputs on the same MCP23017?
I should have explained - the operation of the Photon in this case is like a ‘man in the middle’ between physical control buttons and linear actuators - so the button status is read and then if some sensors indicate it is safe then the actuator will be sent a command (pulse). It allows for the buttons to be ‘locked’ and also actuator commands from the web.
You can do more stuff in Software Timers than in an ISR but you need to consider the limited stack space (reduced depth of function calls) and that all timers share the same thread, hence having one “blocking” callback may bog down all other timers and the resulting backlog may result in a SOS panic crash.
That would also call for thread syncing (e.g. mutex).
But could you do both in the same timer callback and limit the use of the one
Wire object to that thread?
I set aside a couple of days to test this setup with some added debug output to understand what was going on and full control over the WAP (i.e. test WAP that could be turned on or off).
Findings were that WAP being off does not make a difference - which is very good because it shows the application thread is not being held up during repeated connection retries.
The blocking in the loop wasn’t actually blocking. The photon is used to scan 4 sets of up/down buttons and send TTL pulses to a monitor lift controller. What was happening was that an occasional button bounce or stickiness was confusing the logic which uses a method of dead-reckoning to track the position of the lift actuator - the logic then (correctly for the information it had) block further actions from button presses and made it appear like the button was not being read. The introduction of software debounce (there is already electronic debounce) and some changes in the polling times and pulse times has removed the problems.