Connect with us

Voltage controlled thru opamp playing up?

Discussion in 'LEDs and Optoelectronics' started by diagnostix, Apr 2, 2014.

Scroll to continue with content
  1. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    Ah ha. Increasing the frequency will cause your output filter to antenuate any noise from the output even further improving matters. Still could be the opamp. Just a thought.
    Adam
     
  2. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    Thanks Adam, really appreciate your input.

    But what part though, tried removing the 100n and still same, most interesting for me is the fact at low volts, 1,0v the input rises instead of the output falling as per program, can't help but think there is a connection here to the solution!
     
  3. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    Try to connect a 1V d.c input directly to the opamp from a PSU and vary the voltage up and down a bit and see what happens. Remember to disconnect the filter at the front end to stop your main input from effecting anything. Then put a 56K resistor inline and do the same, tell us what it does.
    Adam
     
  4. KrisBlueNZ

    KrisBlueNZ Sadly passed away in 2015

    8,393
    1,271
    Nov 28, 2011
    Re your code in post #19, there is an obvious problem: the while(1) is inside the loop! I don't think that's valid C code; a do without a corresponding while() isn't valid syntax.

    I would approach this problem using some debug code to output diagnostic information from the serial port. To start with, I would just output two decimal numbers in ASCII format, with a space between them and a carriage return and linefeed after. Transmit at 115200 bps and capture the data with a PC running a terminal emulator program.

    The numbers should be res and pwm_duty. Generate the ASCII string and transmit it out the serial port each time round the loop. Then you can vary the input to the circuit and watch what's happening on the terminal. You should see the res vary over the range 0~1023 (your comment says it's a 10-bit ADC) and the pwm_duty value should vary over the range 0~255.

    There's probably a bug with your code to convert R_IN and R2_IN to R_OUT and R2_OUT:
    If the condition is true, you perform two calculations to set R_OUT and R2_OUT, but if it's not true, no values are assigned to R_OUT and R2_OUT.

    Also, identifiers in ALL CAPS are traditionally only used for constants and #defined values; variable names are usually in lower case or mixed case.

    You have done the conversion in a very complicated and inefficient way. Floating point operations are very expensive on the PIC. In fact, anything bigger than 8 bits (char or unsigned char) is expensive, but floating point is probably about two orders of magnitude more expensive!

    If you simply want to take a 10-bit value in the range 0~1023 into a proportional value from 0~255, you just shift it right by two bits. You could replace all of your floating point calculations with that operation and see whether it fixes the problem. I assume this won't be a permanent solution because you will be changing the conversion once you get the simple version working.

    When you do change your logic, I would strongly recommend that you avoid floating point as much as possible. If you do need to use floating point, try to get the compiler to precalculate as many values as possible. Your code in post #19 you are converting a 10-bit raw ADC value to an 8-bit PWM control value using the following steps:

    1. R_IN = res * VREF/1024.0;
    2. Conditionally, R_OUT = R_IN * .82;
    3. pwm_duty = R_OUT * 51.2;

    Step 1 requires at least one, possibly two floating point operations. The multiplication must be performed with a floating point multiply; the division (VREF/1024.0) could be optimised out by the compiler if it was smart enough to notice that VREF is a const, but I suspect it wouldn't, because VREF is actually a variable.

    Step 2 conditionally performs another floating point operation, and step 3 performs another.

    You can eliminate some inefficiency by only scaling once, and more by getting the compiler to precalculate VREF / 1024.0.

    If you can't eliminate floating point entirely, there are several ways to improve efficiency. You could perform the scaling calculation using the raw value from the ADC, giving a floating point result in the range 0~1023 (assuming the scaling will be less than 1.0), put that back into an integer variable, and scale it from a 0~1023 range to a PWM control value (0~255) in the integer domain using two right shifts (value >>= 2).

    Or you could scale your ADC raw values to floating point numbers in the range 0.0~1.0 by dividing them by 1023, perform the scaling, then translate back to PWM control control values by multiplying them by 255.

    In all cases you should consider how rounding will be performed by the conversions to and from floating point.

    Finally, const unsigned short VREF = 5.00 is confusing, if not invalid syntax; short integers cannot have decimal places!

    If you just want to apply scaling and offset, and don't need the MCU for anything else, this can be done with op-amps and precision resistors.
     
    Last edited: Apr 6, 2014
  5. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    Nice one Kris. I don't quite understand his set up can you explain? So what is he doing, is he outputting PWM into the filter and then this is creating an approx d.c voltage of 1-5V depending on the duty cycle? Can you tell me from his code what the timings are.
    Cheers Adam
     
  6. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    If there was a software fault why would it work by increasing the frequency?
    Any ideas?
    Adam
     
  7. KrisBlueNZ

    KrisBlueNZ Sadly passed away in 2015

    8,393
    1,271
    Nov 28, 2011
    Yes Adam, he is sampling two analogue inputs via the 10-bit ADC, conditionally scaling them if three digital inputs are all high, then outputting them to the two PWM generators, to produce waveforms with an average voltage between 0V and 5V, which are heavily filtered and buffered.

    I can't be sure what the timings are, because I don't know which PIC variant he's using.

    I don't know, but I'm not confident that it does. When working in unfamiliar territory, people often try to solve problems by applying the "try anything and everything I can think of, in random combinations, with no plan; introduce new mistakes by accident, and don't take proper notes" technique. So, specifics of the problem description can be misleading.

    diagnostix, what PIC are you using?
     
  8. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    Guys, thanks for your valued inputs. I am using PIC18F45K22 I/P on internal osc 16MHz. I think the problem is software generated. I am trying to reduce the load of the PIC by making the code more efficient. VCC is a clean constant 5.0v so have removed VREF, I have changed the:

    res = ADC_Get_Sample(6); // Get 10-bit results of ADconversion
    R_IN = res * VREF/1024.0; // Calculate R1-IN in Volts

    to

    res = ADC_Get_Sample(6); // Get 10-bit results of ADconversion
    R_IN = rail_res * 0.00488; // Calculate R1-IN in Volts

    which seems to help matters, I am trying to improve the code further as I am now confident this is where the problem lies.

    I have only been studying electronics for 6 months so forgive any obvious errors on my part. Instead of declaring R_IN and R2_IN as float, is there a better or more efficient declaration?

    Thanks guys.
     
    Last edited: Apr 6, 2014
  9. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    There is nothing to forgive, this is what learning is all about. Can you give me your PWM timings please that produce the averaged d.c? I would like to try something. Even though the fault might be in the software I am still not happy with the hardware arrangement.
    OMO
    Adam
     
  10. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    Hi Adam

    OK, so we are using PIC18F45K22 with internal osc set to 16MHz, we are setting PWM at 20KHz which is giving us an output of 1253Hz.

    I will upload our latest schematic tonight as it has changed slightly.

    We are basically pulling a variable 0-5v dc voltage from a transducer, through a unity gain buffer, converting thru ADC, adapting the value by a known percentage, outputting by PWM filtered to a dc voltage back thru unity gain buffer to output. Not a complicated job I would not think, but it is throwing serious headaches my way. Appreciate all inputs.
     
  11. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    Updated schematic

    Any patent errors?

    Thanks
     

    Attached Files:

  12. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    So 1253Hz should be equivalent to what 5V out from the last buffer or 0V? Is this a square wave? if not what duty cycle are you using. Can you give me the range of frequencies that you are using to give you a 0-5V out of the last buffer.
    Adam
     
  13. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    Hi, PWM is constant at all voltages, as we are filtering to DC, but we have a solution now of sorts. Seems the compiler was not switching internal clock speed to 16MHz and was running on default 1MHz. This seems to have cured it. Am interested though if you think there is an error on our buffer set up?
     
  14. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    Can you explain with your software fix why this caused the buffer to suddenly go up rather than down at 0.9V? Does it do this now?
    PWM is constant at all voltages? I don't understand this then how does the filter average out different voltages then? Sorry might not be understanding what your doing. PWM indicates you are changing the pulse width the name PWM is the action of modulating the pulse width i.e. changing it. Just outputting a pulse train is not what I would call PWM.
    Sorry if I sound Dumb
    Adam
     
  15. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    Sorry Adam maybe I didn't explain it right, our PWM frequency is static, but we are varying the Pulse width (but same frequency). I will test this further tomorrow and let you know as my test gear is at work, on the bench supply the hardware/software has always worked perfectly which is odd. Our PWM frequency is now set to 4KHz, only the duty cycle is changing to give us a voltage (square wave) the filter then filters to analogue then to DC.

    Thanks
     
  16. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    Ah that makes sense. So a 50-50 DC your hoping to get 2.5V I guess
    Thanks
    Adam
     
  17. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    Correct. Tested today and at 0.95v any attempt to reduce the output voltage still causes a rise on the input to around 1.10v. Does not do this on the bench supply, works perfect there! But from there it seems to rise at the right ratio all the way to 5.00v.
     
  18. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    Did you get the timings for me? What is the duty cycle from the processor for when you expect to see 0.95V on the output of the opamp.
     
  19. diagnostix

    diagnostix

    15
    0
    Apr 2, 2014
    100% / 5 x. 95 = 19% duty. Thanks.
     
  20. Arouse1973

    Arouse1973 Adam

    5,165
    1,087
    Dec 18, 2013
    Thanks
    Adam
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-