I am working on an Arduino based ATX-PSU Super-Capacitor Testing Apparatus.
I have most of the hardware roughly done.
Below is a pic of the apparatus so far and also attache is a hand drawn schematic.
Note: I meant to write Arduino PWM pin#13 on the hand-drawn schematic.
Ok so....
I want the code to drive the base of the 2n2222 high to charge the cap then drive low... Then I want the second transistor to be driven high to dump the energy stored in the cap across the LED and resistor...
I want to analog read the voltage across the cap 100% of the time.
I plan on doing the energy density calculations afterwards using the change in 67% of the charge voltage across a know resistance over time..
But for right now I just want to be able to get a digital readout of the changing voltage while the arduino simultaneously charges and discharges the cap via the PWM-Transistor- 12V Relay Combo.
Here is the code I am using so far.. It is working to charge and discharge the caps but the serial read only happens once per loop and I kind of need it happen continuously...
(I cannot wait to become more fluid with coding, I am Electronics Engineering Technologist program at Sheridan College, Brampton, Ontario, Canada... Next semester I take my first course in C coding...
I am really horrible at programming to date.
Anyways, I hope to hear from back from someone on this.
Any help would be greatly appreciated.
(P.S. The drawing is using a 22000uF cap and 3.3V from the ATX... I have ordered some buck converters and will be getting my 2V for the actual super-capacitor energy density tests in a couple of weeks... So the only difference in the end product will be that the cap will be a homemade super-capacitor (various types made from various recipes) and the voltage will be supplies from an adjustable buck converter bumping 12VDC down to 2VDC, also the LED in parallel with the load resistor will be removed. I will use an over-rated (5 watt or so) high precision resistor...
stowite:
I don't understand why you have the 330 ohm resistor in parallel with the LED! Should it not be in series?
The whole load circuit is wrong. First of all the LED needs a current limiting resistor. But it can't be in series with the 330 ohm because that is presumably the test load. The LED junction drop will not allow the cap to discharge properly. I would just remove the LED entirely.
aarg:
The whole load circuit is wrong. First of all the LED needs a current limiting resistor. But it can't be in series with the 330 ohm because that is presumably the test load. The LED junction drop will not allow the cap to discharge properly. I would just remove the LED entirely.
When the capacitor is not being charged, other than the Arduino input, there is no load so I assumed that the LED was there just to indicate the capacitor was being charged.
Hello Stowite,
Thank you for the response!
Yes the LED light was just in there as an indicator.
I am just responding to say thanks for the input and when I get a chance later on today I will thoroughly review the information you have shared.
Thanks a million.
(I have to go write an exam right now)
But after that I will be on this, the code you have written looks more along the lines of what I am trying to accomplish.
I will come back to this in a few hours.
Peace
Ben
Also,
In the final version, when load testing and data-logging the voltage drop over the resistor there will be no LED light in the load circuit.
The LED in parallel is just there to show that the circuit was working while I was running initial tests.
The final stage of the device will include a 12V - 2V DC-DC buck converter that will charge the home-made super caps to 2V then discharge them to below 0.66V.
These data-logged #s will be used for first figuring out capacitance calculations, then those #s will be used to figure energy density calculations. so... (67%V-drop) in seconds, time/resistance = capacitance
then use the capacitance calculation to figure out Joules/meterCubed.. Then we can know the energy density of various super-capacitor recipes.
It seems to be working out pretty good so far.
Anyways, thank you all so much for your help.
I really appreciate it.
I feel confident that I have enough arduino code figured out to log the data I require.
Peace,
Ben
BenKomisar:
The LED in parallel is just there to show that the circuit was working while I was running initial tests
For those tests, be aware that any readings you take at the analogue input will be affected by the presence of the LED if the voltage exceeds the Vf of the LED.
I built BenKomisar's capacitor testor circuit but I want to run the Arduino a little differently and calculate the value of the capacitor and serialprint it out.
Here is what I want it to do:
Charge the capacitor for 5 seconds then shut off charge for 1 sec .
Begin discharge and stop at a time when the " if " conditions are met.
Record time in milliseconds and analog voltage.
Record to memory the initial voltage as voltage1 and initial milliseconds as time1. These values will be used in calculations later in the sketch.
5 .Start the void loop and serial print out subsequent voltages and milliseconds recorded as voltage2 and time2. When the subsequent voltage2 is less than or equal to 36.8% of the initial "voltage1" break out of the loop and calculate the capacitance in farads which is (( time2 - time1 ) divided by 1000 ) divided by the load resistance in ohms which is 330 ohms. From Tau = RC , where Tau is the time in seconds when the voltage drops to 36.8% of the initial voltage1.
I have posted my sketch. When I compile I get a " 'voltage1' was not declared in this scope " error. I declared voltage1 before the loop. Why doesn't it see it? I am a newbie at this and I spent a lot of time searching online for examples to fiqure this out myself without success. I would appreciate any help on this.
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
unsigned long time;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
analogRead(A1);
digitalWrite(13, HIGH);
delay(5000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(12, HIGH);
int sensorValue1 = analogRead(A1);
float voltage1 = sensorValue1*(5.0/1023.0);
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage1);
float time1 = millis();
delay(250);
}
void loop() {
// put your main code here, to run repeatedly:
int sensorValue2 = analogRead(A1);
float voltage2 = sensorValue2*(5.0/1023.0);
float time2 = millis();
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage2);
float volt36_8 = voltage1*0.368;
delay(250);
if (voltage2 <= volt36_8)
{
float capvalue = ((time2 - time1) / 1000) / 330;
Serial.print(capvalue);
Serial.print(" ");
Serial.print("Farads");
}}
When I compile I get a " 'voltage1' was not declared in this scope " error. I declared voltage1 before the loop. Why doesn't it see it?
Because you declare voltage1 in setup(), it is local to setup and goes out of scope upon exit from setup(). Declare voltage1 outside of any function to make it global, then it will be visible everywhere in the sketch. Or declare voltage1 in loop(), then it is local to loop().
Thanks for the quick reply. I thought about putting it in the void loop but it can't go in there because I want the first voltage read to be recorded to memory as voltage1 which is the sensor value at time1. This value can't change because it is the initial voltage to be use later in the calculation of capacitance. If it is put in the loop it will change voltage1 to the current voltage which is constantly decreasing as the capacitor is discharging. Because " voltage1 = sensorValue1*(5.0/1023.0); ".
So declare voltage1 before setup() (make it global), read and record voltage1 in setup(). Voltage1 will not change until you change it.
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
unsigned long time;
float voltage1; // declare voltage1 as a global variable.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
analogRead(A1);
digitalWrite(13, HIGH);
delay(5000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(12, HIGH);
int sensorValue1 = analogRead(A1);
voltage1 = sensorValue1*(5.0/1023.0); // assign a value to voltage1
Thanks, that cleared up the declaration problem. I did not know you can declare variables globally.
It now prints the milliseconds time and decreasing voltage OK but there is something wrong now with the breaking of the loop with the "if" statement because in now it continues to record time and voltage, when the voltage is zero it prints the wrong capacitance in farads. It never stops recording time and voltage. It should stop recording when subsequent voltage readings " voltage2 "is <= 36.8% of voltage1.
float volt36_8 = voltage1*0.368;
delay(250);
if (voltage2 <= volt36_8 ) // print stuff if voltage2 is LESS THAN or equal to 36.8% of voltage1
{
float capvalue = ((time2 - time1) / 1000) / 330;
Serial.print(capvalue);
Serial.print(" ");
Serial.print("Farads");
}
So as long as voltage2 is less than 36.8%, print stuff. Once the cap is discharged the if will execute forever or until voltage2 increases above 38.6% (which will never happen). So tell the program to not continue after voltage2 is less than or equal to 38.6%. Declare a global flag (boolean doneFlag = false). Change the if so that once voltage2 drops below 38.6% to not execute any more by setting the flag.
You did not post your new code so I will show with the last code posted. You will have to reset the Arduino to do another cap.
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
unsigned long time;
float voltage1;
boolean doneFlag = false;
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
analogRead(A1);
digitalWrite(13, HIGH);
delay(5000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(12, HIGH);
int sensorValue1 = analogRead(A1);
voltage1 = sensorValue1*(5.0/1023.0);
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage1);
float time1 = millis();
delay(250);
}
void loop()
{
// put your main code here, to run repeatedly:
int sensorValue2 = analogRead(A1);
float voltage2 = sensorValue2*(5.0/1023.0);
float time2 = millis();
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage2);
float volt36_8 = voltage1*0.368;
delay(250);
if (voltage2 <= volt36_8 && doneFlag == false)
{
doneFlag = true; // voltage2 is less than 38.6% so don't do this any more
float capvalue = ((time2 - time1) / 1000) / 330;
Serial.print(capvalue);
Serial.print(" ");
Serial.print("Farads");
}
}
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
unsigned long time;
float voltage1; // declare voltage1 as a global variable.
float time1 = millis(); // declare time1 as a global variable.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
analogRead(A1);
digitalWrite(13, HIGH);
delay(5000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(12, HIGH);
int sensorValue1 = analogRead(A1);
float voltage1 = sensorValue1*(5.0/1023.0);
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage1);
delay(250);
}
void loop() {
// put your main code here, to run repeatedly:
int sensorValue2 = analogRead(A1);
float voltage2 = sensorValue2*(5.0/1023.0);
float time2 = millis();
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage2);
float volt36_8 = voltage1*0.368;
delay(250);
if (voltage2 <= volt36_8)
{
float capvalue = ((time2 - time1) / 1000) / 2;
Serial.print(capvalue);
Serial.print(" ");
Serial.print("Farads");
}}
Here is what it is printing out towards the end and not stopping:
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
unsigned long time;
float voltage1;
float time1;
boolean doneFlag = false;
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
analogRead(A1);
digitalWrite(13, HIGH);
delay(5000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(12, HIGH);
int sensorValue1 = analogRead(A1);
voltage1 = sensorValue1*(5.0/1023.0);
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage1);
float time1 = millis();
delay(250);
}
void loop()
{
// put your main code here, to run repeatedly:
int sensorValue2 = analogRead(A1);
float voltage2 = sensorValue2*(5.0/1023.0);
float time2 = millis();
Serial.print(millis()); //prints time since program started
Serial.print(" ");
Serial.println(voltage2);
float volt36_8 = voltage1*0.368;
delay(250);
if (voltage2 <= volt36_8 && doneFlag == false)
{
doneFlag = true; // voltage2 is less than 38.6% so don't do this any more
float capvalue = ((time2 - time1) / 1000) / 2;
Serial.print(capvalue);
Serial.print(" ");
Serial.print("Farads");
}
}
I calculate from the voltage at 25811 milliseconds ( 0.70 volts) " 9.90 farads" and the sketch calulated it as "12.78 farads" which is close but off more than it should be.