Hello World!
I've written a little code that would mimic a leaky integrator, however, there are several problems when I run it.
First, in one of the sub if loops i try to compute vout using this function, vout = vout * (exp(-time/tao)). The function returns a vout = nan (not a number). However, this function should decay to zero as t-> infinity.
The next problem is computing vout in using vout = vin* (1-exp(-time/tao)). My trial input voltage is roughly 5V and my tao is 5.10389. However, according to my serial print this gives a result of infinity.
Looking at my serial print, time is also not increasing.
Below is what my serial readout is repeating over and over again.
Any ideal would be greatly appreciated!
vout_int: vin_int: time_int:
inf ---------4.9951 ---------2230 ---------
vout_int: vin_int: time_int:
inf ---------4.9951 ---------2230 ---------
vout_int: vin_int: time_int:
inf ---------4.9951 ---------2230 ---------
// Libraries
#include <math.h>
// Initializing Pin layout
const int vinPin = 0; // pin that the sensor is attached to
const int resetPin = 2; // pin the pushbutton is attached to
const int inhibitPin = 3; // pin that trips relay
// Variable declaration
unsigned long time; // creates a time variable
int reset;
int inhibit;
float vin; // variable for input voltage
float vout; // variable for output voltages
// Constants
const int vthresh = 1; // threshold voltage at which the circuit trips the relay
const int gain = 1; // unity gain of the AD620
const float tao = 5.10389; // rc time constant
const float rsense = 0.5; // resistance of the sense resistor
void setup()
{
Serial.begin(9600);
Serial.println("start");
// Defines pin asinput or output
pinMode(vinPin, INPUT);
pinMode(resetPin, INPUT);
pinMode(inhibitPin, OUTPUT);
vin = 0; // initial input voltage is 0
vout = 0; // initial output voltage is 0
digitalWrite(inhibitPin, HIGH);
}
void loop()
{
// Reads the value of switch
reset = digitalRead(resetPin);
// Looks to see if switch has been pressed
if(reset == HIGH)
{
// Begins counting up every microsecond
time = micros();
// Sets inhibit value to LOW
digitalWrite(inhibitPin, LOW);
while(vout < vthresh)
{
vin = getVoltage(vinPin); // reads voltage from the inputPin
if(vin == 0)
{
vout = vout * exp(-time/tao);
Serial.println("\nvout_decay:\ttime_decay:\ttao_decay:");
Serial.println("---------------------------------------------");
Serial.print(vout, 4);
Serial.print("\t");
Serial.print(time, 4);
Serial.print("\t");
Serial.print(tao, 4);
Serial.println("\t");
if(vout < 0)
{
vout = 0;
}
}
else
{
vout = vin * (1 - exp(-time/tao));
Serial.println("\nvout_int:\tvin_int:\ttime_int:");
Serial.println("---------------------------------------------");
Serial.print(vout, 4);
Serial.print("\t---------");
Serial.print(vin, 4);
Serial.print("\t---------");
Serial.print(time, 4);
Serial.println("\t---------");
}
}
digitalWrite(inhibitPin, HIGH);
}
else
{
digitalWrite(inhibitPin, HIGH);
}
}
// Function Declaration-----------------------------------------------------------------
float getVoltage(int pin)
{
return (analogRead(pin) * 0.004882814);
// This equation converts the 0 to 1023 value that analogRead()
// returns, into a 0.0 to 5.0 value that is the true voltage
// being read at that pin.
}
I'm too lazy to work out what you're trying to do with vin and vout there. If you're having trouble with time-based arithmetic, it would be simpler to investigate if you just write a minimal sketch to evaluate the arithmetic. For example, you could print out time, time/tao, exp(time/tao) to make sure these expressions are evaluating as you expect before you try to use them in your integrator.
One problem is that you are mixing float and integer types in ways that likely discard precision. Make sure all the numeric constants are 1.0, not just 1. vthresh should be "const float vthresh = 1.0", for example. Mixing float and int without careful attention can easily lead to strange results.
Thanks for the recommendations. That fixed one problem.
Do have a recommendation on how to increment time? time = micros(); does not change in time, so when i feed it into both vout equations i get back a the same number.
vout = vin * (1 - exp(-time/tao));
looks like it contains a long int divided by a float, which is a mistake.
do your
time=micros() at the different times before calling your line to get different values of
vout = vin * (1 - exp(-(float)time/tao));
Some people might emphasise two different long int time values by naming them differently.
For example, I'll declare long ut1; long ut2; and use those to hold two different outputs of micros().
Thanks AD2049Q for the replay.
I incorporated what I believed you meant with respect to implementing time.
It does indeed count up, however I am still having the problem with the variable declaration to calculate the exponential properly. Do you have any recommendations?
Overall Code with changes in how time is implemented
// Libraries
#include <math.h>
// Initializing Pin layout
const int vinPin = 0; // pin that the sensor is attached to
const int resetPin = 2; // pin the pushbutton is attached to
const int inhibitPin = 3; // pin that trips relay
// Variable declaration
unsigned long ut1; // creates time variable 1
unsigned long ut2; // creates time variable 2
int reset;
int inhibit;
float vin; // variable for input voltage
float vout; // variable for output voltages
// Constants
const float vthresh = 1.0; // threshold voltage at which the circuit trips the relay
const float gain = 1.0; // unity gain of the AD620
const float tao = 5.10389; // rc time constant
const float rsense = 0.5; // resistance of the sense resistor
void setup()
{
Serial.begin(9600);
Serial.println("start");
// Defines pin asinput or output
pinMode(vinPin, INPUT);
pinMode(resetPin, INPUT);
pinMode(inhibitPin, OUTPUT);
vin = 0.0; // initial input voltage is 0
vout = 0.0; // initial output voltage is 0
digitalWrite(inhibitPin, HIGH);
}
void loop()
{
// Reads the value of switch
reset = digitalRead(resetPin);
// Looks to see if switch has been pressed
if(reset == HIGH)
{
// Sets inhibit value to LOW
digitalWrite(inhibitPin, LOW);
while(vout < vthresh)
{
vin = getVoltage(vinPin); // reads voltage from the inputPin
if(vin == 0)
{
ut1 = micros();
float par1 = ut1 / tao;
vout = vout * exp(-par1);
Serial.println("\nvout_decay:\ttime_decay:\ttao_decay:");
Serial.println("---------------------------------------------");
Serial.print(vout, 4);
Serial.print("\t");
Serial.print(ut1, 4);
Serial.print("\t");
Serial.print(tao, 4);
Serial.println("\t");
if(vout < 0)
{
vout = 0;
}
}
else
{
ut2 = micros();
float par2 = ut2 / tao;
vout = vin * (1 - exp(-par2));
Serial.println("\nvout_int:\tvin_int:\ttime_int:");
Serial.println("---------------------------------------------");
Serial.print(vout, 4);
Serial.print("\t---------");
Serial.print(vin, 4);
Serial.print("\t---------");
Serial.print(ut2, 4);
Serial.println("\t---------");
}
}
digitalWrite(inhibitPin, HIGH);
}
else
{
digitalWrite(inhibitPin, HIGH);
}
}
// Function Declaration-----------------------------------------------------------------
float getVoltage(int pin)
{
return (analogRead(pin) * 0.004882814);
// This equation converts the 0 to 1023 value that analogRead()
// returns, into a 0.0 to 5.0 value that is the true voltage
// being read at that pin.
}