PMunch / badger

Keyboard firmware written from scratch using Nim
72 stars 7 forks source link

Low-power mode and other power-preserving techniques #5

Open dumblob opened 2 years ago

dumblob commented 2 years ago

I wonder how power efficient this firmware is or could be made.

  1. Do you deliberately turn off everything (peripherals, ADCs, flash memories, co-processing engines, special counters, etc.) in the uC which is not being used for the keyboard?

  2. Do you support something like automated sleep mode after the keyboard is not being used for a while? Depending on uC we could sleep even during a press (i.e. before depressing) and not just between a depress and next press. See related next question.

  3. Do you support avoiding current going through all keys if none of them is pressed? I mean I heard of a trick to "invert" the low/high states of buttons but didn't try it myself yet (this would also require a near-instantaneous awakening of the keyboard from the deep sleep in (2) ).

PMunch commented 2 years ago

I haven't really done any kinds of optimisations like that as of yet. Badger in it's current state is pretty bare-bones, almost more like a library than a fully completed keyboard. That being said I just plugged it into a "Charger Doctor" and that isn't able to detect any current flowing through it. The display goes down to 0.01A or 10mA, but it also lists a 10mA error range. I tried to connect an old mouse to it as well, and it goes between showing 0.01 and 0.00, so that seems to use more power. Unfortunately I don't have an easy set-up to inline my multimeter with a USB connector, so I can't easily get a reading for how little it actually consumes.

dumblob commented 2 years ago

Wow you're quick!

Once I get the HW (with the supply chain issues etc. this might take many weeks), I can measure it with multimeter (I'll cut some USB cable to run it through it - with USB 2.0 this rough method still works :wink:). Another method would be to calculate it from having some capacitor or battery charged to a given degree and measure its voltage every 5 minutes or so.

Do you think the aforementioned SW adjustments make sense?

PMunch commented 2 years ago

Haha, to measure that I just had to put my hand in a drawer next to me and replug a USB, not the most time-consuming task.

I probably should make a USB power measurement rig anyways, I think I have some USB sockets and old cables lying around so shouldn't be too hard. I'll update you if I get around to it.

Number one definitely makes sense, disabling anything that isn't required should be easy enough. I've also thought about sleep modes, which would essentially be required if this where to be run as a bluetooth keyboard. The problem here is to have a good wake-up condition. Essentially if you want to have a key able to wake-up the keyboard then you'd need a way to detect any key-press regardless of key without scanning the matrix. Shouldn't be impossible, but I haven't looked into how this could be done, and it would probably require a different interface between the two halves (the TRRS plugs I use now only have four connectors, which are all used for I2C and power).

Same goes for point number three, but sleeping between keystrokes is going to add latency no matter which way you do it, whether or not that latency matters at all is a different question.

All in all I think there's a lot that can be done to conserve power here, but I haven't really looked too deep into any one of these.

PMunch commented 2 years ago

Okay, so after cutting a cable in half and replacing the fuse in my multimeter with a hex-bit (whoops, that fuse has apparently been blown for a while) I was able to measure the amperage. It seems to be right about 29mA at 4.45V, so about 129 milliwatts so about 120 hours on four AA batteries, not bad without any optimisations!

dumblob commented 2 years ago

The problem here is to have a good wake-up condition. Essentially if you want to have a key able to wake-up the keyboard then you'd need a way to detect any key-press regardless of key without scanning the matrix. Shouldn't be impossible, but I haven't looked into how this could be done, and it would probably require a different interface between the two halves (the TRRS plugs I use now only have four connectors, which are all used for I2C and power).

Actually this might be side-stepped with the trick of an "inverted" state of (some) keys. But I can't comment on that off the top of my head without investigating what I read back then when I spotted it.

Okay, so after cutting a cable in half and replacing the fuse in my multimeter with a hex-bit (whoops, that fuse has apparently been blown for a while) I was able to measure the amperage. It seems to be right about 29mA at 4.45V, so about 129 milliwatts so about 120 hours on four AA batteries, not bad without any optimisations!

I didn't even sit down to read your code and you already have most of the answers :open_mouth:. Thanks!

29mA at 4.45V is good for USB-connected full-on uC without any optimization. But it's too much for an external USB keyboard. I wonder how deep the different sleep modes of the Teensy 2.0 uC can be regarding the wake-up delay. For me I think 3-5ms delay to waste only on "wake up" is still acceptable. But if it'd be more, then it could pose a problem (latencies add up - considering the i2c communication etc.).

All in all I'm afraid that we can't go much deep as we can't turn off USB to avoid endpoint renegotiation on key press/depress which I suppose would add tens of milliseconds of latency at the least (or actually probably hundreds because os-dependent routines for device detection would need to fire and configure it as keyboard all the way up to the user interface which would resemble an avalanche of expensive hooks).

But maybe USB protocol is tolerant and we can actully turn off USB for a very short time periodically which could again save some power for us. IDK

PMunch commented 2 years ago

Do you have a link explaining the inverted state thing?

The mouse I'm using uses 40mA while moving and 20mA while standing still, but I can't really measure my keyboard consumption easily since it's a Bluetooth one. I guess I should try to disable various stuff, and possibly do some sleeping in between matrix reads or something just to check it out.

Very good point about USB renegotiation, but maybe light-sleep is still possible? Another thing that would bring the power consumption way down according to this is to turn the clock speed down, it currently runs at the full 16Mhz.

dumblob commented 2 years ago

Do you have a link explaining the inverted state thing?

Ok, it seems my memory was too vague and it doesn't apply to Badger. But anyway, I've remembered the project so I simply asked about it and here is what it was about: https://github.com/betrusted-io/betrusted-hardware/issues/5 .

The mouse I'm using uses 40mA while moving and 20mA while standing still, but I can't really measure my keyboard consumption easily since it's a Bluetooth one. I guess I should try to disable various stuff, and possibly do some sleeping in between matrix reads or something just to check it out.

:+1:

Very good point about USB renegotiation, but maybe light-sleep is still possible?

From my experience with embedded uCs I guess there are even multiple light-sleep modes which won't cut off USB completely.

Another thing that would bring the power consumption way down according to this is to turn the clock speed down, it currently runs at the full 16Mhz.

Yes! I totally forgot about this one. Shame on me. That's one of the main sources of power consumption (and preservation).