Programming troubleshooting for Aruino Super-Cap testing apparatus. (ATX-PSU)

Hello Everyone,
My name is Ben.

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.

void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
int analogRead(A0);
}
void loop() {
int analogRead(A0);
Serial.println(A0);
delay(100);
digitalWrite(13, HIGH); 
delay(3000); 
digitalWrite(13, LOW); 
delay(1000); 
digitalWrite(12, HIGH); 
delay(3000); 
digitalWrite(12, LOW); 
delay(1000); }

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...

Thanks again everyone.

Peace.

Sincerely

Ben Komisar

several things at a time.

This will show how to do timing without using delay().

Hello groundfungus,
Thanks for the sharing that link. And I have looked over the example.

It is still eluding me, how to analog read and serialprint the analog A0 input pin while letting the PWM output pins do their thing.

I will keep trying to figure this out until I get it.

All I want is the 5V as a value between 0-1023. Then I can do all the math and energy density calculations on software on the computer.

Anywasys, thanks for the help, any and all help is greatly appreciated.

Peace

Sincerely
B

I tried this code out... It seems to work kind of for what I am going for.

void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
analogRead(A1);}

void loop() {
int sensorValue = analogRead(A1);
float voltage = sensorValue*(5.0/1023.0);
digitalWrite(13, HIGH);
delay(3000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(12, HIGH);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
Serial.println(analogRead(A1));
delay(250);
digitalWrite(12, LOW);
delay(1000);
}

im not sure what you are doing but the code you are using needs to be non blocking

look at the blink with out delay example.

also please learn how to post code correctly.

test this sketch. Its written to be readable so it does waste a lot of memory.

unsigned long lastPrintTime = 0;
unsigned long dischargeStartTime = 0;
unsigned long chargeStartTime = 0;
unsigned long pauseStartTime = 0;

unsigned long printInterval = 250; //1000ms to a second
unsigned long chargeTime = 3000;
unsigned long dischargeTime = 1000;
unsigned long pauseTime = 1000;
byte stage = 1;

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  int sensorValue = analogRead(A1);
  float voltage = sensorValue * (5.0 / 1023.0);

  //print results every 250ms
  if (currentMillis - lastPrintTime >= printInterval) {
    Serial.print("input raw ");
    Serial.print(sensorValue);
    Serial.print(" voltage ");
    Serial.print(voltage, 1);

    switch (stage) {
      case 1:
        Serial.println("  charge in progess");
        break;
      case 2:
        Serial.println("  full charge i guess paused");
        break;
      case 3:
        Serial.println("  discharge in progess");
        break;
      case 4:
        Serial.println("  fully discharged paused");
        break;
    }
    lastPrintTime = currentMillis;
  }


  //each stage when complete moves to the next stage
  //at the end of each stage the current time in millis is
  //recorded for the next stage

  if (stage == 1) {
    if (currentMillis - chargeStartTime >= chargeTime) {
      digitalWrite(13, LOW);
      stage = 2;
      pauseStartTime = currentMillis;
    }
    else {
      digitalWrite(13, HIGH);
    }
  }
  if (stage == 2) {
    if (currentMillis - pauseStartTime >= pauseTime) {
      stage = 3;
      dischargeStartTime = currentMillis;
    }
  }

  if (stage == 3) {
    if (currentMillis - dischargeStartTime >= dischargeTime) {
      digitalWrite(12, LOW);
      stage = 4;
      pauseStartTime = currentMillis;
    }
    else {
      digitalWrite(12, HIGH);
    }
  }
  if (stage == 4) {
    if (currentMillis - pauseStartTime >= pauseTime) {
      stage = 1;
      chargeStartTime = currentMillis;
    }
  }
}

I don't understand why you have the 330 ohm resistor in parallel with the LED! Should it not be in series?

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.

Diodes across the relay coils? Cathode to +.

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 :slight_smile:

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.

Hi All,

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:

  1. Charge the capacitor for 5 seconds then shut off charge for 1 sec .

  2. Begin discharge and stop at a time when the " if " conditions are met.

  3. Record time in milliseconds and analog voltage.

  4. 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().

Variable Scope

Hi,

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.

Here is what the serial print looks like:

(Millisec) (Voltage)

5999 1.99 (initial voltage volatage1)
6250 1.87
6501 1.85
6752 1.83
7003 1.81
7254 1.79
7503 1.77
7754 1.75
8005 1.73
8256 1.71
8507 1.70
8758 1.68
9009 1.66
9259 1.64

( appended to save space)

finally:

99036 0.00
99287 0.00
99537 0.00
0.30 Farads99788 0.00
100039 0.00
0.30 Farads100291 0.00
0.30 Farads100542 0.00
0.30 Farads100793 0.00
0.31 Farads101045 0.00
0.31 Farads101296 0.00
101547 0.00
0.31 Farads101798 0.00
0.31 Farads102049 0.00
0.31 Farads102300 0.00
0.31 Farads102552 0.00
0.31 Farads102803 0.00
0.31 Farads103055 0.00
0.31 Farads103306 0.00
0.31 Farads103557 0.00
0.31 Farads103809 0.00
0.31 Farads104059 0.00
0.32 Farads104311 0.00

(continues forever)

  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");
  }
}

Hi,

Here is the new code:

  #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:

(Millisec) (Voltage)
90008 0.01
90259 0.01
90510 0.01
90761 0.01
91012 0.00
91262 0.00
91512 0.00
91763 0.00
92014 0.00
92265 0.00
92516 0.00
92767 0.00
93018 0.00
93268 0.00
93519 0.00
93769 0.00
94020 0.00
94271 0.00
94522 0.00
94773 0.00
95024 0.00
95275 0.00
95525 0.00
95776 0.00
96026 0.00
96277 0.00
96528 0.00
48.26 Farads96780 0.00
97030 0.00
48.52 Farads97282 0.00
97532 0.00
48.77 Farads97783 0.00
48.89 Farads98034 0.00
49.02 Farads98286 0.00
49.14 Farads98537 0.00
49.27 Farads98789 0.00
49.39 Farads99040 0.00
49.52 Farads99291 0.00
49.65 Farads99543 0.00
49.77 Farads99793 0.00
49.90 Farads100045 0.00
50.02 Farads100296 0.00
50.15 Farads100547 0.00
50.27 Farads100799 0.00
50.40 Farads101050 0.00
50.53 Farads101302 0.00
50.65 Farads101553 0.00
50.78 Farads101805 0.00
50.90 Farads102055 0.00
51.03 Farads102306 0.00
51.15 Farads102558 0.00
51.28 Farads102809 0.00

( on and on, doesn't stop)

It does not stop reading time and voltage. The actual capacitor value is 10 farads.

Uploaded your new code which is this:

#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");
  }
}

Here is what it reads out now:

23554 0.79
23804 0.78
24055 0.77
24306 0.75
24557 0.74
24808 0.73
25058 0.72
25309 0.71
25560 0.70
12.78 Farads25811 0.70
26062 0.69
26312 0.68
26563 0.67
26814 0.66
27065 0.65
27316 0.64
27567 0.63
27817 0.63
28068 0.62
28319 0.61
28570 0.60
28820 0.59

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.