[Nut-upsuser] Supporting a DIY UPS with minimal effort butmaximum gain

Jim Klimov jimklimov+nut at gmail.com
Fri May 17 13:42:29 BST 2024


Looks very great, thanks for writing this! I gather you'd port this to the
Wiki page you've started, too?

A couple of comments:

> So I run a NUT server on a Raspberry PI which is connected via USB to my
DIY-NAS Arduino.

DIY-UPS?

> See drivers/arduino-hid.c for the list of supported IDs...

Since NUT v2.8.1 [PR #1369], the `usbhid-ups` driver allows the user to
specify a `subdriver` in config - to use the specific mapping for the
specified vendorid:productid (and/or other matching options involved),
allowing for IDs not yet known to NUT (built into any driver) or to use a
different subdriver than the one associated with those IDs (some vendors
historically have same IDs used for significantly different products).
Either way, while it is ideally preferable to test and post PRs with
correct out-of-the-box detection of devices handled by this or that code,
the specimens seen roaming in the wild keep eluding any pre-created
matchers that are set in stone for the particular build of (packaged) NUT.
This feature allows for at least some more tweaks and experiments in the
field.

Hope this helps,
Jim Kl.imov



On Fri, May 17, 2024 at 1:05 PM Kelly Byrd <kbyrd at memcpy.com> wrote:

> Ha! I got several on and off list requests for details, so I'll give a
> bunch of details here and then maybe I can move this to a wiki page others
> can help edit.
>
> WARNING! WARNING! WARNING!
> Be careful! My implementation required opening up high power components,
> and dealing with 120VAC mains power and high currents on 12VDC. If you
> decide to tackle any of this yourself, you need to understand how to do
> this safely, size components appropriately, etc.
>
> My goal is to keep a home Internet connection available during a power
> outage. This doesn't happen that often, but it bugged me when it did and I
> like playing with power-related things, so this became a fun project to
> tackle. I guess I should mention that my home network gear is in a rack in
> the garage. "modem", router, switch, wifi APs powered over PoE from the
> switch, NAS, and typically a Raspberry Pi or two doing whatever "always on"
> things I want. I also previously built a substantial portable battery box
> that will power other appliances like TVs and computers, but the networking
> gear is all in the garage and I can't power both at once without some very
> long extension cables snaking through the house.
>
> I noticed a few years ago that my Internet connection stayed up during a
> couple of different neighborhood power outages, assuming I could power the
> gear on my side. I guess the equipment on the ISP side is far enough away
> that it isn't affected? For a few years, I did this with a 12V inverter
> connected to an EV (an electric car). It turns out the 12V system in many
> EVs will provide 12V power through a DC step-down from the main traction
> battery. I really only need like 15A and previous testing made me confident
> I could safely do this as long as the main battery had capacity left. So, I
> did that for a while, but earlier this year we sold the EV and became a
> one-car household. So...what do I do? I had an inverter, if I could get
> batteries and a way to charge them, I should be most of my way toward a DIY
> UPS, right?
>
> Specs/Requirements
> * AC power needed is typically about 150W, I typically use 300W as a value
> for max surge. If I turn off my NAS, the load is only about 50-55W AC. I
> was aiming for 2-3 days of power for this load, and can live without the
> NAS during an outage, so I need 2.8-4.3kWh of capacity with the NAS off.
>
> * While I do want this to work, this is a fun personal project. Mucking
> with it is part of the goal. I had some hobby money to spend, but not
> infinite. I wanted to reuse things I had on hand or could get easily for
> v1. I also get to decide how reliable it needs to be.
>
> The system is:
> * AIMS Pure Sine 12V 600W Inverter. I had it already. Having this inverter
> on hand drove the decision for 12V vs 24/48V. Also, power needs are
> relatively low so 12V doesn't lead to more than 55A of current, and that's
> only when charging from a deep discharge.
>
> * RV Converter/Charger: PowerMax PM4 55A 12V. This is a lead acid battery
> charger that will also provide power after batteries are charged. Many
> battery chargers are not designed to be run 24/7, this one is.
>
> * Two 12V 200Ah Renology AGM deep cycle batteries wired in parallel. Got a
> deal on these. I decided I was ok with 75%-80% DoD even though these are
> lead acid. This gives me about 3.5kWh of usable AC capacity.
>
> * Batteries and charger are wired up with 4AWG, the inverter is something
> smaller, I think 6AWG?
>
>
> What I have built is a double conversion online system. The inverter is
> powering the AC load all the time. There's no transfer switch. There's
> lower efficiency when power is on because the normal power path is always
> AC->DC->AC. I did this because I wasn't confident in my ability to find a
> transfer switch that would transfer fast enough and it was one more thing
> to figure out and buy. In my head, this online architecture is simpler, but
> I may change it in the next version. I worry a bit about the inverter being
> ok running full time, but since it is rated for 600W and I use only 150W
> all the time, I decided it's ok. When it fails, I'll figure out something
> else.
>
> I chose lead acid deep-cycle batteries because if you're willing to
> discharge them to 70-80% they're very cost effective vs LiFePO4 or other
> lithium types. I know this will shorten the number of cycles I get from
> them. I'm ok with that. In this application, they sit at 100% for all but
> maybe a few hours to a few days a year. They may see one or two deep
> discharges a year. If I get five years out of them, that's great!
>
> I calculated roughly 3.5kWh of usable capacity for these two wired in
> parallel. Running with the NAS off is maybe 5A from the DC side of things,
> which is a really low load for a 400Ah battery bank. They are very heavy,
> but I already had a heavy duty storage rack next to the load, so that's not
> a problem in this case. Also, the voltage range for 12V lead acid batteries
> is still better supported than LiFePO4. Right now, there are still more
> (and lower cost) chargers and inverters that assume a lead acid voltage
> range. As an example, my inverter will shut down if it sees over about
> 14.6V.
>
> So, how does this fit into NUT? One key aspect of my capacity planning
> was: "normal load is ~150W, but if the NAS turns off, I can make that
> 50-60W.". My NAS is a QNAP, it has NUT installed. Before this DIY UPS, I
> was using an APC consumer UPS connected to the NAS via USB so it would turn
> off 5 min after mains power went off. That's the behavior I wanted for my
> DIY UPS.
>
> So how did I do this?
>
> Gear:
> * Arduino Pro Micro clone. It has a micro USB port built in and is
> commonly used for "make an Arduino appear to be some USB device" projects.
> It can be powered over USB, or by 5VDC directly to pins.
>
> * AC detection module: https://www.amazon.com/gp/product/B082PWV586.
> Gives me an opto-isolated "is the mains AC present" signal the Arduino can
> read.
>
> * Raspberry Pi running NUT. I wish I didn't need this, but I do for now.
> While building and debugging the Arduino code, I needed to modify the NUT
> code. Those patches made it in v2.8.1 and v2.8.2 NUT releases, but I still
> don't think my QNAP NAS has v2.8.2 available. I eventually plan to remove
> this.
>
> I put the AC detection module and the Arduino inside the PowerMax
> converter/charger enclosure, on a little 3D printed mount. The AC module
> connect to the AC input terminals inside the PowerMax and then the signal
> side connects to a pin on the Arduino and pulls it high (or low, I forget)
> when the AC is gone. I run a USB cable out of the PowerMax case which
> connects to the RPi running NUT. The RPi is powered by the inverter, and it
> powers the Arduino over USB. The RPi stays on during a power outage.
>
> So now I can write some Arduino code that loops and checks the status of a
> digital pin. How do I pretend to be a UPS in a way NUT will recognize?
>
> Some googling led me to the HIDPowerDevice project.
> https://github.com/abratchik/HIDPowerDevice. That is a library for
> Arduino MCUs that does all the protocol for getting an Arduino device to be
> recognized as a HID compliant UPS device over USB. You use it by
> periodically calling a `sendReport` function with various flags set. Ex:
> PowerDevice.sendReport(HID_PD_REMAININGCAPACITY, &iRemaining,
> sizeof(iRemaining));
> PowerDevice.sendReport(HID_PD_PRESENTSTATUS, &iPresentStatus,
> sizeof(iPresentStatus));
>
> `iPresentStatus` is a bit field with a ton of info in it, like:
> PRESENTSTATUS_ACPRESENT, PRESENTSTATUS_DISCHARGING,
> PRESENTSTATUS_CHARGING, etc. See the project for full details.
>
> So, now my Arduino code loop does this:
> Check status of AC on/off pin.
> Set/clear PRESENTSTATUS_ACPRESENT and set
> PRESENTSTATUS_CHARGING/PRESENTSTATUS_DISCHARGING accordingly.
> Call `sendReport` from the HIDPowerDevice library.
> Sleep a second, loop.
>
> In reality, my loop does a little bit more than this. It loops every
> second, but only sends a report if some status changed but waits no more
> than every 5 seconds between reports in any case. NUT (and Windows, and
> MacOS) seem to expect this.
>
> So, assuming I can get NUT to recognize the Arduino Micro as a UPS, this
> should work. I had two problems getting NUT to recognize the Arduino:
> 1) Will NUT recognize the default Arduino vendor and product id (vid:pid)?
> The answer is YES! There is an Arduino subdriver for usbhid in NUT. It
> looks like the HIDPowerDevice project author added this originally a few
> years ago! See drivers/arduino-hid.c for the list of supported IDs. If you
> end up with an Arduino device that has another vid/pid combo, it would need
> to be added there.
>
> 2) When using the HIDPowerDevice library, the Arduino Micro presents as a
> composite HID device, so it is more than one HID type at once. AFAICT, real
> world examples of composite devices are rare, but it is in the HID spec. In
> this exact case the Arduino presents as both serial/comm interface
> (typically used for debug output when running code from the Arduino IDE)
> and as a HID Power Device (the HID term for UPS status over USB). This all
> works now as of NUT 2.8.2.
>
> Note that the Arduino subdriver is not as full featured as something like
> the APC subdriver. I don't think it allows for NUT to set values on the
> Arduino HID device. I don't know if the Arduino HIDPowerDevice library
> supports this either. I have only tested the send-a-report-periodically
> code path.
>
> NUT config
> What I really wanted was for my NAS to shut down when mains power goes
> away. My QNAP NAS runs NUT, but I needed 2.8.2 and getting a new version on
> there was more than I wanted to tackle, especially since my PRs weren't in
> a release version of NUT at that time. So I run a NUT server on a Raspberry
> PI which is connected via USB to my DIY-NAS Arduino. The RPi does not react
> to changes in the UPS at all. It  makes them available over the network to
> the NUT instance running on the QNAP NAS. The QNAP NAS is then configured
> to poll the RPi NUT instance for UPS status and set to shut down if AC
> power is out for 5 min. I would rather not deal with this extra RPi in the
> setup, but it was the easiest way forward for me. Once NUT 2.8.2 is
> available for my QNAP NAS. I'll get rid of it.
>
>
> Optional Upgrade
> DC voltage sensing to give an idea of remaining runtime or remaining
> capacity. Since this is too long already, I'll try to be brief. One thing I
> did a month or so after the initial install was add DC voltage detection to
> the Arduino side of things:
>
> Gear:
> * 0-25VDC voltage sensor (https://www.amazon.com/gp/product/B01HTC4XKY).
> It's a voltage divider, let's my code sense the DC voltage.
>
> * External ADC: ADS1115 board. I wanted higher resolution DC voltage
> detection.
>
> My code then changed to take readings from the ADS1115 and convert that
> into a rough "50-100% capacity remaining" that I can report to NUT. It took
> a while to get right and it's only "accurate enough", not "trust this to a
> millivolt level of accuracy". For now it's just nice to have and I enjoyed
> having to learn about ADC measuring on Arduino enough to get this accurate
> enough to report with 1% differences in capacity.
>
> Future
> I've been researching designing a PCB and doing an "all-in-one" UPS. I'll
> talk more about that on the wiki page as well.
>
> I guess I should share my Arduino code on GitHub too.
>
> On Thu, May 16, 2024 at 10:59 AM gene heskett via Nut-upsuser <
> nut-upsuser at alioth-lists.debian.net> wrote:
>
>> On 5/16/24 08:59, Jim Klimov via Nut-upsuser wrote:
>> > I agree with earlier posters, such documentation can help future
>> > tinkerers. There is probably more than just one to hold the hand and
>> > walk through the ordeals :)
>> >
>> > Perhaps a new page at https://github.com/networkupstools/nut/wiki
>> > <https://github.com/networkupstools/nut/wiki> can be a good location...
>> >
>> > Jim
>> >
>> Great Idea Jim.
>> >
>> > On Thu, May 16, 2024 at 1:29 PM Bill Gee <bgee at campercaver.net
>> > <mailto:bgee at campercaver.net>> wrote:
>> >
>> >     Hi Kelly -
>> >
>> >     As an Arduino nerd, I am interested in this!  I am sure others on
>> the
>> >     list would be interested.  If nothing else, it would be nice to have
>> >     some documentation in the archives.
>> >
>> >     I assume you set it up as an online system rather than a standby
>> >     system.
>> >        Right?  If true, then the choice of inverter is fairly
>> critical.  It
>> >     has to be bomb-proof reliable.
>> >
>> >     What did you choose for battery voltage?  What is the power
>> capacity of
>> >     the inverter?
>> >
>> >     Which Arduino did you use?  All of my Arduino projects use the Pro
>> >     Mini,
>> >     though it would be quite easy to get some other model for this.
>> >
>> >     Thanks -
>> >     ===============
>> >     Bill Gee
>> >
>> >     On 5/15/24 20:11, Kelly Byrd wrote:
>> >      > I put together my own DIY UPS,  it's a RV charger/converter, an
>> >      > inverter, and some batteries. I use an Arduino and the
>> >     HIDPowerDevice
>> >      > library (https://github.com/abratchik/HIDPowerDevice
>> >     <https://github.com/abratchik/HIDPowerDevice>
>> >      > <https://github.com/abratchik/HIDPowerDevice
>> >     <https://github.com/abratchik/HIDPowerDevice>>) to get it to talk
>> to
>> >     NUT.
>> >      > Been working great for months!
>> >      >
>> >      > The Arduino is connected to two modules:
>> >      > * AC detection circuit to measure mains power on/off
>> >      > * Voltage divider and an external ADC to get a reasonably good DC
>> >      > voltage level for the battery which I turn into the a charge
>> >     percentage.
>> >      >
>> >      > This uses the USBHID driver in NUT and "just works" as long as
>> >     you're
>> >      > using NUT 2.8.2 or later. I used the example code in the
>> >     HIDPowerDevice
>> >      > library as a starting point for running on my Arduino.
>> >      >
>> >      > I can share more specifics about the Arduino side of things off
>> >     list if
>> >      > you want, the NUT side of things is pretty boring and normal.
>> >      >
>> >      > On Wed, May 15, 2024 at 3:27 PM Kiril Zyapkov via Nut-upsuser
>> >      > <nut-upsuser at alioth-lists.debian.net
>> >     <mailto:nut-upsuser at alioth-lists.debian.net>
>> >      > <mailto:nut-upsuser at alioth-lists.debian.net
>> >     <mailto:nut-upsuser at alioth-lists.debian.net>>> wrote:
>> >      >
>> >      >     Hello,
>> >      >
>> >      >     I found out about NUT just days ago while searching for a
>> >     solution
>> >      >     for my home setup. After some digging through the interwebs,
>> >     I come
>> >      >     to you with questions.
>> >      >
>> >      >     I'm putting together a DIY 12V UPS, very similar to what this
>> >     guy did:
>> >      >
>> >      >     [1]
>> >      >
>> >
>> https://baldpenguin.blogspot.com/2015/10/diy-12v-ups-for-home-network-equipment.html
>> <
>> https://baldpenguin.blogspot.com/2015/10/diy-12v-ups-for-home-network-equipment.html>
>> <
>> https://baldpenguin.blogspot.com/2015/10/diy-12v-ups-for-home-network-equipment.html
>> <
>> https://baldpenguin.blogspot.com/2015/10/diy-12v-ups-for-home-network-equipment.html
>> >>
>> >      >
>> >      >     The objective is to keep a bunch of mini PCs and network gear
>> >     online
>> >      >     for as long as the battery lasts and then provide a mechanism
>> >     for a
>> >      >     graceful shutdown of my NAS and other appliances for which
>> >     cutting
>> >      >     power would not be healthy. The project above is missing the
>> >      >     "connected" part. I want to get mine to play with NUT nicely.
>> >     Other
>> >      >     prior art is this project:
>> >      >
>> >      >     [2] https://github.com/xm381/Raspberry-Pi-UPS
>> >     <https://github.com/xm381/Raspberry-Pi-UPS>
>> >      >     <https://github.com/xm381/Raspberry-Pi-UPS
>> >     <https://github.com/xm381/Raspberry-Pi-UPS>>
>> >      >
>> >      >     Mentioned in a previous thread here:
>> >      >
>> >      >     [3]
>> >      >
>> >
>> https://alioth-lists.debian.net/pipermail/nut-upsuser/2018-August/011198.html
>> <
>> https://alioth-lists.debian.net/pipermail/nut-upsuser/2018-August/011198.html>
>> <
>> https://alioth-lists.debian.net/pipermail/nut-upsuser/2018-August/011198.html
>> <
>> https://alioth-lists.debian.net/pipermail/nut-upsuser/2018-August/011198.html
>> >>
>> >      >
>> >      >     A valid approach -- emulates an existing protocol on an
>> arduino.
>> >      >
>> >      >     Are there other similar projects that you know of? I found
>> >     plenty of
>> >      >     "DIY UPS" projects, but none were "smart".
>> >      >
>> >      >     I am able to put together firmware for some micro which will
>> take
>> >      >     care of measuring voltages, currents, possibly also turn
>> on/off
>> >      >     loads, serial or USB or IP are options. Not sure yet what
>> >     hardware
>> >      >     features I'll put together, but this depends somewhat on the
>> >      >     approach for getting this thing integrated with NUT. PSUs and
>> >      >     batteries are already on the way, and my junk drawers have
>> most
>> >      >     other parts I may need.
>> >      >
>> >      >     So, options found so far:
>> >      >
>> >      >     * Use genericups. Least favorite option, very limited
>> features
>> >      >
>> >      >     * Use the same approach as [2]. If I were to go that route --
>> >     which
>> >      >     is the best protocol to pick for emulation? I'm looking for
>> >      >     something simple, extensible/flexible and well-documented.
>> >      >
>> >      >     But what I really wish was possible was the ability to
>> >     describe my
>> >      >     device in some format, feed it to a generic driver in NUT and
>> >      >     profit. I see some efforts have been made in this direction,
>> most
>> >      >     notably:
>> >      >
>> >      >     [4]
>> >      >
>> >     https://github.com/networkupstools/nut/wiki/Data-Mapping-File-(DMF)
>> >     <
>> https://github.com/networkupstools/nut/wiki/Data-Mapping-File-(DMF)>
>> >      >
>> >       <
>> https://github.com/networkupstools/nut/wiki/Data-Mapping-File-(DMF) <
>> https://github.com/networkupstools/nut/wiki/Data-Mapping-File-(DMF)>>
>> >      >
>> >      >     What is the state there? Is it usable for USB HID? Or, how
>> hard
>> >      >     would it be to make it usable? Even a modbus description will
>> >     do --
>> >      >     implementing the modbus server (yes, server, I'm being
>> >      >     politically-correct) over serial or even TCP is easy, if only
>> >     there
>> >      >     was a way to dump a CSV with register descriptions in some
>> >     magical
>> >      >     driver...
>> >      >
>> >      >     And yet another approach which comes to mind is to implement
>> my
>> >      >     driver as an external executable. This may be completely
>> >     unfeasible
>> >      >     and stupid, and please let me know if it is. But, from what I
>> >      >     gather, drivers run in their own process and talk to the
>> >     daemon via
>> >      >     a UNIX socket. Why not make it possible for the driver to be
>> just
>> >      >     any executable, built/deployed outside of the NUT codebase?
>> The
>> >      >     socket protocol seems simple enough, and this will allow for
>> ...
>> >      >     creativity. It could be implemented in any language
>> (including
>> >      >     scripting languages) and need not depend on anything
>> >     NUT-specific,
>> >      >     other than maybe some common CLI interface and/or
>> configuration.
>> >      >
>> >      >     I'm hoping the NUT masters will have some insight. Thanks for
>> >      >     working on this!
>> >      >
>> >      >     Cheers,
>> >      >     Kiril
>> >      >     _______________________________________________
>> >      >     Nut-upsuser mailing list
>> >      > Nut-upsuser at alioth-lists.debian.net
>> >     <mailto:Nut-upsuser at alioth-lists.debian.net>
>> >      >     <mailto:Nut-upsuser at alioth-lists.debian.net
>> >     <mailto:Nut-upsuser at alioth-lists.debian.net>>
>> >      >
>> >
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser
>> >     <
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser>
>> >      >
>> >       <
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser <
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser>>
>> >      >
>> >      >
>> >      > _______________________________________________
>> >      > Nut-upsuser mailing list
>> >      > Nut-upsuser at alioth-lists.debian.net
>> >     <mailto:Nut-upsuser at alioth-lists.debian.net>
>> >      >
>> >
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser
>> >     <
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser>
>> >
>> >     _______________________________________________
>> >     Nut-upsuser mailing list
>> >     Nut-upsuser at alioth-lists.debian.net
>> >     <mailto:Nut-upsuser at alioth-lists.debian.net>
>> >
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser
>> >     <
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser>
>> >
>> >
>> > _______________________________________________
>> > Nut-upsuser mailing list
>> > Nut-upsuser at alioth-lists.debian.net
>> > https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser
>>
>> Cheers, Gene Heskett, CET.
>> --
>> "There are four boxes to be used in defense of liberty:
>>   soap, ballot, jury, and ammo. Please use in that order."
>> -Ed Howdershelt (Author, 1940)
>> If we desire respect for the law, we must first make the law respectable.
>>   - Louis D. Brandeis
>>
>>
>> _______________________________________________
>> Nut-upsuser mailing list
>> Nut-upsuser at alioth-lists.debian.net
>> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser
>>
> _______________________________________________
> Nut-upsuser mailing list
> Nut-upsuser at alioth-lists.debian.net
> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/nut-upsuser
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/nut-upsuser/attachments/20240517/c85c1933/attachment-0001.htm>


More information about the Nut-upsuser mailing list