Connect with us

CPU Power Supply Mod

  • Howdy!

    This project came out of wanting to etch my first useful PCB (up to now all the PCBs I've made have been tests). I have a old CPU power supply that's been laying around for awhile, so I decided to convert it to a PSU I could use on my bench.

    First I started googling around for info on it, and found that it uses a standard computer PSU pin-out called ATX 2.x. The wikipedia article on it is here: https://en.wikipedia.org/wiki/ATX#Power_supply.

    The specifications for the power supply are as follows:
    • +3.3VDC/17A
    • +5VDC/22A
    • +5VDC/2A (Standby)
    • +12VDC/18A
    • -12VDC/0.8A
    • 300W Max power
    I'm planing to make all the circuitry handle about 3A maximum current draw on each voltage (I'm going to fuse it for 2.5A for now though). If I ever want to be able to draw more current then that (which is not likely), I guess will just have to modify it some more. :D
    =========================================

    So the first order of business - draw a schematic. Here it is:
    Schematic.jpg

    I decided to use a PIC18F1220 for this project because I have quite a few laying around. A 1602 LCD will be used for the user interface – I'll need some way of telling the user which voltages are switched on. Three switches will work for user control (Select/up/down – or something like that).

    P4 is a jumper (it connects PGD to ON1 and PGC to ON2) and is there for when the PIC is programmed – Since I ran out of I/Os I had to use the two pins that are for programming the PIC. And when the PIC is programmed, I don't want anything screwing up the communication between the computer and the PIC, so P4 should be unjumped while programming (is that even a word? :D).
    =========================================

    Here's the PCB layout:
    PCB_Layout.JPG

    Yes, I know that the fuses overlap other parts - The plan is to have the fuses mounted on the back side of the circuit board and the rest of the parts on top. The relays are just some high current ones that I salvaged from a used circuit board (I think they where out of a broken fryer to be exact).

    Unfortunately, I will have to solder about eight jumpers on where I couldn't figure out how to run a trace (not shown here, but they can be seen in the KiCAD file as un-routed traces). I guess I should have tried to optimize it a little more, but space was kind of lacking...
    =========================================

    On to etching!
    IMG_0005-Small.JPG IMG_0006-Small.JPG
    The first photo is right after the toner transfer - As you can see, there are quite a few spots were the toner did not stick ideally. The next photo is after touching up with a sharpie.

    I think I may have rushed the toner transferring part a little, and that's why it didn't turn out so good - I could have redone it, but I didn't want to use up any more of my all to little supply of glossy paper.

    So after etching I realized that sharpie is probably not the best resist – it appeared that some had come off during the process... Here's a photo of the PCB after patching the broken traces with solder (sorry I forgot to take a photo right after etching. o_O):
    IMG_0010-Small.JPG

    I guess the next step will be drilling the holes on the PCB – But unfortunately my drill bits haven't arrived yet, so I guess I will have to call it for now.

    =========================================
    10/7/15

    Well the drill bit's came in - here's a photo after drilling:
    AfterDrill-small.jpg

    I had some trouble with the drill bit's breaking but with some help, I got it worked out here: https://www.electronicspoint.com/threads/drill-bits-for-homemade-pcbs.275652/page-3 - Thanks to all who contributed! :)

    I also decided to try and put a silkscreen on the board:
    IMG_0085-small.jpg
    I used the same method as I did for the copper side. But as you can see, on the right side of the left board the transfer moved and blurred out. It doesn't really matter much though, because this was more of a test to see if I could do it and the relays will cover it up.

    =========================================
    Next step - Soldering!
    IMG_0672-small.jpg IMG_0671-small.jpg

    Everything soldered up pretty nicely. I used stranded wires for the LCD connections so it could be lifted backwards if I need to get at the parts under it. I decided to mount a switch instead of a jumper on P4 which should make it a little less painful to program it.

    Everything was going good until I realized that somewhere along the line the connector for the power supply got mirrored on the PCB! I guess I will just have to hand wire it. :mad:

    =========================================
    10/13/15

    So I opened up the power supply case to cut out some wires that I don't need for this project, and looky what I found:
    BADCAP1.jpg BADCAP2.jpg
    I guess this power supply has had a lot of on hours - as I remember though, the computer I pulled it from still worked so I think I will just over look that for now...

    Next I made a chassis out of the metal from an old popcorn can (it's tin so it solders nicely), and attached the circuit board to the power supply. Here's a photo:
    Case.jpg BOLT.jpg
    Photo two is a nut I soldered to the chassis so I could attach the circuit board to it with screws (aka make it easy to take apart and troubleshoot when it doesn't work :rolleyes:). I had to get out the weller 140W soldering gun to make the joints as my regular soldering iron just couldn't cut the mustard.

    It lives!!
    ON.jpg
    The display looks kind of weak but it may just be a bad LCD.

    Next step will be to write some code.

    =========================================
    10/29/15

    I guess the next step isn't going to be writing code - instead it will be trouble shooting the PSU!

    So after playing around with a little code, things just didn't seam to be working right. I decided to check the standby voltage, and to my great surprise it read about 2.8VDC (not 5V as expected)! So I hooked it up to the scope (being careful to hook ground up in the right spot ;)) and here's what I got:
    OSC_CAPT2.jpg
    Look liked the fault of a seriously bad capacitor to me! So I wrote down the values of all the caps that looked suspicious and bought some new ones from digikey (of much higher quality).

    After putting the new caps in, I turned it on and the problem seamed to still be there... After some more experimenting I found out that all the screws that hold the circuit board in place have to be in for the unit to work (they connect to the metal chassis completing the ground plane). It now works great - all the voltages are nice and flat (the LCD works a lot better too).

    =========================================
    11/14/2015

    Well, I finished up the code. Here's the main part of it:
    Code:
    /***********************************************
    * File:   Main.c                              *
    * Author: Supercap2F                          *
    *                                             *
    * Created on October 9, 2015, 5:18 PM         *
    ***********************************************/
    /***********************************************
    * Included files                              *
    ***********************************************/
    #include <xc.h>
    #include "CPU_Power_Supply_Mod.h"
    #include "Hitachi_LCD.h" // .h file with all display functions
    #include "Bitmaps.c"     // c file with all the CGRAM data in it
    /***********************************************
    * Definitions                                 *
    ***********************************************/
    
    /***********************************************
    * Device configuration                        *
    ***********************************************/
    #pragma config OSC=INTIO2 // internal oscillator, port function on RA6 and RA7
    #pragma config FSCM=OFF   //
    #pragma config IESO=OFF   //
    #pragma config PWRT=ON    // power up timer enabled
    #pragma config BOR=OFF    // brown out reset off **MAY NEED TO BE CHANGED**
    #pragma config WDT=OFF    // watch dog timer off
    #pragma config MCLRE=ON   // MCLR pin is for reseting
    #pragma config LVP=OFF    // low voltage programming is off
    #pragma config STVR=ON    // stack overflow will cause a reset
    
    #define COME_FROM_DEFAULT 0
    #define COME_FROM_PAIR 1
    #define CALL_PAIR_MENU 2
    #define RETURN_TO_DEFAULT 3
    
    
    /***********************************************
    * Function Definitions                        *
    ***********************************************/
    void DefaultMenu(void);
    void StandbyMenu(void);
    unsigned char OptMenu(unsigned char z);
    void PairMenu();
    
    
    /***************************************************************
    * Program entry point - Main Function                         *
    ***************************************************************/
    int main()
    {
    
        /***********************************************
         * Oscillator Configuration                    *
         ***********************************************/
        OSCCONbits.IRCF0=1; // set main clock to 8MHz
        OSCCONbits.IRCF1=1;
        OSCCONbits.IRCF2=1;
    
        /***********************************************
         * I/O Setup                                   *
         ***********************************************
         * RA0 - SW1    | RA1 - SW2  | RA2 - PN    |   *
         * RA3 - PG     | RA4 - SW3  | RA6 - SDI   |   *
         * RA7 - LCHCLK | RB0 - -12V | RB1 - +12V  |   *
         * RB2 - SFTCLK | RB3 - eLCD | RB4 - rsLCD |   *
         * RB5 - rwLCD  | RB6 - +5V  | RB7 - +3.3V |   *
         *                                             *
         ***********************************************/
        TRISA=0b00010011;  // set I/O ports to either input (1) or output (0)
        LATA=0b00000000;   // clear outputs
        ADCON1=0b11111111; // make all outputs/inputs digital
    
        TRISB=0b00000000; //  set I/O ports to either input (1) or output (0)
        LATB=0b00000000;  // clear outputs
    
        PN=1;
        RL12V=1;
        RLn12V=1;
        RL5V=1;
        RL3V3=1;
    
        /***********************************************
         * interrupt Setup                             *
         ***********************************************/
        RCONbits.IPEN=0;     //Turn off interrupt priority
    
        /***********************************************
         * Timer0 Setup                                *
         ***********************************************
         * Timer0 is for any blinking character on the *
         * screen. The TMR0IF flag is set when ever    *
         * the display should blink.                   *
         ***********************************************/
        TMR0L=0;             // clear the timer0 count
        TMR0H=0;             //
        T0CON=0b10010011;    // setup timer0 so that:
                             //      it is a 16 bit timer
                             //      it counts on clock cycles
                             //      it uses a pre-scaler set to 128 so the timer rolls over every 1.04s
        INTCONbits.TMR0IF=0; // clear the timer 0 flag bit
    
        /***********************************************
         * Main Code                                   *
         ***********************************************/
           LCDwrcmd(0b00111100); // 8 bit mode
           LCDwrcmd(0b00000110); // address counter will increment
           LCDwrcmd(0b00001100); // cursor off display on blink off
           LCDwrcmd(0b00000001); // clear display
           __delay_ms(2);
       
           StandbyMenu();     // first call the standby function so the power supply will turn on in standby mode
           while(1)           // repeatedly call default menu
               DefaultMenu(); //
       
    }
    
    /***************************************************************
    * StandbyMenu Function - This function is called when ever    *
    * the power supply needs to go into standby mode.             *
    ***************************************************************/
    void StandbyMenu(void)
    {
        PN=1;                           // set the power supply to standby mode
        LCDwrcmd(0b00000001);           // clear the display
        __delay_ms(2);                  // delay for 2mS to wait for last command to register
        LCDwrstring("    STANDBY    "); // write standby to the screen
        while(1) {                      // loop (almost) forever
            if(SW1 || SW2 || SW3){      // check if any switches where pressed
               __delay_ms(12);          // debounce
                   while(SW1 || SW2 || SW3); // wait for switches to be let off of
                   PN=0;                // turn on power supply
                   return;              // return to where the function was called from
               }
            }
    }
    
    /***************************************************************
    * DefaultMenu Function - In this function you can turn off/on *
    * individual voltages.                                        *
    ***************************************************************/
    void DefaultMenu(void)
    {
        /***********************************************
         * Variable Definitions                        *
         ***********************************************/
        int x,y;    // random variables
        int last=0; // variable the keeps track of the last cursor state
    
    
        struct MenuDisplay {             // structure that holds general information
            unsigned char Addr[5];       // addresses of each place the cursor can be
            unsigned char CurrentSelect; // current place where the cursor is
            unsigned char ONorOFF[5];    // variable that keeps track of each voltages on/off state
            unsigned char Pair;
        };
    
        struct MenuDisplay MenuItem = {  // create the structure
            0x04,0x09,0x0F,0x45,0x4C,    // fill up the Addr variable
            0,                           // fill up the CurrentSelect variable
            0,0,0,0,0,                    // fill up the ONorOFF variable
            0b00000101
        };
    
        /***********************************************
         * Setup the LCD                               *
         ***********************************************/
        for(y=0;y<8;y++) // this loop loads the custom characters into the CGRAM
                for(x=0;x<7;x++)
                {
                    LCDwrcmd((0b01000000|x)|(y<<3));
                    LCDwrchar(Default_Menu_Bitmaps[y][x]);
                }
       LCDsetaddr(0); // set address to start - else it will still write to the CGRAM
    
       LCDwrstring("12V=/ 5V=/ 3V3=/"); // default menu screen (all outputs off)
       LCDsetaddr(0x40);                //
       LCDwrstring("-12V=/      MENU"); //
    
       /***********************************************
        * This loop scans the keyboard and the TMR0   *
        * flag, and updates the screen/relay states   *
        * accordingly                                 *
        ***********************************************/
       while(1) {
           if(SW3==1) {        // check to see if the move right key was pressed
               __delay_ms(12); // debounce if it looks like it was pressed
               if(SW3==1) {    // if it was pressed
                   LCDsetaddr(MenuItem.Addr[MenuItem.CurrentSelect]); // set the cursor to the current address
                   if(MenuItem.CurrentSelect==4)                      // if the current address is the menu option
                       LCDwrstring("MENU");                           //    set it to "MENU" to make sure it's not highlighted
                   else                                               //    when current selection is switched
                       LCDwrchar(MenuItem.ONorOFF[MenuItem.CurrentSelect] ? 0x00:0x2F); // else
                                                                      //    make sure either the power symbol or the '/' symbol
                                                                      //    aren't highlighted (according to if the voltage is
                                                                      //    on or off)
               
                   MenuItem.CurrentSelect++;     // change where the cursor is
                   if(MenuItem.CurrentSelect==5) // if it equals five (i.e. if it's off the screen)
                       MenuItem.CurrentSelect=0; //     then move it to the first place on the screen
                   while(SW3==1);                // wait for the switch to be let off of before moving forward in the code
               }
           }
       
           if(SW2==1) {        // check to see if the move left key was pressed
               __delay_ms(12); // debounce if it looks like it was pressed
               if(SW2==1) {    // if it was pressed
                   LCDsetaddr(MenuItem.Addr[MenuItem.CurrentSelect]); // set the cursor to the current address
                   if(MenuItem.CurrentSelect==4)                      // if the current address is the menu option
                       LCDwrstring("MENU");                           //    set it to "MENU" to make sure it's not highlighted
                   else                                               //    when current selection is switched
                       LCDwrchar(MenuItem.ONorOFF[MenuItem.CurrentSelect] ? 0x00:0x2F); // else
                                                                      //    make sure either the power symbol or the '/' symbol
                                                                      //    aren't highlighted (according to if the voltage is
                                                                      //    on or off)
               
                   if(MenuItem.CurrentSelect==0) // if the current selection is zero
                       MenuItem.CurrentSelect=5; //     set it to 5 so a negative number is not created
                   MenuItem.CurrentSelect--;     // change where the cursor is
                   while(SW2==1);                // wait for the switch to be let off of before moving forward in the code
               }
           }
       
           if(SW1==1) {        // check to see if the select key was pressed
               __delay_ms(12); // debounce if it looks like it was pressed
               if(SW1==1) {    // if it was pressed
                   if(MenuItem.CurrentSelect==4) { // if the current selection is "MENU"
                       while(SW1);                 // then wait for the switch to be let off of
                       RL12V=1;                    // turn off all relays
                       RLn12V=1;                   //
                       RL5V=1;                     //
                       RL3V3=1;                    //
                       if(OptMenu(COME_FROM_DEFAULT)==CALL_PAIR_MENU) // call menu function, and if pair menu was selected
                           PairMenu();             // call pair menu
                       return;                     // return - i.e. reset this function
                   }
                   else {                                                               // else
                       MenuItem.ONorOFF[MenuItem.CurrentSelect]=~MenuItem.ONorOFF[MenuItem.CurrentSelect]; // invert the current state
                                                                                        // of the selected voltage
                       LCDsetaddr(MenuItem.Addr[MenuItem.CurrentSelect]);               // set the cursor to the current selection              
                       LCDwrchar(MenuItem.ONorOFF[MenuItem.CurrentSelect] ? 0x00:0x2F); // depending on what state the selections is
                                                                                        // being changed to, put up the correct symbol
                       switch(MenuItem.CurrentSelect) {                                 // this switch turns on/off the appropriate
                           case 0:                                                      // relay based upon the selection
                               RL12V=~MenuItem.ONorOFF[MenuItem.CurrentSelect];         //
                               break;                                                   //
                           case 1:                                                      //
                               RL5V=~MenuItem.ONorOFF[MenuItem.CurrentSelect];          //
                               break;                                                   //
                           case 2:                                                      //
                               RL3V3=~MenuItem.ONorOFF[MenuItem.CurrentSelect];         //
                               break;                                                   //
                           case 3:                                                      //
                               RLn12V=~MenuItem.ONorOFF[MenuItem.CurrentSelect];        //
                               break;                                                   //
                       }
                   }
                   while(SW1==1); // wait for the switch to be let off of before moving forward in the code
               }
           }
       
           if(INTCONbits.TMR0IF) {           // if the TMR0 flag is set (i.e. the cursor needs to change state)
               LCDsetaddr(MenuItem.Addr[MenuItem.CurrentSelect]); // set the cursor to the current address
               if(MenuItem.CurrentSelect==4)                      // if it's on "MENU"
                   if(last)                                       //    invert it based upon it's last state
                       LCDwrstring("MENU");                       //
                   else {                                         //
                       LCDwrchar(0x02);                           //
                       LCDwrchar(0x03);                           //
                       LCDwrchar(0x04);                           //
                       LCDwrchar(0x05);                           //
                   }
               else                                               // if it's on anything besides "MENU"
                   if(MenuItem.ONorOFF[MenuItem.CurrentSelect])   //    invert it based upon it's last state
                       LCDwrchar(last ? 0:1);                     //
                   else                                           //
                       LCDwrchar(last ? 0x2F:0x06);               //
      
               last=last ? 0:1;     // invert the last variable so the last cursor state can be kept track of
               INTCONbits.TMR0IF=0; // reset the TMR0 flag
           }
       }
       while(1);
    }
    
    /***************************************************************
    * OptMenu Function - This is the base menu function. It       *
    * displays the options based upon where is was called from.   *
    ***************************************************************/
    unsigned char OptMenu(unsigned char z)
    {
        /***********************************************
         * Variable Definitions                        *
         ***********************************************/
        int x;        // random support variable
        int update=1; // this variable is set when the screen needs to be updated
    
        const unsigned char AlternateDisplay[]="INDIV On/Off"; // alternate menu option
    
        struct MenuDisplay {            //
            unsigned char CurrentItem;  // holds the current selected option
            unsigned char Items[3][13]; // holds the names of all the options
        };
        struct MenuDisplay Menu ={
            0,                     // put zero in the current item variable
            "Standby",             // name of option one
            "All On/Off",          // name of option two (assuming it's not reloaded)
            "Back"                 // name of option three
        };
    
        /***********************************************
         * Main Code                                   *
         ***********************************************/
        if(z==COME_FROM_PAIR)                         // if this function was called from the pair menu function
            for(x=0;x<12;x++)                         // load the alternate menu option
                Menu.Items[1][x]=AlternateDisplay[x]; //
    
        LCDwrcmd(0b00000001); // clear display
        __delay_ms(2);        // wait for the display to be cleared
    
        while(1) { // main code loop
        
            if(update){                                    // if the display needs to be updated
                LCDsetaddr(0x00);                          // set the address to the start of the display
                LCDwrchar(Menu.CurrentItem+1+0x30);        // write the current menu items number
                LCDwrstring(": ");                         //
                LCDwrstring(Menu.Items[Menu.CurrentItem]); // write the current option to the display
                LCDwrstring("        ");                   // clear the rest of the line
                LCDsetaddr(0x0F);                          // write the left arrow character on the last character space
                LCDwrchar(0x7F);                           //
                LCDsetaddr(0x40);                          // reset the address to the second line
            
                if(Menu.CurrentItem<2) {                         // if the second option should not be a blank line
                    LCDwrchar(Menu.CurrentItem+2+0x30);          //     write the option after the current item to the second line
                    LCDwrstring(": ");                           //
                    LCDwrstring(Menu.Items[Menu.CurrentItem+1]); //
                    LCDwrstring("        ");                     //     clear the rest of the line
                }                                                //
                else                                             // else if the second line should be blank
                    LCDwrstring("                ");             //     clear the line
                update=0;                                        // reset the update flag
            }
            if(SW3){                        // if the move down key was pressed
                __delay_ms(12);             // debounce
                if(SW3) {                   // if it's still pressed
                    if(Menu.CurrentItem==2) // if the current item is the last option
                        Menu.CurrentItem=0; //     reset to the first option
                    else                    // else
                        Menu.CurrentItem++; //     increment the current selection
                    update=1;               // set the update flag so the display will show the new change
                    while(SW3);             // wait for the switch to be let off of
                }
            }
            if(SW2){                        // if the move up key was pressed
                __delay_ms(12);             // debounce
                if(SW2) {                   // if it's still pressed
                    if(Menu.CurrentItem==0) // if the current item is the first option
                        Menu.CurrentItem=2; //     set it to the last option
                    else                    // else
                        Menu.CurrentItem--; //     de-increment the current selection
                    update=1;               // set the update flag so the display will show the new change
                    while(SW2);             // wait for the switch to be let off of
                }
            }
            if(SW1){                                    // if the select switch was pressed
                __delay_ms(12);                         // debounce
                if(SW1) {                               // if it's still pressed
                    while(SW1);                         // wait for it to be let off of
                    switch(Menu.CurrentItem) {          // see what is selected
                        case 0:                         // if it's the standby option
                            StandbyMenu();              //     call the standby function
                            return(0);                  //     return to the function that called this function
                        case 1:                         // if it's the All On/Off/INDIV On/Off option
                            if(z==COME_FROM_PAIR)       //     check what fucntion called this one
                                return(RETURN_TO_DEFAULT); //  if it was the pair menu return with a message to return to default
                            else                        //     if was called by the default menu function return with a message to
                                return(CALL_PAIR_MENU); //     call the pair menu function
                        case 2:                         // if it's the back option
                            return(0);                  //     return
                    }
                }
            }
        }
        return(0);
    }
    
    /***************************************************************
    * PairMenu Function                                            *
    ***************************************************************/
    void PairMenu()
    {
        /***********************************************
         * Variable Definitions                        *
         ***********************************************/
        static bit OnOrOff;       // 1 is on
        static bit CurrentSelect; // if 1, then the selection is "MENU".
        static bit Last;          // if 1, then the text is inverted
    
        /***********************************************
         * Setup the display and relays                *
         ***********************************************/
        OnOrOff=0;       // clear each variable or it will have it's value from last time
        CurrentSelect=0; //
        Last=0;          //
        RL5V=1;          // turn off all relays
        RL12V=1;         //
        RL3V3=1;         //
        RLn12V=1;        //
    
        LCDsetaddr(0x00);                // write the menu to the display
        LCDwrstring("All Voltages:/  "); //
        LCDsetaddr(0x40);                //
        LCDwrstring("            MENU"); //
    
        /***********************************************
         * Main Code Loop                              *
         ***********************************************/
        while(1) {
            if(INTCONbits.TMR0IF) {          // if the blink flag is set
                if(CurrentSelect) {          // if the current selection is "MENU"
                    LCDsetaddr(0x4C);        //     set the address to the start of the "MENU" text
                    if(Last) {               //     if the text should be inverted
                        LCDwrchar(0x02);     //         write "MENU" inverted to the display
                        LCDwrchar(0x03);     //
                        LCDwrchar(0x04);     //
                        LCDwrchar(0x05);     //
                    }                        //
                    else                     //     else
                        LCDwrstring("MENU"); //         write "MENU" not inverted on the display
                }                            //
                else {                       // else the selection is the power symbol
                    LCDsetaddr(0x0D);        //     set the address to where the power symbol is
                    if(Last)                 //     if it should be inverted
                        LCDwrchar(OnOrOff ? 0x01:0x06);//then write the right symbol based upon if the voltages are on or off
                    else                     //     else if it shouldn't be inverted
                        LCDwrchar(OnOrOff ? 0x00:'/');// then write the right symbol based upon if the voltages are on or off
                }                            //
                Last=~Last;                  // reset the last inverted state
                INTCONbits.TMR0IF=0;         // clear the flag
            }
        
            if(SW3 || SW2) {                 // if the move up or move down button was pressed
                __delay_ms(12);              // debounce
                if(SW3 || SW2) {             // if there still pressed
                    if(CurrentSelect) {      // if the current selection is menu
                        LCDsetaddr(0x4C);    //     write "MENU" to make sure it's not inverted when the selection is changed
                        LCDwrstring("MENU"); //
                    }                        //
                    else {                   // else if the selection is the power symbol
                        LCDsetaddr(0x0D);    //     write the appropriate symbol to make sure it's not inverted when the selection is
                        LCDwrchar(OnOrOff ? 0x00:'/');//changed
                    }                        //
                
                    CurrentSelect=~CurrentSelect; // swap the current selection
                }                                 //
                while(SW3 || SW2);                // wait for the switch to be let off of
            }
        
            if(SW1) {                   // if the select switch was pressed
                __delay_ms(12);         // debounce
                if(SW1) {               // if SW1 is still pressed
                    LCDsetaddr(0x0D);   // set the address to where the power symbol is
                    if(CurrentSelect) { // if the current selection is "MENU"
                        while(SW1);     // wait for the switch to be let off of
                        if(OptMenu(COME_FROM_PAIR)==RETURN_TO_DEFAULT) { // if the user selects INDIV from OptMenu                           
                            RL5V=1;     // turn off all relays
                            RL12V=1;    //
                            RL3V3=1;    //
                            RLn12V=1;   //
                            return;     // return to the INDIV menu
                        }
                        LCDsetaddr(0x00);                // if the user wants to continue on this menu
                        LCDwrstring("All Voltages:");    //    redraw the menu
                        LCDwrchar(OnOrOff ? 0x00:'/');   //
                        LCDwrstring("  ");               //
                        LCDsetaddr(0x40);                //
                        LCDwrstring("            MENU"); //
                    
                    }
                    else {                // if the current selection is the power symbol
                        RL5V=~RL5V;       // switch the state of all the relays
                        RL12V=~RL12V;     //
                        RL3V3=~RL3V3;     //
                        RLn12V=~RLn12V;   //
                        OnOrOff=~OnOrOff; // and switch the state of the OnOrOff variable
                        if(Last)          // redraw the display to reflect the changes
                            LCDwrchar(OnOrOff ? 0x01:0x06); //
                        else              //
                            LCDwrchar(OnOrOff ? 0x00:'/'); //
                    }                     //
                    while(SW1);           // wait for the switch to be let off of
                }
            }
        }
        return;
    }
    
    (This isn't the whole code, as there are a bunch of different files - they can be found on Github though)

    Here's a photo of the power supply's main screen:
    IMG_1013C.jpg

    And the finished power supply above my desk:
    IMG_1007C.jpg

    I'm pretty happy about how it turned out. It doesn't look very good from the front though - I'll probably make a cover for it some time in the future.

    =========================================
    6/15/2016

    I 3D printed a front cover for the power supply, and with a little paint it looks pretty good:
    IMG_0069-copy.jpg
    (The 3D model of it can also be found on the github project page)

    Thanks for reading!! :)

    P.S. All the design files for the project are on GitHub: https://github.com/Supercap2F/CPU-Power-Supply-Mod
Electronics Point Logo
Continue to site
Quote of the day

-