SmartSpin2k icon indicating copy to clipboard operation
SmartSpin2k copied to clipboard

[FR] Idle sleep mode

Open eMadman opened this issue 3 years ago • 15 comments

Issue in-home use opens up the possibility that SS2K will be left plugged in for extended periods of time, broadcasting its availability over Bluetooth and maintaining connectivity.

Describe the solution you'd like timeout that disables wifi and bluetooth until the device is woken up by button press on the shifters... maybe the same approach that's used for reconnecting (ie, hold both buttons for 3s)

Describe alternatives you've considered pull the darn plug

eMadman avatar Feb 23 '22 20:02 eMadman

Good idea, we can send ESP32 into Hibernation mode and wake up when a shifter is pressed. How should we calculate the timeout? Is it possible to detect that now data from Power Meter / Zwift / HR Belt are received? If this is possible adding a "LastReceiveTimestamp" to BLE Client / BLE Server and checking this timestamp in the main loop should work. If timeout expires, all task are killed and ESP32 is sent to hibernation mode. If possible step driver could also getting disabled.

After shifter interrupt, all getting enabled. https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html

Need to check if shifter interrupt is able to wake up ESP32 from hibernation.

MarkusSchneider avatar Feb 24 '22 08:02 MarkusSchneider

I believe hardware interrupts are the preferred method for wakeups actually.

I'd say if no clients or servers are connected and no shifter has been pressed for 30 minutes, hibernate. We can already check clients with: https://github.com/doudar/SmartSpin2k/blob/d0d6a524ddd10927f569f89a7e77cc8793693ce7/src/BLE_Server.cpp#L548-L555

You could also check connected servers by implementing the following function:

int connectedServerCount() {
  int _serverCount = 0;
  for (i = 0; i < BLEDevice::getClientListSize; i++) {
    if (BLEDevice::getClientByID(i)) { //nullptr check
      if (BLEDevice::getClientByID(i)->isConnected()) {
        _serverCount++;
      }
    }
  }
  return _serverCount();
}

On wakeup, I think it's probably best to run all of setup, but maybe it's not needed :man_shrugging:

Is this something you're interested in implementing Markus? I'm super busy with work for the next month.

doudar avatar Feb 24 '22 15:02 doudar

Something to consider... I don't think heart rate monitors go to sleep on their own. At least, I think mine stays on until it times out due to lack of heart rate. The power meter and spin bike usually power down after inactivity though

eMadman avatar Feb 24 '22 16:02 eMadman

Something to consider... I don't think heart rate monitors go to sleep on their own. At least, I think mine stays on until it times out due to lack of heart rate. The power meter and spin bike usually power down after inactivity though

Wouldn't that be considered inactivity on the part of either device though? (lack of heart rate == inactivity)

doudar avatar Feb 24 '22 16:02 doudar

Good point! I fell into the whatabout trap of "what if the user leaves the HRM on for an extended period post-ride"

eMadman avatar Feb 24 '22 16:02 eMadman

I've tested hibernation mode and got it working. But wake up is only working if a RTC Pin is used. RTC GPIOs are highligted in light orange in the picture below.

For the shifter Pin 18 + 19 is used. These pins are no RTC Pins.

Now we have to options:

  • use RTC Pins for shifters
  • use extra button for wake up

image

If you like to test it by your own:

  • I've created a new branch "hibernation_mode-#331"

see main.cpp https://github.com/doudar/SmartSpin2k/blob/ff1c02d92f93bc81c9d6fe285fe907faa03f8e2b/src/Main.cpp#L419-L430

and index.html image

also update HTTP_Server_Basic.cpp and added an Endpoint for hibernation request.

MarkusSchneider avatar Feb 27 '22 13:02 MarkusSchneider

I think moving these pins is something we should target in the new pcb.

I propose adding another section to the platformIO.ini for pcb2 and then compiler if statements in settings.h for the pin labeling and hibernation modes.

We will probably do this anyway because there's a fair chance pcb 2.0 will incorporate a larger psram esp32.

Let me know what you're thinking for pin mapping so we can draw up a plan.

Tagging @alexquilty on the conversation as well.

doudar avatar Feb 27 '22 14:02 doudar

Conditional compile is a good idea. Hibernation has also benefits for "old" boards only wake up is not working and you have to re power the board, but suspend mode will work if you forget to plug out the board.

For pin mapping I have no preferences any RTC Pin will work. If you like, I can implement hibernation mode now (including BLE traffic check) and the wake up function comes then with the new pcb.

MarkusSchneider avatar Feb 27 '22 15:02 MarkusSchneider

Conditional compile is a good idea.

Hibernation has also benefits for "old" boards only wake up is not working and you have to re power the board, but suspend mode will work if you forget to plug out the board.

For pin mapping I have no preferences any RTC Pin will work.

If you like, I can implement hibernation mode now (including BLE traffic check) and the wake up function comes then with the new pcb.

Any chance you could do a periodic wakeup to scan for BLE and if one of the selected devices is available, do a full setup, if not sleep again?

If WiFi stays powered down, power consumption is very minimal.

doudar avatar Feb 27 '22 15:02 doudar

I've added light sleep mode. In light sleep any gpio is able to wake up 😉.

BLE, ERG and HTTP is stopped while sleep mode is enabled.

https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/src/Main.cpp#L425-L446 After wake up the whole setup and loop logic is called.

Also added new field in rtConfig. https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/include/SmartSpin_parameters.h#L94-L95

to hold the last BLE connection timestamp. With every new BLE Client message, lastBLEPackateTimestamp is getting updated. Hope this is the right place to check for BLE messages 😐. https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/src/BLE_Client.cpp#L40-L48

In the main loop, a check is made and if last BLE message is older then 30 Minutes, sleep mode is entered (L179-180). https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/src/Main.cpp#L173-L182

MarkusSchneider avatar Mar 01 '22 14:03 MarkusSchneider

Looks good!

@MarkusSchneider , do you think we should still move the shifter pins to an RTC pin in PCB version 2.0?

One of my concerns is the shifters are currently on the JTAG pins, so even if we don't use deep sleep, maybe we still should move them?

doudar avatar Mar 01 '22 14:03 doudar

I've added light sleep mode. In light sleep any gpio is able to wake up 😉.

BLE, ERG and HTTP is stopped while sleep mode is enabled.

https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/src/Main.cpp#L425-L446

After wake up the whole setup and loop logic is called. Also added new field in rtConfig.

https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/include/SmartSpin_parameters.h#L94-L95

to hold the last BLE connection timestamp. With every new BLE Client message, lastBLEPackateTimestamp is getting updated. Hope this is the right place to check for BLE messages 😐.

https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/src/BLE_Client.cpp#L40-L48

In the main loop, a check is made and if last BLE message is older then 30 Minutes, sleep mode is entered (L179-180).

https://github.com/doudar/SmartSpin2k/blob/042fa5a2f47ddad88acacc008de028da5b32baa2/src/Main.cpp#L173-L182


Your current tests only check for a remote server connected to our client. We have use cases where only a remote client is going to be connected to our server and those should be checked.

You should add a test for this by using this function:

https://github.com/doudar/SmartSpin2k/blob/d0d6a524ddd10927f569f89a7e77cc8793693ce7/src/BLE_Server.cpp#L548-L555

or by putting your existing rtconfig time stamps on

https://github.com/doudar/SmartSpin2k/blob/1f8d20299e34dc9c27d6b98c2bcb9d22a16e3918/src/BLE_Server.cpp#L621 and https://github.com/doudar/SmartSpin2k/blob/1f8d20299e34dc9c27d6b98c2bcb9d22a16e3918/src/BLE_Server.cpp#L354

doudar avatar Mar 01 '22 16:03 doudar

Ok thx for point this out, I'll add the update of the timestamp also to the BLE-Server.

Yes, leaving JTAG Pins free will allow to use a JTAG Debugger for development. I tried it in the past and had to move the shifter GPIOs. With PCB 2.0 we can go with deep sleep and RTC GPIOs (to consume less power) for the old version light sleep will be ok I think. Main benefit is that BLE is disabled and advertising is stopped. I'll do a test tomorrow if all works well, I create a pull request 👍

MarkusSchneider avatar Mar 01 '22 16:03 MarkusSchneider

Ok thx for point this out, I'll add the update of the timestamp also to the BLE-Server.

Yes, leaving JTAG Pins free will allow to use a JTAG Debugger for development. I tried it in the past and had to move the shifter GPIOs. With PCB 2.0 we can go with deep sleep and RTC GPIOs (to consume less power) for the old version light sleep will be ok I think. Main benefit is that BLE is disabled and advertising is stopped. I'll do a test tomorrow if all works well, I create a pull request 👍

Awesome!

I have a meeting in person tomorrow with the Purdue senior design project EE's that are going to be working on the PCB, so if you can think of anything else that should be done on the new PCB, please let me know. I'll also be sure to get you one of the new PCB's once we have working prototypes.

doudar avatar Mar 01 '22 16:03 doudar

@MarkusSchneider , I'm just going through old issues and wonder if this is one we can tidy up and merge into develop?

doudar avatar Jul 09 '22 00:07 doudar