Digitally controlled voltage with feedback.

Discussion in 'Embedded Systems and Microcontrollers' started by coinmaster, Feb 19, 2016.

  1. coinmaster

    Thread Starter Member

    Dec 24, 2015
    350
    6
    I'm trying to create a digitally controlled voltage which I will end up using for a software controlled voltage divider for a high voltage circuit control around 600v.

    For now I am trying to get it to work on 5v.

    This is the general idea

    feedbacks-1_800x482.gif

    I want precise output voltages so I want to negate any non-linearities in the transistor with digital feedback from a voltage sense IC or something.
    So basically I'll tell the controller that I want x voltage on the output and if the voltage on the output reads more or less than that voltage then it will self correct.
    This is the code I'm using right now
    Code (C):
    1.  
    2. // the setup routine runs once when you press reset:
    3. void setup() {
    4.   // initialize serial communication at 9600 bits per second:
    5.   Serial.begin(9600);
    6.   pinMode(13,OUTPUT);
    7. }
    8.  
    9. // the loop routine runs over and over again forever:
    10. void loop() {
    11.   //Power source for adjustable voltage
    12.   digitalWrite(13, HIGH);
    13.   // Reads potentiometer voltage to get a reference number used for intended output voltage
    14.   int reference = analogRead(A1);
    15.   // Takes analogRead value and turns it into the intended voltage reference number
    16.   float ReferenceNumber = reference * (5.0 / 1023.0);
    17.  
    18.   // Translation from intended voltage number to analogWrite voltage
    19.   float output=ReferenceNumber*(225/5.0);
    20.   // output to transistor base
    21.   analogWrite(9,output);
    22.   // reads the output voltage for feedback control
    23.   int feedback = analogRead(A0);
    24.   // If the output voltage is greater or less than the intended voltage then the opto-isolator bias will be adjusted.
    25.     if (feedback*(255/1023.0) > output ) {
    26.   output = -1 ;}
    27.   if (feedback*(255/1023.0) < output ) {
    28.   output = +1 ;}
    29.  
    30.   //Prints the output voltage
    31.   Serial.println(feedback* (5.0 / 1023.0));
    32. }
    I'm using a potentiometer to adjust the reference voltage and then I'm converting the reverence voltage number into analogWrite voltage which is then read by analogRead at the output and the output is adjusted based on whether the output is lower or higher than the reference number.

    It works but it is not stable, it fluctuates all over within a volt or more.
    Is there some problem in the concept of my code or something?
    I only started learning digital electronics and coding a couple days ago.

    Moderators note: changed code tags to C
     
    Last edited by a moderator: Feb 20, 2016
  2. Alec_t

    AAC Fanatic!

    Sep 17, 2013
    5,813
    1,105
    R9/C1 introduce a considerable delay between the commanded voltage output and the AnalogRead value that you want. I don't see any delay routines to allow for that?
     
  3. coinmaster

    Thread Starter Member

    Dec 24, 2015
    350
    6
    What do you mean? How is my RC filter delaying the output voltage?

    Also I changed the code and switched the supply pins on the arduino and this is the result
    http://imgur.com/RSRyUwz
    The stability is much better but the accuracy is off. Perhaps the ADC does not have a high enough resolution?
    This is the code I am now using

    Code (C):
    1.  
    2. int PWMout = 9; // Ouput PWM pin
    3. int output = 255; //Start PWM at 255 as this is zero voltage output, because the circuit is a shunt regulator.
    4. // the setup routine runs once when you press reset:
    5. void setup() {
    6.   // initialize serial communication at 9600 bits per second:
    7.   Serial.begin(9600);
    8.   pinMode(13, OUTPUT);
    9.   pinMode(A0, INPUT);
    10.   pinMode(A1, INPUT);
    11.   pinMode(PWMout, OUTPUT);
    12. }
    13.  
    14. // the loop routine runs over and over again forever:
    15. void loop()
    16. {
    17.   digitalWrite(13, HIGH);
    18.   // Reads potentiometer voltage to get a reference number used for intended output voltage
    19.   int reference = analogRead(A1);
    20.  
    21.   // Takes analogRead value and turns it into the intended voltage reference
    22.   float ReferenceVoltage = reference * (5.0 / 1023.0);
    23.  
    24.   // reads the feedback output voltage for feedback control
    25.   int feedback = analogRead(A0);
    26.   float FeedbackVoltage = feedback * (5.0 / 1023.0);
    27.  
    28.   // If the feedback voltage is greater than the reference then the PWM needs to be increased to increase shunt current.
    29.   if (FeedbackVoltage > ReferenceVoltage )
    30.   {
    31.     output = +1 ;
    32.   }
    33.  
    34.   // If the feedback voltage is less than the reference then the PWM needs to be decreased to decrease shunt current.
    35.   if (FeedbackVoltage < ReferenceVoltage )
    36.   {
    37.     output = -1 ;
    38.   }
    39.  
    40.   // Check output value and limit maximum and minimum
    41.   if (output >= 255)
    42.   {
    43.     output = 255;
    44.   }
    45.   if (output <= 0 )
    46.   {
    47.     output = 0;
    48.   }
    49.   // Print variables
    50.   analogWrite(PWMout, output);
    51.   //Prints the voltages
    52.   Serial.print("Reference ");
    53.   Serial.print(ReferenceVoltage);
    54.   Serial.print("/tFeedbackVoltage ");
    55.   Serial.print(FeedbackVoltage);
    56.   Serial.print("/tPWMout ");
    57.   Serial.println(output);
    58. }
    59.  
     
    Last edited: Feb 20, 2016
  4. dannyf

    Well-Known Member

    Sep 13, 2015
    1,835
    367
    it is very hard to stablize a mixed signal control loop.

    The universal trick is to lower the gain - but it comes with its bag of negativity as well.
     
  5. dannyf

    Well-Known Member

    Sep 13, 2015
    1,835
    367
    You are doing "on/off" control - may not be the best approach.

    I would try this:

    1) measure the analog output (middle of R5/R7);
    2) if it is great than your desired output, increment output; else decrement output; update pwm duty cycle
    3) go back to 1).

    You can adjust the stepping of the increments / decrements.
     
  6. coinmaster

    Thread Starter Member

    Dec 24, 2015
    350
    6
    Um, is that not what I am doing now? Check out my last post.

    Also I changed it to
    Code (C):
    1.  
    2.   if (FeedbackVoltage > ReferenceVoltage )
    3.   {
    4.     output++ ;
    5.   }
    6.  
    7.   // If the feedback voltage is less than the reference then the PWM needs to be decreased to decrease shunt current.
    8.   if (FeedbackVoltage < ReferenceVoltage )
    9.   {
    10.     output--;
    11.   }
    and the result is the same, whether I use +1 or ++

    The error margin is pretty much eliminated after changing the supply pin and refining the code. The main issue is accuracy http://imgur.com/L3D2Ygz I'm assuming this is a resolution issue? The aruino only has 8 bits ADC.
     
    Last edited: Feb 20, 2016
  7. Alec_t

    AAC Fanatic!

    Sep 17, 2013
    5,813
    1,105
    The R9/C1 time constant is 100mS, so a voltage change at the Arduino output will not appear across C1, and hence at the 'Voltmeter' node, immediately.
     
  8. dannyf

    Well-Known Member

    Sep 13, 2015
    1,835
    367
    Code (Text):
    1.  
    2. [LIST=1]
    3. [*]// If the feedback voltage is greater than the reference then the PWM needs to be increased to increase shunt current.
    4. [*] if (FeedbackVoltage > ReferenceVoltage )
    5. [*] {
    6. [*]    output = +1 ;
    7. [*] }
    8. [*]
    9.  
    10. [*] // If the feedback voltage is less than the reference then the PWM needs to be decreased to decrease shunt current.
    11. [*] if (FeedbackVoltage < ReferenceVoltage )
    12. [*] {
    13. [*]    output = -1 ;
    14. [*] }
    15. [/LIST]
    16.  
    That's what you wrote.
     
  9. coinmaster

    Thread Starter Member

    Dec 24, 2015
    350
    6
    Oh right time constant, almost forgot about that. It doesn't seem that you can get a good time constant with good filtering. How to solve this? Maybe I have to resort to a full on DAC?
     
Loading...