I've been googling my head off trying to get this sketch to work, but thus far I'm having no luck.
one particular part of my sketch is acting up but the rest seems to work as expected. I've snipped out the relevant pieces of code here.
The expected behavior is that if the measured voltage is above the upper threshold, the variable ADJ_STATE will iterate UP until it's within range, and if below the lower threshold, will iterate DOWN til within range. If the range limits are reached it'll go into an error state and blink a feedback led.
The actual behavior is that despite being out of range (in either direction) the ADJ_STATE variable never is changed, and always stays at 0 or whatever I set it to during setup for testing purposes. To clarify, the function for checking the reference voltages are returning correct values.
Any help would be appreciated!
float senseHighThrs = 2.47; // Upper threshold voltage of circuit before adjustment
float senseLowThrs = 1.90; // Lower threshold voltage of circuit before adjustment
volatile int ADJ_STATE = 0; // Variable for voltage adjustment state
int folRead = 0;
float VRef = 0.00; // variable to store the value read from the reference voltage
int vadjRead = 0;
float VAdj = 0.00;
float diffAdjL = 0.00;
float diffAdjH = 0.00;
void setup() {
pinMode(V_FOLLOW_PIN, INPUT);
pinMode(VADJ_SENSE_PIN, INPUT);
Serial.begin(9600);
Serial.println("Initializing...");
}
void adjustState() {
if ( diffAdjL > 0) {
ADJ_STATE = ++ADJ_STATE;
}
if ( diffAdjH > 0) {
ADJ_STATE = --ADJ_STATE;
}
}
void loop() {
// Blink LED's on init
if (BlinkCount > 0) {
BlinkState = !BlinkState;
digitalWrite(ERR_LED, BlinkState);
digitalWrite(TRG_OUT, BlinkState);
delay(150);
BlinkCount = --BlinkCount;
}
// Check voltage of first and second stages and compare against thresholds
folRead = analogRead(V_FOLLOW_PIN);
VRef = folRead * (5.0 / 1023.0);
vadjRead = analogRead(VADJ_SENSE_PIN);
VAdj = vadjRead * (5.0 / 1023.0);
float diffAdjL = VAdj - senseLowThrs;
float diffAdjH = senseHighThrs - VAdj;
// Voltage state adjustment
adjustState();
// Voltage divider adjustment
adjustVoltage();
// Check for error state
checkError();
Serial.print("Voltage Reference:");
Serial.println(VRef);
Serial.print("Amp Sense:");
Serial.println(VAdj);
Serial.print("Adjustment State:");
Serial.println(ADJ_STATE);
Serial.print("Low Diff:");
Serial.println(diffAdjL);
Serial.print("High Diff:");
Serial.println(diffAdjH);
delay(150);
}
Sadly that syntax had no effect. Still acts the same. I'm trying not to post the entire sketch before I have a github repository up and a few of these kinks ironed out, but would it help to see the whole thing?
It would be best to post an MCVE. That's the smallest code that actually compiles and demonstrates the problem. It should include nothing unrelated to the problem.
float senseHighThrs = 2.47; // Upper threshold voltage of circuit before adjustment
float senseLowThrs = 1.90; // Lower threshold voltage of circuit before adjustment
volatile int ADJ_STATE = 0; // Variable for voltage adjustment state
//int ADJ_STATE = 0; // Variable for voltage adjustment state
int folRead = 0;
float VRef = 0.00; // variable to store the value read from the reference voltage
int vadjRead = 0;
float VAdj = 0.00;
float diffAdjL = 0.00;
float diffAdjH = 0.00;
void setup()
{
// pinMode(V_FOLLOW_PIN, INPUT);
// pinMode(VADJ_SENSE_PIN, INPUT);
Serial.begin(9600);
while(!Serial);
Serial.println("Initializing...");
}
void adjustState() {
if ( diffAdjL > 0.0)
{
ADJ_STATE++;
}
if ( diffAdjH > 0.0) {
ADJ_STATE--;
}
}
void loop() {
#if 0
// Blink LED's on init
if (BlinkCount > 0) {
BlinkState = !BlinkState;
digitalWrite(ERR_LED, BlinkState);
digitalWrite(TRG_OUT, BlinkState);
delay(150);
BlinkCount = --BlinkCount;
}
// Check voltage of first and second stages and compare against thresholds
folRead = analogRead(V_FOLLOW_PIN);
VRef = folRead * (5.0 / 1023.0);
vadjRead = analogRead(VADJ_SENSE_PIN);
VAdj = vadjRead * (5.0 / 1023.0);
float diffAdjL = VAdj - senseLowThrs;
float diffAdjH = senseHighThrs - VAdj;
#endif
VRef = 1023 * (5.0 / 1023.0);
VAdj = 984 * (5.0 / 1023.0);
diffAdjL = VAdj - senseLowThrs;
diffAdjH = senseHighThrs - VAdj;
// Voltage state adjustment
adjustState();
// Voltage divider adjustment
//adjustVoltage();
// Check for error state
//checkError();
Serial.print("Voltage Reference:");
Serial.println(VRef);
Serial.print("Amp Sense:");
Serial.println(VAdj);
Serial.print("Adjustment State:");
Serial.println(ADJ_STATE);
Serial.print("Low Diff:");
Serial.println(diffAdjL);
Serial.print("High Diff:");
Serial.println(diffAdjH);
delay(1000);
}
ADJ_STATE increases as expected.
I had to comment-out/disable code because I don't have the same connections, external setup etc, not to mention I don't see "adjustVoltage()". There might be something going on in the disabled code or in adjustVoltage that's zeroing out ADJ_STATE before you print it.
Try adding a print of ADJ_STATE before adjustVoltage(), just for poops and giggles.
Ok yeah definitely something in the adjustVoltage() function is causing it. If I comment that function, it iterates properly. With it uncommented and a second print stuck inside the adjustState() function, I get 1 on the function, and 0 on the output at the bottom.
So yeah that's somewhere for me to start!
Edit: Ok so there's really not much to this function, so i can't figure out what exactly is pissing it off. Funny thing is I added a serial print to that function and it's not outputting anything. So it's like that function is just zeroing out the variable and not doing what I've programmed.
Anyhoo, here's the function with the serial print output tacked on:
What exactly is the purpose of your adjustment? Could you tell a little more about the background? I feel like the code, especially your adjustVoltage function, needs a lot of refactoring.
For example, if your ADJ_STATE = 5, the adjust function will hit all these if-blocks. They will all evaluate to true, so all are executed. Is this intended?
if (ADJ_STATE > 0) {
}
if (ADJ_STATE > 1) {
}
if (ADJ_STATE > 2) {
}
if (ADJ_STATE > 3) {
}
if (ADJ_STATE > 4) {
}
pyr0ball:
Since it's a float, the math comes out the same either way.
Try plugging it into a scientific calculator
It does make a difference (about 4% for 10000 for example).
pyr0ball:
Since it's a float, the math comes out the same either way.
Try plugging it into a scientific calculator
First of all, a scientific calculator is better at math than an Arduino. That's why in most cases it's better to avoid it all together. Float != just a decimal point.
Second, spot the more significant change beside losing the brackets
LightuC:
What exactly is the purpose of your adjustment? Could you tell a little more about the background? I feel like the code, especially your adjustVoltage function, needs a lot of refactoring.
For example, if your ADJ_STATE = 5, the adjust function will hit all these if-blocks. They will all evaluate to true, so all are executed. Is this intended?]
Yes that's intended.
The important part of that section is that the error state is tripped when the ADJ_STATE is lower than 0 or higher than 4.
More accurately, the lower states become irrelevant as they get superceded by the next highest one. It seemed cleaner to code it that way rather than calling out each specific state.
How this is being utilized is basically as a coarse digipot in a voltage divider that effects the reading of VADJ_SENSE_PIN. As each pin is pulled low by the controller, it essentially connects to ground, changing the effective value of the resistor connected to ground.
I'm on a phone at the moment but I can upload a schematic that shows a bit more what it's doing when I get back in front of a PC
If ADJ_STATE > 1 for example, you first enter the ADJ_STATE > 0 block. In there, you put your VADJ_R2 to INPUT. Then the block exists, directly entering the next ADJ_STATE > 1 block.
In here you directly redefine your VADJ_R2 pin to OUTPUT. This doesn't make to much sense for me. Why not use if/else if and skip the unnecessary cases?
pyr0ball:
How this is being utilized is basically as a coarse digipot in a voltage divider that effects the reading of VADJ_SENSE_PIN. As each pin is pulled low by the controller, it essentially connects to ground, changing the effective value of the resistor connected to ground.
Okay, so you get some kind of input and based on that you change your output resistors value. And what exactly is the purpose of iterating the ADJ_STATE variable? Why not directly switch the resistors based on the input? You might also want to take a look at digital potentiometer ic's, there are plenty ready to be used on the breadboard.
AWOL:
Nope.
(Time for you to get a better scientific calculator)
I think Septillion is more on point about this. Here's where I was making that assumption from:
^ screenshot from the scientific function on windows' calculator shows exactly the same value in either instance.
LightuC:
In here you directly redefine your VADJ_R2 pin to OUTPUT. This doesn't make to much sense for me. Why not use if/else if and skip the unnecessary cases?
Redefining it as an output is necessary as it's defined as an input during the setup phase. I do this to turn it into a "disconnected" pin. If I left it as an output but pulled it high, it would not have the intended effect. I need the pin to either be "disconnected" by redefining it as an Input or pulled low by redefining it as an output and setting it to LOW.
LightuC:
Okay, so you get some kind of input and based on that you change your output resistors value. And what exactly is the purpose of iterating the ADJ_STATE variable? Why not directly switch the resistors based on the input? You might also want to take a look at digital potentiometer ic's, there are plenty ready to be used on the breadboard.
Digital potentiometers are expensive as all getout when compared with 4x resistors, and the circuit needs to be self-adjusting without external input. I've got it designed down to a pretty decently narrow range that I should be able to account for with the 5 effective voltage divider values I've set here. Also before you ask, the same reason is why I'm using the arduino's digital pins as gates rather than including transistors. I've got a very limited amount of space to work with as an additional factor.
As to why I need to iterate them rather than directly switch, the voltage could be different depending on oodles of different conditions, and I won't know exactly how much adjustment is needed in either direction until the circuit is active. Incrementing/decrementing is the best way I could think of to programmatically/automatically adjust the circuit.
Here's the portion of the schematic that this is dealing with:
pyr0ball:
Redefining it as an output is necessary as it's defined as an input during the setup phase. I do this to turn it into a "disconnected" pin. If I left it as an output but pulled it high, it would not have the intended effect. I need the pin to either be "disconnected" by redefining it as an Input or pulled low by redefining it as an output and setting it to LOW.
Fair enough, but it doesn't make sense to set it as an input and some 5-10 clock cycle later set it as an output. Why not set it directly to output?
pyr0ball:
As to why I need to iterate them rather than directly switch, the voltage could be different depending on oodles of different conditions, and I won't know exactly how much adjustment is needed in either direction until the circuit is active. Incrementing/decrementing is the best way I could think of to programmatically/automatically adjust the circuit.
So you use your resitor ladder to generate a certain voltage between 0 and 5 volts? You could use the analogWrite function of the arduino, combined with a properly sized low pass filter at the output. This will also reduce your footprint.
I don't know what is connected to your ladder's output, but if it has a fixed input impedance, the voltages you produce are constant. Furthermore, if VADJ_R0 is low, the other pins won't have any effect anyways.