+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 20 of 32

Thread: Solar Charge Controller

  1. #1

    Default Solar Charge Controller

    Hello all once again! I have been tinkering with another project (of course) which involves charging a 12V 7AH Sealed battery using a 24V 18W solar panel. Sounds simple enough? Use an LM317 set to 13.8V and let it sit..... Well, I have already done this, but the battery takes WAY too long to fully charge. I am hoping to make something much better without spending a small fortune. I would also like to be able to add onto the current capabilities so I can add more solar panels and more batteries in the future. I know there are MPPT controllers which are extremely expensive, and there are other charge controllers on Amazon which are less than $50 which would work for now, but what is the fun of buying someone else's project :p

    So...where do I start...? First off, I have basic electronics knowledge, enough to be dangerous. Second, I don't know how to properly charge a battery except connecting a premade charger to it. I understand a little, but I probably need to learn more about it. Reading these "informational" posts about how to charge batteries are not very informational to me since 90% of the information is gibberish to me. I am a hands on learner and will probably learn this better if I just jumping in and started building it. But...before I can start, I have some questions base on my current research. Please keep in mind I am trying to build a very inexpensive charge controller..... I would prefer to use what parts I have on hand in my electronic collection to keep cost as low as possible. I know it may not be as efficient as a $100+ controller, but if it works for what I need, great!

    First Question :
    Since I have a 24V solar panel and a single 12V battery, I am sure 24V pulsed or directly connected into the 12V battery is probably not a good idea for battery life. What is the best method of charging an SLA battery? PWM, constant voltage / current, other?

    Second :
    Once question 1 is answered, monitoring battery voltage and maybe even charge current will be needed. I know that an ADC circuit is needed to monitor voltage, but what about current? I have read using a very low resistance resistor can work and so can a [url href="http://www.reuk.co.uk/Make-a-Shunt-Resistor.htm"]DIY shunt resistor[/url], but once I have the resistor or shunt resistor, what do I do then?

    Third :
    I am sure Mosfets will come into play in my circuit somewhere but the problem is, I don't know much about them nor how to "properly" activate the gate without a mosfet driver. I have several Mosfets on hand only because i wanted to tinker with them and learn how to not blow them up in a circuit. Is activating a Mosfet the same as a standard transistor?

    That's all I can think of right now. I am sure there will be plenty more questions!

    EDIT * The reason this is in the Prop forum is because I plan on using the Prop to control the entire controller.

  2. #2

    Default Re: Solar Charge Controller

    Tim Nolan has a nice tutorial that may help you some. http://www.timnolan.com/index.php?pa...-solar-charger I was looking at adapting his arduino MPPT project to the Propeller and piggy back the power tracking with position tracking.

  3. #3

    Default Re: Solar Charge Controller

    I have read his article, but without the same setup, I would not know what to change to work with my setup. I have a 24V solar panel and a 12V battery. He has a 12V solar panel, and a 12V battery. Can I pulse the 24V directly to the battery till it is full?

  4. #4

    Default Re: Solar Charge Controller

    Hello,

    A battery will not be hurt at all by connecting a higher voltage solar panel to it; in fact, the voltage will be clamped to the battery voltage, and the solar panel will put out something very close to its short circuit current if it is rated for a much higher voltage.

    I'm not sure what you mean by "pulse"; you should use PWM, and an ADC to measure the voltage. For a lead-acid battery, you don't need to know the current going into the battery to properly charge it. It should have a 3-stage charging profile as follows:

    Stage 1 (bulk): direct connection to the battery until it reaches the "absorb" voltage; this should be about 14.1 V for a sealed lead acid battery, but the battery manufacturer knows for sure.

    Stage 2 (absorb): adjust the PWM to maintain the absorb voltage either for a fixed amount of time (usually about 2 hours), or if you have implemented current measurement, until the current goes down to about C/100 to maintain the absorb voltage. C/100 means 0.07 A for a 7 Ah battery.

    Stage 3 (float): reduce the PWM to maintain float voltage, usually about 13.2 V, but again, check with the battery manufacturer.

    Most cheap battery chargers combine the absorb and float stages, and use a single average voltage (usually about 13.8 V). This will (as you've noticed) take a long time to fill, and will shorten the life somewhat by keeping it at too high a float voltage.

    An optional 4th stage is equalization, which is an occasional controlled overcharge to equalize the voltage in the individual cells in the battery; this is usually not done with sealed batteries because it causes them to gas and, since they are sealed, it can't be replaced. This is one reason why real flooded batteries work better in solar service.

    You can set up the stages as a state machine, with the criteria listed above for transitioning between stages (in practice, there are often some intermediate stages that are useful). I'm including a routine I've written for this purpose, but beware that I've not implemented this, so it's not tested. I'm pretty sure it'll work, but use at your own risk. Look in particular at the "switch BATTERY_STATE" segment in the function regulateBattery below. It's way more complicated than you need, since it also does MPPT and a dump load, but it should give you some idea.

    David Voss

    Code:
    /*******************************************************************************
     Program:       REsys, module Regulate, v.0.1, 14 July 2012
    
    
     Written by:    David Voss, Tree of Life Foundation Renewable Electronics,
                    Patagonia, AZ
    
    
     Copyright:     2012, David Voss. Released under the GNU GPL; see the bottom of
                    the file for terms of use.
    
    
     Purpose:       Routines to regulate battery, solar, and wind generator
    
    
     Target:        ANSI C
     ******************************************************************************/
    
    
    #include "main.h"    // Sets the part # and includes all the other necessary
                         // include files. See it for details.
    
    
    /*******************************************************************************
     regulateBattery
     *******************************************************************************
     There are 4 ways this controller can regulate the battery: a dump load, solar
     PWM, solar MPPT, and to NOT regulate the battery (i.e., just a battery
     monitor). Depending on the settings in the Makefile, conditional compilation
     chooses how to regulate. At times, this makes the code a little confusing, but
     it allows there to be only one copy of the main logic, so if it needs to be
     changed, it only needs to be changed once, and it should stay consistent.
    
    
     Regulation is set up as a state machine with the below battery states (see
     'switch (BatteryState)'). In the descriptions, MPPT means that all available
     current is flowing to the battery; PID means that the net current is reduced
     from what is available to maintain a particular voltage setpoint.
     ******************************************************************************/
    
    
    void regulateBattery(void) {
    
    
       if (Implemented.WIND) {             // Calculate RE Buss Voltage Setpoint
    
    
          REbussSetpoint = MinREbussSetpoint;
    
    
          if ((SolarDutyCycle < SOLAR_DUTY_CYCLE_MARGIN) && 
              (REbussSetpoint < REbussVolts * RE_BUSS_MARGIN))
             REbussSetpoint = REbussVolts * RE_BUSS_MARGIN;
    
    
          MinREbussSetpoint = BatteryVolts;
       } // end if (Implemented.WIND)
    
    
    
    
       switch (BatteryState) {
        
          case BATTERY_STATE_BULK:
    
    
             /* All available current is flowing to the battery, and
                BatteryVolts < AbsorbSetpoint. MPPT. */
    
    
    
    
                /* Check if we've reached the Absorb Setpoint */
    
    
                if (BatteryVolts >= AbsorbSetpoint) {
                   BatteryState = BATTERY_STATE_ABSORB;
                   BatterySetpoint = AbsorbSetpoint;
                   TimeStamp = Time;        // Initialize TimeStamp
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                   /* Nothing to be done here */
    
    
                }
                break;
    
    
    
    
          case BATTERY_STATE_ABSORB:
          
             /* The AbsorbSetpoint voltage has been reached, but the current
                necessary to maintain that setpoint is greater than
                FloatTransitionAmps (or we've only been below FloatTransitionAmps
                for less than FloatTransitionTime). PID. */
    
    
    
    
                /* Check if we've met the float criteria (only check the timeout;
                   the only way the timeout can get large enough is if the current
                   is small enough; if the current is too big, the timeout is reset
                   each time). */
    
    
                if (Time - TimeStamp > TransitionTimeout) {
                   BatteryState = BATTERY_STATE_FLOAT;
                   BatterySetpoint = FloatSetpoint;
    
    
    
    
                /* Check if we can't maintain absorb voltage anymore, and the
                   TransitionTimeout (from BATTERY_STATE_REFLOAT) has expired. */
    
    
                } else if ((BatteryVolts < AbsorbSetpoint - HysteresisVolts) &&
                   (Time - TimeStamp > TransitionTimeout))
                {
                   BatteryState = BATTERY_STATE_BULK;
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                   /* Reset the time stamp if the current is still bigger than
                      FloatTransitionAmps */
    
    
                   if (BatteryAmps > FloatTransitionAmps) TimeStamp = Time;
                }
                break;
    
    
    
    
          case BATTERY_STATE_FLOAT:
          
             /* The FloatTransitionAmps and TransitionTimeout requirements have been
                met, and the voltage has been reduced to FloatSetpoint. PID. */
    
    
    
    
                /* Check if we can't maintain float voltage anymore */
    
    
                if (BatteryVolts < FloatSetpoint - HysteresisVolts) {
                   BatteryState = BATTERY_STATE_UNDERFLOAT;
                   TimeStamp = Time;
    
    
    
    
                /* Check if equalize criteria has been met */
    
    
                } else if ((BatteryAhSinceEqualize > EqualizeMaxAh) |
                    (Time - EqualizeTimeStamp > EqualizeMaxInterval) |
                    (BatteryMinSoC < EqualizeSoC))
                {
                   EqualizeAccumulatedTime = 0;
                   BatteryState = BATTERY_STATE_UNDEREQUALIZE;
                   TimeStamp = Time;
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                   /* Nothing to be done here */
    
    
                }
                break;
    
    
    
    
          case BATTERY_STATE_UNDERFLOAT:
    
    
             /* The available current isn't enough to maintain the FloatSetpoint
                anymore. MPPT. */
    
    
    
    
                /* Check if we've reached the float voltage again */
    
    
                if (BatteryVolts >= FloatSetpoint) {
                   BatteryState = BATTERY_STATE_REFLOAT;
                   TimeStamp = Time;
    
    
    
    
                /* Check if the RefloatTimeout has expired */
    
    
                } else if (Time - TimeStamp > RefloatTimeout) {
                   BatteryState = BATTERY_STATE_BULK;
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                   /* Nothing to be done here */
    
    
                }
                break;
    
    
    
    
          case BATTERY_STATE_REFLOAT:
          
             /* The FloatSetpoint has been reached again after having gone below it,
                and we're checking if it can be maintained with less than
                FloatTransitionAmps within FloatTransitionTimeout. PID. */
            
    
    
                /* Check if we've met the criteria to return to float mode */
    
    
                if (BatteryAmps < FloatTransitionAmps) {
                   BatteryState = BATTERY_STATE_FLOAT;
    
    
    
    
                /* Check if we can't maintain float voltage anymore */
    
    
                } else if (BatteryVolts < FloatSetpoint - HysteresisVolts) {
                   BatteryState = BATTERY_STATE_UNDERFLOAT;
    
    
    
    
                /* Check if the transition timeout has expired */
    
    
                } else if (Time - TimeStamp > TransitionTimeout) {
                   BatteryState = BATTERY_STATE_BULK;
                   TimeStamp = Time;                      // Initialize TimeStamp
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                   /* Nothing to be done here */
    
    
                }
                break;
    
    
    
    
          case BATTERY_STATE_EQUALIZE:
          
             /* The EqualizeSetpoint has been reached, but EqualizeAccumulatedTime <
                EqualizeTime and EqualizeTimeout hasn't expired yet. PID. */
            
    
    
                /* Check if the EqualizeTime has been met */
    
    
                if (EqualizeAccumulatedTime >= EqualizeTime) {
                   BatteryState = BATTERY_STATE_FLOAT;
                   BatterySetpoint = FloatSetpoint;
                   EqualizeTimeStamp = Time;
                   BatteryAhSinceEqualize = 0.0;
                   BatteryMinSoC = 100;
    
    
    
    
                /* Check if we can't maintain equalize voltage anymore */
    
    
                } else if (BatteryVolts < EqualizeSetpoint - HysteresisVolts) {
                   BatteryState = BATTERY_STATE_UNDEREQUALIZE;
    
    
    
    
                /* No change of state */
    
    
                } else {
                   EqualizeAccumulatedTime++;
                }
                break;    
    
    
    
    
          case BATTERY_STATE_UNDEREQUALIZE:
          
             /* All available current => battery in order to reach the equalize
                voltage (either in transition from float or fallen down a bit from
                the EqualizeSetpoint due to lack of net current). MPPT. */
    
    
    
    
                /* Check if we've reached equalize voltage */
    
    
                if (BatteryVolts >= EqualizeSetpoint) {
                   BatteryState = BATTERY_STATE_EQUALIZE;
                   BatterySetpoint = EqualizeSetpoint;
    
    
    
    
                /* Check if the EqualizeTimeout is expired */
    
    
                } else if (Time - TimeStamp > EqualizeTimeout) {
                   BatteryState = BATTERY_STATE_BULK;
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                   /* Nothing to be done here */
    
    
                }
                break;
    
    
       } // End switch BatteryState
    
    
    
    
       /* Now either maximize the power to the battery if we're in a non-regulating
          battery state or use PID to regulate to the BatterySetpoint if we're in a
          regulating state. */
    
    
       if (BatteryState % 2) {             // All of the non-regulating states are
                                           // ODD, so (State % 2) would be true (1).
    
    
          /* We're in a non-regulating battery state (BULK|UNDERFLOAT|UNDEREQUALIZE)
             and we want to maximize net current flowing into the battery. */
            
          if (Implemented.DUMP_LOAD) {
             dumpSetDutyCycle(0.0);        // Make sure there's no dump load
          }
    
    
          if (Implemented.SOLAR) {
             if (Implemented.SOLAR_MPPT) {
                solarMPPT();               // Maximize current
             } else {
                solarPWM();                // Connect if current available
             }
          }
    
    
          if (Implemented.WIND) {
    
    
             /* Use PID on the REbuss=>Battery buck converter to maintain the
                REbussSetpoint voltage, which should keep the TSR of the wind
                generator where we want it to be, and maximize its current. */
    
    
             pid(&REbussSetpoint, &REbussVolts, &REbussPID, &REbussDutyCycle);
          }
          
       } else {                            // if (BatteryState % 2)
        
          /* We're in a regulating battery state (ABSORB|[RE]FLOAT|[RE]EQUALIZE) */
    
    
          if (Implemented.DUMP_LOAD) {
    
    
             /* Note that since increasing the dump duty cycle _decreases_ the net
                current into the battery, the setpoint and actual values are doubly
                reversed to give a positive error, i.e., BatteryVolts - *Setpoint
                instead of *Setpoint - BatteryVolts, giving negative feedback. */
    
    
             if (Implemented.WIND) {
    
    
                /* Use PID on the dump load to maintain the REbuss voltage */
    
    
                pid(&REbussVolts, &REbussSetpoint, &DumpPID, &DumpDutyCycle);
    
    
    
    
                /* Use PID on the REbuss=>Battery buck converter to maintain the
                   Battery voltage */
    
    
                pid(&BatterySetpoint, &BatteryVolts, &REbussPID, &REbussDutyCycle);
    
    
                REbussSetDutyCycle(REbussDutyCycle);
    
    
    
    
             } else {                      // no Wind Generator
    
    
                /* Use PID on the dump load to maintain the Battery voltage */
    
    
                pid(&BatteryVolts, &BatterySetpoint, &DumpPID, &DumpDutyCycle);
    
    
             } // end if (Implemented.WIND)
    
    
             dumpSetDutyCycle(DumpDutyCycle);
             
          } else {                         // no dump load
    
    
             /* Use PID on either the solar buck converter (if there's MPPT) or the
                direct PWM (if no MPPT) to maintain the Battery voltage. */
    
    
             pid(&BatterySetpoint, &BatteryVolts, &SolarPID, &SolarDutyCycle);
    
    
          } // end if (Implemented.DUMP_LOAD)
    
    
       } // end if (BatteryState % 2)
    
    
       if (Implemented.SOLAR) solarSetDutyCycle(SolarDutyCycle);
    
    
    } // End function 'regulateBattery'
    
    
    
    
    
    
    /*******************************************************************************
     monitorBattery
     ******************************************************************************/
    
    
    void monitorBattery(void) {
    
    
       if (BatteryVolts > EqualizeSetpoint - HysteresisVolts) {
          BatteryState = BATTERY_STATE_EQUALIZE;
       } else if ((BatteryVolts > AbsorbSetpoint - HysteresisVolts) &&
                  (BatteryVolts < AbsorbSetpoint + HysteresisVolts)) {
          BatteryState = BATTERY_STATE_ABSORB;
       } else if ((BatteryVolts > FloatSetpoint - HysteresisVolts) &&
                  (BatteryVolts < FloatSetpoint + HysteresisVolts) &&
                  (BatteryAmps < FloatTransitionAmps)) {
          BatteryState = BATTERY_STATE_FLOAT;
       } else {
          BatteryState = BATTERY_STATE_BULK;
        }
    } // End function 'monitorBattery'
    
    
    
    
    /*******************************************************************************
     pid
     ******************************************************************************/
    
    
    void pid(float *setpoint, float *actual, PID *pid_ptr, unsigned short *duty) {
    
    
       float             error, accumulated_error, new_duty;
       unsigned short    duty_increment;
    
    
       error = *setpoint - *actual;  // (setpoint - actual) gives negative feedback
    
    
       accumulated_error = pid_ptr->accumulated_error + error;
    
    
    
    
       /* Correct accumulated error if it's getting too big from saturation. */
    
    
       if (accumulated_error > pid_ptr->max_accumulated_error) {
          accumulated_error = pid_ptr->max_accumulated_error;
       } else if (accumulated_error < -pid_ptr->max_accumulated_error) {
          accumulated_error = - pid_ptr->max_accumulated_error;
       }
       pid_ptr->accumulated_error = accumulated_error; // Store it for next time
    
    
       duty_increment = (unsigned int)           // Compute PID duty cycle increment
          (error * pid_ptr->proportional_gain +                       // P
          accumulated_error * pid_ptr->integral_gain +                // I
          (error - pid_ptr->old_error) * pid_ptr->derivative_gain);   // D
    
    
       pid_ptr->old_error = error;   // Store current error as the next 'old' error
    
    
       if (duty_increment > pid_ptr->max_duty_increment) {
          duty_increment = pid_ptr->max_duty_increment;
       } else if (duty_increment < -pid_ptr->max_duty_increment) {
          duty_increment = -pid_ptr->max_duty_increment;
       }
    
    
       new_duty = *duty + duty_increment;
    
    
        if (new_duty > pid_ptr->max_duty_cycle) {
          *duty = pid_ptr->max_duty_cycle;
       } else if (new_duty < pid_ptr->min_duty_cycle) {
          *duty = pid_ptr->min_duty_cycle;
       } else {
          *duty = new_duty;
       }
    
    
    } // End function 'pid'
    
    
    
    
    
    
    /*******************************************************************************
     solarMPPT
     *******************************************************************************
     Solar maximum power point tracking is set up as a state machine, with the below
     states, which can be sequentially moved through.
    
    
     This routine only gets called when we're trying to maximize power from the
     solar panels; therefore, it does not implement charge controlling (for that,
     see 'regulateBattery' above).
    
    
     Note that to save on parts and complexity, the high-side MOSFETs of the buck
     converter may not be able to be set to a duty cycle of 1, but only about 0.95
     (SolarPID.max_duty_cycle). Therefore, whenever the solar panels are connected,
     the current may be passing through the buck converter, so there might not
     really be a 'BATTERY_STATE_DIRECT'. Even if this is the case, it's still useful
     to maintain a separate state to reduce the condition checks per pass.
     ******************************************************************************/
    
    
    void solarMPPT(void) {
         
        // Since PID and MPPT are never active at the same time, we use some PID
        // volatile memory for MPPT to save global SRAM.
        #define old_amps     SolarPID.old_error
    
    
        switch (SolarState) {
            
            case SOLAR_STATE_OFF:
          
                /*  Not enough voltage to get any current from panels. Note that
                    even though we lose a bit of current by disconnecting at very
                    low current values (SolarMinDirectCurrent), it's justified in
                    that no diodes (and their attendant voltage drop, which wastes
                    much  more power than we are losing here) are necessary. */
    
    
    
    
                /*  Check if solar voltage is high enough to connect and charge. */
    
    
                if (SolarVolts >= SolarMinVolts) {
                    SolarState = SOLAR_STATE_DIRECT;
                    SolarDutyCycle = SolarPID.max_duty_cycle;
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                    /* Nothing to be done here; remain off */
    
    
                }
                break;
    
    
            case SOLAR_STATE_DIRECT:
          
                /*  We're getting current, but not enough to justify maximum power
                    point tracking (it's less than SolarMinMPPTamps), so the panels
                    are connected directly to the battery (well, not necessarily;
                    see the note in the function header above). */
    
    
    
    
                /* Check if we should disconnect */
    
    
                if (SolarAmps < SolarMinDirectAmps) {
                    SolarState = SOLAR_STATE_OFF;
                    SolarDutyCycle = SolarPID.min_duty_cycle;
    
    
    
    
                /* Check if we should switch to MPPT */
    
    
                } else if (SolarAmps > SolarMinMPPTamps) {
                    SolarState = SOLAR_STATE_MPPT;
                    old_amps = SolarAmps;
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                    /* Nothing to be done here; remain direct */
    
    
                }
                break;
    
    
            case SOLAR_STATE_MPPT:
          
                /* Maximum power point tracking is active. */
    
    
    
    
                /*  Check if the current is low enough that we should revert back to
                    a direct connection */
    
    
                if (SolarAmps < SolarMinMPPTamps) {
                    SolarState = SOLAR_STATE_DIRECT;
                    SolarDutyCycle = SolarPID.max_duty_cycle;
    
    
                #ifdef _SOLAR_MPPT_SWEEP_
    
    
                /* Check if our sweep timeout has expired and we should sweep */
    
    
                } else if (Time - SolarSweepTimeStamp > SolarSweepInterval) {
    
    
                    /* nada; not implemented yet */
    
    
                #endif
    
    
    
    
                /* No change of state */
    
    
                } else {
    
    
                    /* Implement "Perturb and Observe" to get Maximum Power Point */
    
    
                    if (Flag.PERTURB_DIRECTION == 1) {
                        if (SolarAmps >= old_amps) {
                            SolarDutyCycle++;
                        } else {
                            SolarDutyCycle--;
                            Flag.PERTURB_DIRECTION = 0;
                        }
                    } else {
                        if (SolarAmps >= old_amps) {
                            SolarDutyCycle--;
                        } else {
                            SolarDutyCycle++;
                            Flag.PERTURB_DIRECTION = 1;
                        }
                    }
    
    
    
    
                    /* Keep duty cycle within bounds */
        
                    if (SolarDutyCycle > SolarPID.max_duty_cycle) {
                        SolarDutyCycle = SolarPID.max_duty_cycle;
                    } else if (SolarDutyCycle < SolarPID.min_duty_cycle) {
                        SolarDutyCycle = SolarPID.min_duty_cycle;
                    }
    
    
                    old_amps = SolarAmps;
                }
                break;
    
    
            #ifdef _SOLAR_MPPT_SWEEP_
    
    
            case SOLAR_STATE_SWEEP:
          
                /*  Periodically (SolarMPPTsweepInterval) sweep from
                    SolarMinSweepVoltage to SolarMaxSweepVoltage to find the maximum
                    power point and make sure we're not in a local maximum that is
                    less than the real maximum. */
    
    
                /* later, dude (currently no way to get to this state) */
    
    
                break;
            #endif
    
    
        } // end switch MPPTstatus
    
    
    } // end solarMPPT
    
    
    
    
    
    
    /*******************************************************************************
     solarPWM
     *******************************************************************************
     This function gets called if the battery is regulated with a dump load, and
     there is solar, but no MPPT.
     ******************************************************************************/
    
    
    void solarPWM(void) {
    
    
        switch (SolarState) {
        
            case SOLAR_STATE_OFF:
            
                if (SolarMinVolts >= BatteryVolts) {
                    SolarState = SOLAR_STATE_DIRECT;
                    SolarDutyCycle = 1.0;
                }
                break;
    
    
            case SOLAR_STATE_DIRECT:
    
    
                if (SolarAmps < SolarMinDirectAmps) {
                    SolarState = SOLAR_STATE_OFF;
                    SolarDutyCycle = 0.0;
                }
                break;
    
    
        } // end switch (SolarState)
    
    
    } // end solarPWM()
    
    
    
    
    /*******************************************************************************
     *                Terms of Use - GNU General Public License                    *
     *******************************************************************************
     * This file is part of REsys, a subset of REcollection.                       *
     *                                                                             *
     * REsys is free software: you can redistribute it and/or modify it under the  *
     * terms of the GNU General Public License as published by the Free Software   *
     * Foundation, either version 3 of the License, or any later version.          *
     *                                                                             *
     * REsys is distributed in the hope that it will be useful, but WITHOUT ANY    *
     * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS   *
     * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more       *
     * details.                                                                    *
     *                                                                             *
     * You should have received a copy of the GNU General Public License along     *
     * with REsys (named 'COPYING' in the top-level directory). If not, see        *
     * <http://www.gnu.org/licenses/>.                                             *
     ******************************************************************************/

  5. #5

    Default Re: Solar Charge Controller

    You can improve on the method altosack outlines by using an adjustable switching regulator to set optimum voltages/currents for each of the stages he mentions. It will also require monitoring both the voltage and current going to the battery, so it needs a bit more circuitry and smarts than most chargers.

    Stage 1 (bulk): The microcontroller adjusts the output voltage of the switcher to produce maximum current in to the battery while monitoring the voltage until it reaches the "absorb" voltage. This provides maximum charging efficiency.

    Stage 2 (absorb): The microcontroller adjusts the switcher to maintain the absorb voltage until the current goes down to C/100.

    Stage 3 (float): reduce the switcher output to maintain float voltage.

    Not only does this reduce charging time, but it increases battery life quite a bit. Also, in some ways I find the circuitry involved is actually easier to work with and more flexible than most advanced charging circuitry.
    In science there is no authority. There is only experiment.

  6. #6

    Default Re: Solar Charge Controller

    ok, so from what I gather, I need to find an adjustable switching regulator which will be able to handle the output voltage and current I am needing. This part of the circuit will control output to the batteries using PWM set by the Prop.

    EDIT : Found this switching regulator here : http://www.jameco.com/webapp/wcs/sto...0001_120977_-1 If I need more than 3A, can I "stack" these to handle more?

    So for stage 1 this is what I need to do? :
    Bypass switching regulator circuit and dump pure solar power into batteries via a MOSFET transistor using PWM. Between pulses of the PWM the battery voltage will be read(?) so when the voltage is at the desired charged voltage (13.6), stage 2 will kick in. Other calculation / measuring would need to be included to ensure the solar panels can provide the needed voltage so Stage 2 does not kick in too quick.

    Stage 2? :
    The Prop will activate the Adjustable Switching regulator circuit and the deactivate direct MOSFET circuit to output a specific voltage to the battery?. The PWM frequency will stay the same for the Adjustable Switching regulator circuit(?) while the current continues to be pumped into the battery at the regulators current limit. The stronger the regulator the faster stage 2 will complete? During each pulse the current will be read to ensure it is higher than C/100 (7Ah / 100 = 70mA?). When lower than C/100 go to stage 3

    Stage 3 :
    Unsure what to do here since the current flow will still be the same through the adjustable switching regulator. Is it possible to reduce current on demand?

  7. #7

    Default Re: Solar Charge Controller

    First, let me say that I have not built a battery charger using a solar panels and batteries as small as you are using. I installed a new charger to upgrade an existing solar cell array (48V, 2400W) and battery system. My suggestion was based on that installation and servicing the equipment for several years.
    The charger was a programmable output voltage switching regulator controlled by a microcomputer that monitored the battery voltage and charging current. The software controlled the charging current by increasing or decreasing the output voltage of the switching regulator. After several years of operation the customer was impressed by how well the system worked and how much longer the batteries lasted. The description altosack posted is pretty well identical to part of the setup and calibration section of the user manual for the charger.

    The switching regulator you posted should work well for your solar cell and battery. Your solar cell is rated at 18W so even if the switcher had 100% efficiency (which it does not, it is ~ 77%) the MAXIMUM current out at 13.2V would only be ~ 1.4 Amps. The regulator would be used for all 3 stages to get maximum charging efficiency, and it should never be bypassed.

    So for stage 1 (bulk): The MICROCONTROLLER adjusts the SWITCHING REGULATOR OUTPUT VOLTAGE to produce maximum current in to the battery while monitoring the voltage until it reaches the "absorb" voltage. This provides maximum charging efficiency. The only time you would need to limit the current would be if you had a very high output solar cell array charging a small capacity battery.

    Stage 2 (absorb): The MICROCONTROLLER adjusts the SWITCHING REGULATOR OUTPUT VOLTAGE to maintain the “absorb” voltage until the current goes down to C/100.

    Stage 3 (float): The MICROCONTROLLER adjusts the SWITCHING REGULATOR OUTPUT VOLTAGE to maintain the float voltage.
    In science there is no authority. There is only experiment.

  8. #8

    Default Re: Solar Charge Controller

    I also just found this : http://www.jameco.com/webapp/wcs/sto...001_2057801_-1
    It has better efficiency and a 5A ability. Is this one "stackable" to handle more current?

    So I take it that the voltage measurement for stage 2 is taken in series from the regulator to the battery is the "absorb" voltage?

    In Stage 1, how would you know that the maximum current was going into the battery based on voltage output of the regulator?

    In stage 3, how would maintaining the float voltage be possible when there will always be current flowing from the switching regulator unless the voltage is less than the battery is charged at? Or... do I have this wrong?

  9. #9

    Default Re: Solar Charge Controller

    altosack,

    "A battery will not be hurt at all by connecting a higher voltage solar panel to it; in fact, the voltage will be clamped to the battery voltage, and the solar panel will put out something very close to its short circuit current if it is rated for a much higher voltage." - I'm going to have to respectfully disagree with this statement. Without any regulation / monitoring you can easily overcharge and damage a battery. Damage can include bursting, drying up, leaking, etc. This depends on both the battery under charge, and the capacity of your solar panels.

    Reading further though I see that this is not a direct connection but a switched power supply to the battery. Still though, the first statement is a little misleading.

    email - Beau Schwabe || BS Circuit Designs

    web - www.BScircuitdesigns.com
    IC's * Inductive proximity sensors * Misc * and more!!

    Do YOU need custom programming? PIC micro? Basic Stamp? Propeller? A custom PCB design? or even a 3D-print design? ... Then send me an e-mail lets talk, I have +20 years experience.

  10. #10

    Default Re: Solar Charge Controller

    Doing more research and have learned a little more. Figured out what the Absorb voltage is I think. Now I am trying to see if the above regulator in my last post is able to be stacked (More than one used in the same circuit going to the same output. Also trying to figure out a DAC that could be used with them. Any help on this would be greatly appreciated!

  11. #11

    Default Re: Solar Charge Controller

    I think there are some misunderstandings due to terms.

    There are two common ways for a charge controller to operate: [simple] PWM, which can never deliver more than the short-circuit current of the solar panel into the battery, but is very easy to implement, and MPPT (maximum power point tracking), which uses some form of DC-DC converter (usually a buck converter in practice) to maximize the current into the battery, which can, in certain circumstances, be more than the short circuit current of the solar panel. MPPT is far more challenging to implement, because you have to place the MOSFET in the positive leg, meaning the gate driver supply has to be 12-15V above that, and must be floating (not at a fixed voltage). This is non-trivial to implement.

    To me, "switching regulator" means a packaged device that you connect a choke (coil) and capacitors to provide a more efficient power supply than a linear regulator, usually for signal electronics, not power electronics. However, I assume that kwinn is speaking of a discrete buck converter, because I've never heard of a packaged switching regulator that can put out 2400W ! In any case, both a packaged switching regulator and a discrete buck converter are ways of implementing MPPT.

    Quote Originally Posted by eagletalontim View Post
    I also just found this : http://www.jameco.com/webapp/wcs/sto...001_2057801_-1
    It has better efficiency and a 5A ability. Is this one "stackable" to handle more current?
    The only way that buck converters can be stacked is if they are out-of-phase with each other and maintain that phase relationship from one cycle to the next. Separate packaged components cannot do this. However, discrete buck converters can be driven by a Prop (one phase per cog, each phase with a primary and a diode MOSFET), and the phase relationship can be maintained by the shared system counter. The only other microcontrollers I've run across that can do this in a DIP package are some 16-bit dsPICs that are limited to 4 phases (not too bad, really, but they are simply not Props !), unless you use multiple chips.

    So I take it that the voltage measurement for stage 2 is taken in series from the regulator to the battery is the "absorb" voltage?
    All regulating voltages (including absorb, float, and equalize) are measured across the battery, not in series with anything.

    In Stage 1, how would you know that the maximum current was going into the battery based on voltage output of the regulator?
    You wouldn't, but in fact you don't care about the voltage output of the regulator, or the input voltage of the solar panels. You measure the current into the battery, which is what you are trying to maximize, and adjust the PWM to that effect. A common way of doing this is with the "perturb and observe" algorithm (a simple version is implemented in the code I gave in my first reply).

    In stage 3, how would maintaining the float voltage be possible when there will always be current flowing from the switching regulator unless the voltage is less than the battery is charged at?
    To maintain float voltage (or any voltage above the resting voltage), current must be flowing into the battery, although it can be quite small, perhaps between C/200 and C/1000 into a well-charged battery. With MPPT, making the voltage differential between the output of the buck converter and the battery very small will reduce the amount of current flowing to that which you need. The voltage will hunt a certain amount, but this can be minimized by implementing PID on the duty cycle. With simple PWM, if the directly connected current is 1A, setting the PWM duty cycle to 10% will put in 0.1A; as required current to maintain float voltage get small, there can be some hunting here, also, which can, again, be minimized by implementing PID on the duty cycle.


    As I said in my first reply, you don't need to measure current to implement 3-stage charging (although I like to have this information, anyway) with simple PWM, but you will need to measure it to implement MPPT. To measure it, you will need a low-resistance precision resistor (often called a shunt); common ones are 0.1 and 1.0 milli-ohms, but you may be able to get away with 10 milli-ohms in your low current application. (Higher resistance gives better accuracy and lower current capacity.)

    The voltage across the shunt can be calculated by: V = I R (voltage = current x resistance); for example, 2A into a 1 milli-ohm shunt will have a 2 mV differential. This is hard to read with any accuracy with a single-ended ADC; it's best to use a differential ADC with gain (the voltage difference between the two sides of the shunt will be multiplied by the gain, usually between 32 and 128 times). Two differential ADCs with gain in a DIP are the Nuvoton NAU7802 (~18-bits effective resolution, (2) sigma-delta inputs) and an Atmel ATtiny261A (a cheap microcontroller with 10-bits effective resolution, probably enough, with some oversampling, for your application, and with (11) SAR inputs).


    Beau, I don't think the statement I made is at all misleading, since I think it is completely understood that we are monitoring the battery and feeding it with a switched connection (else we would not need a Prop, which is probably not the way that you want us to go !).

  12. #12

    Default Re: Solar Charge Controller

    @altosack

    My apologies for misusing the term “switching regulator”. You are correct, it was a discrete switching power supply with a 50A output current. IIRC the description was “Digitally controlled variable voltage switching power supply”.

    @eagletalontim

    I am not sure if the switching regulators can be stacked. No experience with doing that. I don't see any need for more current unless you are planning on a much larger system than the 18W solar panel and 7AH battery in your initial post. On the other hand I don't see why they could not be stacked, although it might require some additional circuitry to balance the current between the regulators.
    In science there is no authority. There is only experiment.

  13. #13

    Default Re: Solar Charge Controller

    Ok, I think I understand a little better now I looked up a buck converter and found this :

    http://www.daycounter.com/LabBook/Bu...quations.phtml

    Not sure if this is the proper way to connect it for what I need, but I can now see how it is possible to get 1000W + controllers using MOSFETs.

    With simple PWM, if the directly connected current is 1A, setting the PWM duty cycle to 10% will put in 0.1A; as required current to maintain float voltage get small, there can be some hunting here, also, which can, again, be minimized by implementing PID on the duty cycle.
    Not sure what PID is. Could you explain this? I am still trying to get a grasp on PWM and how you can change output voltage based on the pulse width. For Buck mode (Stage 1) the pulse width will be spaced far out to allow a large amount of current through but what about voltage? Voltage and Current are changed at the same time right? So this would mean I would have to put more than 13.6V voltage into the battery in stage 1 since my panel outputs 24V?

    I have been reviewing this schematic and trying to figure it out : http://www.timnolan.com/uploads/Ardu...duinoSolar.pdf

    Q3 which is a mosfet appears to be a direct short when it is activated. What is the purpose of it?
    The MAX4173H appears to be a current sensing chip, but it is surface mount only? Is there an alternative besides using a chip? Maybe an ADC function or something different that I don't have to spend money on right now?

    I already have some MOSFETs on hand that I am sure I could use for the time being until I am able to order better ones. Problem is, I don't know how to "properly" run them without a mosfet driver which I don't have. Is it possible to run them reliably with just the Prop and a few resistors?

  14. #14

    Default Re: Solar Charge Controller

    Take a look at http://en.wikipedia.org/wiki/PID_controller for an explanation of pid loops.

    As for the operation of the buck switching regulator, the central component of that circuit is the inductor. The inductor stores energy as a magnetic field. Referring to the schematic on the LM2678 data sheet, when the output voltage drops below the chips internal reference voltage (as sensed by the "feedback" pin) it turns on the transistor that connects the input voltage to the left side of the inductor. The current through the inductor increases (the magnetic field also increases) and charges the output capacitors until the output voltage exceeds the reference voltage. At this point the chip turns off the transistor, the magnetic field around the inductor collapses transferring its stored energy into the output capacitors, and once the output voltage drops below the reference voltage the cycle repeats.
    In science there is no authority. There is only experiment.

  15. #15

    Default Re: Solar Charge Controller

    Ok, reading that made me even more scared of attempting this project. I don't understand any of the symbols or any of the formula's. The first paragraph of that page made me have to get up and clear my mind! Electronics to me is turning a device on or off as needed. Knowing that 12V cannot go into the base of a standard transistor is learned by doing it and watching it explode.... Throw in some resistors till it does not get hot anymore and bam, it works! I have worked with most transistors and understand what they need to turn on and off so I don't burn up as many components as I used to.

    Is PID needed for what I am trying to do? Is there a PID for dummies reference that I can look at that include a complete schematic?

  16. #16

    Default Re: Solar Charge Controller

    I don't think a pid is really needed for this, but a quick look in the OBEX found 3 that could be possibly be used, although they may need to be modified.

    Here is what the microcontroller software needs to do for each stage of charging.

    For stage 1 (bulk): The microcontroller would start the switching regulator at a low voltage and execute a loop that increments the output voltage and measures the charging current to find the peak current.
    Once the initial peak current has been found it would vary the voltage up and down a small amount to maintain the peak current. It also monitors the output voltage to see if has reached the “absorb” voltage at this point.

    Stage 2 (absorb): Once the “absorb” voltage has been reached the microcontroller would maintain that output voltage from the switcher and monitor the current until it goes down to C/100.

    Stage 3 (float): The microcontroller adjusts the switcher output voltage to maintain the float voltage.


    You will need to measure the charging current and the switcher output/battery voltage which can be done with a 2 channel adc or 4 prop pins used to make 2 sigma/delta adc's.

    You will also need to control the switcher output voltage which can be done using a dac or a prop pin and pwm.
    In science there is no authority. There is only experiment.

  17. #17

    Default Re: Solar Charge Controller

    Eagletalontim,

    I hope you don't find this patronizing, but I sincerely recommend that you start with a simple PWM controller, and do not attempt MPPT for the first iteration. Nothing you build will be wasted, and it can all be applied to MPPT if and when you are ready and you find it necessary (it may, in fact, not be necessary). Even though I'm a mechanical engineer with many solar electric installations under my belt, and I've been studying electronics for quite a while and have a good understanding (probably better than many electrical engineers), I'm going to start with simple PWM, also, because it's a prudent and effective path to take.

    PID stands for Proportional, Integral, Derivative, and is a (software) method for convergence to a desired output for a controller, and, as such, there is no schematic. You don't really need it as long as you don't mind having the voltage hunt around a bit instead of being a steady-state absorb or float value. This won't significantly shorten the life of your battery. Definitely, start simple, and if and when you want to add a little finesse to your voltage control, read up on PID and look at the subroutine in my regulate.c file, and we'll help you.

    All you need for a simple PWM solar controller is a Prop, an ADC chip, a gate driver, and a MOSFET. A recommended extra is a 16x4 (or so) character LCD so you can output the voltage and whatever else you want to see. Put the MOSFET in the battery negative connection, and use the battery positive for the power supply for the gate driver. Use the ADC chip (I recommend the Nuvoton NAU7802 because it's accurate, easy-to-use, and it can also read the current when you're ready to do that) to read the voltage, and implement the 3 charging stages outlined before in software. I think the "regulate.c" file I included is a good starting point; you can remove all the stuff about the RE buss, wind, dump loads, and PID, if you want to.

    Phase 2 would be to implement current measurement; with that, you can do all the things that a state-of-charge meter (such as a TriMetric 2025) can do, if you want to write the software to do it, and you can transition from the absorb stage to the float stage with a more accurate method than simply timing it.

    Phase 3 would be to implement PID.

    Phase 4 would be to implement MPPT.

  18. #18

    Default Re: Solar Charge Controller

    I may have kind of understood this PID by reading a whole bunch of articles on it and piecing together what I could understand. From what I gather, all the PID does is take a reading (in this case Voltage) and stores it, then take previously stored reading and makes a determination on what should be done based on a Set reading. I can also make a future assumption on what the next reading will be based on previous stored data and compensate on it's own.

    What I figure this would be useful for is to take a known voltage of 13.8V and set it as the "Need" variable. Then begin taking samples of the voltage that is charging the batteries. If the first sample is say 14.0V, an adjustment is made to the PWM duty cycle to drop the voltage to be closer to the "Need" Variable based from starting preset "step" amount of say +/- 50?. Then take another reading and check it against the previous reading. Let say that reading is 13.5V. This means that the duty cycle was changed too much and needs to be adjusted accordingly. So to do this, I would take the previous reading of 14.0V and the latest reading of 13.5V and put them through the formula below to find the difference in percentage.:

    Code:
     Is       %
    ----- = ------
    Of      100
    
    Or...
    
    Reading      %
    ------------ = ------
    Need         100
    So first reading was 14.0V which when put through the formula above (14.0 * 100) / 13.8 = 101.45%
    Then the second reading would be (13.5 * 100) / 13.8 = 97.83%
    So the preset "step" amount of -50 from the duty cycle made a 3.62% change in voltage which is too much so the "step" variable needs to be changed to not change the voltage so much in the next adjustment.
    To do this, there will be another formula which I am working on to get the adjusted step amount. Will post once I figure it out.

  19. #19

    Default Re: Solar Charge Controller

    So having the Mosfet on the positive side is not a good idea? I have a few P channel Mosfets that I can use for now that can for sure handle the current I am working with plus WAY more. If I follow this schematic in the last post here http://forums.parallax.com/showthrea...=1#post1035582 could I use that? I even have the MPSA06 on hand

  20. #20

    Default Re: Solar Charge Controller

    Hopefully my previous post will not go left unanswered, but I also have a change in the PID math I think....

    Predefined values
    Pulse Period = 1000 ' just an example
    "Need" Voltage = 13.8V
    Step Increment = 50

    First Reading (Stored reading) = 14.0V
    Second Reading (Last reading) = 13.5V
    Difference = 14.0 - 13.5 = 0.5

    So in theory for each value of the Step Increment (50) the voltage change is 0.01V
    So to reach our goal, the Step value should change to (Need Voltage - Last Reading) = 0.3 Difference from last reading to needed voltage / Current Step increment voltage change (0.01) = New Step increment value : 30

    So to sum it all up.....
    New PWM Pulse period = Pulse Period + (Need Voltage - Last Reading) / ((Stored reading - Last Reading) / Last Step Increment Value)

    I will have to test this in a program to see if this is anywhere close to what I need, but I don't feel like writing a program right now :p

+ Reply to Thread

Similar Threads

  1. [unsolved] How would you charge a dozen AA cells with a 12V 5W solar panel?
    By Microcontrolled in forum General Discussion
    Replies: 9
    Last Post: 03-25-2011, 01:06 AM
  2. Solar Charge Controller Ideas... Thinking out loud
    By Beau Schwabe (Parallax) in forum General Discussion
    Replies: 14
    Last Post: 08-23-2008, 09:24 AM
  3. solar power to charge batt or capacitor
    By Blake in forum BASIC Stamp
    Replies: 1
    Last Post: 07-22-2007, 06:00 AM
  4. Solar panel maximum charge rate
    By metron9 in forum General Discussion
    Replies: 13
    Last Post: 12-10-2006, 02:04 AM
  5. Replies: 10
    Last Post: 12-08-2004, 12:32 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts