Recently I have been exploring the possibility of powering projects with solar and a supercap, followed by a 3.3volt micro-power boost converter.
I already had 100F Samwha GreenCaps, but I needed to bridge longer after dark/rainy days, so I ordered a 10-pack of 500F Samwha GreenCaps from ebay.
Most of them lasted shorter than the 100F caps I already had.
Wanted to understand, so I added some resistors on top of an Uno and wrote a sketch to test leakage (which can be significant) and value of the caps.
Disapponting results (some tested as low as 50F), until I got some 400F AVX caps.
They had lower leakage than any of the Samwha caps, and were close to their rated value.
Sketch attached, so you can try yourself.
Charging and soak times mimic real-world solar charging, not the unrealistic (72-hour) leak test from the datasheets.
For consistent (leakage) results you should pre-charge the cap to 1volt on a power supply for a day.
Or run the test the next day (the end of the sketch leaves the cap at ~1volt).
Leo..
/* Arduino Uno
12x 330 ohm from pin 2-13 to a star point
330 ohm from A0 to star point
6k8 between Aref pin and 3.3volt pin, to create a 2.7volt Aref, ! measure it !
1N4004 diode (protection) between star point and 5volt, cathode (ring) to 5volt
supercap connected to star point (+) and two ground pins (-)
*/
const float Aref = 2.71;
const unsigned long soakDuration = 10800000; // milliseconds (3 hours)
const unsigned long selfDischargeDuration = 14400000; // (4 hours)
const unsigned long interval = 300000; // minimum interval (5 minutes)
const byte firstPin = 2, lastPin = 13, measurePin = A0; // 12 charge/discharge pins
unsigned long startMillis, stopMillis, voltMillis, soakMillis; // timing
float volt, prevVolt, leakage, capValue, capCal = 0.000048; // calibration factor
void voltage() { // print periodically while waiting
if (millis() - voltMillis > interval) {
volt = trunc(analogRead(measurePin) * Aref / 1024 * 100) / 100; // truncated to two decimal places
if (volt != prevVolt) { // only print changes
Serial.print(volt);
Serial.println(" volt");
prevVolt = volt;
}
voltMillis = millis();
}
}
void charge() {
for (byte i = firstPin; i <= lastPin; i++) {
pinMode(i, OUTPUT);
digitalWrite(i, HIGH);
}
}
void discharge() {
for (byte i = firstPin; i <= lastPin; i++) {
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
}
}
void floating() {
for (byte i = firstPin; i <= lastPin; i++) {
pinMode(i, INPUT);
digitalWrite(i, LOW); // make sure pull up is off
}
}
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL); // switch to 2.7 volt Aref
if (analogRead(measurePin) == 1023) Serial.println(F("Connect cap\n"));
while (analogRead(measurePin) == 1023);
Serial.println(F("Supercapacitor evaluation"));
for (byte i = 0; i < 25; i++) Serial.print(F("="));
Serial.print(F("\nSelf-discharge and value test\nInitial charge: "));
delay(5000); // time to properly connect cap
Serial.print(analogRead(measurePin) * Aref / 1024);
voltMillis = millis();
Serial.println(F(" volt\nCharging to 2.7 volt"));
charge();
while (analogRead(measurePin) < 1023) voltage();
Serial.println(F("Timed hold at 2.7 volt"));
soakMillis = millis(); // mark
while (millis() - soakMillis < soakDuration) {
if (analogRead(measurePin) < 1023) charge();
else floating();
voltage();
}
floating();
Serial.println(F("Self-discharge test"));
soakMillis = millis(); // mark
while (millis() - soakMillis < selfDischargeDuration) voltage();
Serial.print(F("Self-discharge: "));
leakage = ((1023 - analogRead(measurePin)) * Aref / 1024) / (selfDischargeDuration / 1000000000.); // (dV / dt)
Serial.print(leakage, 1);
Serial.println(F(" uA/F (should be ≤2.5uA/F)"));
if (analogRead(measurePin) < 2.2 * 1024 / Aref) {
Serial.println("Excessive leakage\nRe-charging to 2.2volt");
charge();
while (analogRead(measurePin) < 2.2 * 1024 / Aref) voltage();
}
Serial.println(F("Value test\nDischarging to 1 volt"));
discharge();
while (analogRead(measurePin) > 2 * 1024 / Aref) voltage();
startMillis = millis(); // 2 volt mark
Serial.println(F("Measurement startpoint"));
while (analogRead(measurePin) > 1024 / Aref) voltage();
stopMillis = millis(); // 1 volt mark
floating();
capValue = (stopMillis - startMillis) * capCal;
for (byte i = 0; i < 33; i++) Serial.print(F("="));
Serial.print(F("\nCapacitor value: "));
Serial.print(capValue, 0);
Serial.print(F(" Farad\nSelf-discharge: "));
Serial.print(leakage, 1);
Serial.print(F(" uA/F\nCapacitor self-discharge: "));
Serial.print(leakage * capValue, 0);
Serial.println(F(" uA"));
for (byte i = 0; i < 33; i++) Serial.print(F("="));
Serial.println("");
}
void loop() {
}