user61950: I am new to the Arduino world and I hope I can find a solution here. The code below functionally works ok. The problem I have is, at line 45 I've inserted an if statement to change dac_value. It is very slow while serial and all that is outside if works fast/fine... What would be a solution to make it fast? Tried if - else if and also while... result is the same. Hope someone can help. Thank you.
{    
#include <Arduino.h>
#include <Wire.h>
// #include <LiquidCrystal_I2C.h>
#define MCP4725 0x61
#define MCP4725B 0x60
unsigned int val;
byte buffer[3];
byte buff[3];

int ClockPinV = PB1; 
int ClockPinA = PA6; 
const int currsensPin = PA3;
const int voltsensPin = PA2;

void setup()
{
  Serial.begin(115200);
  pinMode(currsensPin , INPUT_ANALOG);
  pinMode(voltsensPin , INPUT_ANALOG); 
  pinMode(ClockPinV , INPUT);
  pinMode(ClockPinA , INPUT);
  Wire.begin();
}

int val0 = 1024;
int val1 = 4096;
volatile int dac_value = 0;

void loop()
{
  analogReadResolution(12);


  volatile int svolt = analogRead(ClockPinV);
  volatile int scurr = analogRead(ClockPinA);
  volatile int set_voltage = (3.3/4096)*svolt;
  volatile int set_curr =  (3.3/4096)*scurr;
  volatile int securr = analogRead(currsensPin);
  volatile int real_curr = (3.3/4096)*securr;
  volatile int sevolt= analogRead(voltsensPin);
  volatile int real_output2 = (3.3/4096)*sevolt;
  

if(real_curr < set_curr){
    if(set_voltage > real_output2)
    {
      dac_value = dac_value + 1;
    }
    if(set_voltage < real_output2)
    {
      dac_value = dac_value - 1;
    }  
  }
  else if(real_curr > set_curr)
  {
    dac_value --;         
  }

  dac_value = constrain(dac_value, 0, 2673);
  buffer[0] = 0b01000000; //control byte
  buffer[1] = dac_value >> 4; //MSB 11-4 shift right 4 places
  buffer[2] = dac_value << 4; //LSB 3-0 shift left 4 places
  
  Wire.beginTransmission(MCP4725); //address device
  Wire.write(buffer[0]); //pointer
  Wire.write(buffer[1]); //8 MSB
  Wire.write(buffer[2]); //4 LSB
  Wire.endTransmission();

  // val1 = constrain(val1, 0, 2673);
  buff[0] = 0b01000000; //control byte
  buff[1] = svolt >> 4; //MSB 11-4 shift right 4 places
  buff[2] = svolt << 4; //LSB 3-0 shift left 4 places
  
  Wire.beginTransmission(MCP4725B); //address device
  Wire.write(buff[0]); //pointer
  Wire.write(buff[1]); //8 MSB
  Wire.write(buff[2]); //4 LSB
  Wire.endTransmission();

  
  Serial.println("=============================");
  Serial.println("=============================");
  Serial.println("========= Volt Test =========");
  Serial.println("test: " + String(set_voltage));
  Serial.println("      " + String(real_output2));
  Serial.println("======== Current Test =======");
  Serial.println("test: " + String(set_curr));
  Serial.println("      " + String(real_curr));
  Serial.println("=============================");
  Serial.println("=============================");
}
}


user68310: The if statements (plural) you posted on GitHub are a lot different to the one you posted above. They contain a lot of of print commands to the LCD, so I think this is what is slowing your code down. It's a fair effort at nicely formatting the output on the display, but is rather convoluted.
Here is a simplified version which writes to the LCD as little as possible (2 cursor moves and 2 prints). The formatting of the string is done in Arduino memory before sending it out to the LCD as one complete string.
I couldn't understand your variable names, so I've renamed them.
setup()
I moved the analogReadResolution(12) from loop() to setup() for a slight performance gain.
void setup()
{
  pinMode(currsensPin , INPUT_ANALOG);
  pinMode(voltsensPin , INPUT_ANALOG);
  pinMode(voltPin, INPUT_ANALOG);
  pinMode(currPin, INPUT_ANALOG);
  Wire.begin();
  lcd0.begin(20, 4);
  lcd0.backlight();

  analogReadResolution(12);  // Moved from loop(). Only need to call it once.

  Serial.begin(115200);
}

loop()
I've grouped the analogue reads together to give a smaller sampling window. Since it's for a control loop, these values should ideally be sampled at exactly the same time and synchronised to a clock (e.g. in hardware).
float real_current_offset = 0;

void loop()
{
  //
  // Obtain data samples as close together as possible with no interrupts.
  //
  cli();  // Disable interrupts.
  int svolt = analogRead(voltPin);
  int scurr = analogRead(currPin);
  int raw_voltage = analogRead(voltsensPin);
  int raw_current = analogRead(currsensPin);
  sei();  // Enable interrupts.

  // Calculate set voltage and current.
  float set_voltage = (3.3 / 4096) * svolt;
  float set_current =  (3.3 / 4096) * scurr;

  // Calculate real voltage and current.
  float real_voltage = (3.3 / 4096) * raw_voltage;
  float real_current = raw_current * (3.3 / 4096) - real_current_offset;
  float real_current_ma = real_current * 1000.0;
  
  int dac_value = dac_value
              + (real_current <= set_current) * (set_voltage > real_voltage)
              - (real_current < set_current) * (set_voltage < real_voltage)
              - (real_current > set_current);

  buffer[0] = 0b01000000;
  buffer[1] = dac_value >> 4;
  buffer[2] = dac_value << 4;
  Wire.beginTransmission(MCP4725);
  Wire.write(buffer[0]);
  Wire.write(buffer[1]);
  Wire.write(buffer[2]);
  Wire.endTransmission();

  DisplayDataOnLcd(set_voltage, set_current, real_voltage, real_current);
}

DisplayDataOnLcd()
I created a new function for displaying the data on the LCD. It's good practice to break the code down into smaller functional blocks.
void DisplayDataOnLcd(const int set_voltage, const int set_current, const int real_voltage, const int real_current)
{
  Serial.println("\nLCD Data Display");

  // Define the formats for printing to the LCD.
  const char *data_format_set  = "Set : %s V %s mA";
  const char *data_format_real = "Real: %s V %s mA";
  char voltage_str[10];
  char current_str[10];
  char data_str[30];

  // Format the set voltage and current, and display on the LCD.
  dtostrf(set_voltage, 6, 3, voltage_str);
  dtostrf(set_current, 6, 3, current_str);
  sprintf(data_str, data_format_set, voltage_str, current_str);
  lcd0.setCursor(0, 0);
  lcd0.println(data_str);
  Serial.println(data_str);

  // Format the real voltage and current, and display on the LCD.
  dtostrf(real_voltage, 6, 3, voltage_str);
  dtostrf(real_current, 6, 3, current_str);
  sprintf(data_str, data_format_real, voltage_str, current_str);
  lcd0.setCursor(0, 1);
  lcd0.println(data_str);
  Serial.println(data_str);
}


61950: <p>I am new to the Arduino world and I hope I can find a solution here. The code below functionally works ok. The problem I have is, at line 45 I've inserted an <code>if</code> statement to change <code>dac_value</code>. It is very slow while serial and all that is outside <code>if</code> works fast/fine... What would be a solution to make it fast? Tried <code>if</code> - <code>else if</code> and also <code>while</code>... result is the same. Hope someone can help. Thank you.</p>
<pre><code>{    
#include &lt;Arduino.h&gt;
#include &lt;Wire.h&gt;
// #include &lt;LiquidCrystal_I2C.h&gt;
#define MCP4725 0x61
#define MCP4725B 0x60
unsigned int val;
byte buffer[3];
byte buff[3];

int ClockPinV = PB1; 
int ClockPinA = PA6; 
const int currsensPin = PA3;
const int voltsensPin = PA2;

void setup()
{
  Serial.begin(115200);
  pinMode(currsensPin , INPUT_ANALOG);
  pinMode(voltsensPin , INPUT_ANALOG); 
  pinMode(ClockPinV , INPUT);
  pinMode(ClockPinA , INPUT);
  Wire.begin();
}

int val0 = 1024;
int val1 = 4096;
volatile int dac_value = 0;

void loop()
{
  analogReadResolution(12);


  volatile int svolt = analogRead(ClockPinV);
  volatile int scurr = analogRead(ClockPinA);
  volatile int set_voltage = (3.3/4096)*svolt;
  volatile int set_curr =  (3.3/4096)*scurr;
  volatile int securr = analogRead(currsensPin);
  volatile int real_curr = (3.3/4096)*securr;
  volatile int sevolt= analogRead(voltsensPin);
  volatile int real_output2 = (3.3/4096)*sevolt;
  

if(real_curr &lt; set_curr){
    if(set_voltage &gt; real_output2)
    {
      dac_value = dac_value + 1;
    }
    if(set_voltage &lt; real_output2)
    {
      dac_value = dac_value - 1;
    }  
  }
  else if(real_curr &gt; set_curr)
  {
    dac_value --;         
  }

  dac_value = constrain(dac_value, 0, 2673);
  buffer[0] = 0b01000000; //control byte
  buffer[1] = dac_value &gt;&gt; 4; //MSB 11-4 shift right 4 places
  buffer[2] = dac_value &lt;&lt; 4; //LSB 3-0 shift left 4 places
  
  Wire.beginTransmission(MCP4725); //address device
  Wire.write(buffer[0]); //pointer
  Wire.write(buffer[1]); //8 MSB
  Wire.write(buffer[2]); //4 LSB
  Wire.endTransmission();

  // val1 = constrain(val1, 0, 2673);
  buff[0] = 0b01000000; //control byte
  buff[1] = svolt &gt;&gt; 4; //MSB 11-4 shift right 4 places
  buff[2] = svolt &lt;&lt; 4; //LSB 3-0 shift left 4 places
  
  Wire.beginTransmission(MCP4725B); //address device
  Wire.write(buff[0]); //pointer
  Wire.write(buff[1]); //8 MSB
  Wire.write(buff[2]); //4 LSB
  Wire.endTransmission();

  
  Serial.println(&quot;=============================&quot;);
  Serial.println(&quot;=============================&quot;);
  Serial.println(&quot;========= Volt Test =========&quot;);
  Serial.println(&quot;test: &quot; + String(set_voltage));
  Serial.println(&quot;      &quot; + String(real_output2));
  Serial.println(&quot;======== Current Test =======&quot;);
  Serial.println(&quot;test: &quot; + String(set_curr));
  Serial.println(&quot;      &quot; + String(real_curr));
  Serial.println(&quot;=============================&quot;);
  Serial.println(&quot;=============================&quot;);
}
}
</code></pre>
 68310: <p>The <code>if</code> statements (plural) you <a href="https://github.com/mariusdp/psu_test/blob/master/main.cpp" rel="nofollow noreferrer">posted on GitHub</a> are a lot different to the one you posted above. They contain a lot of of <code>print</code> commands to the LCD, so I think this is what is slowing your code down. It's a fair effort at nicely formatting the output on the display, but is rather convoluted.</p>
<p>Here is a simplified version which writes to the LCD as little as possible (2 cursor moves and 2 prints). The formatting of the string is done in Arduino memory before sending it out to the LCD as one complete string.</p>
<p>I couldn't understand your variable names, so I've renamed them.</p>
<h1>setup()</h1>
<p>I moved the <code>analogReadResolution(12)</code> from <code>loop()</code> to <code>setup()</code> for a slight performance gain.</p>
<pre class="lang-cpp prettyprint-override"><code>void setup()
{
  pinMode(currsensPin , INPUT_ANALOG);
  pinMode(voltsensPin , INPUT_ANALOG);
  pinMode(voltPin, INPUT_ANALOG);
  pinMode(currPin, INPUT_ANALOG);
  Wire.begin();
  lcd0.begin(20, 4);
  lcd0.backlight();

  analogReadResolution(12);  // Moved from loop(). Only need to call it once.

  Serial.begin(115200);
}
</code></pre>
<h1>loop()</h1>
<p>I've grouped the analogue reads together to give a smaller sampling window. Since it's for a control loop, these values should ideally be sampled at exactly the same time and synchronised to a clock (e.g. in hardware).</p>
<pre class="lang-cpp prettyprint-override"><code>float real_current_offset = 0;

void loop()
{
  //
  // Obtain data samples as close together as possible with no interrupts.
  //
  cli();  // Disable interrupts.
  int svolt = analogRead(voltPin);
  int scurr = analogRead(currPin);
  int raw_voltage = analogRead(voltsensPin);
  int raw_current = analogRead(currsensPin);
  sei();  // Enable interrupts.

  // Calculate set voltage and current.
  float set_voltage = (3.3 / 4096) * svolt;
  float set_current =  (3.3 / 4096) * scurr;

  // Calculate real voltage and current.
  float real_voltage = (3.3 / 4096) * raw_voltage;
  float real_current = raw_current * (3.3 / 4096) - real_current_offset;
  float real_current_ma = real_current * 1000.0;
  
  int dac_value = dac_value
              + (real_current &lt;= set_current) * (set_voltage &gt; real_voltage)
              - (real_current &lt; set_current) * (set_voltage &lt; real_voltage)
              - (real_current &gt; set_current);

  buffer[0] = 0b01000000;
  buffer[1] = dac_value &gt;&gt; 4;
  buffer[2] = dac_value &lt;&lt; 4;
  Wire.beginTransmission(MCP4725);
  Wire.write(buffer[0]);
  Wire.write(buffer[1]);
  Wire.write(buffer[2]);
  Wire.endTransmission();

  DisplayDataOnLcd(set_voltage, set_current, real_voltage, real_current);
}
</code></pre>
<h1>DisplayDataOnLcd()</h1>
<p>I created a new function for displaying the data on the LCD. It's good practice to break the code down into smaller functional blocks.</p>
<pre class="lang-cpp prettyprint-override"><code>void DisplayDataOnLcd(const int set_voltage, const int set_current, const int real_voltage, const int real_current)
{
  Serial.println(&quot;\nLCD Data Display&quot;);

  // Define the formats for printing to the LCD.
  const char *data_format_set  = &quot;Set : %s V %s mA&quot;;
  const char *data_format_real = &quot;Real: %s V %s mA&quot;;
  char voltage_str[10];
  char current_str[10];
  char data_str[30];

  // Format the set voltage and current, and display on the LCD.
  dtostrf(set_voltage, 6, 3, voltage_str);
  dtostrf(set_current, 6, 3, current_str);
  sprintf(data_str, data_format_set, voltage_str, current_str);
  lcd0.setCursor(0, 0);
  lcd0.println(data_str);
  Serial.println(data_str);

  // Format the real voltage and current, and display on the LCD.
  dtostrf(real_voltage, 6, 3, voltage_str);
  dtostrf(real_current, 6, 3, current_str);
  sprintf(data_str, data_format_real, voltage_str, current_str);
  lcd0.setCursor(0, 1);
  lcd0.println(data_str);
  Serial.println(data_str);
}
</code></pre>
