4

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

chicks
  • 227
  • 4
  • 10
Marius
  • 41
  • 2

1 Answers1

4

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

tim
  • 699
  • 6
  • 15