Yet another WIP post! If you hadn't noticed, most of my posts are going to be edited over time, since I'm using it as a way of documenting projects.
This is sort of a post-project documentation attempt at something me and my brother in law made early 2022. The gist of the project is I 'needed' a UPS that could run a lot of electronics without dropping at all. Mostly I just wanted to try building a UPS. Part of the inspiration came from running multiple 3D printers at the same time, on a rural power grid. It's quite frustrating when you lose dollars of filament every time the power blinks! 3D printing can already be pretty hit or miss, you don't need additional losses just from power quality.
This might be pretty obvious, but you probably shouldn't try and build anything like this unless you know what you're doing. For a ton of reasons. First, there's the safety risk of working on 120V circuits, the risk of working with batteries, the risk of damaging your expensive electronics, the risk of running afoul of local regulations, the risk of potentially starting a fire, et cetera! If I really needed a good, reliable, trustworthy, safe UPS for my electronics I would buy one. This is primarily an educational project.
Anyway. The core idea is simple. Use an inverter attached to some 12v batteries to provide an always-available backup 120V supply, and then switch over to that automatically when the mains power is interrupted. Besides being to keep 3d printers running, this system could run my computer and some other electronics as well. It's essentially just determined by what power level inverter you have.
The Algorithm
My brother in law actually wrote a really good document about his approach. I'm basically copying the whole thing here. As far as I know he doesn't have a website, but his gitlab is here, and his github is here. The repository he has the code in is private, otherwise I'd just link that. Anyway, credit for the following goes to Josh Barksdale!
Data Acquisition and Voltage Thresholds
We will be using the ATMega328p’s onboard ADC to measure an attenuated version of the voltage on the 120V mains with a DC offset applied. Our incoming signal should look something like this:
The scale and offset will vary a bit, so we’ll have a calibration routine to find the zero-voltage, negative-peak, and positive-peak values in the graph below.
Key:
• solid red: positive peak voltage when mains are working normally
• solid green: zero voltage
• solid blue: negative peak voltage when mains are working normally
• green dotted lines: zero-crossing threshold voltages
• red/blue dotted lines: max/min peak threshold voltages
The distance between solid lines and their associated thresholds is equal to 10% of the distance between the positive and negative peak voltages.
The CPU frequency of the ATMega328p will be set to 16 MHz and we’ll be scaling it by a factor of 128 to generate the ADC clock. The ADC will operate in free-run mode, continuously taking readings with a conversion time of 13.5 clock cycles. Thus the ADC sample rate will be:
Fs = 16MHz / (128 * 13.5) = 9.259 kHz
This will give 154 samples per period of the 60 Hz voltage signal we’re measuring.
Fault Detection
Define some states which correspond to different sections of the 60 Hz wave:
If the voltage spends too much or not enough time in a given state, a fault has occurred. Note that for all states, the voltage threshold to enter the state is different from the voltage threshold to exit the state, so Schmitt triggering is not needed.
State | Typical Duration [Samples] | Min. Duration [Samples] | Max Duration [Samples] |
A | 4.9 | 1 | 10 |
B | 27.1 | 10 | 40 |
C | 45.1 | 25 | 60 |
D | 4.9 | 1 | 10 |
E | 27.1 | 10 | 40 |
F | 45.1 | 25 | 60 |
[ END Josh section ]
The Circuit
The core idea is to use solid state relays in order to quickly transfer power between mains and backup. Most automatic transfer switches for things like RVs or boats do this pretty slow, taking even several seconds to switch between the two. Another approach is to simply run all of the time on your inverter, but switch the inverter's power between two different DC sources (mains and battery backup powered). Keeping an inverter running everything all the time incurs efficiency losses however, and you have to buy a huge inverter to run any kind of household load. That's fine if you want to just run a couple 3D printers, but this approach doesn't scale well.
There are many descriptions of the different kinds of UPS systems, but here is a good overview I found. This UPS that we're building is therefore a Standby UPS, where the mains AC takes priority and the inverter takes over in case of a fault.
Anyway, here's a basic schematic of the approach.
In reality, the SSR and the contactor are controlled via different control lines. And there is some additional circuitry (some FETs to run the relays, for example), but that's sort of the core idea.
The Inverter
I bought a 1500W "GoWISE" power inverter off of Amazon for this project. I actually meant to get a 1000W one, but due to a miscommunication with my wife I have 500W extra. This is a "Pure Sine Wave" inverter, meaning it goes through a lot of effort to produce an actual sine wave on the output instead of a square wave from a simple H-bridge or something. The downside of a pure sine wave inverter is they are typically less efficient and more expensive than the other types, but should work for just about anything that mains power runs.
I actually took apart and dissected the inverter I got, since understanding more about UPS systems also requires knowing about DC-AC conversion. The basic design is pretty simple, there is a high power DC-DC circuit board that steps up the input 12v to something more like 200v (I forget the actual voltage). This new high voltage is fed into the DC-AC stage, which creates the actual 120v output. This is essentially a high speed FET circuit with many paralleled FETs attached to a heatsink, run by a PIC microcontroller if I remember correctly. There was additional sense circuitry, as well as FET drivers to convert the signal from the MCU to something capable of driving MOSFETs very quickly. I believe there was also signals going back and forth from the DC-DC board and the MCU, probably for sense and protection. Finally there was some basic output filtering and distribution.
Dave's EEVlog actually has a really good video on this topic, I highly recommend watching it. This should be the one. There are a lot of other details that go into making a good UPS (or at least inverter). Things like active power factor correction are probably very important if you're driving heavily inductive or capacitive loads. Safety, voltage quality, efficiency, heat management, this kind of thing gets very complicated very quickly.
The peak power of my inverter is actually rated at 3000W, which seemed far more in line with the components and circuitry I was checking while looking inside the inverter. The company also sells a 2000W and 3000W version of the inverter which look identical to this one in the listing. I am just a little curious if they are using the same design for all of their builds, and simply setting a software limitation to separate the models they sell. Based on some quick calculations on their FETs alone, it seemed like they were only using a fraction of their thermal headroom in my inverter.
Results
We moved back into the city shortly after we built the prototype UPS, so I actually haven't really used it. We did test it out somewhat beforehand however, and what we found seemed promising. It did seem to successfully transfer power when the mains were cut, and wouldn't even flicker a light. I believe we ran a monitor and/or desktop computer on it as well, but don't quite remember.
Further improvements
Ideally, in a sort of hybrid always-on inverter setup like this one, the inverter would be in-phase with the mains power in order to prevent any weird hiccups when transferring between the two. Additionally, if something were to fail, and you were to connect mains power directly to your inverter, it could be very bad. For the prototype, I'm relying on lots of testing and hoping if something ever does glitch, that the inverter's protection circuitry is fast enough to prevent any damage.
The code
Josh has since made the repository public, and the code is available there. Quite a bit of the code is for managing the internals of the Arduino, setting up things like the timers and ADC. It's not strictly necessary to write it as it has been written, but it's definitely provides the best practice and the most control.
Comments