Bridge auto tune

Hi
I am working on Wheatstone bridge, on the left side is a photoresistor , exposed to daylight, on right side is a photocoupler.
Brightness of the photo diode is regulated by 2 buttons to balance the bridge.
I want to replace 2 buttons by 1 button, when I press it the bridge should auto tune to minimum voltage of the bridge = currentValue.
This is what I did and error.
Can you help me ?

HardwareTimer pwmtimer4(4);// pulse duty =i
int i;
int ovfi;
int volt;
int Value;
int currentValue;
int previousValue;
int maxValue = 0; // store max value here
int minValue = 1024; // store min value here

#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);

void setup() {
//////////////////////
pwmtimer4.pause();
pwmtimer4.setPrescaleFactor(3);
pwmtimer4.setOverflow(2000);
//pwmtimer4.setCompare(TIMER_CH2, 2880);
pwmtimer4.refresh();
pwmtimer4.resume();
/////////////////////
pinMode(PB0, INPUT_ANALOG);
pinMode(PB9, INPUT_PULLDOWN);
lcd.begin(16, 2);
}
void loop()
{
float volt = analogRead(PB0);
volt = (volt * 3.3) / 4095.0;

ovfi = 3000 - i;
pwmtimer4.setCompare(TIMER_CH2, i); // PWM High Pulse width
/*
///////////////////////
if (digitalRead(PB9) == HIGH)
{
if (i < 3000)
{
i++;
}
}
if (digitalRead(PB6) == HIGH)
{
if (i > 0)
{
i–;
}
}
///////////////////////////
*/
previousValue = currentValue; // store what was read last time
currentValue = analogRead(PB0); // get a new reading

if (digitalRead(PB9) == HIGH)
{
//if (i < 3000)
if (previousValue > currentValue) = 1 // if = true = ++ , if false = –
{
i++;
}
else
{
i–;
}

///////////////////////////////
if (currentValue = minValue)
{
  currentValue  = minValue;
}
break; // stop changing "i" at minimum of currentValue

}

////////////////////////////////

lcd.clear();
lcd.setCursor(0, 0);
lcd.print(volt);
lcd.setCursor(0, 1);
lcd.print( Value);
delay(100);
}

The error
tuning:59:39: error: expected primary-expression before ‘=’ token

 if (previousValue > currentValue) = 1 // if = true = ++ , if false  = --

                                   ^

tuning:73:5: error: break statement not within loop or switch

 break;

 ^~~~~

exit status 1
expected primary-expression before ‘=’ token

The compiler doesn’t know what you intend by if (previousValue > currentValue) = 1
You are comparing two values which will be true (1) or false (0) then assigning that compare the value of 1. Essentially you dont need the =1
if (previousValue > currentValue)

break; needs to be inside the if loop. ie before the } bracket.

Also if (currentValue = minValue) is assigning minValue to currentvalue you need to use ==

Regards
Jim

I marked the brackets for “if” and break is inside of them.

if (digitalRead(PB9) == HIGH)

{ // start if loop

//if (i < 3000)
if (previousValue > currentValue) // if = true = ++ , if false = –
{
i++;
}
else
{
i–;
}

///////////////////////////////
if (currentValue = minValue)
{
  currentValue == minValue;
   break; // stop changing "i" at minimum of currentValue
}

// break; // stop changing “i” at minimum of currentValue

} // end of if loop

error: break statement not within loop or switch

    break; // stop changing "i" at minimum of currentValue

exit status 1
break statement not within loop or switch

Sorry, didn’t read your code closely enough with respect to the use of break;
The compiler is correct; break; can only used in while, for and switch statements.

If you want the code to stop changing i when the values are the same, place a while loop around the if statement.

while (currentValue != minValue)                   // not equal
{  
  if (previousValue > currentValue)               // if = true = ++ , if false = –
    {
        i++;
    }
    else
    {
        i–-;
    }
}

The while loop will be executed as long as currentValue is not equal to minValue, when they are equal the while loop will be ignored. The other code in void loop() will still be executed.

Note: the following code is not needed. Also the == and = were around the wrong way. Below is the correct way.

if (currentValue == minValue)
{
  currentValue  = minValue;
}

Thanks again.
That was the question which I intended to ask.
Now I going to build the circuit and test your code.

This is updated code.
No reaction to the button, when I disable " if (digitalRead(PB9) == HIGH)" the LCD is blank .

HardwareTimer pwmtimer4(4);// pulse duty =i
int i;
int ovfi;
int volt;
int Value;
int currentValue;
int previousValue;
int maxValue = 0; // store max value here
int minValue = 4095.0; // store min value here

#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);

void setup() {

pwmtimer4.pause();
pwmtimer4.setPrescaleFactor(3);
pwmtimer4.setOverflow(2000);
//pwmtimer4.setCompare(TIMER_CH2, 2880);
pwmtimer4.refresh();
pwmtimer4.resume();

pinMode(PB7, PWM); //duty regulated for balance
pinMode(PB0, INPUT_ANALOG);
pinMode(PB6, INPUT_PULLDOWN);
pinMode(PB9, INPUT_PULLDOWN);
lcd.begin(16, 2);
}
void loop()
{
float volt = analogRead(PB0);
volt = (volt * 3.3) / 4095.0;

ovfi = 3000 - i;
pwmtimer4.setCompare(TIMER_CH2, i); // PWM High Pulse width

previousValue = currentValue; // store what was read last time
currentValue = analogRead(PB0); // get a new reading
//////////////////////////
if (digitalRead(PB9) == HIGH)

while (currentValue != minValue)                   // not equal
{
  if (previousValue > currentValue)               // if = true = ++ , if false = –
  {
    i++;
  }
  else
  {
   i --;
  }
}

////////////////////////

//lcd.clear();
lcd.setCursor(0, 0);
lcd.print(volt);

lcd.setCursor(0, 1);
lcd.print( currentValue);
//lcd.print( minValue);
lcd.setCursor(8, 1);
lcd.print( i);
//delay(100);
}

I did this way

previousIrms = currentIrms; // store what was read last time
currentIrms = analogRead(PA7); // get a new reading

////////////////////////
while ((digitalRead(PB9) == HIGH) && currentIrms!= minIrms)
{
if (previousIrms < currentIrms) // if = true = ++ , if false = –-
{
i++;
}
// else
if (previousIrms > currentIrms)
{
i --;
}
break; // stop tuning at min Irms
}
/////////////////////////////

I changed DC voltmeter to AC voltmeter so the name Value is now Irms.
It is almost working, the problem is that While loop is not stopping running at minimum of Irms.
The “break” function is not working as expected.

Yes … The while loop will continue forever as the condition will always be true. (in my example, my error) The original error was break; being used where it was not expected by the compiler. Hence an example while statement.

I did what I should have done originally and copied your code into my Ardunio IDE, it allows me to better understand the code. It didn’t compile because PB0 and pwmtimer are not defined for the UNO, but that doesn’t matter.

I think the solution is to use an if statement for currentValue != minValue. That way the if statement will only execute if they are not the same. The rest of the loop() will run as normal. Using a while loop only confused things, sorry.

void loop()
{
  float volt = analogRead(PB0);
  volt = (volt * 3.3) / 4095.0;
  ovfi = 3000 - i;
  pwmtimer4.setCompare(TIMER_CH2, i); // PWM High Pulse width
  previousValue = currentValue; // store what was read last time
  currentValue = analogRead(PB0); // get a new reading
  if (digitalRead(PB9) == HIGH) {
    if (currentValue != minValue) {
      if (previousValue > currentValue) {
        i++;
      } else {
        i--;
      }
    }
  }
  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(volt);

  lcd.setCursor(0, 1);
  lcd.print( currentValue);
  //lcd.print( minValue);
  lcd.setCursor(8, 1);
  lcd.print( i);
  //delay(100);
}

By the way it is best practice to initialize variables when you declare them. The first time i is used in the void loop() but it is not initialized. With the ATMega this is not a problem as memory is cleared on power up, not always the case with other processors.

int i = 0;
int ovfi = 0;
int volt = 0;
int Value = 0;
int currentValue = 0;
int previousValue = 0;

Thanks for explanation, I will try this.
I am using stm32f103, to use this code for Uno in most cases it is enough to change the name of the pins, change PB0 to A0.

In this case may not work because timer setup in UNO is done in different way .

I reversed "i++ and i-- " because I received negative “i”
The tuning do not stop at minimum.
I tried change the name “Value” to “Irms” because for AC voltmeter it is the signal from bridge to pin PA7. The reason for changing to AC is that mimimum is around 0 V , for DC is - 3V…

HardwareTimer pwmtimer4(4);// pulse duty =i
#include “EmonLib.h”
#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);
EnergyMonitor emon1;

float cur, acur[50], sumc;

///////////////////
int i = 0;
int ovfi = 0;
int volt = 0;
int Value = 0;
int currentValue = 0;
int previousValue = 0;
int minValue = 0;
int (Irms) = 0;
int currentIrms = 0;
int previousIrms;
int maxIrms = 0; // store max value here
int minIrms = 4095.0;
//////////////////
/*
int i;
int ovfi;

int (Irms);
int currentIrms;
int previousIrms;
int maxIrms = 0; // store max value here
int minIrms = 4095.0;
*/
void setup()
{
pwmtimer4.pause();
pwmtimer4.setPrescaleFactor(3);
pwmtimer4.setOverflow(2000);
//pwmtimer4.setCompare(TIMER_CH2, 2880);
pwmtimer4.refresh();
pwmtimer4.resume();

pinMode(PB7, PWM); //duty regulated for balance
pinMode(PB0, INPUT_ANALOG);
pinMode(PB6, INPUT_PULLDOWN);
pinMode(PB9, INPUT_PULLDOWN);
pinMode(PA7, INPUT); // Irms
lcd.begin(16, 2);

emon1.current(PA7, 2.8);
}

void loop()
{
/////////////////////////////////
/*
ovfi = 3000 - i;
pwmtimer4.setCompare(TIMER_CH2, i); // PWM High Pulse width
previousIrms = currentIrms; // store what was read last time
currentIrms = analogRead(PA7); // get a new reading

if (digitalRead(PB9) == HIGH) {
if (currentIrms != minIrms) {
  if (previousIrms > currentIrms)

*/
///////////////////////////////////
ovfi = 3000 - i;
pwmtimer4.setCompare(TIMER_CH2, i); // PWM High Pulse width
previousValue = currentValue; // store what was read last time
currentValue = analogRead(PA7); // get a new reading

if (digitalRead(PB9) == HIGH) {
if (currentValue != minValue) {
if (previousValue > currentValue)
{
i–;
}
else
{ i ++;
}
}
}

lcd.setCursor(0, 1);
lcd.print( currentIrms);
//lcd.print( minValue);
lcd.setCursor(8, 1);
lcd.print( i);
//delay(100);

emon1.calcVI(20, 2);
float Irms = emon1.Irms;
lcd.setCursor(0, 0);
lcd.print(“U=”);
lcd.print(Irms); // amplitude of input signal
//delay (500);
}

After pressing the button many times (for about 1 min) I can observe auto tuning, it seems that program has problem to reliable determinate the minimum, some time the “i” is negative.
With manual tuning (using 2 buttons) the “i” is always positive between 0 to 3000.

This is the fun part of programming, it almost works but not quite. Changing code, seeing what happens and rewarding when you finally get it right.

Using if (currentValue != minValue) is only false when both values are exactly the same.
currentValue is set by analogRead which is unlikely to ever match minValue. It might, but it could miss by 1 or 2 and the if statement would be true and you would get the conditions you see now.

To stop this you would use if (currentValue > minValue).
This will be true as long as currentValue is greater than minValue. When it is equal or lower the statement will be false.

if (digitalRead(PB9) == HIGH) {
  if (currentValue > minValue) {
    if (previousValue > currentValue) {
      i++;
    } else { 
      i--;
    }
  }
}

To stop negative values of i you could use the following. It stops i from ever going less than zero.

if ( i > 0) { 
 i--;
}

Make sure your increments and decrements have two pluses or minuses and no space between the variable and the operator.

I tried your last code = no respond to button pressing.

another approach
////////////////////////////////

if (digitalRead(PB9) == HIGH)

this two lines will make sure that when button is pressed the bridge will tune in right direction

{
i++; // do this if currentValue is decreasing = decreasing is true,if is false do - else
}
else
{
i–; // do this so currentValue is decreasing = decreasing is true
}

now is need a function which will stop the tuning when currentValue start increasing

if currentValue > previousValue brake ?? the loop above = stop tuning

That was the idea of using while and brake functions

My original response was to the two compiler errors and what was causing them.
I have tested the logic as per your program code; the variable ‘i’ tracks what ever level is read by analogRead() and it will go negative.

I am unclear as to exactly what you intend by the code.
It looks like ‘i’ is used to change the pulse width of a PWM pin. You want this pulse width to represent the minimum value read from an analog pin when a button is pressed.
The code simply wont do this, I have simulated the analog input and ‘i’ does not reflect the minimum value. It varies as the input varies.

Sorry, dont think I can help much until have a better grasp on what you want to do.
Jim

To check the formula I make this program and is working as expected so there is a problem with analog reading.
Probably some signal noise is confusing the program.
Instead LCD print can be used serial print.

#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);
int i = 0;
void setup() {

pinMode(PB9, INPUT_PULLDOWN);
lcd.begin(16, 2);
}

void loop() {
if (digitalRead(PB9) == HIGH)
{
//if (currentIrms > minIrms)
if (i < 180)

{
  i++;
  //delay(300);
}
else
//if (currentIrms < previousIrms)
{
  i--;
  //delay(300);
}

}
lcd.setCursor(0, 0);
lcd.print( i);
}


After pressing the button on LCD I have i = 180 +/- 1 so tuning is working good.

Now I am trying to tune the bridge to 0.5V, for some reason tuning is ignoring value of the “Irms”, sould stop at 0.5V of signal on PA7.
This line ( amplitude input signal ) " Irms = analogRead(PA7); " is ok, = correct numbers on LCD.
The question is; testing with “i” the program is working ok , but not with input signal ?
I think, this is the problem from beginning.

HardwareTimer pwmtimer4(4);
#include “EmonLib.h”
#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);
EnergyMonitor emon1;

float cur, acur[50], sumc;

int i = 0;
int ovfi = 0;
int (Irms) = 0;
int currentIrms = 0;
int previousIrms;
int maxIrms = 0;
int minIrms = 4095.0;

void setup()
{
pwmtimer4.pause();
pwmtimer4.setPrescaleFactor(3);
pwmtimer4.setOverflow(2000);
//pwmtimer4.setCompare(TIMER_CH2, 2880);
pwmtimer4.refresh();
pwmtimer4.resume();

pinMode(PB7, PWM); //duty regulated for balance
pinMode(PB9, INPUT_PULLDOWN);
pinMode(PA7, INPUT); // Irms
lcd.begin(16, 2);

emon1.current(PA7, 2.8);
}

void loop()
{

ovfi = 300 - i;
pwmtimer4.setCompare(TIMER_CH2, i);

/////////////////////////////////////
Irms = analogRead(PA7);

if (digitalRead(PB9) == HIGH)
{
if (Irms > 0.5)
{
i++;
}
else
{
i–;
}
}
////////////////////////////////////
emon1.calcVI(20, 2);
float Irms = emon1.Irms;

lcd.setCursor(0, 0);
lcd.print(“I=”);
lcd.print(Irms);
lcd.setCursor(0, 1);
lcd.print( i);
delay (50);
}

both Irms are ignored by code ?
After pressing the button “i” start from 0 and is increasing (100, 3000 ++ ) as long as button is pressed, 0.5 V corresponds to i = 35.

Irms = analogRead(PA7);

if (digitalRead(PB9) == HIGH)
{
if (Irms > 0.5)
{
i++;
}
if (Irms< 0.5)
{
i–;
}
}

I dont know if this is the reason but your code below looks like 'i-’ not 'i--'. ie 2 minuses. To decrement it needs to be '--' same as increment '++'. But it might be the way the forum page treats text. When you post code you should use the </> preformated tag.

Hope you get it working.
Regards
Jim

I did it, it is tuning to 0.5V, now I need to tune to minimum. I have a problem with this lines.
indent preformatted text by 4 spaces

currentIrms = analogRead(PA7); // get a new reading
currentIrms = ?? ??
currentIrms = float Irms = emon1.Irms; = not good

//////////////////////////////
indent preformatted text by 4 spaces
HardwareTimer pwmtimer4(4);
#include “EmonLib.h”
#include <LiquidCrystal.h>
LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5);
EnergyMonitor emon1;

float cur, acur[50], sumc;

int i = 0;
int ovfi = 0;
int (Irms) = 0 ;
int currentIrms = 0;
int previousIrms = 0;
int maxIrms = 0;
int minIrms = 4095.0;

void setup()
{
pwmtimer4.pause();
pwmtimer4.setPrescaleFactor(3);
pwmtimer4.setOverflow(2000);
//pwmtimer4.setCompare(TIMER_CH2, 2880);
pwmtimer4.refresh();
pwmtimer4.resume();

pinMode(PB7, PWM); //duty regulated for balance
pinMode(PB9, INPUT_PULLDOWN);
pinMode(PA7, INPUT); // Irms
lcd.begin(16, 2);

emon1.current(PA7, 2.8);
}

void loop()
{

pwmtimer4.setCompare(TIMER_CH2, i);
emon1.calcVI(20, 2);

///////////////////////////////////////
float Irms = emon1.Irms;

////////////
previousIrms = currentIrms; // store what was read last time
// currentIrms = analogRead(PA7); // get a new reading
//currentIrms = ?? ??
//currentIrms = float Irms = emon1.Irms; = mot good
//////////
if (digitalRead(PB9) == HIGH)
{
if (Irms > 0.5)

  //if (previousIrms < currentIrms)
  ///////////////////////////////////////////

{
  i++;
}
else
{
  i--;
}

}
lcd.setCursor(0, 0);
lcd.print(“V=”);
lcd.print(Irms);
lcd.setCursor(0, 1);
lcd.print(“I=”);
lcd.print( i);
//delay (50);

}

</> Problem to use it.
I click on it and have this message
indent preformatted text by 4 spaces
but no place to paste the code