UPS (Uninterruptible Power Supply) Reference Design Overview
UPS (Uninterruptible Power Supply) Reference Design provides a ready-made uninterruptible power supply solution with the flexibility of a microcontroller - PIC17C43 that offers a low cost solution and high performance not found in other microcontrollers. The PIC17C43 (datasheet) microcontroller manages all the control of the UPS system.
The PIC17C43 PWM controls an inverter whose output, when filtered, results in a sinusoidal AC output waveform. Fault signaling can be initiated internal or external to the PIC17C43 depending on the type of fault. A fault will disable the entire inverter. The output voltage and current will be monitored by the PIC17C43 to make adjustments “real-time” to correct for DC offset and load changes.
The PIC17C43 uses zero crossing for synchronization of input voltage/phase to output voltage/phase. All internal module synchronization is handled by the PIC17C43.
PIC17C43 Microcontroller Benefits
-
• Digital Filtering
• Parts and Complexity Reduction
• Peripheral Integration
• Ease of Interfacing
• High Quality Sine Wave - High throughput allows for high quality output
• Time to Market
• Flexibility - core control features and operations can be changed with software modifications only
• Transportability of Design
• Variable Loop Response
• Testability
System Overview
The Uninterruptible Power Supply (UPS) is supplying power based on the input power, if the unit is plugged in, or based on the batteries. The input power is filtered (when available) for common mode noise and is protected from surges/spikes by input power protection circuitry. Then the power goes into the power factor correction (PFC) module which forces the input current to be sinusoidal so that power utilization is more efficient. The PFC module also rectifies the input AC power to produce voltage-regulated DC power which is used by the rest of the functional modules.
This reference design is for guidance only, and it is anticipated that customers will modify parts of it. The PIC16/17 family of microcontrollers offers a wide variety of options for a UPS design from the PIC16C72 to the PIC17C756.
The PIC16C72, PIC16C73A, PIC16C74A, PIC17C43, and PIC17C756 all have the processing throughput to generate the sine wave described in this documentation.
Hardware Overview
The PIC17C43 is the heart of this reference design (see the picture below). The high performance of the Harvard architecture gives the user the throughput needed for high quality sine wave generation. The single-cycle multiply means faster program execution and response to waveform changes. Only 8 bits of the 10-bit PWM is needed to resolve a high quality output waveform.
Software Overview
The PIC17C43 embedded software controls the operation of the AC sine wave generation. It is imperative that the loop response be fast enough to minimize distortion on the output wave. Therefore, the throughput of the microcontroller is a critical parameter.
System Specifications
-
AC Input: 120/240 VAC ± 10%, 50/60 Hz ± 3Hz
UPS Output: 120/240 VAC ± 10%, 50/60 Hz ± 3Hz (User-Selectable), Sinusoidal
Rating: 1400 VA
Input Filtering: EMI/RFI Filtering
Metal Oxide Varistor (MOV) for Spike/Surge Protection
Schematics
The UPS schematics may be obtained on the Download section or on the Microchip site.
The UPS may be split into 4 main circuits:
-
Input Power
Factor Correction
Battery Boost
Free-Running Chopper
Inverter
The UPS is an on-line device which normally will have the Power Factor Correction circuit feeding the Chopper, which then feeds the Inverter. If the input power should be lost, the Power Factor Correction circuit falls out of the power flow and the Battery Boost circuit automatically provides power to the Chopper.

UPS circuit board (PCB) power flow
In the Battery Boost circuit, the transistor pairs are connected in parallel for the purpose of handling high currents. The current transformer T2 is connected as shown to sense each pair’s current with just one transformer, i.e., to prevent it from saturating. The control for the 120V/240V relay (power switch) was not implemented. Wherever input power monitoring would take place, monitoring for 120 or 240V would also occur and switch the relay. These functions would be placed before the PFC circuit.
The Power Factor Correction circuit is provisional, so the parts listed are generic parts.
Source Code
/***************************************************************************** * Filename: MAIN.C ****************************************************************************** * * Author: Dave Karipides * Company: APS, Inc. * Date: 3-3-97 * Compiled Using MPLAB-C Rev 1.21 * ****************************************************************************** * * Include Files: * ****************************************************************************** * * Description: The main routine calls all the functions for generating * an OPEN_LOOP or FEEDBACK sine wave of either 50 or 60 Hz. * ****************************************************************************** * * Revisions: * 3/3/97 Added FEEDBACK LOOP * * ******************************************************************************/ /***************************************************************************** * main() * * Description: The main routine initializes the registers and loops * forever. All control is handled in the TMR0 INT * routine. * * * Input Variables: NONE * * Output Variables: NONE * * ******************************************************************************/ //#define OPEN_LOOP #define FEEDBACK //#define 50Hz #define 60Hz #pragma option v #include <17c43.h> #include#include #ifdef OPEN_LOOP // This table yields Full VRMS input unsigned char const pwmtab[32]={0,25,50,74,98,120,142,162,180,197,212, 225,235,244,250,254,255,254,250,244,235, 225,212,197,180,162,142,120,98,74,50,25}; #endif #ifdef FEEDBACK // This table yields slightly less than Full VRMS input unsigned char const pwmtab[32]={0,20,40,60,79,97,114,131,145,159,171, 181,189,197,202,205,206,205,202,197,189, 181,171,159,145,131,114,97,79,60,40,20}; #endif long read_ad(unsigned char); // Prototype for A/D converter function unsigned char index; // Index into the sinewave reference table unsigned char sign; // Flag used to unfold sinewave reference table long reference; // Value of the sinewave refrence after unfolding unsigned char reference_lo @ reference; // V1.21 of Compiler does not type cast unsigned // char to long so we will write to low byte separately long out_volt; // Magnitude of the output voltage; long y; // Variables used in compensation routine long yold; long x; long xold; long ad_value; // A/D Converter Value void main(void) { CLRWDT(); PORTC = 0; // Zero out portc latches DDRC = 0x22; // Set up Data direction register for C DDRB = 0; // Set up Data direction register for B PR1 = 0xFF; // Setup PR1 register (24.4Khz @ 25Mhz clk) PW1DCL = 0; // Set low bits of PWM to 0 PW1DCH = 0; // Init PWM duty cycle to 0 T0STA = 0x20; // Configure Timer0 prescaler INTSTA.T0IE = 1; // Enable Timer 0 interrupt TCON1.TMR1CS = 0; TCON1.T16 = 0; TCON2.TMR1ON = 1; // Start timer 1 (PWM timer) TCON2.PWM1ON = 1; // Turn on the PWM CPUSTA.GLINTD = 0; // Unmask the interrupts index = 0; // Initialize variables sign = 0; y = 0; yold = 0; x = 0; xold = 0; PORTC.0 = 1; // Enable the Inverter while(1); // Loop forever, execute in INT Routine } #ifdef FEEDBACK __TMR0() // Timer interrupt { T0STA.T0CS = 0; // Stop timer PORTB.7=1; #ifdef 60Hz TMR0L=0xA5; TMR0H=0xF9; // Make Timer0 interrupt at 3.84KHz for 60Hz output #endif #ifdef 50Hz TMR0L=0x5F; // Make Timer0 interrupt at 3.20KHz for 50Hz output #endif T0STA.T0CS = 1; // Start timer CLRWDT(); reference = 0; // Clear Reference Value reference_lo = pwmtab[index]; // Lookup the value of the sinewave reference if (!index) // Toggle Sign Every Cycle Through table sign = ~sign; ++index; // Increment index if (index == 32) // If end of table, reset counter index = 0; if (sign) // If negative going wave { reference = ~reference; // V1.21 of Compiler negate (-ref) doesn’t work for reference = reference + 1; // ref<=0 } ad_value = read_ad(0); out_volt = ad_value - 512; // Read output voltage (512 counts=0 volts out) // Form the expression y = yold + (0.09261 * (x + xold)) // Where yold, xold is the value of y, x from the previous sample // x is the , formed by the difference between the output // of the inverter and the reference signal. x = out_volt - reference; y = ((x + xold) * 24); y = y / 256; y = y + yold; if (y >= 0) { PORTC.2 = 0; // Set positive going cycle } else { PORTC.2 = 1; // Set negative going cycle y = ~y; y = y + 1; } if (y > 255) y = 255; // Limit y PW1DCH = y; // Update duty cycle xold = x; // Store previous sample’s state yold = y; PORTB.7=0; } #endif #ifdef OPEN_LOOP // The inverter runs in an open loop mode with OPEN_LOOP defined. __TMR0() // Timer interrupt { T0STA.T0CS = 0; // Stop timer #ifdef 60Hz TMR0L=0xA5; TMR0H=0xF9; //Make Timer0 interrupt at 3.84KHz for 60Hz output #endif #ifdef 50Hz TMR0L=0x5F; //Make Timer0 interrupt at 3.20KHz for 50Hz output TMR0H=0xF8; #endif T0STA.T0CS=1; //Start timer CLRWDT(); PW1DCH = pwmtab[index]; if (!index) { PORTC.0 = 0; // Gate Drive off PORTC.2 = ~PORTC.2; // Flip Pos/Neg bit PORTC.0 = 1; // Gate Drive on } ++index; if (index == 32) index = 0; PORTC.3 = ~PORTC.3; // Toggle bit to test freq. } #endif long read_ad(unsigned char channel) { long result; PORTC.6 = 1; // Write bit high PORTC.7 = 1; // Read bit high PORTC.4 = 1; // Chip select high DDRD = 0; // Make PORTD an output PORTD = 0x04; // Single ended mode signed 10 bit chan 0 Right justified PORTC.4 = 0; // Select chip PORTC.6 = 0; // latch command word int A/D PORTC.6 = 1; // Start conversion PORTC.4 = 1; // Deselect chip while (PORTC.5); // Wait for conversion to complete DDRD = 0xFF; // Make PORTD an input PORTC.4 = 0; // Select chip PORTC.7 = 0; // Read high byte *( ((unsigned char*)&result) + 1) = PORTD; PORTC.7 = 1; PORTC.4 = 1; PORTC.4 = 0; PORTC.7 = 0; // Read low byte *( ((unsigned char*)&result) ) = PORTD; PORTC.7 = 1; PORTC.4 = 1; // Reset chip select lines return (result); // Return data }
Bill of Materials
Buy now all these materials from Farnell (24h delivery).
UPS Demo Unit
The Demo Unit is a subset of the UPS. This unit was designed to showcase the inverter, featuring the PIC17C43 microcontroller. Therefore, there is no battery back-up circuitry. The circuit boards used on the demo unit are the inverter drive PCB, the inverter control PCB and a bias supply board used to supply 15Vdc to the unit’s discrete components.

Demo Partial Assembly - Top View
Follow these steps to demo the UPS Demo Unit:
-
1. Plug the receptacle end of a power cord into the UPS Demo Unit “AC Input”. Plug the pronged end of the power cord into an AC wall socket.
2. Plug the load into the UPS Demo Unit “Load” socket (Optional). Make sure load can be driven by the UPS Demo.
3. Connect an oscilloscope probe to the UPS Demo Unit “Load Monitor” BNC connector.
4. Display (Stepped Down) AC Output waveform on oscilloscope.
Go to Download (UPS_reference_design.zip) section or to Microchip.
Buy now from Farnell (24h delivery).