Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
A Proper Uppercut
Sep 30, 2008

cakesmith handyman posted:

Is it more efficient to step the voltage up or down? With 2 or 4 x 18650 you can choose either way.

Googling "pi alternatives" gives you a hundred but I've no experience with them.

I was debating this, but it's much easier to get a BMS that can handle a 1s battery rather than one that needs to do balancing with multiple cells. That's the conclusion I came to anyway.

Adbot
ADBOT LOVES YOU

Cory Parsnipson
Nov 15, 2015

cakesmith handyman posted:

Is it more efficient to step the voltage up or down? With 2 or 4 x 18650 you can choose either way.

Googling "pi alternatives" gives you a hundred but I've no experience with them.

I came across this article that seems to do a similar comparison: https://www.eetimes.com/buck-boost-vs-buck-converter-its-about-battery-life-in-portables/

eetimes posted:

Throughout most of the battery discharge curve, both converters operate in a buck mode (Figure 3). This gives the performance advantage to the buck converter, which has one less power MOSFET in the power conversion process. Below 3.5V, the buck-boost converter input current increases (Figure 6). This increasing current, compounded with the characteristic increasing battery discharge rate, quickly discharges the battery below 3.5V (Figure 4).

In summary, the buck converter consistently displayed equal or better battery life. At 300mA, the buck output voltage remained within the 5% tolerance for up to nine minutes longer than the buck-boost. Additionally, the buck converter continued to operate in dropout mode, tracking the battery voltage for an additional four minutes. At 800mA, the battery life was identical for both converters.

Note that part where it says "This increasing current, compounded with the characteristic increasing battery discharge rate, quickly discharges the battery below 3.5V". In my post before, I mentioned that the boost converter caused extra current draw from the batteries (is harder on them) to step the voltage up to 5V. The buck converter steps down the voltage and steps up the current which means less current draw on the batteries. What these guys are saying is that when the buck/boost switches to boost mode because the batteries' voltage drop, it starts drawing current at a higher rate and the batteries drain a lot faster, meaning that the time spent in boost mode is smaller. So it seems the buck converter gives you better returns. This seems to apply only for tasks that weren't power hungry. Otherwise, the battery life was identical regardless of which converter was used.

I guess it boils down to the physical realities of boost vs buck conversion and the fact that the buck converter design uses less components and has a smaller footprint. However, this experiment was dealing with 3.7-4.2V cells and getting 3.3V output out of them. We're kind of in a tough spot where we need 5V from 3.7V cells and that kind of sucks in every combination. This means we have some extra cons to the buck conversion approach because we have to deal with balancing cells put in series and the extra space that the additional cells take up.

A Proper Uppercut posted:

I was debating this, but it's much easier to get a BMS that can handle a 1s battery rather than one that needs to do balancing with multiple cells. That's the conclusion I came to anyway.

Same. I might do a bigger battery pack later but the first one is going to be 1s for me.

Cory Parsnipson
Nov 15, 2015
This battery babysitter kind of loving sucks

First order of business should be to hook up the babysitter to external power and then to the RPi and watch it act as a wall power passthrough and see if that works. Cool, so I'm reading the hookup guide again, and I realize that I needed to figure out a way to hook the babysitter to the battery. I bought a JST PH connector kit and crimper as I showed in my last post to fix the problem.

But what about hooking up the babysitter to the RPI?

...gently caress. Didn't think that far ahead. The documentation shows them using another JST PH connector, which is a cool coincidence because I have that stuff too! Except I want a right angle connector and my kit only has straight ones. No problem, if I bend the pins and solder it in upside down, there's just enough length for me to fasten it to the board. It's not like I've hosed myself in the past by bending pins that shouldn't have been bent.


One connector straight out of the box, and another where I bent the pins

What, but what about the other side of this wire? How am I supposed to hook this up to the RPI???

...gently caress. Didn't think that far ahead. The RPI has a micro usb port that I've been using to plug into power. I could also solder wires directly to the underside of the exposed power USB traces (eww definitely not), or I could also use two dupont connectors to plug into the 5V and gnd GPIO pins. This latter method isn't recommended because the pins aren't rated for high currents and don't have a fuse in front of them like the USB port does.



Welp, I guess I'll just buy some micro USB connectors and make myself a bespoke cable. I got me an Amazon prime trial so I'm going to be ordering a lot of stuff off Amazon this month. I can't really recommend the connectors I got, however, because they have these spikes that stick out of the connector that make it a real pain to pull out the connector from the socket.



This actually works, according to my multimeter. I needed to bend the wires down and I reinforced the solder joints with superglue and electrical tape. It's kind of an ugly solution, especially since the HDMI port is right next to it. So for the prototype, I'll have to figure out what I'm going to do to expose the HDMI port while keep the power USB port completely inside the case.





So I hooked everything up without the batteries just to check if it can passthrough and... nothing. A quick peek back at the documentation for what the voltage drop on this thing is... Allegedly 0.1V-ish... I'm using a cell phone wall wart that is rated 5V and 1.8A*. Measuring the output voltage into the RPi shows me ~4.83V. This should have been within the tolerance for the RPI to power up, but as can be seen in the previous two pictures, there's no activity in the screen or the green flashing LED that should have powered up when I plugged in the power. And the ip address is nowhere to be found on my network so I can't ssh into it. The thing never even booted up.


"Frick"

*Since the RPI3 could potentially draw up to 2.5A, I should use a wall wart rated for 2.5A. This is why the Raspberry Pi Foundation stresses that you need to buy their special, high quality power supplies. :rolleyes: I think I should be fine for the most part, unless I run into a case where I end up revving the RPI3 up so hard it actually hits 2.5A of current draw. I'll find a better power supply later!

Wait a minute, wasn't this thing made for portable RPi projects? Why don't these pieces fit together? Wtf???

SparkFun posted:

You can swap the RedBoard out for any Arduino-compatible development board. Regardless of whether it runs at 3.3V or 5V, 8MHz or 16MHz, any Arduino should work with the Battery Babysitter's fuel gauge IC.

:thunk: Oops.

Arduinos can run at any voltage between 3.3V and 5V. Maybe they have a buck/boost converter on the board. Whatever it is, the Raspberry Pi people should copy whatever the Arduino people did. (To be fair, the Arduino is a low power and low performance micro controller compared to a full blown ARM single board computer. But still, what the gently caress.) Man I'm really getting into the weeds here. BUT THAT'S OKAY. I haven't exhausted all my backup options yet. I still have to add on the boost converter for the battery anyway, so hopefully that should fix all my problems even with external power. (As a side note, if we're boosting off external power, even if it's just a tiny bit of voltage step up, we are increasing current usage coming from the power supply and the wall outlet. This means I'm running up against the 1.8A rating even faster than I'd expect and that's not good. I'm risking having the RPI brown-out and possibly corrupt the SD card and in the most catastrophic case, the power supply would heat up too much and catch fire. But I mean, I'd have to encode a lot of 4k video for that to happen, I think.)

cakesmith handyman
Jul 22, 2007

Pip-Pip old chap! Last one in is a rotten egg what what.

I don't use anything other than OEM pi PSUs, they're useless for anything else but I've never had a power issue with one of those in the loop.

I'm sure someone will tell me I'm wasting my money, but it's only £7.50

Cory Parsnipson
Nov 15, 2015
No it's definitely not a waste of money, don't get me wrong. The power rating is important, it's just annoying that you need to keep track and that everything is different even though they all look the same on the outside. I'm probably gonna order one off Amazon today.

Cory Parsnipson
Nov 15, 2015
drat, I got this huge box in the mail yesterday and I didn't even order anything big. I wonder what it could be?



Oh shoot, there's another large box inside of it.



It's the boost converter! Jesus, did I mess up and buy something the size of a grapefruit again?



:what:

Good news is that, no it's not huge. But, man, I got some recyclin' to do.

Bad news: this boost converter isn't what I need

Cory Parsnipson posted:

This stupid loving babysitter has a section that's 5 paragraphs long with a "TL;DR" in the middle to summarize the first 3 paragraphs just to tell you what the output voltage of this circuit should be. It varies anywhere between 3.6 to 5V depending on whether the external power and/or battery is present and how charged the battery is and the load.

I took a closer look at the MPS datasheet and the boost converter part that I ordered only works between 2.7V and 4.2V and I forgot that I need to handle what happens when the external power is plugged in. The SparkFun babysitter will give me up to 5V in that case and that means I can't use this part on the output.

Commodore_64 posted:

Good news! There is such a thing as a buck/boost or sepic controller. I’ve had great luck with this company for past hobby projects. https://www.pololu.com/category/133/step-up-step-down-voltage-regulators

Commodore_64 found me a perfect buck/boost converter that looks like it'll work. I ordered one and it should be here in several days. In the meantime, I need to figure out if I can return the MPS one...

OSH Park is here

Oh also, I got a package from OSH park!



Huh, I wasn't expecting it to come with the mouse bites still attached. Looks great though. I need something to file down the points on it. I don't think I'm going to assemble these boards unless I really have to. I have all the parts to make one, but I'm saving them for the JLCPCB design that I made. That's gonna be a challenge.

Cory Parsnipson
Nov 15, 2015
First Class is a Euphemism for Coach

So I really hope this first class package estimated for between 3 - 8 days would go a lot faster than the 3 - 8 days estimate, especially since it's coming from... *checks notes* Las Vegas and going to California. Maybe please don't sit there in San Francisco for 3 days doing nothing?



Ok cool. That's fine. The package did come in today, though. So I can figure out how to use it today.

JLCPCB is also here, but I'm too lazy to open it


Ooooh


:what: Between the haribos and this advertisement in the shape of a puzzle, these electronics companies are really trying hard to get me to connect with my inner four year old.



The boards were underneath the puzzle and it's weird looking at something that's not ENIG plated. Also weird seeing the dpad contacts in real life. They're beautiful ;_;

By the way...

I started playing Breath of the Wild a few weeks ago (which could be behind my noticeable lack of productivity lately...) and I've really been missing out. It feels so amazing playing it in portable mode. None of this time trial, mission based horse poo poo. This is a real, actual whole-rear end game on a tablet and it's a lot of fun. It's rekindling the excitement and inspiration for why I want a portable in the first place. This is nice and I wasn't expecting that to happen. Also Breath of the Wild is amazing. When I open a treasure chest, I've literally gasped (because many times the contents are genuinely useful), when I shoot a pig and get some meat to finish a quest I cheer because the hunting system was nuanced and difficult enough that I needed to learn how to do it and fail at it a few times beforehand. I climb up to a hill and look through a scope at mountains and strange landmarks and I can go to those places out of curiosity and every moment has me feeling like I'm advancing towards the main goal of saving the world. All the game systems are unexpectedly complex, and reinforce the focus of surviving and exploring. It's really strange playing a Zelda game and feeling like I'm playing Metal Gear Solid and I really dig it. Goddamn, I love Metal Gear Solid.

Cory Parsnipson fucked around with this message at 02:43 on Aug 10, 2021

Vim Fuego
Jun 1, 2000


Ultra Carp
I am nowhere near caught up, I'm still back on page 2. But this is an excellent thread. It reminds me of Ben Heck's youtube videos. Thanks for sharing!

Cory Parsnipson
Nov 15, 2015

Vim Fuego posted:

I am nowhere near caught up, I'm still back on page 2. But this is an excellent thread. It reminds me of Ben Heck's youtube videos. Thanks for sharing!

Oh, thanks man, I really appreciate that. It gets worse after page 2. :unsmigghh: I'll get it eventually.

Cory Parsnipson
Nov 15, 2015
Here's the buck/boost converter. It's even smaller than the other one. The page has a warning that says it can get hot enough to burn you, so I'll need to be careful not to have the big components touch any PLA or sensitive components around it.



A little bit of cutting and some soldering later...



And it still doesn't work! I checked the voltage and now the babysitter is outputting 3.01V and the converter is somewhere like 4.04V so the raspberry pi definitely isn't turning on. I don't know exactly what is going on, but I ordered a 3A power supply designed for the raspberry pi to see if it's the power supply that's doing this. When everything except the raspberry pi is hooked up the babysitter and converter are at 5V as expected. Man, this is annoying especially since the raspberry pi by itself can run off any of the cell phone power supplies I have lying around in my room, but if I add my lovely battery pack onto it, I exceed the power budget that they can give me. (If that even is what's going on here.) This is turning into a real clusterfuck. :thunk:

EDIT: FIGURED IT OUT

Under the charging current section of the battery babysitter, there's a part that talks about configuring the charge current to the battery. The default is 100mA (booo! it's a safe default to trickle charge the battery, but not nearly enough for running a raspberry pi). I didn't think this would really impact how much current comes out of the babysitter, but knowing all this shenanigans they did with "output current is the sum of battery supplied current and external current", made this seem like a good thing to try.

Well, I won't cancel the raspberry pi power supply because it's still safer to use that. Another thing to note is that this babysitter circuit itself becomes a bottleneck for power transfer and may cause complications if the raspberry pi actually ends up hitting the full 2.5A load. I will need to understand the design and make the 2.0 version of this part carefully so it doesn't poo poo itself at max load.

Cory Parsnipson fucked around with this message at 08:17 on Aug 12, 2021

Cory Parsnipson
Nov 15, 2015
I charged the battery up using the babysitter so now it's sitting at an "ok" 4.12V. (Ideally it's supposed to be 4.2V) and I went off the grid for approximately 1 minute and 13 seconds.



:hellyeah:

Earlier I stuck the battery in and tried to start it up and it didn't work. That time, the battery was at 3.63V, which is slightly lower than the 3.7V (the nominal operating voltage of a lithium cell when it's discharging). This is concerning because we should be able to discharge the battery down to 3V, but if it already doesn't work at 3.6V, then that's the entire lower 50% of the battery's charge that we can't use. I think the fact that the babysitter is designed to only supply 1.5A with just the battery exacerbates this issue (because I think the boost converter would need extra room in the current rating to boost a lower voltage to 5V). Not entirely sure about that yet...

So now I gotta fit all this into the frame I made and hope that it all doesn't sum up to a grand total of 15 minutes of battery life. Currently I'm in the "step-down-voltage-is-way-more-efficient" crowd because having a lower C rating on discharge prolongs battery life and is more delicate on the batteries but most importantly reduces the current requirements of the device and I feel like that might be really useful.

There's also a few other things I need to do too. I have to put in a momentary push button to let you turn the device on and off. This might be really difficult. The turning on part, I mean. Turning off is simple. I hook the button to a raspberry pi GPIO and ground and then write a bash script to listen on the falling edge of the GPIO and then throw up a confirmation that will run sudo shutdown -h now. Turning it back on sounds more difficult. There's this whole issue of power draw while suspended. The raspberry pi sucks at this and specifically the RPi3 draws almost as much power, ~300mA) halted as it does when it's on and idling. I don't think the RPi4 is any better. (Yes, this does baffle the members of the RPi forum). If the raspberry pi just sucks, there's not much I can do about it.

Maybe there could be a way to physically disconnect the battery pack from the RPi on shutdown, but then turning it back on seems hard. Hmmm....

Cory Parsnipson
Nov 15, 2015
I think the battery system is good to go for now. That doesn't mean it's not absolutely crappy and inefficient but it will let me unplug and gently caress off somewhere for a little while. I will do some battery life tests later and I still need to hook up the I2C port for the fuel gauge.

Also, more exciting news: what started as a throwaway add-on has revealed itself to have some juicy potential. I was digging around into adding a power button to the Raspberry Pi because power buttons are actually a lot more complicated than they appear unless you are happy with a toggle switch or something that physical connects and disconnects the wires to the power supply.

It's a power button. How complicated can it be???

The simplest thing is to get a toggle switch that will physically disconnect or connect the wires between the power supply and the Raspberry Pi and be done with it. This has numerous cons for our purposes. For one, if you accidentally bump it at any time, the power will cut out and then you can say bye to your current game data. Worst case, you can corrupt the SD card if it's in the middle of a write. To properly shutdown you will have to initiate with software, wait for the system to shutdown, and then toggle the switch to disconnect the power supply. Who wants to do that with high level consumer electronics? This ain't 1995 bitch, no way am I gonna manually flip a switch after waiting for the computer to halt. Also toggle switches are relatively expensive and bulky--i.e. like one of those metal pole things on an airplane dashboard. That'll look really stupid sticking out of a gameboy. Or cool, if you like the whole vintage/steampunk aesthetic, but that's not me.

Here's my ideal power switch:

* Momentary press to turn on from powered down state.
* Momentary press when the device is on will show a status overlay with battery percentage and maybe other metrics I'll discover that I want later after using it
* Short press and hold (~3 seconds) will open a dialog box with confirmation for shutdown (or sleep, if possible to implement)
* Long press and hold (~10 seconds, actual time is negotiable) will do a hard shutdown of the device by disconnecting the power supply. This is for when the RPi freezes or crashes and you need to reset it.

This is pretty much how the 3DS, Switch, smart phones, and most modern electronics behave.

Man how are we gonna do that? I am absolutely not ready to just think up my own poo poo to accomplish that. But here's the awesome part! This is all possible and completely able to be implemented thanks to the fact that a lot of smart people wanted to do exactly this and were also experimenting with Raspberry Pi's (and other embedded SBCs and microcontrollers). Yes, that's right. I think I can get this into the prototype instead of pushing it back to the second version like I've been doing to everything up until now.

Soft Latching Power Button

There's a whole class of things called "Soft Latching Power Button/Soft Latching Circuits". "Soft Power button" means the button is hooked up to GPIO and uses software to handle a portion of its operation. The "latching" part refers to the fact that you use a momentary push button to bridge a signal only while you have the button pressed down and then the signal goes back to normal when the button is released, but the circuit remembers that you pressed the button. Subsequent presses of the momentary push button will toggle the circuit state. This is interesting to me, because I'm familiar with a latch in a digital logic context but I wouldn't have thought to use this pattern with discrete transistors and using a button as the clk and enable signals. I suppose this is actually the original way transistors were used, weren't they?

I dug up this circuit that someone designed from a project called Mosaic that was linked off the Raspberry Pi forums.



From the description on the page, it sounds like it does pretty much everything I ask for, but holy hell. How does this even work???? This is just a tangle of poo poo connected to other poo poo. I had some serious learning to do, so I did what everyone else does when presented with an important task requiring you to learn information that must not be incorrect: look stuff up on Google and YouTube.

A look up of "soft power button" or "soft latching power button" or some variation of the phrase will give you a bunch of useful education resources on Google. Knowing the names of things is extremely helpful. In particular, I came across this one video off EEV blog talking about these things. He starts from scratch and goes through the thought process of designing a similar but different soft latching power button circuit from the Mosaic design above. I thought this video was invaluable for understanding how the circuit works and how different circuit paths are activated depending on how the transistors are biased and how the user presses the button. All other designs operate on the same basic principle with small variations depending on their feature set. EEVblog is really good. (NOTE: you still need intermediate knowledge of circuit design and a basic knowledge of semi-conductors to understand this stuff. FYI in case you watch the video and things still don't make sense.)

I then found a blog post on Hackaday where there is another video where some dude analyzes five different latching power switch designs and that was kind of helpful to see an alternate explanation. Also, the Mosaic design was the second circuit he talked about so that was extremely useful. Unfortunately, he said he couldn't get this design to work right, so that's not a good sign. Maybe it has a design flaw, but I don't know enough to know that.

Just to summarize, here's a block diagram with all the power system components in it:



CONVENIENCE MAKES US WEAK :black101:

Oof. I found a soft power switch on Sparkfun. I was going to finish trying to understand how the circuit work and then buy the components and make something on a protoboard, but this prebuilt board is tempting. At 4 bux, it's pricey but I'm only going to need one. Decisions, decisions...

Cory Parsnipson fucked around with this message at 00:22 on Aug 15, 2021

babyeatingpsychopath
Oct 28, 2000
Forum Veteran


Just caught up on this thread. Wonderful work; this battery stuff is nontrivial. I'm glad you're learning a lot so that revision (whatever this one is + however many it takes) will be to your liking. I experienced sublime joy when Iclicked back to the subforum screen to find that there was a new post! Excellent!

I looked at the soft power switch pretty hard; I'm not sure it's what you need. That soft power switch still requires the device on the far side to enable/disable the power line. So you'd need some kind of tiny MCU attached to the soft power switch to actually enable/disable the power line and also be talking to the RasPi. Since you can't just have the raspi idling waiting for the power button to get pressed.

If I'm reading the code right, every time the power button is tapped, the device on the far side of "system power" gets full system voltage. It's then up to it to determine what it wants to do. The example sketch has it turning system power off if the button was pressed for <100ms. I don't think a pi will come out of sleep in enough time for this thing to work standalone.

You have another mcu onboard, right? One that could be super-fast-boot and low-power sleep (with a wake on pinchange interrupt) that could also do your power stuff?

edit: didn't say the important stuff first.

babyeatingpsychopath fucked around with this message at 00:48 on Aug 15, 2021

Cory Parsnipson
Nov 15, 2015

babyeatingpsychopath posted:

Just caught up on this thread. Wonderful work; this battery stuff is nontrivial. I'm glad you're learning a lot so that revision (whatever this one is + however many it takes) will be to your liking. I experienced sublime joy when Iclicked back to the subforum screen to find that there was a new post! Excellent!

I looked at the soft power switch pretty hard; I'm not sure it's what you need. That soft power switch still requires the device on the far side to enable/disable the power line. So you'd need some kind of tiny MCU attached to the soft power switch to actually enable/disable the power line and also be talking to the RasPi. Since you can't just have the raspi idling waiting for the power button to get pressed.

If I'm reading the code right, every time the power button is tapped, the device on the far side of "system power" gets full system voltage. It's then up to it to determine what it wants to do. The example sketch has it turning system power off if the button was pressed for <100ms. I don't think a pi will come out of sleep in enough time for this thing to work standalone.

You have another mcu onboard, right? One that could be super-fast-boot and low-power sleep (with a wake on pinchange interrupt) that could also do your power stuff?

edit: didn't say the important stuff first.

Thanks for the support! I guess I am learning a lot and surprised at how much readily available information is out there. I think it's a bit hard to know where to start, but once I got going, it wasn't as inscrutable as I thought it would be.

Good point on the soft power switch. I didn't look into it closely, but yeah it does sound like for power on, they're expecting some sort of polling done to come out of sleep. I think it should be okay to not implement that and have any momentary tap of the button power up the system. That would make it similar to the other circuits I was looking at. The schematic (https://cdn.sparkfun.com/assets/5/6/6/6/0/SparkFun_Soft_Power_Switch.pdf) of the sparkfun thing seems almost identical to the Mosaic design, so I think this is possible. Though, on the other hand, having a delay for turn on would be a nice touch, I think. If I wanted to do that, I think it would get kind of tricky. I could use the controller Arduino to do the polling but that would mean I need to hook up a GPIO from the arduino and the raspberry pi together and power the Arduino separately from the raspberry pi as well.

This did remind me of another thing I needed to follow up on but forgot about. The videos I was watching state that it's important that the MCU GPIO pin is set to pullup so when the controller receives power, the gpio pin powers the transistor being used as a latch. That made me curious because the raspberry pi takes a really long time to boot up, so I was wondering if that would be a problem. I think this is similar to the the question you're asking about the microcontroller polling for a wakeup signal. I think I should read the sparkfun and other circuit documents closely and see if I can come up with any answers or insights into these two questions.

Cory Parsnipson
Nov 15, 2015
Ok so I took a, uh..., "unintentional" vacation, but now I'm back. I did another pass of the two videos I linked in my last post and tried to follow everything more closely.

"If I'm reading the code right, every time the power button is tapped, the device on the far side of "system power" gets full system voltage. It's then up to it to determine what it wants to do. The example sketch has it turning system power off if the button was pressed for <100ms. I don't think a pi will come out of sleep in enough time for this thing to work standalone."

Yes, it looks like the pi is unable to take advantage of this feature and the provided code for a hysteresis enabled power on. It does not have any sleep mode support, and disconnecting the power supply on power on/off is a mutually exclusive kernel mod to any low power mode for some reason. Fortunately, because the latching is done completely in hardware, we can just ignore the soft on functionality and still have a working system.



So when the user presses the power button when the system is off, it will connect power to the device through the first (upper) transistor. Since the power button shorts to ground and the first transistor is a PMOS the first transistor is turned on, and the output voltage of the first transistor feeds into the gate of the second. This second transistor stays on, causing the power to continued to be supplied to the system even after the user releases the power button without any microcontroller code or intervention required. I believe that the Sparkfun Arduino sketch assumes you want to make the user hold down the power button for some time to turn the device on so that you are less likely to turn on the device by accident. This is a really nice feature to have and I think may be worth trying to build in a really, really cheap microcontroller with a tiny physical footprint into this circuit if I were making a commercial level product (which I want to do at some point). For the time being, I think I can skip this part and have something that will accidentally turn on if you jostle the button and hope it doesn't happen very often. (Haha watch me complain about this later. Calling it now...) Maybe I can mitigate this by having the actual button be recessed in the case a little.

"The videos I was watching state that it's important that the MCU GPIO pin is set to pullup so when the controller receives power, the gpio pin powers the transistor being used as a latch. That made me curious because the raspberry pi takes a really long time to boot up, so I was wondering if that would be a problem."

Same as above, the latching is done completely in hardware, so the circuit is not dependent on the device booting up fast enough and setting a GPIO to high to keep it on. I think I got confused because in the hackaday video I linked, the first design is one that is for microcontroller type devices that requires the GPIO to be set high to keep the circuit on. However, it does look like some special mods need to be done to successfully turn off the device using this circuit.

First of all, the RPI foundation endorsed way of turning off the RPI is to put the device in halt and then use GPIO3 to boot the RPI back up by using a switch to short it to GND. To be clear, "halt" is supposedly a low power mode where the device is off and unable to execute any code. This is in contrast to sleep or hibernate where stuff has been written to DRAM/storage and will resume somehow when it's woken up. Imo, this is pretty useless because not only does the RPI halt consume a ridiculous amount of power (up to ~200mA, about the same as if it were powered on and idling) you can't run any periodic routines so why bother having this thing halted at all??? It appears the only advantage of this setup is that you don't have to physically disconnect and connect the power cable if you want to power cycle the RPi.

I'm going to ignore all that stuff, because it sucks. Instead, with this soft power latching circuit, we can use it to physically disconnect the RPI from the power supply (a.k.a. the battery) on shutdown. This will draw nearly no power when off. And then when the user presses the power button, everything happens as described above. To shutdown properly, though, means that we need to set the GPIO pin from the Raspberry Pi to LOW after shutdown so that the RC part behind the lower transistor will discharge and disconnect the power supply after approx. 6 seconds (if we're talking about specifically the SparkFun product). Otherwise, the RPI will stay halted and hooked up to the battery, draining it as if it were on the entire time. I could set the GPIO to low in a script before shutting down, but I hate having a race condition even if 6 seconds to shutdown should be more than enough time. I'd rather set a GPIO as the system is halted and fortunately, this is supported by Raspberry Pi using a specific dt-overlay. So I'll need to figure out how to get that working.

Gonna pick up a Sparkfun thingy cause I'm lazy.

Bad news for gamers

Because of all that stuff I talked about with RPi not officially supporting a sleep mode, I realized that most likely we will not be able to do some sort of sleep or suspend/resume in a portable RPi device. This came up a few times when people were talking about the Valve Steam Deck and I didn't realize how important this feature was to portable gaming. Indeed I use it all the time too but never noticed because of how seamlessly it worked. It is unlikely that someone other than the RPI foundation could get sleep working on a raspberry pi because a feature like this requires a comprehensive system in place on all levels of the SoC to work and the current RPI products out there have none of the required hardware in place to enable it. Maybe I'll figure out a way to work around it some day, but it's a long shot.

Cory Parsnipson
Nov 15, 2015
Just gonna leave this here for later so I don't forget the pinout for the audio system...



Hooking up the Fuel Gauge



I got some dupont connector wires and soldered the 4 pins of the fuel gauge. The I2C interface only needs two pins (SDC and SDA), but the babysitter requires a power (VPU) and also provides us something called GPOUT which is intended for me to wire up to a GPIO pin and set up an interrupt for specific events like when the battery percentage changes. I thought it would be worth adding the extra pin because having the battery life display updated on an interrupt seems more efficient than polling for the battery state.



One step forward, two steps back

Ok, so when I hooked it up, I discovered that something Very Bad(TM) happens. If I'm running off battery power and the RPI is booting by itself, most of the time it works perfectly fine. It's headless (no screen or input devices) but I can interface with it through SSH and the wireless. However, if I hook up the LCD screen and any of the other power drawing peripherals, the RPI will go into a boot loop. :argh:

Plugging the babysitter into USB power makes the brown outs go away, but that's a load of crap. What's even the point of having this if I need to keep it plugged in all the time to prevent it from shutting down?? I found this thread from the RPI forums where someone was running into the same problem but they were using a different power supply. I finally had to dig out the oscilloscope I bought off ebay a really long time ago to see if I saw a similar temporary voltage drop as that other guy did.




Yarp. That's a voltage drop, alright. loving poo poo SUCKS


The pololu buck/boost converter is keeping this thing at a respectable 5.2V under normal conditions. Perfect!


Looks like it bottoms out momentarily at 3.4V.


And spends some time at 4.16V.

The other guy's solution seemed to be adding a huge big rear end cap in parallel with the output voltage so I tried that:


1000 uF 6.3V cap

And the thing boots up now! This feels like a kind of a really lovely workaround though. Like a real bubble gum and tape type of thing. The person in the other thread came back and seemed to imply the cap wasn't enough to solve their problems. They disappeared afterwards without saying if they got it working or anything, which kind of sucks. Looks like I'm on my own. I vaguely remember that there's a lot of care taken to remove "ripples" from power supply designs. Maybe it's time to checkout what the big deal about that is...

Also, just like that person, I soon discovered that the cap by itself wasn't enough. I hooked up the speakers and everything and it boots to the RetroPie menu perfectly. Unfortunately, when I try to actually play a game, the controls mysteriously stop working. I believe this might be because the CPU load of the RPi gets higher and then there isn't enough power to keep the RPI and Arduino powered up. I think I need to up the power requirements of the power supply. I think the Sparkfun battery babysitter maxes out at 1.5A and that's not even enough for the RPI at full throttle, so I guess I really need something with a higher current rating.

UGHHHHHHHHH

Edit:

Cory Parsnipson posted:

Unfortunately, when I try to actually play a game, the controls mysteriously stop working. I believe this might be because the CPU load of the RPi gets higher and then there isn't enough power to keep the RPI and Arduino powered up. I think I need to up the power requirements of the power supply. I think the Sparkfun battery babysitter maxes out at 1.5A and that's not even enough for the RPI at full throttle, so I guess I really need something with a higher current rating.

I take this back. I no longer have any clue what is going on here. I took the power supply components out and plugged the thing directly into usb power and the controller stops working when I open an emulator. I might have corrupted a config file or something when it was power cycling and I had the cut the power off a whole bunch. So, good-ish news maybe?

Edit edit:

The controller's busted again. Not sure what's going on. Both analog sticks aren't responding and the left dpad button isn't working. Everything else is fine. Wires look connected. Man...

Cory Parsnipson fucked around with this message at 04:25 on Aug 30, 2021

Cory Parsnipson
Nov 15, 2015
I feel bad about double posting so soon but this is a pretty cool milestone. First, I got the controller working again, but I have no idea how or why. All I did was open the frame back up and wiggle some stuff around and then re-flash the firmware on the Arduino a couple of times. That part of the device is real sketchy and I really need to hurry up and put an enclosure around it so hopefully it doesn't break anymore. What might have happened is that the Arduino firmware was corrupted from the device being power cycled so much. Man, I hate it when this happens. I loving hate not knowing exactly what's going on. :mad:

It's trying to take the S2 Engine into itself???

https://i.imgur.com/P5DqaPO.mp4
So while I was testing out the once-again-working controller, I realized that I have achieved portability!

https://i.imgur.com/gfkVIot.mp4Woo hoo

So I guess the cap really helps and isn't as bad of a bodge as I said previously. I mean, in many designs you see capacitors shoved in many places to decouple some periodic signals and smooth out ripples and basically, this cap is in a place you'd find it in many other designs. On the other hand, this is kind of a quick fix in that it smooths out temporary drops in voltage when the device is drawing more power than the supply can handle and there's no guarantee that the power supply is adequate for all use cases. For instance, I might find it browning out if I'm doing more intensive stuff like playing a game and reading/writing data via wireless. Or opening chrome, compiling packages, etc. It's very hard to find out what the continuous output current of the SparkFun babysitter is, but it sounds like it's around 1.5A. I need something that's at least 3A for a proper power supply, I think.

That being said, this is the first instance where I have all the basic features working. I could technically take this mass of circuits and plastic and walk around the house with it. Or lay on my bed and play Super Metroid with it while its guts are splayed out like it's the beginning of Saving Private Ryan. I don't want to risk it though, without designing the fasteners and enclosures to hold everything securely, I could risk snagging a wire and really doing some damage.

For this next week I'm going to continue trying to interface with the fuel gauge and looking to write some scripts to add a battery level overlay on the screen. I think that should keep me occupied until the soft latching power switch gets here.

SOON.

Cory Parsnipson
Nov 15, 2015
The absolute state of this prototype

I'm in the middle of getting this fuel gauge up and running and that's been giving me some hands on time with the prototype. I'm going to use this post to take an inventory of my experiences with it. Spoiler: It's not good...

The stupid controller is really janky

So I've had recurring problems with the Arduino controller buttons that I made and I'm not exactly sure where on the stack it's going wrong. Here's what the symptoms are: The left dpad button sucks. It usually doesn't work, but if I wiggle the wires around sometimes it comes back and works as intended. Otherwise, it's unresponsive. The multimeter shows everything is connected properly and will beep if I press the dpad down, but for some reason it doesn't register on the Arduino side. What it looks like it could be is (1) a programming bug or (2) some kind of psycho issues with the Arduino running on low voltage (3) some inadequate solder joint or (4) socket connection. The analog sticks seem to give if the Arduino gets aggressively power cycled, but they also come back every so often. Not sure what's going on there either, but root cause could be the same as the dpad button.

Verdict: Not Cool. Seriously. :mad: You don't gently caress with game input. I think I'm going to have to really spend some time debugging this just before I put the enclosure on it.

SparkFun Battery Babysitter Runs Super Hot

There were some a lot of growing pains with this thing. Aside from the fact that its continuous output current isn't enough for my needs, it's actually not too shabby. I found out that if you are using it to charge at 1.5A and power the RPi at the same time, it get really hot. According to the internal temperature sensor on the fuel gauge, it peaks at allegedly 58C (140F). The sensor actually reports the temperature in units of 0.1 Kelvin (LOL). This is real freakin hot. It's right up at the glass temp of PLA so I'm going to have to be careful what pieces touch this thing and what is next to it as well.

Verdict: So spice! So spice!!

More data on Brown-outs

Ok this is interesting. Whenever I try to turn the device on and it goes into reboot loops, I've discovered that it's probably because the battery is "empty". Meaning that, if 3V is absolutely empty, then the battery is around or slightly higher than 3.2V. Some devices, especially this one I made, aren't efficient enough to take advantage of the full voltage range of the lipo. l'm going to estimate that 3.2V to be the lowest voltage this device can operate at. As in zero percent on the battery gauge. Also I think I've witnessed a brown-out when the battery was around 3.6V. Will be sure to do more testing for this.

This is good, because then the brown-outs are very predicable. The device was shutting off because the battery was empty! Duh. Now if only I had the fuel gauge and power on/shutdown scripts working so it would be smart enough not to go into a boot loop.

The device appears to be fine when the battery has a lot of charge, like around 4.1 - 3.7V. Again, I'll try and do more testing to figure out what the threshold actually is.

Verdict: Meh. The big rear end cap is necessary and helping, but doesn't solve the underlying problem of having an inefficient system operating on a single 3.7V lipo cell. Good news is that the brown-outs can mostly be avoided by making sure the battery is charged.

bq27441 fuel gauge development

Looking into the fuel gauge is going slow, but it is very interesting. I've been able to access it over I2C and read the settings. I'm writing a bash script library to make it easier to use:

https://github.com/CoryParsnipson/rpi-proto-1/tree/5802654b067e77ff95f8cfffef7c5b16568a8c15/code/power/bq27441_lib

This is to format the output to be easily readable and so that I don't have to manually type in all the I2C commands. Most amusingly, I've been doing this all through SSH on the RPI itself. I have it on an odd corner of my desk running on battery and interfacing via SSH on wireless. So I'm actually already using it as a dev station and writing code from my desktop but it's actually happening on my little portable. I have it plugged in at the moment, because it doesn't have the multiple hours of battery life for me to slowly work through all this.


Same energy

Verdict: Six thumbs up! The command line dev experience on this thing is awesome. I've even had to physically plug in a keyboard into the device to display that splash image of an eva head so the USB Hub I stuck in it is already paying off.

In the next post I'll go into more detail about the library and the fuel gauge and interfacing with it via I2C.

Cory Parsnipson fucked around with this message at 10:03 on Sep 2, 2021

Cory Parsnipson
Nov 15, 2015
Configuring and Interfacing with the BQ27441 Fuel Gauge

So this fuel gauge's part number is BQ27441 from Texas Instruments and comes integrated right on the Sparkfun battery babysitter. After working on this thing for almost a week, it's turning out to be really cool. Very good part, props to Texas Instruments. Right now I am at the point where I can read sensor data off the fuel gauge and I was able to calibrate it last night. Some of the info included is temperature of the babysitter IC, remaining charge (as a percentage), estimated battery life (i.e. how long before it can't hold a charge), voltage, and average current.

I2C and I2C related setup



I2C is the protocol we're going to use to communicate between the BQ27441 and the Raspberry Pi. This has nothing to do with the power supply or battery or anything, it's just the generic name of the communication protocol and hardware to support it. It's really simple and works pretty well.

For using the I2C controller on the Raspberry pi, there's some configuration needed.

1. The I2C dt-overlay needs to be enabled and the I2C module must be enabled through raspi-config. Then reboot and check if the I2C devices are recognized with ls /dev/*i2c*
2. Install i2c-tools package for i2cdetect and bash i2c commands.
3. Run i2cdetect to figure out which I2C address the fuel gauge has. (Mine ended up to be 0x55)

So I ssh into the raspberry pi and run these commands:

code:
pi@slackerpi:~ $ ls /dev/*i2c*
/dev/i2c-1

pi@slackerpi:~ $ sudo apt-get install -y i2c-tools
pi@slackerpi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- 55 -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Poking around in the fuel gauge

I haven't decided what framework I want to make the screen overlay app in yet so I settled on using bash scripts for experimenting. There were a couple C libraries that I found, but it was a real pain to get them working, so I passed on them. Bash has i2cset and i2cget for reading and writing to the fuel gauge, respectively. So all our interactions will be reading and writing locations in memory some of which are memory mapped IO on the fuel gauge side. As I said before, the protocol is refreshingly simple!

https://linux.die.net/man/8/i2cget
https://linux.die.net/man/8/i2cset

These two pages contain all there is to know about using the I2C protocol through the linux shell. Next, while we can send random reads and writes to and from the device, we need to know exactly how the fuel gauge works. That's where the BQ27441 Technical Reference comes into play. Reading this is kind of a drag, as is usual for pouring over technical documents, but it's pretty short and informative as far as datasheets go.

There's a table near the beginning with all the "standard" commands. Basically just do an I2C read of the first number under the "Command Code" of the row you want and make sure to do a word (w) read to get both bytes. As part of the I2C command, we need the -y (non-interactive), "1", and "0x55" parameters. The "1" comes from the I2C controller device id off of /dev/i2c-1 and 0x55 is the fuel gauge device id we used i2cdetect to figure out.



code:
// get state of charge; showing 0% battery life (not calibrated yet)
pi@slackerpi:~ $ i2cget -y 1 0x55 0x1C w
0x0000

// get temperature in units of 0.1 deg kelvin (shows 0xcd8 -> 328.8 K -> 55.65 C -> 132.17 F)
pi@slackerpi:~ $ i2cget -y 1 0x55 0x02 w
0x0cd8
Initial poking around seems to be successful. Note that for the state of charge, it was zero when I tried it at first, but after I plugged in the power cord and let the charge move up and down it started giving me different numbers. The temperature command was what I was using to measure the temperature when it got hot in the last post. I don't really have anything else that can measure the temperature of this thing, so I'm just at the mercy of what the sensor reports. The measurements seem sensible.

Ok cool, right? What do I do now.

BQ27441 Quick Start Guide and First Time Configuration

In various places, the BQ27441 technical reference is pared with the Quick Start Guide. The quick start guide sounds like what I should have started with but I think it's good that I saved it for now because I don't think I had enough context to understand it. Long story short, the quick start guide says we need to do a 1 time configuration of parameters to get the fuel gauge readings accurate that just involves setting 4 parameters. It says "1 time" but this needs to be done every time a different type of battery is swapped out. For this project, that will literally only be 1 time. This fuel gauge is pretty cool because it needs very little configuration and takes care of all the estimation and other stuff with sophisticated algorithms based on measured data from the battery itself. The actual explanations in the TI docs talking about battery composition and chemistry and physics go over my head.

I was messing around with the commands above and I read the state of charge a couple times a minute and saw how quickly the battery charge dropped. I estimated the battery life to be almost two hours but it was dropping a percentage point about once a minute, if not slightly faster. It goes to show how little 2 hours of battery life really is, but even for that length this was kind of quick. It felt like when you have an old phone and the battery dies really quickly. Except that this is a power supply with a new battery that's like 3 times the capacity of a cellphone battery... I'd later find out that the default battery capacity on the fuel gauge is 1340 mAh, which is just over half of the actually capacity of my 2600 mAh battery, so it makes sense why it was dropping so fast now. It's thinking the battery we have is half the size it actually is.

The four config parameters we need to change are Design Capacity, Design Energy, Terminate Voltage, and Taper Rate. The quick start guide explains what these are, but I'll do it again here too.

Design Capacity - This is the capacity of the battery in mAh. So for us, this should be 2600 mAh (or 0x0A28 in hex)

Design Energy - Calculate the total nominal power of the battery by multiplying the design capacity with the voltage of the lipo cell (3.7V). For the 18650 I have, it is 9620 mW.

Terminate Voltage - This is the minimum operating voltage of the system. If the battery voltage falls lower than this, the system will shutdown. Earlier I said maybe I'll do 3.1 or 3.2V and the default value of this is 3.2V, so we'll go with that for now.

Taper Rate - Ok this one is kind of confusing. The quick start guide has more details that I don't understand but basically this parameter is needed by the fuel gauge to keep an accurate charge state when the battery transitions to being fully charged. Also, the units on this thing are "0.1 Hr rate". Trippy.

Calculating taper rate was pretty involved. The guide has an example which really helps, but you need to go digging into the datasheet of the power supply IC in the battery babysitter to find some of the values that the taper rate calculation needs. The guide says this:



I don't know what the taper current of the battery babysitter is. But looking into the datasheet has a big table of all the stuff and it's here:



Yeah, nice and simple. :rolleyes: The taper current is the current that the charger trickle charges the battery at when the battery is detected to be at full charge. This is called "Iterm" by the other IC. As you can see in the picture above, the terminal current is 0.9 to 0.11 of the charge current if you've set the jumpers to enable fast charging at 1.5A (which I did). In the quickstart example, they use the max value of the terminal current as taper current so it's 0.11 * Icharge. That's 0.11 * 1500 mA = 165 mA. So Taper Rate = Design Capacity / (0.1 * Taper Current) = 2600 / (0.1 * 165) = 157.6 [0.1-hr rate] And round it to 158 because we can only write integral values.

Reading and Writing Block Data Registers

And the last part of the loving-with-bq27441 storyline is to write the config values to the fuel gauge block data storage. At this point I decided that I wanted to read the register values first just so I could confirm when they change and to figure out what the default values are. Ok so how do we do this? The quick start guide and technical reference both have a list of I2C commands we need to do in order to modify the block data...


Ooooh, it's just 27 quick and easy steps :unsmigghh:

It's time to break out the bash scripting. I've attempted to follow this flow chart in a bash library: https://github.com/CoryParsnipson/rpi-proto-1/blob/f7d86a479fcedddccb0dd7ccebd2c42fc12f5679/code/power/bq27441_lib/bq27441_lib.sh

Not going to go into the details but it took days of writing this up... And here's me attempting to read the config registers using this series of commands:

code:
enter_extended_mode

BLOCKDATA=$(read_block_data 0x52 0x0A 2)
printf "DESIGN CAPACITY: %d mAh\n" $BLOCKDATA

BLOCKDATA=$(read_block_data 0x52 12 2)
printf "DESIGN ENERGY: %d mWh\n" $BLOCKDATA

BLOCKDATA=$(read_block_data 0x52 0x10 2)
printf "TERMINATE VOLTAGE: %d mV\n" $BLOCKDATA

BLOCKDATA=$(read_block_data 0x52 27 2)
printf "TAPER RATE: %d [0.1 Hr rate]\n" $BLOCKDATA

exit_extended_mode
read_control_status true
All that stuff in the flowchart is hidden in the "enter/exit_extended_mode" functions. We need to seal/unseal the device, write commands to enter CFG UPDATE mode, write commands to enter block data access, then choose the block subclass and block offset. Then we can do the read. Btw, seal/unsealing the device is added by TI to prevent people from accidentally overwriting config parameters during normal usage. You're supposed to "seal" the device when development is done and this disables most of the commands the device will respond to. If you need to update the config or something else, you need to unseal it, do your stuff, and then re-seal it.

code:
pi@slackerpi:~/code/battery-i2c $ ./read_config.sh
DESIGN CAPACITY: 1340 mAh
DESIGN ENERGY: 4960 mWh
TERMINATE VOLTAGE: 3200 mV
TAPER RATE: 100 [0.1 Hr rate]
Success!

Cool, now that I am able to easily read the config registers without having to type in a bunch of stuff, it's time to get the write working. This turned out to be much more complicated due to having to compute the checksum. Also one gotcha is that when you do a block write, the new value isn't actually written to the device. So if you read from the register you wrote to immediately afterwards, you'll still get the old value. The memory isn't updated until you write the correct checksum (if it's not correct, the write will be refused) and then perform a soft reset. This has implications on the checksum calculation so I had to use the formula they provided to calculate checksum deltas. Anyway, once that worked, I was able to write the values.

code:
pi@slackerpi:~/code/rpi-proto-1/code/power/bq27441_lib $ ./write_config.sh
Unsealing to enter extended mode.
Control Register Status: 0x009e
------------------------
Shutdown Enabled: false
Watchdog Reset: false
Sealed: false
Columb Counter Auto Calibration: false
Board Calibration Routine Active: false
Qmax updated: false
Resistance Updated: false

Flags Register: 0x0098
------------------------
OVER TEMP DETECTED: false
UNDER TEMP DETECTED: false
FULL CHARGE DETECTED: false
FAST CHARGING ENABLED: false
OCV MEASUREMENT TAKEN: true
POR OR RESET OCCURRED: false
CFG UPDATE MODE: true
BATTERY INSERTION DETECTED: true
STATE OF CHARGE < THRESHOLD 1: false
STATE OF CHARGE < THRESHOLD F: false

Waiting for SETCFGUPDATE to be set...
Exiting extended mode.
Unsealing to enter extended mode.
DESIGN CAPACITY: 2600 mAh
DESIGN ENERGY: 9620 mWh
TERMINATE VOLTAGE: 3200 mV
TAPER RATE: 158 [0.1 Hr rate]
Waiting for SETCFGUPDATE to be set...
Exiting extended mode.
Control Register Status: 0x201e
------------------------
Shutdown Enabled: false
Watchdog Reset: false
Sealed: true
Columb Counter Auto Calibration: false
Board Calibration Routine Active: false
Qmax updated: false
Resistance Updated: false

Flags Register: 0x0008
------------------------
OVER TEMP DETECTED: false
UNDER TEMP DETECTED: false
FULL CHARGE DETECTED: false
FAST CHARGING ENABLED: false
OCV MEASUREMENT TAKEN: false
POR OR RESET OCCURRED: false
CFG UPDATE MODE: false
BATTERY INSERTION DETECTED: true
STATE OF CHARGE < THRESHOLD 1: false
STATE OF CHARGE < THRESHOLD F: false
Now the fun begins

Writing the bash script was interesting to me because it was a novel experience, but now I get to do the really cool stuff of writing scripts and getting the interrupts working for power notification events and displaying the status on screen. The power switch won't be here until Monday at least, so let's see how far I can get this weekend.

Cory Parsnipson fucked around with this message at 03:08 on Sep 4, 2021

babyeatingpsychopath
Oct 28, 2000
Forum Veteran


These last three posts have been solid awesome.

Myself, I love poring through datasheets and doing esoteric i2c stuff.

I wonder if the [.1 Hr rate] is the 10C rate for the battery, or if it's the .1C rate.... The example makes it seem like it's 1/10 of the 1C rate, but who knows!

To expand a bit: Say you have a "1AH" battery pack. The 1C rate would be 1 amp for 1 hour for the battery to go from full to empty. The 10C rate would be how many amp-hours you could get out of the battery at 10A. It may be more or less than 1AH depending on chemistry. The .1C rate works the same; how many AH you get from the battery at 100mA. This is very frequently more than the 1C capacity, but not always. Some chemistries love dumping power and don't trickle it out well. Some chemistries like giving a little juice for a long time.

babyeatingpsychopath fucked around with this message at 08:09 on Sep 4, 2021

Cory Parsnipson
Nov 15, 2015

babyeatingpsychopath posted:

Myself, I love poring through datasheets and doing esoteric i2c stuff.

I was thinking a little bit and yeah I guess I did have a lot of fun doing the fuel gauge stuff. It's not really fair for me to say it was boring, because if I didn't like it I wouldn't have actually done it. The fuel gauge was a new type of sensor for me and I was interested in learning how it worked in detail. I think the only problem is that I have the attention span of an unmedicated 12 year old so sitting down and reading through the docs without fidgeting is really hard right now.

babyeatingpsychopath posted:

I wonder if the [.1 Hr rate] is the 10C rate for the battery, or if it's the .1C rate.... The example makes it seem like it's 1/10 of the 1C rate, but who knows!

To expand a bit: Say you have a "1AH" battery pack. The 1C rate would be 1 amp for 1 hour for the battery to go from full to empty. The 10C rate would be how many amp-hours you could get out of the battery at 10A. It may be more or less than 1AH depending on chemistry. The .1C rate works the same; how many AH you get from the battery at 100mA. This is very frequently more than the 1C capacity, but not always. Some chemistries love dumping power and don't trickle it out well. Some chemistries like giving a little juice for a long time.

Oh I see, that makes a bit more sense. It's a good addition to my intuitive understanding of it.

Cory Parsnipson
Nov 15, 2015

Cory Parsnipson posted:

The power switch won't be here until Monday at least, so let's see how far I can get this weekend.

Narrator: He did not get very far.

Welp, I ended up playing Breath of the Wild the entire weekend. Got to Zora's domain, did the divine beast Vah Ruta quest and it was freaking awesome.

Also,



babyeatingpsychopath
Oct 28, 2000
Forum Veteran


This is a valuable use of your time, and I'm happy to continue to watch your progress.

What's in the box?

Cory Parsnipson
Nov 15, 2015

babyeatingpsychopath posted:

What's in the box?

It's the latching power switch! Now I won't have to hurt my fingers pulling the battery out of the socket.

babyeatingpsychopath
Oct 28, 2000
Forum Veteran


Cory Parsnipson posted:

It's the latching power switch! Now I won't have to hurt my fingers pulling the battery out of the socket.

After ripping a thumbnail nearly off trying to get an 18650 out of my battery holder, I installed a commercial snap-action 120V 15A switch in-line. Yeah, just a straight wall switch from the project box. Overkill, maybe, but prototypes are designed to have kludges.

Cory Parsnipson
Nov 15, 2015
Latching Power Switch Integration



This thing is nice and small. The black solder and resist and silkscreen makes this look really cool.

But first, a quick test...

The Raspberry pi has a dtoverlay pre-built package that seems designed specifically for these types of switches called gpio-poweroff. Looking at some of the documentation makes it sound like I need to make a few really complicated changes to get it working though...

code:
Name:   gpio-poweroff
        active_low              Set if the power control device requires a
                                high->low transition to trigger a power-down.
                                Note that this will require the support of a
                                custom dt-blob.bin to prevent a power-down
                                during the boot process, and that a reboot
                                will also cause the pin to go low.
I don't know what a dt-blob.bin is or how to make one or even what changes this thing wants me to make. For now, I'm going to add this line to /boot/config.txt and see what happens:

code:
dt-overlay=gpio-poweroff,gpiopin=6,active_low=1,timeout_ms=6000


Here's my test rig. I'm using the babysitter power supply to power the breadboard here. And I've got an LED attached to one side of the power rail. Another cable is being used to power the Raspberry pi directly through its micro usb port and I've hooked up the GPIO pin 6 in question to the other side of the LED. The idea is that when the GPIO pin goes low, the LED will turn on since the voltage difference is now larger when it turns off. No video, but doing my tests, I found that the LED turns on at halt and it doesn't turn on during boot or reboot, which is exactly how I want it to behave. So I'm not sure what the documentation is getting at...

Hooking up the GPIO and the power switch


Electronics lasagna



Not much has changed, but it feels better since I can just press a button to do things now. It doesn't work though!

Booting up - this works fine. This is great. The power-on latching works as expected. Awesome!

Turning off - this doesn't work. :( 9 times out of 10, the device just ends up rebooting. I see that the power LED on the power switch remains on. What I think is happening is either the GPIO pin is too weak to drive the switch to ground or there is too long a delay to do that. What does work is if I press and hold the power button during shutdown. (Doing this shorts the power button circuit path to ground.)

Reboot - inconclusive. If shutdown doesn't work, then I can't really test the reboot.

Emergency Shutoff - this doesn't work. I didn't realize that the gpio-poweroff overlay isn't exactly what I need. When the system is on, GPIO 6 is driven high as an output. When the system goes into halt, it is driven low. This means that the node attached to the GPIO is kept at 3.3V so if I press and hold the power button I think the node isn't going to ground for some... reason...

Aaand I just realized I didn't hook up the ground pin coming off the switch... I'm gonna eat dinner and then go fix that...

=============

Ok so I hooked up the ground, but nothing changed. I think I'm going to have to learn how the device tree works.

https://www.raspberrypi.org/documentation/computers/configuration.html#device-trees-overlays-and-parameters
https://www.raspberrypi.org/documentation/computers/configuration.html#device-pins-during-boot-sequence

Cory Parsnipson fucked around with this message at 08:19 on Sep 11, 2021

Cory Parsnipson
Nov 15, 2015
Emergency Power off is working now

Ok so remember when I mentioned something about how I need to change the gpio-poweroff overlay to set GPIO6 to an input instead of driving it high as an output when the system is on?

Cory Parsnipson posted:

Emergency Shutoff - this doesn't work. I didn't realize that the gpio-poweroff overlay isn't exactly what I need. When the system is on, GPIO 6 is driven high as an output. When the system goes into halt, it is driven low. This means that the node attached to the GPIO is kept at 3.3V so if I press and hold the power button I think the node isn't going to ground for some... reason...

Yeah, this is possible with the "input" parameter of the gpio-poweroff dtoverlay. So if I change the command to this:

code:
dt-overlay=gpio-poweroff,gpiopin=6,active_low=1,input=1
GPIO 6 goes to high-z while the device is powered on and then when I press and hold the power switch, it does a hard shut off at around 13 seconds. Good, so that's one less thing I need to worry about.

Oh and by the way, despite being in the documentation timeout_ms is not recognized by a parameter, so I took it out. I found this out by running sudo vcdbg log msg. This parameter was supposed to control how long the RPI waits while halted before issuing a kernel panic. The idea is that the power switch is supposed to cut the power before the timeout and so the kernel panic would be a failsafe for this.

Soft Power Switch Troubles

Well, this thing doesn't look like it's going to be easy to get working. Drat. I broke out the oscilloscope again so I could at least try and see what was going on.



I pulled out a ground signal for reference and then GPIO6 onto the red power rail of the breadboard. The sense/ctrl pin of the power switch is also hooked up to this signal. What I find is that the GPIO pin does go low and stays that way indefinitely, if I take off the power supply and use USB power directly to the raspberry pi. So far so, good. The oscilloscope shows some random floating voltage until the RPi shuts down, then the signal goes to 0V and stays there until I remove the power.

Things get fucky when I add in the power switch. What I see is that sometimes, the signal goes low as expected, but only stays this way for about 5 seconds-ish. Then for some reason, it jumps back to 3.3V and the device instantly reboots! This is currently the bain of my existence. I have no idea what's going on, and don't really know where to look. I'm going to have to keep at it and hope something pops up.

Confusion over best location of power switch

To add to this mess, I also realized that I might have my power switch situated in the wrong place in my power system. Here's the current layout reposted:





Note that the power switch is between the output of the buck/boost converter and goes directly into the Raspberry pi. One of the features of this power switch is that you can allegedly charge the battery by going through the body diode of the top transistor with the charger. For that to work, that means I need to put the power switch between the battery and the input of the sparkfun babysitter. Like so:




I had to recrimp some wires and wasted a bunch of JST PH sockets... These are in short supply right now so that's a really bad thing.

So I moved it and guess what? It still does exactly the same weird behavior when I try and turn the device off! Well poo poo. And to add to this, charging through the power switch doesn't even work. If I plug in the charger while the system is off, the switch oscillates on and off and the charger turns on and off about once a second as well. I don't think... it's supposed to do that.

Although another tidbit I discovered is that if I have the charger plugged in and I try to turn off the system, the device ends up turning off successfully and the GPIO stays low. (Then it does that weird, bad behavior I just described). I'm hypothesizing that maybe exceeding some "timeout" threshold is causing excessive power consumption and then taxing the babysitter so that it browns out at the last second. The raspberry pi documentation mentioned that not disconnecting in time could see excessive power consumption.

Options...

So I could either go back to the first configuration and have charging that's not broken. On the other hand, I did a test last night where I left the battery in with the switch turned off and it went from 71% charged to 58% charged over the course of ~12 hours. This is pretty bad if accurate. The babysitter has a disable switch to disconnect the battery. It also has a through-hole connection to control this switch via GPIO so I might want to try and get that working too.

The second option is to go with the new layout and try and fix the charging too. The advantage is that when the switch is off, the battery is disconnected so there's pretty much no power draw.

cakesmith handyman
Jul 22, 2007

Pip-Pip old chap! Last one in is a rotten egg what what.

I was wondering the other day what this project would look like if you prototyped a giant don't-give-a-poo poo version with none of the finesse and cleverness you've put into this and realised it'd be a gargantuan 8lb cyberpunk monster and I'm glad you're doing it the way you are.

Cory Parsnipson
Nov 15, 2015

cakesmith handyman posted:

I was wondering the other day what this project would look like if you prototyped a giant don't-give-a-poo poo version with none of the finesse and cleverness you've put into this and realised it'd be a gargantuan 8lb cyberpunk monster and I'm glad you're doing it the way you are.

Thanks, that makes me feel better about the choices I've made so far. I've seen other people prototype their stuff by getting a large piece of wood and screwing all the circuit boards down on it to make things less of a hassle while they work out the system, and then tear it down and try and arrange things more compactly after that, especially with all the small boards that make up the power supply. Occasionally that thought pops up in the back of my mind and I wonder if I could have done things faster that way. That seems to be the more "engineer" way to do this, you know the "rapid prototyping" and "failing fast" you hear all the startup bros talking about. Once I get a few more projects under my belt, I think I should try that and see how it goes.

But sometimes you just gotta get started and go on an adventure :downs:

Cory Parsnipson
Nov 15, 2015

Cory Parsnipson posted:

But sometimes you just gotta get started and go on an adventure :downs:

Speaking of adventure :downs:...

I was looking into why the shutdown was causing a reboot and moving wires around and lo and behold a few seconds of fast boot cycling later, I've corrupted my SD card. :doh: I didn't get a backup either so I had to re-image it (luckily the card isn't dead) and then a few hours later I had everything almost back to where it was and I tried the power switch again and now it turns off as expected. :confused:

The oscilloscope shows everything happening almost exactly the same. The GPIO pin goes low and then at the last minute, it goes to 2.6-3.3V ish volts, but this time, the power switch turns off instead of rebooting the Pi. The raspberry pi OS version is newer and I'm missing all the settings that I changed to get the 1.8" TFT LCD screen working, so there's a lot of variables in play here. I hope rebuilding/wiggling wires around and finding everything magically working doesn't become a recurring theme here...

Reboot is working too, but charging is still broken.

EDIT:

Ok so I ran down the battery because when I wrote this I was at full charge and it turns out it starts rebooting during shutdown again. For the record I was at 34% charge, but the brownouts might start earlier than that. Probably just gonna work on the mounting brackets and call this an L. :sigh:

Cory Parsnipson fucked around with this message at 22:20 on Sep 14, 2021

cakesmith handyman
Jul 22, 2007

Pip-Pip old chap! Last one in is a rotten egg what what.

L for learning.

Cory Parsnipson
Nov 15, 2015

Perfect. :eng101:

I tried to fix the charging, but it looks beyond my abilities at the moment. The SparkFun Power Switch Repo claims that it supports charging:

SparkFun posted:

The Soft Power Switch supports battery charging. If the target device has onboard LiPo charging, current can be passed back through the cut-off circuit and charge the battery.

I think this means that it will pass through the top transistor in the diagram below. And the blue arrow shows how, if I have it configured in the auto-off position, it will remain off while charging too. The problem is the "sense/ctrl" pin is tied to ground when the device is off (see "GND" arrow at the bottom).



I don't know how the circuit behaves with that information and how the second transistor on the bottom acts. The behavior I observe is that the charging light blinks on and off repeatedly when the device is turned off and plugged into the wall. The oscilloscope shows me the gate of the bottom transistor periodically switches between ~1V and -4-5V. This means the 22uF cap is charging and discharging as the current between the charger and the battery is being disrupted. Why is this happening? Well I can tell you it has something to do with the sense/ctrl pin being tied to ground, but that's as specific as I can get.

To continue my trend of putting transistors in places and barely understanding why, I tried putting a PMOS transistor in between the sense/ctrl pin and the rest of the power switch. This fixes the charging/discharging since the PMOS is now off when the device is off as well. But wait there's more bullshit. If the charger is put into the circuit, I can no longer turn on the device. Why is this? Looks like pressing down the button isn't enough to bring the node connecting the two transistors to ground. I don't know why. So I have doubts when Sparkfun claims you can charge through this thing. Or maybe I'm doing it wrong, but I have no idea because they have basically no documentation for this thing.

Also putting this PMOS in place messes up the shutdown process and also makes it so that I can no longer sense when the button is pressed at the microcontroller side. So much for that...

Anyway that's as far as I'm going to chase this for the moment, and this means a few weird things wrt to the prototype:

1. You can only charge this thing when it's turned on.
2. Plugging in the device to wall power when it is off will turn it on.
3. If you plug in the device into wall power and then turn it off, you will be unable to turn it on while it is plugged into the wall.

:bravo: I'll figure that poo poo out the next time around. :hmmyes:

Cory Parsnipson fucked around with this message at 08:26 on Sep 15, 2021

Cory Parsnipson
Nov 15, 2015
Crosspost from the Learning Electronics thread cause I can't stop thinking about it :qq:

tl;dr - I used an online circuit simulator utility to try and understand what's happening with the power switch. The tool is pretty cool. Did I learn anything about how it works? Well, no. :sweatdrop: I gotta crack open an intermediate circuits textbook and brush up on it to understand this stuff probably. No way around it.

Cory Parsnipson posted:

Stack Machine, I forgot to thank you earlier for the suggestions. I opened a topic in the SparkFun forums to get some help from one of their service people and now I'm waiting for them to respond. I don't really have high hopes, so I'm gonna put the switch back in its original spot and see if I can disconnect/reconnect the battery when the device is off some other way.

Also, Forseti (I think?) posted about the Falstad circuit simulator a little while back and I just remembered about it so I went to check it out. This tool is really well made and has an extremely nice drawing UI! It's perfect for my non-SPICE-havin'-rear end. Turns out it's powerful enough to simulate the power switch schematic and I was able to see it turn on and off:


From off position, closing the (left) switch delivers power to the RPI. The LED turns on.


The RPI GPIO (right) switch going low causes the switch to turn off. This takes approx 5 seconds because instead of a 22uF cap I put in a 10uF cap so I wouldn't have to wait so long. The turn happens around when Vgs of the simulated NMOS drops below 1.5 ish volts.


Pressing down the hardware switch (left) also causes the switch to turn off. The sim time step is so small that this takes forever in wall clock time.


The switch acts as I observe in real life when charging is attached and I try and press down the hardware switch.

With the charging happening, the gate of the NMOS on the bottom takes an inconvenient amount of time to turn off. Also the charging voltage source supplies power to the node that connects the two MOSFETs together and that appears to be keeping the top PMOS on. So maybe this is why the RPi turns on when I plug in the power and why if I shut it down and then try and turn it on again, nothing happens (the RPi is expecting an edge somewhere I think).

It just looks to me that this circuit wasn't designed to operate with power coming in from the place that the load is supposed to be. The Sparkfun marketing department must have had a hand in writing the feature description because I'm becoming more and more convinced that you just can't use the switch this way. :thunk: :thunk: :thunk: I guess modern electronics use a more elaborate solution than this.

Slugworth
Feb 18, 2001

If two grown men can't make a pervert happy for a few minutes in order to watch a film about zombies, then maybe we should all just move to Iran!
Very interesting stuff, but I keep finding myself thoroughly confused about why this stuff isn't like, a solved problem. It doesn't seem you're inventing some crazy new technology - Are there not people who have hooked up a raspberry pi to a screen and a battery? Why is there not a resource you can crib from that's just "use this battery, this switch, and this battery tender"?

I don't know if this reads as "you are doing something wrong", it's meant as "I'm surprised someone else hasn't done the same thing and documented it", you know?

Cory Parsnipson
Nov 15, 2015

Slugworth posted:

Very interesting stuff, but I keep finding myself thoroughly confused about why this stuff isn't like, a solved problem. It doesn't seem you're inventing some crazy new technology - Are there not people who have hooked up a raspberry pi to a screen and a battery? Why is there not a resource you can crib from that's just "use this battery, this switch, and this battery tender"?

I don't know if this reads as "you are doing something wrong", it's meant as "I'm surprised someone else hasn't done the same thing and documented it", you know?

Good question! Sometimes in a few of my previous jobs, I end up grumbling to myself something similar at 3AM on some odd day. Perhaps someone with more experience could provide some opinions (I'm open to input. I'll try not to get my feelings hurt... :sweatdrop:). Let me elaborate on a few of my own reasons why I think this is:

#1 - In general, the tech stuff is never as easy as it sounds mostly because there's always small, hidden details that gently caress you up.

If you're learning to do anything tech related, there's going to be a period where you run into every problem. For instance, if you wanna install react to make a webpage, you gotta learn how to use npm, webpack, rollup. You run into the six million eccentricities of javascript. And then if you want to go outside the single page webapp stencil of the tutorial, you need to modify the build scripts to add variables and introduce multiple directories. "Why isn't my react app building properly? I'm seeing <random build script error> when I do `npm build`???", "why doesn't it see this build variable???" These could take a whole afternoon of debugging. Multiply that by the 20 "quick and easy" steps to set up the framework and you could be doing this for months if you don't ask for help. I've hit that a lot in this project already with wiring problems and a lot of gotchas that the battery babysitter has. "I just want to make a webpage" :negative: -> the experience isn't going to be plug and play unless you want exactly what the tutorial does and maybe a few minor modifications.


Me at my computer, trying to program in ruby. Seriously?? There's like a million specialized keywords. How is it that I can look at a bunch of tutorials and still not know anything about how ruby works????

#2 - Going to the bitbuilt forums are the closest thing you'll get to a guide.

Not only is a there a section for forum guides, you'll pick up on some common parts and patterns if you follow build logs and discussions between users. I mentioned the battery guide that explains most of the background information and then recommends a single piece of technology you can buy that is like the "forum preferred" way of doing things. This isn't a kit though, so you'll find there's absolutely no documentation that comes with this part. And if you've never done it before, then you'll be running into problems from #1 every step of the way... The only guarantee you have is that other people tried it and it works for their own specific project. If your project is similar enough, then you can assume you'll have a similar amount of success using it. The bitbuilt forums have been invaluable to me, but there's also not nearly enough material to cover everything I need, so for some things I'm on my own.



#3 - There are drop in parts, but...

I used the OSOYOO LCD screen. It was 50 bux and it comes with an enclosure which is bulky and limits the kinds of things I can do with this part. This screen in particular was very non-invasive and getting it to work was a surprise. All I did was plug in the DSI cable and it worked straight out of the box! No hassle, no configuration needed. That is the ultimate dream, but not everything can be designed to Just Work(TM) like that. OSOYOO lucked out in that the Raspbian linux distro already has mature and great hardware support for their LCD out of the box. (By the way, I really like Adafruit products because the designers are so good, many of them drop in with no hassle like this). On the other hand, I was looking also at the Pimoroni 4" LCD that has perfect specs, except that it connects to the RPi with a pin header connection that literally uses every single pin on the raspberry pi. This doesn't play well with the other parts of my project because I need at least 5 pins to do other things not just powering the screen. A drop in part means you trade convenience for higher expense and lower flexibility. Another thing to think about is that this up-front convenience is gained by delaying R&D (I learned absolutely nothing about interfacing with LCD screens). For example, this LCD screen is bulky so I may need to switch to a generic LCD later. Also if I was mass producing this, $50 vs $18 might be the difference between being able to manufacture this or going bankrupt. So later down the road I will need to spend more time with a less user friendly but more flexible LCD.

There are power supply drop in solutions too. Like PiJuice, Various UPS "Hats" and fully integrated solutions. I skipped on PiJuice because it's expensive, has a pre-defined form factor, and may or may not have the combination of features and specs I need for my specific project. This project has relatively stringent requirements on physical size and power consumption that severely limits the types of pre-made solutions I can use (see next point). Playing with electronics is like trying to put together legos that were, not only made by different companies, but also don't have standardized sizes and specifications. The pieces claim to fit together, but also just don't line up. :shrug:



#4 - Making a portable Raspberry Pi is actually kind of hard.

Most of the guides out there that tell you how to add a power button assume you're going to use it like a desktop PC and most of the guides that tell you how to add a battery pack assume you're going to use it like an embedded microcontroller Power consumption and space aren't really concerns and/or they're expecting you to be idle 99% of the time. Not to mention that the design of the RPi SoC isn't very conducive to efficient power usage, as I've mentioned wrt the operating voltage and lack of sleep/low power options. I haven't explicitly heard anyone say this, but I speculate that the lack of examples is because a lot of people tried and found it was a huge pain in the rear end and wasn't worth it.

#5 - I work slooooowly. Very slowly



I get bogged down in details a lot and this slows me down immensely. Remember #1? A lot of people would be happy to get something 80% working and move on, but here I am spending two weeks because the power switch doesn't work if the device is off but plugged into the wall outlet. But it works in every other situation! The Raspberry Pi Fusion guy used an SPDT switch and called it a day. I bet he doesn't accidentally toggle the switch very often if at all. But I mean, would you see a smartphone with a toggle switch?? Not saying my way is better. I've always been this way since I've been a kid. Someone gives a demo and shows off something cool. The only thing I can focus on is that it doesn't have the frills or doesn't look exactly like the commercial version. This is a cheap knockoff! This is an "engineering art" of balancing these things. You want quality and polish for the final product but you can't spend eternity getting all the loose ends tied together when you're not in the final stages of the project timeline.

I was thinking drat, this switch looks easy based on all the guides and tutorials. All I need to do is drop this circuit in the middle of my design and I can have a soft power button like a smartphone. That's awesome! Then I get it and try it and, as expected, it doesn't work the first time. So I think, okay, well let me spend just one day working it out. And then that day passes, I make some progress and I feel like I'm close, so I say, "Ok I'll spend one more day". Three days later, I'm trying to think of another angle to attack before I'm ready to move on. And then I'm working on this other thing and distracted by the fact that I couldn't get the power switch to work. So I'll have an idea while working on something else and then go back to the power switch thinking, "ok let me just try this one thing and maybe it'll work now???".

I also chose the battery babysitter instead of the bitbuilt recommended one because it looked convenient, had a fuel gauge, and used only 1 battery (space saving) but turned out to be kind of a bear to get working. I didn't drop it because of sunk cost fallacy and also because it cost me 20 bux and also has literally all the features I want in one package except for the singular fact that it's max continuous output current is 1.5A instead of 3A. Looking for other legos to replace this would mean not having a battery reading or finding 3-4 other pieces to replace this one piece.

If I was working a job, the approach would be completely different. The objective is non-negotiable (get the raspberry pi working on a battery pack or the project is cancelled). So the first step becomes, what's the easiest quickest thing I can do? (Instead of, what do I need to make a dope, fun product?) I go for a drop in solution. Lets say I estimate a week, but I run into #1 a whole bunch and by the end of the week my thing isn't working. So at this point I need to open a customer support case with the vendor and I need to tell my manager that I'm going over my estimate. At this point we need to compromise. The soft power switch is ripped out and replaced with a SPDT switch. We have to bargain with marketing to get the battery life decreased to 1hr. I use a 1s BMS with no fuel gauge (and pray I get that working on time). And then I have to open a pending story in the issue tracker to get the soft power switch working and that this will be done in the next iteration of things when the first wave of crunch time is over. V1.0 of the product ships and customers complain that the whole thing is a pile of trash because it successfully plays games and is portable but has nagging, unpolished features like you need to manually shut off the switch and doing it too early will corrupt your SD card. Two years later, V4.0 of the device debuts and still has an SPDT switch that everyone constantly complains about and prefers the competitor's product over, because every time I have bandwidth to revisit the project, I've been explicitly told by my manager that I shouldn't be working on this because it isn't high priority. :unsmigghh:



Anyway, that's my excuse. :cheeky:

Cory Parsnipson fucked around with this message at 21:44 on Sep 18, 2021

cakesmith handyman
Jul 22, 2007

Pip-Pip old chap! Last one in is a rotten egg what what.

A lot of truth there. Yes most people making pi's portable are either going overkill with massive batteries or slimming the hardware down to a pi zero or even smaller and even then they'll work around an issue like "can't turn on while plugged in" because working around it is easier than fixing it.

Cory Parsnipson
Nov 15, 2015
I'd like a massive battery that would last around 8 hours. But yeah a lot of RPi projects make some design decisions I wouldn't make, presumably to reign in scope and that's why I want to make one for myself! Overall, it's a ton of work even to just get something with a bunch of workarounds in it...

Fuel Gauge Interrupt Handling

I want to finish the whole software/hardware loop before I put all the pieces in place and mount everything. Being able to see the remaining battery percentage will be helpful during testing, I think. So one last piece of glue logic is to handle the interrupts that we generate from the fuel gauge. The babysitter has an external output called "GPOUT" that can be configured to go off for certain events. This signal should go into one of the GPIO of the Raspberry Pi and then we need to read this and act accordingly.

I cracked open the technical reference again and looked for info under the "GPOUT" heading. The good news is that we don't even need to change anything! All the defaults are perfect. The reference says all the configuration parameters are set in a register called "OpConfig" than can be read/written to using the 0x3A command:

code:
pi@slackerpi:~/code/rpi-proto-1/code/power/bq27441_lib $ ./read_opconfig.sh
OpConfig Register: 0x25f8
------------------------
TEMPERATURE SOURCE: INTERNAL
[b]INTERRUPT CONFIG (BATLOWEN): INTERRUPT ON SOC[/b]
RMFCC: true
ENTER SLEEP ENABLED: true
GPIOPOL: ACTIVE LOW
BIE PULLUP ENABLE: None
BATTERY INSERTION ENABLE: AUTOMATIC
The BATLOWEN being 1 means the interrupt will fire if battery falls below a certain percentage. If it's set to 0, it will fire every <SOCI Delta> percentage change. We want the latter because I can always code the former in my interrupt handling script. I need the interrupt to fire every percentage point so I can update the battery percentage display with the new number. Also, lastly, GPIOPOL controls if the signal is active high (signal is normally 0V and then creates a square pulse at 5V to indicate the interrupt has fired) or active low (signal is normally 5V and creates 0V pulse). No need to write anything here.

Ok one more thing. Where the heck do I change the value of SOCI Delta? I need to make sure this is 1% so that the battery percentage will update in a timely manner. It was hard to find, but this variable is stored in the block data, one byte at address 26.

code:
pi@slackerpi:~/code/rpi-proto-1/code/power/bq27441_lib $ ./read_config.sh
Unsealing to enter extended mode.
DESIGN CAPACITY: 2600 mAh
DESIGN ENERGY: 9620 mWh
TERMINATE VOLTAGE: 3200 mV
TAPER RATE: 158 [0.1 Hr rate]
SOCI DELTA: 1 percent
Ok perfect. It's 1%.



Ok now let's handle this mother!

Interrupt Handling Code: Python???

I need to make a script that will be able to read from the GPIO pins and then either use a thread or interrupt to run my bash script to get the state of charge. For Raspberry Pi, I kept getting recommended a python library to work with GPIO called RPi.GPIO. So let's install that:

code:
# manually switch from python2 to python3
$ sudo rm /usr/bin/python
$ sudo ln -s /usr/bin/python3 /usr/bin/python

# Install python pip.
$ sudo apt-get install python3-pip

# Install RPI.GPIO.
$ sudo apt-get install python3-rpi.gpio
And then make a script to set up an interrupt handler to detect the GPOUT interrupt and the power switch:

code:
def handle_soc_interrupt(channel):
    print("SOC event detected!")

def handle_power_button_interrupt(channel):
    print("Power button press detected!")

if __name__ == '__main__':
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(SOC_GPOUT, GPIO.IN)
    GPIO.setup(POWER_SWITCH_PIN, GPIO.IN)

    GPIO.add_event_detect(SOC_GPOUT, GPIO.FALLING, callback=handle_soc_interrupt)
    GPIO.add_event_detect(POWER_SWITCH_PIN, GPIO.FALLING, callback=handle_power_button_interrupt)

    while True:
        time.sleep(10)
Speaking of tons of hidden little details that gently caress you up... Running this script gives me this error:

code:
pi@slackerpi:~/code/rpi-proto-1/code/power/status_overlay $ sudo python interrupt.py
Traceback (most recent call last):
  File "interrupt.py", line 24, in <module>
    GPIO.wait_for_edge(POWER_SWITCH_GPIO, GPIO.FALLING)
RuntimeError: Error waiting for edge
Fast forward about 12 hours and I've learned enough to figure out that sometimes linux drivers and other kernel modules can claim a GPIO which will lock out anything else that tries to use the same pin. (This is actually a good thing.)

code:
sudo cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-53, parent: platform/3f200000.gpio, pinctrl-bcm2835:
 gpio-5   (                    |sysfs               ) in  hi IRQ
 gpio-6   (                    |power_ctrl          ) in  hi ACTIVE LOW
 gpio-16  (                    |sysfs               ) in  hi IRQ
 gpio-21  (                    |sysfs               ) in  lo IRQ
 gpio-22  (                    |sysfs               ) in  lo IRQ
 gpio-29  (                    |led0                ) out lo
Since I am using the gpio-poweroff overlay, it's claimed GPIO6 and I can't add interrupt handlers or write to it with any software libraries. As advised from the Raspberry Pi Foundation forums, my only option is to tie another GPIO to GPIO6 and do edge detection on that... Great, so now I need to make a Y-shaped dupont connector cable for this thing too. I didn't know GPIO on a raspberry pi would be so jank.

Anyway, I'm using a breadboard right now so the cable splicing can wait. I tied GPIO16 to GPIO6 with a 1k resistor in between in case I accidentally set both to OUTPUT with different values and it worked:

code:
pi@slackerpi:~/code/rpi-proto-1/code/power/status_overlay $ ./status_overlay.py
Power button press detected!
Power button press detected!
Power button press detected!
Power button press detected!
SOC event detected!
Power button press detected!
SOC event detected!
Interrupt Handling Code: C++???

Before I figured out the kernel had a lock on GPIO6, I thought it might be the python library that was screwing up so I made a second version of the interrupt handling test script in C++.

code:
void handleSOCEvent(void) {
  std::cout << "SOC event detected!" << std::endl;
}

void handlePowerButtonEvent(void) {
  std::cout << "Power button pressed!" << std::endl;
}

int main(int argc, char **argv) {
  wiringPiSetupGpio();

  pinMode(PIN_BAT_GPOUT, INPUT);
  pinMode(PIN_BAT_POWER, INPUT);

  wiringPiISR(PIN_BAT_GPOUT, INT_EDGE_FALLING, &handleSOCEvent);
  wiringPiISR(PIN_BAT_POWER, INT_EDGE_FALLING, &handlePowerButtonEvent);

  while (1) {
    std::cout << "Main thread sleeping..." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(10000));
  }
The behavior is identical. So I went back to python because that sounds like it'll be easier.

Cory Parsnipson fucked around with this message at 07:58 on Sep 20, 2021

Cory Parsnipson
Nov 15, 2015
A Second Python Library contender emerges

So someone swung by my question in the RPi forums this morning and recommended another GPIO library, saying that it would let me set a callback to the power switch GPIO without having to tie it to a second pin. This library was called pigpio and then I soon realized it was the author themselves who recommended it to me. (woah)

This library... seems kind of sketch. I mean, the fact that kernel drivers can lock GPIO pins so that nothing else can screw with them is a good thing to prevent write corruption and if this library lets me do what I want by just ignoring it is a little alarming. Also the programming style and documentation just screams something from mid 90s. Don't tell them I said that. :pray:

Reservations aside, once everything was set-up, it did indeed work. I wrote another test script.

Installation was simple:

code:
  $ sudo apt-get install pigpio python3-pigpio
Setup involves running this daemon program that requires root privileges, which is a little more work than the other two options, but still only one line:

code:
  $ sudo pigpiod -s 10
Then add a callback and run the script:

code:
#!/usr/bin/python

import pigpio
import time

POWER_SWITCH_GPIO=6

def cb(gpio, level, tick):
    print("GPIO%d triggered!" % gpio)

if __name__ == '__main__':
    pi = pigpio.pi()
    if not pi.connected:
        print("Not connected to PIGPIO Daemon")

    cb1 = pi.callback(POWER_SWITCH_GPIO, pigpio.FALLING_EDGE, cb)

    while (True):
        time.sleep(10)
Here's the thing. The daemon polls the pins every x microseconds to get the reading of the GPIO pins in real time*. This is also what the callback system is based off of, so there's definitely no real time guarantee (but that's okay for us). This program uses about 6% CPU at all times which is something non-trivial to consider given that we are CPU limited and power limited as a Raspberry Pi game console. This is just behind the 8-ish or so percent that emulation station runs while idling. I actually think making that weird cable and using a second GPIO pin is more preferable here. That's a huge shame because we were so close to having cake and eating it too. :eng99:

*Fun fact: the author of pigpio wrote a Gtk app that turns the raspberry pi into an entry level logic analyzer and that sounds super cool. I might look into this if I need a logic analyzer. Not too confident about the sampling rate, but having a portable analyzer to do some basic debugging work on the go would be really, really neat.

Cory Parsnipson
Nov 15, 2015
Adding A Graphical Overlay to RetroPie/EmulationStation

Now we're heading far into software territory. It's time to take the fuel gauge script I made and display the battery percentage on the screen somewhere so I can use it while playing games. Outside of using SFML, I've never had to make a GUI program in linux before, so I was kind of excited to check it out. I thought I would have to use GTK or something so I looked into getting PyGObject installed, but then I ran into a problem where there was actually no window manager running (so GTK apps are unusuable). Oops. Retropie doesn't use the regular desktop manager stack, I think because it's too computationally expensive to do that and run an emulator at the same time. That is, if you're running Full-rear end Linux(TM) on the RPi the software stack is exactly the same as a desktop and you'll see the familiar gnome/kde desktop. But RetroPie strips a lot of stuff out for performance reasons. Instead, Emulation Station (the name of the RetroArch frontend) directly uses a low level Raspberry Pi library called "DispmanX" and I guess they must have ported or written a higher level library and custom window manager on top of that.


The legendary DispmanX (pictured)

I found a small project made by someone that puts a HUD overlay on a Gameboy Zero, which according to my research is an RPi Zero inside a Gameboy-like case. This script does basically exactly what I need so it's time to COMPLETELY COPY IT :black101: Er, well, I can't just use it as is because the exact specifics of how it interfaces with sensors and stuff is specific to the Gameboy Zero project so I will be heavily inspired by it and changing the parts that don't fit.

Pngview

If you read the GBZ guy's script, he uses something called pngview to display images to the screen. Googling this leads me to a library called raspidmx that is a user-friendly library written in Python and C to go on top of DispmanX written by "AndrewFromMelbourne". I promptly installed it:

code:
mkdir ~/src && cd ~/src
git clone --depth 1 [url]https://github.com/AndrewFromMelbourne/raspidmx.git[/url]
cd raspidmx/
make -j4
sudo cp pngview/pngview /usr/local/bin/
Also the GBZ overlay thing uses Google Material Design icons and after looking through free clipart for battery icons, I decided to use Google Material Design icons as well (pssst, search for battery :ssh:). The icons available for download only give you a completely empty battery and a completely full one, so I needed to GIMP me up some intermediate icons.


Using my Android phone for reference, I see a vertical battery with a white foreground color and a grey background



I made charge levels at 100%, 90, 75, 50, 25, and 10. The empty icon has a special exclamation point. There's also a second set that has a lightening bolt on it to signify charging.

It's time to try and put this picture onto the screen. I secure copied them to the device:

code:
scp images/*.png pi@<homenetwork>:/home/pi/code/rpi-proto-1/code/power/status_overlay/images
And then run pngview but, as expected, nothing happens. There's a utility called vcgencmd that will show you everything being drawn to the display:

code:
pi@slackerpi:~ $ pngview -d 0 -l 3 /home/pi/battery50p.png

[1]+  Stopped                 pngview -d 0 -l 3 /home/pi/battery50p.png
pi@slackerpi:~ $ vcgencmd dispmanx_list
display:0 format:XRGB8888 transform:0 layer:-127 800x480 src:0,0,800,480 dst:0,0,800,480 cost:534 lbm:0
display:0 format:RGBA16 transform:0 layer:0 1x1 src:0,0,0,0 dst:0,0,800,480 cost:564 lbm:1024
display:0 format:RGBA32 transform:0 layer:3 12x22 src:0,0,12,22 dst:394,229,12,22 cost:96 lbm:0
display:0 format:RGBA32 transform:20000 layer:10000 800x480 src:0,0,800,480 dst:0,0,800,480 cost:534 lbm:0
display:3 format:RGB565 transform:0 layer:-127 2x2 src:0,0,2,2 dst:141,32,437,416 cost:362 lbm:1024
so a bunch of stuff is being drawn to display 0 (which is my 5" LCD display). I don't know what display 3 is. Also, you'll notice that an image that is 12x22 pixels is on layer 3, but something 800x480 is on layer 10000. That second thing is probably emulation station. So let's see what happens if we move to a higher layer.

code:
pngview -d 0 -l 10010 /home/pi/battery50p.png

WEH

Did you SEE that poo poo??!? It's on the loving screen. It's working!!! IT'S loving ON THE SCREEN


Yeeeesss. Great success!

Adbot
ADBOT LOVES YOU

cakesmith handyman
Jul 22, 2007

Pip-Pip old chap! Last one in is a rotten egg what what.

Awesome!

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply