Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Battery life lower than expected #1

Open
reversebias opened this issue Apr 23, 2017 · 21 comments
Open

Battery life lower than expected #1

reversebias opened this issue Apr 23, 2017 · 21 comments
Assignees

Comments

@reversebias
Copy link
Owner

I just had a CR2032 battery in one of my keyboard halves die on me, after 2.5 months of use. This is much lower life than I expected, as calculations showed 6-12 months of use.

Possible causes:

  • Too many retransmits due to RF interference (this did happen at an office with lots of wifi devices)
  • Bug in the firmware that causes a lockup and prevents sleep (should look into a watchdog)
  • Dodgy battery, I'll do a discharge test of one of these

If there's none of the above, possible ways to reduce power consumption:

  • Lower maintenance transmit frequency, not even sure if synchronisation is being maintained anyway
  • Reduce channel table size, this will reduce power consumed synchronising channel, at the expense of potentially lower coexistence performance
  • Transmit rate limit, may affect latency performance

I know it'll take months before anyone has another data point, but does anyone have any ideas?

@kdayns
Copy link

kdayns commented May 23, 2017

While waiting for my mitosis parts to arrive, I took a look at the transmiter code and the datasheet of the chip. And I have some ideas how to optimize it:

  • rtc0 runs too fast
    it should not read input faster than switch can provide! I suggest running rtc0 with 200Hz frequency which will read input with 5ms intervals, which effectively provides also debounce and simplifies code! for example, cherry mx debounces in 5ms!
  • aggressive deep sleep
    from datasheet:
    transition from deep sleep to execution state: 400uA in 10us = 4uA*ms
    system on (idle) consumes: 2.6uA with 16kB ram, 3.8uA with 32kB ram, it seems that cpu will use as much ram as needed, so we can assume ~3uA.
    so idling for more than debounce and event transmission seems a big waste of energy! cpu wakes up very fast and note, that keypress will last for ~100ms or even longer (this was what I saw for my keypresses), it is a lot of time to sleep.
  • rtc1 is not needed
    as I understand, QMK needs retransmission for held keys, but it should not retransmit something receiver already knows of, this must be done on the receiver side! If running low battery in the middle of the key press worries somebody then some king of ping can be initiated from the receiver side each second as a liveliness check if indeed key is held down.
  • lower radio data rate will use less energy
    it transmits only 3 bytes, don't know about link layer overhead, but I think the lowest rate will fit.
  • less retransmits
    user should know that the battery is drained by rf pollution (did moving receiver around help?). maybe some pins can be soldered together like a jumper to select retransmit amount (low, high)

when I will get my hands on the cpu and when I will have time to setup the toolchain, I will implement the changes myself if nobody will by that time (2-3 months from now).

@kdayns
Copy link

kdayns commented May 26, 2017

I looked at the SDK and could not figure out default channel table size (it is <16 because of enforced 5 mhz spacing when generated), it is generated from paired hosts id because it must match on both ends. As per documentation, channel table hopping is used for synchronizaiton, afterwards it runs on selected frequency for the synchronization lifetime which can be canged (nrf_gzll_set_sync_lifetime), don't know the defaults, which would be nice!
And regarding frequency, I think that the end of the frequency range tends to be more unused (around 2470-2480Mhz), at least where I am and in US!!
I think that the reciever side could gather some statistics on which channels it recieves data most often and then use that information to eliminate bad chanels, inject some additional to try and update channel table on both ends. This is more effort to develop, but could greatly improve radio part, if it turns out to blame.
Let's see how the radio part will work out for me, I am very concerned and worried of mitosis performance, because I work in very rf polluted enviroment where wireless devices are all over the place.

@reversebias
Copy link
Owner Author

Thanks for the comments!

  • rtc0 runs too fast
    I currently have it counting to 5 in 1ms ticks, to get that 5ms debounce. I think I was in the mindset of a matrix scanning (that needs constant scanning to debounce all keys). Do you see any problem with a 2 sample debounce algorithm?
  • aggressive deep sleep
    I initially didn't care about the 4uA, as using the internal pullups consumes 250uA per held key. However, the current version I'm working on releases the pullups between samples, so this would become the next low hanging fruit.
  • rtc1 is not needed
    It's not so much about QMK, more of my receiver firmware. It assumes that if there's no packets received for a second, that either the keyboard is out of range, or it's in deep sleep. This was to fix a problem I had of the receiver missing the keyrelease event (either brownout or RF collision), and never letting it go. So for long keypresses without any keystate changes on the keyboard end, it needed a maintenance retransmit. 8Hz is too fast for this, but was the slowest prescaler value. Receiver sending out a ping to the keyboards would require the RX radio to be active on the halves, which is on the order of 13mA.
  • lower radio data rate will use less energy
    Yeah, there are many overheads, but lower rate might help my SNR in RF loud environments too.

Default channel table is in sdk/components/properitary_rf/gzll/nrf_gzll_constants.h line 115: {4, 25, 42, 63, 77}, which is just 2404, 2425, 2442, 2463, 2477MHz respectively. If you're feeling a little rebellious, the chip supports channels out of the licenced bands too, but of course I wouldn't default that.
I agree that dynamic table updating is the ideal way, but the current system works very well even in a heavy polluted environment, I've never noticed any missed events or lockups, just high retransmit attempts which causes high battery drain. Well, the high retransmits works well when the battery is above 20%, anyway.

I really appreciate the attention and suggestions, thanks.

@joric
Copy link
Contributor

joric commented Sep 5, 2017

In my case GP batteries went completely dead (0.6v) after about 1 month of sleep mode (jul 31 - sep 5). So yeah, something's going on there.

@reversebias
Copy link
Owner Author

Yeah, this has progressively got worse for me. It may be that I've had a bad batch of batteries, but I've had a few only last a month too. A battery from the same batch with a 10mA CC load lasted out to 120mAh, but pulsed loads are probably a different thing.

I think that the chip draws much more power after a brown out, so internal resistance causing a dropout can can kill the entire cell. Obviously this is a bad thing.

I'm going to try running for a bit with alkaline cells, see if it's a firmware or a battery issue. Because tracing and summing the current for a transmit show millions of keystrokes possible, with 4uA sleep current, shouldn't kill a battery in weeks.

@whostoleallthenames
Copy link

Have you considered adding a pair of through-holes and another regulator to allow for other battery options? For example, a JST connector/header for a thin lipo, or larger through-holes to fit something like this 18650 holder - that would double as a tenting mechanism

@datagrok
Copy link

@whostoleallthenames I used an Adafruit JST-PH breakout board and a pair of female headers to connect a 3.7v lithium polymer battery pack to the programming pins in a way that's easily removable. So far, this is working great, seems like no regulator is required. 😄

mitosis-mod-1
mitosis-mod-2

@whostoleallthenames
Copy link

whostoleallthenames commented Nov 16, 2017

@datagrok Is that powering the board through the programming pins? Which pins are which?

@datagrok
Copy link

@whostoleallthenames yes it is!
Connect the positive terminal to the one closest to the word "Mitosis."
Connect the negative terminal to the one adjacent to that.
The other two are data pins only for programming.
It's the same arrangement on the left and right board (so my little adapter has to be connected upside-down on one side and right-side up on the other).

mitconx

@joric
Copy link
Contributor

joric commented Jul 27, 2018

@kdayns could you look at https://github.com/joric/mitosis/tree/devel/mitosis-bluetooth it's very alpha but it works, maybe you could help with the battery life there as well. I don't think it's even remotely energy effective at the moment.

@joric
Copy link
Contributor

joric commented Aug 4, 2018

I've noticed keyboards send gazell packets in bursts, like 6-7 the same packets for every pressed key. Shouldn't they send only one?

@kdayns
Copy link

kdayns commented Aug 6, 2018

I am running firmware with the following modifications:

  • no rtc1 - no resend timer
  • reciever runs on max power (4db)
  • keybord runs on low power (N12db)
  • lowered the bitrate to 250KBit for better rf sensitivity (timeslot period 2700 )
  • used optimization level of O2
  • max tx attempts lowered to 50 (my testing showed that when tx attempts went over 40, it was almost no chance of delivering it)

I am writing this here because on my rigth side the battery just died in exatly 3 months.
I was expecting much longer life because of the tweaks, but as I already told you, I am working in place with lots of wifi devices around, so maybe it is still a good number, I wanted to know the max I can get.
I will wait for my left side to die and then I will enable rtc1 and see how it will effect the results, because I am getting pissed lately at the stuck keys. Or maybe I have too low keyboard tx power for my aggressive environment.

Joric, I will check this week how many retransmits per keypress I
am getting, but as far as I can remember, you have lower number than I did.

It is hard to know how many keypresses in total was processed by each side for effective comparison, I tried running hid_listed which logged some info, but I think It started to perform not very vell after some hours or days of operation and I dropped the idea.
maybe I will debug it when I will collect the retransmit stats.

It would be interesting to wire the antennas directly together to exclude the radio interferrence in battery life, but then we need somebody to comment on how to properly do that.

@joric
Copy link
Contributor

joric commented Aug 7, 2018

@kdayns I don't know why you have 40 tx attempts I currently just use nrf_gzll_set_max_tx_attempts(0); in mitosis-bluetooth and it apparently works (reversebias uses 100), both for gazell client and for host (they're switchable in runtime). Also there's no debouncing anymore I just scan with 25 ms interval (I thought it sucks but figures out it's a good scan rate, many people use it). With all that, it doesn't look like I'm losing or skip keystrokes. Also I'm completely shutting down the board after, like, 4 minutes and it just reboots on keypress, seems fine.

@kdayns
Copy link

kdayns commented Aug 8, 2018

@joric max tx attempts 0 means maximum!
I am also noticing the same thing about multiple retransmissions, but sending(pressing buttons fast) very often helps, the retransmissions go down, this gave me a clue. I checked the documentation on how the devices mainain the synchronization and found out that nrf_gzll_set_sync_lifetime can change that value which when expired will lead to retransmissions!
When I have time I will try to play with this value, but right now I am getting ~50% packets without retransmissions when typing the other are the same as yours (<10), just collected the stats from 5k strokes.

@kdayns
Copy link

kdayns commented Aug 14, 2018

I tried increasing sync lifetime 2x and collected the stats on ~100k strokes.
This change greatly improved packet delivery for me, packets without re-transmissions have increased from 50% to 67%.
That is significant, but I bet it also depends on the typing speed as well.

@joric
Copy link
Contributor

joric commented Aug 17, 2018

@kdayns, it's claimed that this fork has better battery life:

FYI, there was a bug in the firmware which caused the receiver to constantly search for the boards, thus quickly draining the batteries.

See the fix here: https://github.com/repne/mitosis

After using the fixed firmware, the batteries work just fine. I'm currently 7 months in using the same set of batteries.

If someone could make a pull request out of it and get it merged that'd be cool.

@kdayns
Copy link

kdayns commented Aug 17, 2018

yeah, I don't see the fix too, just different debounce logic. Maybe it is relevant only to the repne's branch.
I just want to remind you, the battery life will be proportional to the amount of typing done.

@joric
Copy link
Contributor

joric commented Aug 17, 2018

@kdayns, not just debounce, it uses a single RTC timer at 125ms. Plus there's something going on with the receiver as well.

@kdayns
Copy link

kdayns commented Aug 17, 2018

I'am also running single rtc but at 1ms, debounce, send and go to sleep.

@nhou7
Copy link

nhou7 commented Aug 29, 2018

I was the one who said he was on 7 months with the same batteries that @joric linked to above. The modifications seriously made a huge difference in battery life.

It seems like he changed up debounce logic, single RTC, antenna at 4 dbm, changes for receiver timeout, (6 ms) and a few other things in the receiver code that I haven't had a chance to sift through yet However, some of it looks like its just cleanup by moving certain things that used to be in the main function into their own separate functions to be called upon.

I'm looking at some of the commentary that Repne made in my Discord channel while he was actively working on the fork, and here are a few things he mentioned:

I've cleaned up the receiver code
and made the antenna to work at 4 dbm (it was 0)
it will consume more power, but thanks to the many power fixes I've made to the original firmware, it should at least cancel out (but I'm much more optimistic than that)
timeout time it's been set to 6 seconds (that's how long you can press a key)
it was a random amount before

@joric
Copy link
Contributor

joric commented Aug 29, 2018

Thanks, @nhou7 I'll check it up. I'm also considering a possibility of adding bluetooth (nrf5x) support to QMK, instead of adding QMK to the bluetooth firmware (QMK is not really a library, rather a hardware platform), might be easier this way.
Upd. added bluetooth support to this firmware, haven't checked battery life https://github.com/joric/bluetosis but it's sure even worse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants