Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 04:54 28 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Electronics : MAD/OZ AC/DC Charge Controller

     Page 7 of 9    
Author Message
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 03:09pm 01 Nov 2017
Copy link to clipboard 
Print this post

The MOSFETs in the regulator have not failed, it was the IGBT's in the GTI that failed before and caused the big bang.

The Zeversolar GTI is now back online with my off grid Inverter, so far all good.

Update, the Zeversolar completed the day flawlessly, regulation worked well, fingers crossed it stays that way. I just found out this evening that Zeversolar can be controlled via its RS485 port, the adapter to connect it the internet can also be connected to a power monitor and be used to regulate the maximum output of the GTI. Although it would take quite a bit to work it out and would not be transferable to another GTI brand.

Yellow lines are battery volts and Brown/orange is battery current. The dip before going to Float was a cloud.




Edited by Madness 2017-11-03
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 02:00am 09 Nov 2017
Copy link to clipboard 
Print this post

The Zeversolar GTI has been working perfectly for a week now since I discovered the arcing issue. I have not quite got the new boards in operation, few bits wiring to tidy up, will be done in the next few days.




Even though it has been a showery day we had a couple hours of sun this morning and the batteries where back up to 100% charge by 10:30 so the regulator cut back the GTI's output till later in the day when my wife did some baking.
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
oztules

Guru

Joined: 26/07/2007
Location: Australia
Posts: 1686
Posted: 02:00pm 09 Nov 2017
Copy link to clipboard 
Print this post

Looks like the idea is sound... well done up there.

.....oztules
Village idiot...or... just another hack out of his depth
 
Clockmanfr

Guru

Joined: 23/10/2015
Location: France
Posts: 429
Posted: 09:42pm 09 Nov 2017
Copy link to clipboard 
Print this post

Yes, nice one madness for persevering.

Just to recap, that Zeversolar GTI your using is a HF type, ie, no substantial heavy toroid inside. ?
Everything is possible, just give me time.

3 HughP's 3.7m Wind T's (14 years). 5kW PV on 3 Trackers, (10 yrs). 21kW PV AC coupled SH GTI's. OzInverter created Grid. 1300ah 48v.
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 10:37pm 09 Nov 2017
Copy link to clipboard 
Print this post

Yes the Zeversolar is HF and also requires isolation from ground. So I have had to use the isolated power supply to supply 18V to the 3120 gate driver IC and insulate MOSFETs.

Apart from that failure I had which appears to have been caused by the arcing to ground the HF GTI has worked perfectly. I have found it to be much better than the Aero-sharps, the off grid inverter likes it better also. When the GTI is running the OGI is quieter and the waveform is very smooth which I did not get with the A-S GTI.




There are only 10 types of people in the world: those who understand binary, and those who don't.
 
gpalterpower

Senior Member

Joined: 19/07/2009
Location: Australia
Posts: 175
Posted: 08:16pm 10 Nov 2017
Copy link to clipboard 
Print this post

Awesome work there Madness. Glad you got to the bottom of the problem. Fault finding is tedious and time consuming at the best of times.

Perseverance does pay!

Ill be happy to purchase a pair of the boards when they are available. Id like to try it on my 2300W Conergy system

Marcus
if it aint broke dont fix it!!
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 12:59pm 22 Nov 2017
Copy link to clipboard 
Print this post

There has been some progress with the software for the controller however I am having hardware issues with FET's shorting out. This does not stop it charging but does prevent any regulation. I think it may have been due to the voltage for the Arduino dropping too low. I have modified the power supply to see if this cures it.

I have made a lot of changes to Oztules original code, it now includes actual voltage (with battery temperature compensation) and time settings in minutes. The original code timing varies greatly when you make changes to it, this code now uses the millis() function for much more accurate timing. This version also is made to work with a 4 line X 20 Character serial display. A future addition will be the abilty to turn on as required 2 solid state relays for things like diverting power to hot water systems/ pumps etc, I will be using one of these to turn on the AC in my equipment room when temperature rises and there is suffcient power available. Also an Ethernet card to allow networking and data logging (this will have Oztules shaking his head ). To do this I will need to rearrange some of the pins on the PCB, plus I need to resolve the power supply issue before ordering any more PCBs.



I have tested this code by simulating battery volts and temperature, I have not used it in real life yet. However I am confident it is fine,

[code]
// Get 1-wire Library here: http://www.pjrc.com/teensy/td_libs_OneWire.html
#include <OneWire.h>

//Get DallasTemperature Library here: http://milesburton.com/Main_Page?title=Dallas_Temperature_Control_Library
#include <DallasTemperature.h>
// Wire (I2C) Library
#include <Wire.h>

// include the library code:
#include <LiquidCrystal.h>

/*-----( Declare Constants and Pin Numbers )-----*/
// Data wire is plugged into port 8 on the Arduino (can be changed)
#define ONE_WIRE_BUS 8 // NOTE: No ";" on #define


// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass address of our oneWire instance to Dallas Temperature.
DallasTemperature sensors(&oneWire);
#include <LiquidCrystal_I2C.h>

// Start the LCD display library
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address

//===========================MAIN CHARGER SETTINGS, REFER TO YOUR BATTERY MANUAL==================================================================

float batv = 48; // nominal battery voltage 24 OR 48, could work with 12V with 18v power supply for FET driver chips on pcb
int floatVolts = 54.0; // User setting for the FLOAT voltag
int absorbCharge = 59.2; // User setting for the ABSORPTION voltage
long timedOut = 120; // ABSORPTION MINUTES
int startAllOverAgain = 49; // User setting for resetting the charge cycle, usually overnight or after heavy drawdown

//===========================ADVANCED SETTINGS===================================================================================================


float R1 = 105000.0; // resistance of R1 (100K)
float R2 = 8000.0; // resistance of R2 (8K2) For setting up voltage divider to get correct voltage reading Use in conjunction with trim pot on pcb
int pwmmin = 5; // Minimum Output level 0 = will go as low as no output, set higher WITH CAUTION if you want to stop a GTI from restarting during the day if unsure leave at zero





const int numReadings = 5;
int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running [ total
int average = 0; // the average
int voltsinputPin = 3;
float battemp;
float tcomp;
float vout = 0.0;
float vin = 0.0;
int value = 0;
long fullTime = 0; // timer for float stage
int PWMout1 = 5; // fet driver connected to this pin
int PWMout2 = 6; // fet driver connected to this pin
int analogPin = 3; // divided voltage from battery
int pulseVal = 0; // initilise the pulse width to zero of 255
long absorbTime = 0; // initialise the time to zero for the absorb
int increment = 12; // how much to change each pulse width for voltage control definition
int weAreHereNow = 0; // initialize the start stage as zero

unsigned long start, finished, elapsed;
unsigned long astart, afinished, aelapsed, apause, fstart;
boolean r = false;



void setup() {
Serial.begin(9600);
sensors.begin();

// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
pinMode(voltsinputPin, INPUT);
lcd.begin(20, 4);
pinMode(PWMout1, OUTPUT);
pinMode(PWMout2, OUTPUT); // sets the pin 6 as an output for the fet drive
}
}
void loop() {

GetVolts();


}

void GetVolts() {

// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(voltsinputPin);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;

// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;

// calculate the average:
average = total / numReadings;
// read the value at analog input
vout = (average * 5.0) / 1024.0;
vin = vout / (R2 / (R1 + R2)); // Voltage divider calculation
if (vin < 0.09) {
vin = 0.0; //Battery voltage
}
}
sensors.requestTemperatures(); // Send the command to get temperature readings

battemp = (sensors.getTempCByIndex(0)); // convert sensor value to degrees celcius

if (battemp == -127.00) // Measurement failed or no device found, if no temp sensor temperature comp has no effect
{
tcomp = 0;
}
else
{
tcomp = (25 - battemp) * (batv * 0.0025); //used to calculate voltage set point with temperature compensation applied
}

lcd.setCursor(0, 0);
lcd.print("Batt V = ");
lcd.setCursor(9, 0);
lcd.print(vin); //Actual battery volts
lcd.setCursor(15, 0);
lcd.print("C");
lcd.setCursor(16, 0);
lcd.print(tcomp); //Temperature compensation voltage adjustment value add or subtract for difference from 25 degrees
lcd.setCursor(0, 2);
lcd.print("PWM % = ");
lcd.setCursor(8, 2);
lcd.print(pulseVal / 2.55); // print the PWM out as a percentage from 0 - 100 (100% = charging at full avaiable power)

{

if (vin < startAllOverAgain ) //charge cylce starts here
{
lcd.setCursor(0, 1);
lcd.print("Pre-bulk volts ");
start = millis(); //sets start time for when bulk charge starts
}


if (weAreHereNow == 0 && vin > startAllOverAgain) // if stage 1 then we do this routine
{
lcd.setCursor(0, 1);
lcd.print("Bulk = ");
lcd.setCursor (8, 1);
lcd.print((millis() - start) / 60000); // Displays how many minutes since bulk charge started
lcd.print(" min");
}

if (weAreHereNow == 1) // if stage 2 then we do this screen routine

{
lcd.setCursor(0, 1);
lcd.print("Absorb ");
lcd.setCursor (7, 1);
lcd.print(absorbTime); // Display minutes actually at absorb voltage
lcd.setCursor (11, 1);
lcd.print("< Abs");
lcd.setCursor (17, 1);
lcd.print(apause / 60000); // Display minutes below absorb voltage since absorb started
}

if (weAreHereNow == 2)
{
lcd.setCursor(0, 1);
lcd.print("Float ");
lcd.setCursor (8, 1);
lcd.print(fullTime); // Display minutes since float was started
lcd.print(" min ");

}

lcd.setCursor(0, 3);
lcd.print("Battery Temp");
lcd.setCursor (14, 3);
lcd.print (battemp); // Display actual battery temperature
}

if (vin >= (absorbCharge + tcomp) && weAreHereNow == 0) // if we achieve 59v (bulk chg) AND we were in stage zero then change weAreHereNow to 1 as a flag ie absorb
{
weAreHereNow = 1; // weAreHereNow=1 is absorb status
}

//=============bulk routine==============


if ( weAreHereNow == 0) // if in stage 1 then check voltage against bulk charge constant ... can be set in definitions
{ pulseVal = 255; // was not up to bulkCharge, then increase pulse width incrementally
astart = millis(); //sets start time for when absorb charge starts
}

//==========absord routine==============

if ( weAreHereNow == 1 ) // if we are in absorb then do this
{
if (vin >= ((absorbCharge + tcomp) - 0.5)) { // This section is keep track of the time at or just under absorb voltage
aelapsed = ((millis() - astart) - apause); // aelapsed = time from the absorb cycle starting less the time below (absorbCharge + tcomp) - 0.5)
afinished = millis() - apause; // afinished is used to calculate time below absorb
absorbTime = (aelapsed) / 60000; // convert time to minutes

} else {
apause = (millis() - afinished); //time below absorb set point since absorb started
}
if (absorbTime >= timedOut) // once we reach timedOut, we have finished our absorb sequence, change status flag weAreHereNow to 2, and change the voltage now to float value
{
weAreHereNow = 2;
fstart = millis();
}

if (vin < (absorbCharge + tcomp))
{
pulseVal = pulseVal + increment; // was not up to bulkCharge, then increase pulse width incrementally
}


if (vin > (absorbCharge + tcomp))
{

pulseVal = pulseVal - increment;
}

if ( pulseVal >= 255)
{
pulseVal = 255;
}
if ( pulseVal <= pwmmin)
{
pulseVal = pwmmin;
}
}
//=========float routine=======


if ( weAreHereNow == 2) // are we in float charge stage

{
if (vin > ((floatVolts + tcomp) - 0.5))

{
fullTime = (millis() - fstart) / 60000; // increment float timer
}


if (vin < (floatVolts + tcomp))
{
pulseVal = pulseVal + increment; // is not up to float voltage, then increase pulse width incrementally
}


if (vin > (floatVolts + tcomp))
{
pulseVal = pulseVal - increment; // keeping charge in the float band....floatVolts is the constant we use
}

if ( pulseVal >= 255)
{
pulseVal = 255;
}
if ( pulseVal <= pwmmin)
{
pulseVal = pwmmin;
}

}
//==============================write the pulse to the fet======================
analogWrite (PWMout1, pulseVal);
analogWrite (PWMout2, pulseVal); // actually write the data to the fet via pin 6 ...

//=============================================
if (vin < (startAllOverAgain + tcomp)) // Voltage level to restart charge cycle when voltage drops below threshold due to night or very heavy load
{
weAreHereNow = 0; //reset values for start of next charge cycle
absorbTime = 0;
astart = 0;
apause = 0;
aelapsed = 0;
fstart = 0;
fullTime = 0;
}
}
[/code]



Edited by Madness 2017-11-24
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Mulver
Senior Member

Joined: 27/02/2017
Location: Australia
Posts: 160
Posted: 05:13am 24 Nov 2017
Copy link to clipboard 
Print this post

Awesome Work Madness!! I cant wait to get to your point! Hopefully next year ill have some money to throw at a stack of solar panels and i can get started!!
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 10:53am 24 Nov 2017
Copy link to clipboard 
Print this post

Hi Mulver,

I have got to where I am gradual, started off with a few secondhand solar panels, some cheap batteries, second-hand charge controller and an Ebay HF inverter from Taiwan. Made the usual mistake of starting out with 24V. Biggest amount I have spent at any one time was $700. That is until my latest purchase which just arrived today.




Took a bit of brain power to work out how to get it unloaded and to where it sits now.Edited by Madness 2017-11-25
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Tinker

Guru

Joined: 07/11/2007
Location: Australia
Posts: 1904
Posted: 11:40am 24 Nov 2017
Copy link to clipboard 
Print this post

Mad, you are game placing a metal ruler across that box

So, details please, capacity? weight?
If you had to move that box fully equipped with the cells I take my hat off to your brain power
Klaus
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 12:03pm 24 Nov 2017
Copy link to clipboard 
Print this post

Hi Klause,

I am MAD, normally I would agree with you about the ruler but the only part that is not insulated is the actual lugs for the leads leaving the battery bank. Each bolt head is insulated and sealed with o-rings to stop corrosion. But I did place the ruler very carefully just to give some scale for the photo. A rep from Trojan told me their batteries are designed to take a 5000A short without failing, that is something I would not like to try.

Details, 48V FLA 775AH @ 5 hour rate and weighs 1100KG and it was moved as one unit. Each cell is 100 X 200 X 742mm. It is a forklift battery if you had not guessed already, I have seen lots of reports that they are good for 20 years on solar. Wasn't too bad to move once I got it off the trailer, that took a hoist and lifting one end to drag it out, then hooked on to the other end and lifted a little and gradually it moved off. I used about 15 F&P washing machine shafts as rollers.

It is not quite in its final resting place, I have to get the old batteries out first. The scrap price of them is paying 1/3 of the price of the not quite new set. They are secondhand but have been refurbished and come with a 2 year replacement warranty.

All cells measure between 2.13 and 2.16 volts, the insulated bolts have a small hole in the centre for meter probe. Just quickly took one hydrometer reading and it was right to the bottom of the green. Tomorrow I will check and log where they all are after charging.

I expect to average 15% drawdown each night and should be able to keep it above 50% after 3 days of really bad weather.Edited by Madness 2017-11-25
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Revlac

Guru

Joined: 31/12/2016
Location: Australia
Posts: 1026
Posted: 02:14pm 24 Nov 2017
Copy link to clipboard 
Print this post

Well done, they look pretty good, you can move some heavy gear using steal rollers.
Should keep you going.
Cheers
Aaron
Cheers Aaron
Off The Grid
 
Tinker

Guru

Joined: 07/11/2007
Location: Australia
Posts: 1904
Posted: 09:57am 25 Nov 2017
Copy link to clipboard 
Print this post

Awsome. I had no idea that forklift batteries were that heavy. Come to think of it one really wants a forklift to move them .

Not being familiar with these batteries, the clear tubes on top are for recycling water vapor? Do you need to top the cells individually or is there a central filling place, that thicker clear tube in the middle?

I suppose your battery charging inverter will have its work cut out from now on.
Klaus
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 11:40am 25 Nov 2017
Copy link to clipboard 
Print this post

Yes they are really heavy and there are ones at least twice as big as the one I got. Moved it to its final position today after getting all the old batteries out, needed the steel shafts, hoist, crowbar and a few four-letter words but got it there. Not real easy to get it turn a tight corner, but I won in the end. I lifted it up on to 6 50mm square pieces of timber to allow air to flow under it to help keep it cool.

The tubes are the watering system, there is a float in each cell which controls the level, it also pops up into the clear circle on each cap to indicate it is full or low. The photo shows how they look when water is down, I topped it up this morning with a 20 litre container 2.5 metres above the battery top it filled in about 5 minutes using about 15 litres, they were just above the plates prior to that. Those caps have a top that flips open with a hole under it just big enough for a hydrometer to fit in.

The battery was fully charged when I got it, last night it was drawn down to 90% and had no trouble charging it today with almost complete cloud cover and a few showers. It went into float before 11 AM, plus my wife did ironing, washing and used the clothes dryer all powered by solar panels. The hot water system was running for about 4 hours as well which turns on automatically when the voltage is at the set point. So the AC power to the house was over 5KW for quite a few hours.

This the daily report from my GTI.

Date: 2017-11-25
E-Today: 15.0kWh
P-Peak: 3.01kW
Yield: 4.95$
CO2 Avoided: 12.0kg

There would have been similar amount from other anels as well.
Edited by Madness 2017-11-26
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 05:12am 03 Dec 2017
Copy link to clipboard 
Print this post

The new battery is going really well after an initial problem with power dropouts. Turned out someone (not me) had not tightened one of the interconnectors properly, it was about 3/4 of a turn short of being tight. Only showed up when drawing over 100A, since tightening it the battery has been running perfectly. The new battery can complete the absorb cycle @ 59.2 volts and holding that voltage with just 15 amps.

I did not realise just how much power my old crap batteries were losing due to inefficiency, self-discharge etc. They cost me scrap price of $0.40 per KG now I am going to get $0.60 per KG. Here is what $1,200 worth of junk looks like.





Still unable to work out why the newer version of the Charge controller PCB is blowing MOSFET's.

Been working on software for the simpler version. It now includes time delay for resting the charge cycle, equalization cycle and manually being able to put it into Float or Absorb. Holding both Float and Absorb will initiate Equalization. I have also connected the Float button via a voltage divider to the AUX output of one of my Midnite charge controllers. So when the Midnite CC enters float and the AUX outputs 12V this supplies 5V to the pin on the Nano forcing it to enter float at the same time.

Here is the code which may be of help to someone.

[code]
// Get 1-wire Library here: http://www.pjrc.com/teensy/td_libs_OneWire.html
#include <OneWire.h>

//Get DallasTemperature Library here: http://milesburton.com/Main_Page?title=Dallas_Temperature_Control_Library
#include <DallasTemperature.h>
// Wire (I2C) Library
#include <Wire.h>

// include the library code:
#include <LiquidCrystal.h>

/*-----( Declare Constants and Pin Numbers )-----*/
// Data wire is plugged into port 8 on the Arduino (can be changed)
#define ONE_WIRE_BUS 12 // NOTE: No ";" on #define


// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass address of our oneWire instance to Dallas Temperature.
DallasTemperature sensors(&oneWire);
#include <LiquidCrystal_I2C.h>

// Start the LCD display library
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address

//===========================MAIN CHARGER SETTINGS, REFER TO YOUR BATTERY MANUAL==================================================================

float batv = 48; // nominal battery voltage 24 OR 48, could work with 12V with 18v power supply for FET driver chips on pcb
int floatVolts = 54.0; // User setting for the FLOAT voltag
int absorbCharge = 59.2; // User setting for the ABSORPTION voltage
long timedOut = 120; // ABSORPTION MINUTES
int EqualizationCharge = 64.8; // User setting for the ABSORPTION voltage
int startAllOverAgain = 50.5; // User setting for resetting the charge cycle, usually overnight or after heavy drawdown
int startoverdelay = 30; // minutes below startAllOverAgain before reseting cycle

//===========================ADVANCED SETTINGS===================================================================================================


float R1 = 100000.0; // resistance of R1 (100K)
float R2 = 5500.0; // resistance of R2 (8K2) For setting up voltage divider to get correct voltage reading Use in conjunction with trim pot on pcb
int pwmmin = 15; // Minimum Output level 0 = will go as low as no output, set higher WITH CAUTION if you want to stop a GTI from restarting during the day if unsure leave at zero





const int numReadings = 5;
int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running [ total
int average = 0; // the average
int voltsinputPin = 3;
float battemp;
float tcomp;
float tcompl;
float vout = 0.0;
float vin = 0.0;
int value = 0;
long fullTime = 0; // timer for float stage
int PWMout1 = 6; // fet driver connected to this pin
int analogPin = 3; // divided voltage from battery
int pulseVal = 0; // initilise the pulse width to zero of 255
long absorbTime = 0; // initialise the time to zero for the absorb
int increment = 25.5; // how much to change each pulse width for voltage control definition
int weAreHereNow = 0; // initialize the start stage as zero
int weWhereHere = 0;
long resettimer = 0;
long start;
long finished;
long elapsed;
long astart;
long afinished;
long aelapsed;
long apause;
long fstart;
boolean r = false;
const int buttonFloat = 7; // the number of the pushbutton pin
const int buttonAbsorb = 8; // the number of the pushbutton pin
int buttonFState = 0;
int buttonAState = 0;

void setup() {
Serial.begin(9600);
sensors.begin();

// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
pinMode(voltsinputPin, INPUT);
lcd.begin(20, 4);
pinMode(PWMout1, OUTPUT); // sets the pin 6 as an output for the fet drive
}
}
void loop()
{ GetVolts();
}

void GetVolts() {

// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(voltsinputPin);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;

// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;

// calculate the average:
average = total / numReadings;
// read the value at analog input
vout = (average * 5.0) / 1024.0;
vin = vout / (R2 / (R1 + R2)); // Voltage divider calculation
if (vin < 0.09) {
vin = 0.0; //Battery voltage
}
}

buttonFState = digitalRead(buttonFloat);
buttonAState = digitalRead(buttonAbsorb);

if (buttonFState == HIGH) {
weAreHereNow = 2;}// Enter float mode: //Manually select Float State, pin needs 10K pull down resistor to ground to prevent errors

if (buttonAState == HIGH) {
weAreHereNow = 1;}// Enter Absorb mode: //Manually select Absorb State, pin needs 10K pull down resistor to ground to prevent errors

if ((buttonFState == HIGH) && (buttonAState == HIGH)) { // Press both buttons to select Equalization State
absorbCharge = EqualizationCharge;}// Enter Equalization mode: //Manually select Equalization State, for Flooded Lead Acid Batteries only! make sure battery water is above minum before initiating


sensors.requestTemperatures(); // Send the command to get temperature readings

battemp = (sensors.getTempCByIndex(0)); // convert sensor value to degrees celcius

if (battemp == -127.00) // Measurement failed or no device found, if no temp sensor temperature comp has no effect
{
battemp = tcompl; // prevents error if sensor fails to return a result occasionally
}
else
{
tcomp = (25 - battemp) * (batv * 0.0025); //used to calculate voltage set point with temperature compensation applied
tcompl = battemp;
}

lcd.setCursor(0, 0);
lcd.print(vin); //Actual battery volts
lcd.setCursor(6, 0);
lcd.print("C");
lcd.setCursor(7, 0);
lcd.print(tcomp); //Temperature compensation voltage adjustment value add or subtract for difference from 25 degrees
lcd.setCursor(13, 0);
lcd.print(pulseVal / 2.55); // print the PWM out as a percentage from 0 - 100 (100% = charging at full avaiable power)
{

if ((vin < startAllOverAgain) && (resettimer == 0)) //charge cylce starts here
{
lcd.setCursor(0, 1);
lcd.print("PreBulk ");
start = millis(); //sets start time for when bulk charge starts
}


if (weAreHereNow == 0 && vin > startAllOverAgain) // if stage 1 then we do this routine
{
lcd.setCursor(0, 1);
lcd.print("Bulk ");
lcd.setCursor (7, 1);
lcd.print((millis() - start) / 60000); // Displays how many minutes since bulk charge started
}

if (weAreHereNow == 1) // if stage 2 then we do this screen routine

{ if (vin >= ((absorbCharge + tcomp) - 0.5))
{ lcd.setCursor(0, 1);
lcd.print("Absorb ");
lcd.setCursor (7, 1);
lcd.print(absorbTime);// Display minutes actually at absorb voltage
}
else if (vin < ((absorbCharge + tcomp) - 0.5))
{ lcd.setCursor(0, 1);
lcd.print("< Abs ");
lcd.setCursor (7, 1);
lcd.print(absorbTime);
}
if (absorbCharge == EqualizationCharge)
{lcd.setCursor(0, 1);
lcd.print("Equal ");
}

}
if (weAreHereNow == 2)
{
lcd.setCursor(0, 1);
lcd.print("Float ");
lcd.setCursor (7, 1);
lcd.print(fullTime); // Display minutes since float was started
}

lcd.setCursor(11, 1);
lcd.print("T");
lcd.setCursor (12, 1);
lcd.print (battemp); // Display actual battery temperature
}

if (vin >= (absorbCharge + tcomp) && weAreHereNow == 0) // if we achieve 59v (bulk chg) AND we were in stage zero then change weAreHereNow to 1 as a flag ie absorb
{
weAreHereNow = 1; // weAreHereNow=1 is absorb status
}

//=============bulk routine==============


if ( weAreHereNow == 0) // if in stage 1 then check voltage against bulk charge constant ... can be set in definitions
{ pulseVal = 255; // was not up to bulkCharge, then increase pulse width incrementally
astart = millis(); //sets start time for when absorb charge starts
}

//==========absord routine==============

if ( weAreHereNow == 1 ) // if we are in absorb then do this
{
if (vin >= ((absorbCharge + tcomp) - 0.5)) { // This section is keep track of the time at or just under absorb voltage
aelapsed = ((millis() - astart) - apause); // aelapsed = time from the absorb cycle starting less the time below (absorbCharge + tcomp) - 0.5)
afinished = millis() - apause; // afinished is used to calculate time below absorb
absorbTime = (aelapsed) / 60000; // convert time to minutes

} else {
apause = (millis() - afinished); //time below absorb set point since absorb started
}
if (absorbTime >= timedOut) // once we reach timedOut, we have finished our absorb sequence, change status flag weAreHereNow to 2, and change the voltage now to float value
{
weAreHereNow = 2;
fstart = millis();
}

if (vin < (absorbCharge + tcomp))
{
pulseVal = pulseVal + increment; // was not up to bulkCharge, then increase pulse width incrementally
}


if (vin > (absorbCharge + tcomp))
{

pulseVal = pulseVal - increment;
}

if ( pulseVal >= 255)
{
pulseVal = 255;
}
if ( pulseVal <= pwmmin)
{
pulseVal = pwmmin;
}
}
//=========float routine=======


if ( weAreHereNow == 2) // are we in float charge stage

{
if (vin > ((floatVolts + tcomp) - 0.5))

{
fullTime = (millis() - fstart) / 60000; // increment float timer
}


if (vin < (floatVolts + tcomp))
{
pulseVal = pulseVal + increment; // is not up to float voltage, then increase pulse width incrementally
}


if (vin > (floatVolts + tcomp))
{
pulseVal = pulseVal - increment; // keeping charge in the float band....floatVolts is the constant we use
}

if ( pulseVal >= 255)
{
pulseVal = 255;
}
if ( pulseVal <= pwmmin)
{
pulseVal = pwmmin;
}

}
//==============================write the pulse to the fet======================
analogWrite (PWMout1, pulseVal); // actually write the data to the fet via pin 6 ...

//=============================================
if ((vin > startAllOverAgain) && (weAreHereNow == 4))
{ resettimer = 0;
weAreHereNow = weWhereHere;
}
if ((vin < startAllOverAgain) && (resettimer == 0) && (weAreHereNow >= 1))

{ resettimer = millis();
weWhereHere = weAreHereNow;
weAreHereNow = 4;
}
if (resettimer > 0)
{
lcd.setCursor(0, 1);
lcd.print("reseting ");
lcd.setCursor (9, 1);
lcd.print((millis() - resettimer) / 60000); // Display minutes since reset was started
}
{
if ((vin < startAllOverAgain) && (resettimer + ( startoverdelay * 60000)) < millis()) // Voltage level to restart charge cycle when voltage drops below threshold due to night or very heavy load {
{
weAreHereNow = 0; //reset values for start of next charge cycle
absorbTime = 0;
astart = 0;
apause = 0;
aelapsed = 0;
fstart = 0;
fullTime = 0;
resettimer = 0;
}

}
}
[/code]Edited by Madness 2017-12-04
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Revlac

Guru

Joined: 31/12/2016
Location: Australia
Posts: 1026
Posted: 11:25am 03 Dec 2017
Copy link to clipboard 
Print this post

That pile of batteries, They served you well for a bit. looks just like my backyard I have probably twice that many.

The new batteries will charge better on the cloudy days as they are more efficient.
I can't see why the mosfet's should fail, they are only on/off switching?.

Cheers
Aaron
Cheers Aaron
Off The Grid
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 12:02pm 03 Dec 2017
Copy link to clipboard 
Print this post

Price of lead is up so might be a good time to cash in those old batteries in Aaron. The old batteries did the job but they were a pita to top up the water and check specific gravity with so many individual cells.

Yes definitely a big difference on cloudy days, this morning we had partial cloud till around 10 and then it started raining on and off with no breaks in the clouds. We were able to do a load of washing, dry it in the dryer, run a wash in the dishwasher and still got to float by 1 PM. Not long after that, it got really dark and all my panels were making < 50W most of the afternoon.
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 03:31am 16 Dec 2017
Copy link to clipboard 
Print this post

Finally solved the MOSFETs shorting issue, I had to separate the Drains of the MOSFETs from each other as per the diagram. It has been running well with this modification, I am not sure what difference it makes but this how my original design was made and it has not failed.









Edited by Madness 2017-12-17
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
Tinker

Guru

Joined: 07/11/2007
Location: Australia
Posts: 1904
Posted: 08:49am 16 Dec 2017
Copy link to clipboard 
Print this post

Hi mad, trying to understand what you are doing and knowing not much about GTI's...

Must one connect two strings of panels to this GTI or will it work if one has just one string of panels?
Klaus
 
Madness

Guru

Joined: 08/10/2011
Location: Australia
Posts: 2498
Posted: 09:31am 16 Dec 2017
Copy link to clipboard 
Print this post

Hi Tinker,

The GTI has 2 inputs each with its own MPPT circuitry, the maximum power either side can handle is 3500W. I have 2 strings of 2500W each giving a total of 5KW which is the maximum total output for the GTI.

It will work with one string but it is limited to the 3500W, the idea of being split into 2 is you can have each array in different conditions and it will get the most power from each string.

It has me baffled as to why the separation of the drains makes a difference but until I did this it would blow MOSFETs as soon as it starts regulating. At 100% on there was no issue, with only one string of panels connected it was fine, but with both connected it shorted out at least 1 MOSFET instantly when the PWM started.
There are only 10 types of people in the world: those who understand binary, and those who don't.
 
     Page 7 of 9    
Print this page
© JAQ Software 2024