Closed loop control on arduino UNO

I've been trying for quite a while now to write a CLOSED LOOP control code on my arduino UNO. The code should be able to send feedback through a current sensor and output whatever voltage is required based on the resistor value. I would really appreciate it if anyone could point me in the right direction. My code doesn't seem to give the right values.

We do that all the time for our temperature calibrated wind sensors. Without seeing the code it’s hard to help but here’s a problem I’ve seen crop up.

The values coming with analogRead in tend to be graded from 0-1024, whereas values sent out using analogWrites are graded 0-255. So if you are taking the analog value that’s coming in, and its say 340, and passing that directly to the output, the arduino counts up to 255 and then starts again at zero so the final output would actually be 340-255=85, producing a result, but not the one you were expecting.

blaues_blut:
I would really appreciate it if anyone could point me in the right direction. My code doesn’t seem to give the right values.

How can we help if we can’t see your code?
Please post it, between code tags of course. They’re generated by clicking </> in the post and “Reply” windows.

ardshark:
The values coming with analogRead in tend to be graded from 0-1024,

Can ‘analogRead()’ really return a value of 1024?

Hi Steve,
Have I stayed up too late again? Do I not have that right? (1024)

ardshark:
Hi Steve,
Have I stayed up too late again? Do I not have that right? (1024)

No, you're mistaken I'm afraid. A 10-bit ADC can only return up to 1023.
There are 1024 steps, but one of those is 0, so the result will be 0 to 1023.

https://www.arduino.cc/en/Reference/AnalogRead

Oh ok, 1023. 1024 values - sorry was thinking about the bigger problem and wasn't paying attention to the zeros.
But Steve is absolutely right. The highest value analogRead can return is 1023. (except if it's in a Spinal Tap amp)

Also you might want to put dropping resistors on the analog pins. These generally can be 10k 1/4 watt jobs tied from the analog pin to ground. It will change your values but it will ensure when the input voltages drop they have somewhere to go.

It was a trick question :slight_smile: Base 0 vs base 1 counting (just shot myself in the foot recently when I got the partition number wrong on a Linux install). The old grey cells ain't what they used to be :confused:

I’ve been trying for a while now to a CLOSED LOOP control code on my arduino UNO. The code should be able to send feedback through a current sensor and output whatever voltage is required based on the value of resistor value. I would really appreciate it if someone can point me in the right direction.

Here is my code

#include <avr/io.h>
#include <util/delay.h>

int analogIn= A0;
int mVperAmp = 66;
int SensorValue =0;
int Voltagevalue = 0;
int RawVoltage = 0;
int ACSoffset = 5;
int Voltsensor = A2;
int pwm = 3;
int val = 0;

double Voltage1 = 0;
double Voltage =0;
double Amps = 0;
double refcurr = 0.2;
double refvolt = 0.4; 
double sensornew1 = 0;

v0oid setup() {
// initialize serial communication at 9600 bits per second:

  Serial.begin(9600);
  pinMode(pwm, OUTPUT); // output pin for OCR2B
  //pinMode(5, OUTPUT); // output pin for OCR0B
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS20);
OCR2A = 105;
OCR2B = 40;

}
void loop() 
{
  //val = analogRead(analogIn);
  //analogWrite(pwm,127 );

  SensorValue = analogRead(analogIn);
  Voltagevalue = analogRead(Voltsensor);  
  //RawVoltage =analogRead(sensorvoltage);
  Voltage = (SensorValue / 1023.0) ; // Gets you V
  Voltage1 = (Voltagevalue/1023.0);
  Amps = (510.5 - SensorValue)*75.75757576/1023;

 //if (Amps < 0)
 //{
 //Amps = (0)*75.75757576/1023;
  //Serial.print("Current = "); // shows the voltage measured 
  //Serial.println(Amps,3); // the '3' after voltage allows you to display 3 digits after decimal point
  //Serial.print("                     Voltage1 = ");
 // Serial.println(Voltage, 3);
 //}
 //else
 //Amps = (510.5 - SensorValue)*75.75757576/1023;
  //Serial.print("Current = "); // shows the voltage measured 
  //Serial.println(Amps,3); //
  //Serial.print("                     Voltage1 = ");
 //Serial.println(Voltage, 3);
 //delay(1000); 
 

if(Amps < refcurr)
{
   OCR2B=OCR2B+0.9999999999;
   Amps = (510.5 - SensorValue)*75.75757576/1023;
   Serial.print("\t Current = ");
   Serial.println (Amps,3);
   //Serial.print("                     Voltage1 = ");
   //Serial.println(Voltage1, 3);
}

else
   OCR2B=OCR2B-2;
   Amps = (510.5 - SensorValue)*75.75757576/1023;
   Serial.print("\t Current = ");
   Serial.println (Amps,3);
   //Serial.print("                     Voltage1 = ");
   //Serial.println(Voltage1, 3);
   
//if(Voltage1 < refvolt)
//{ 
    //OCR2B=OCR2B+1;
    //Voltage1=(510.5-Voltagevalue)*75.757575/1023;
    //Serial.print("                     Voltage1 = ");
    //Serial.println(Voltage1, 3);
//}
//else 
    //OCR2B=OCR2B-0.5;
    //Voltage1=(510.5-Voltagevalue)*75.757575/1023;
    //Serial.print("                     Voltage1 = ");
    //Serial.println(Voltage1, 3);
delay(1000);
}
Voltage = (SensorValue / 1023.0) ; // Gets you V

No, this doens't get you volts. You still need to multiply by 5.

OCR2B=OCR2B+0.9999999999;

OCR2B is an 8 bit register. It can have integer values from 0 to 255. Trying to add a fractional number to it is pointless.

Your code should pe placed between code tags, not after them.
Like this:-

[code]Place your code here[/code]
It will appear in a block like this

Please edit your post and fix it. It makes it much easier to read, or to copy for pasting into an IDE for verification/testing.

It's a good idea to post code that's actually compilable, whenever possible:-

v0oid setup() {

Also, when you have large sections of code commented out, it's better to not include it in your post. It's a bit confusing to read. Just post the code you want us to actually look at.

(From the look of it, Delta_G has already highlighted your problem(s), but it still wouldn't hurt to at least add code tags for those who read this thread in the future.)

I’ve been trying for quite a while now to write a CLOSED LOOP control code on my arduino UNO. The code should be able to send feedback through a current sensor and output whatever voltage is required based on the resistor value. I would really appreciate it if anyone could point me in the right direction. My code doesn’t seem to give the right values.

This is my code

#include <avr/io.h>
#include <util/delay.h>

int analogIn= A0;
int mVperAmp = 66;
int SensorValue =0;
int Voltagevalue = 0;
int RawVoltage = 0;
int ACSoffset = 5;
int Voltsensor = A2;
int pwm = 3;
int val = 0;

double Voltage1 = 0;
double Voltage =0;
double Amps = 0;
double refcurr = 0.2;
double refvolt = 0.4; 
double sensornew1 = 0;

void setup() {

  Serial.begin(9600);
  pinMode(pwm, OUTPUT); 
  
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS20);
OCR2A = 105;
OCR2B = 40;

}
void loop() 
{
  
  SensorValue = analogRead(analogIn);
  Voltagevalue = analogRead(Voltsensor);  
  
  Voltage = (SensorValue / 1023.0) ; 
  Voltage1 = (Voltagevalue/1023.0);
  Amps = (510.5 - SensorValue)*75.75757576/1023;



if(Amps < refcurr)
{
   OCR2B=OCR2B+0.9999999999;
   Amps = (510.5 - SensorValue)*75.75757576/1023;
   Serial.print("\t Current = ");
   Serial.println (Amps,3);
}

else
   OCR2B=OCR2B-2;
   Amps = (510.5 - SensorValue)*75.75757576/1023;
   Serial.print("\t Current = ");
   Serial.println (Amps,3);
   

delay(1000);
}

Starting a second identical thread with your code correctly posted is not the right way to do things.
Why didn't you just edit this thread and add code tags?

Closed Loop Control on Arduino UNO

Did Delta_G's suggestions help?

Sorry guys I'm new here

blaues_blut:
Sorry guys I’m new here

We were all new once, so we read the instructions at the top of every forum section

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
So we can see how you feedback is connected.

Thanks... Tom. :slight_smile:

JimboZA:
We were all new once, so we read the instructions at the top of every forum section

Which you seem still not to have done since you started a new thread on the exact same thing :angry:

And just FYI - you've have those deep precision decimals to calculate amps (and like the voltage one that DeltaG pointed out, i doubt that is giving you amps either. i realize that it's just a variable but with it being called amps, I didn't want you blowing things up because a variable gave you what you thought was the current.)

But the bigger thing to point out given the precision of the multiplier to get "amps" is: on the UNO, double is the same as float, only 4 bytes of precision not 8 as it is on other boards. The the double will still do math but you won't get the kind of precision the double was made for if you are using an the UNO. So those looooong decimals wont really get used fully.

Please do not cross-post. Threads merged.

Hi,
Please read post #15.
With all these suggestions floating about, what is you current feedback device you are reading FROM, and what is your output device you are writing TO?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

18 posts and we still have no idea what your feedback and output devices (make/model/dataspec?) are and how they interact.

Thanks… Tom… :slight_smile: