0
\$\begingroup\$

I have a specific situation i am trying to wrap my head around but i think it should have a general formalism to address the problem.

I have designed a BiQuad controller for a buck converter and i am trying to implement this controller using a uC routine. the design of the BiQuad is done in the S-domain and converting this controller to the discrete form is a well known procedure and no mystery there.

My concern is about the form of the error signal. the error signal is a simple difference between 2 analog signals (V_reference - V_out). i am using ADC converter to sample V_Out that maps it to an integer value in the range [0 - 65536] which correspond to (0 -> Vcc) [vcc here is related to the ADC converter].

now the floating point coefficients of my discrete BiQuad controller need to be a adjusted to accommodate the fact that the error signal i am feeding it is not a real value but an integer mapped value, right ?

while i can covert the ADC reading to a floating point real representation of the error signal , but i would rather do the computation with integer value to make the controller code run faster.

let's assume this simple :

PWM_Duty = a0 * error + a1 * previous_error + b0 * previous_PWM_Duty.

error, previous_error: 32-bit integer value mapped from floating point value by the ADC converter.

a0,a1,b0: floating point coefficients obtained by the controller design.

PWM_Duty,previous_PWM_Duty: the control signal that change the duty cycle of the PWM, it is an integer value between 0 and 100.

my question is how to convert b0, a1 ,a2 to make the control equation do the right controlling it did in the analog world ?

hopefully i am asking the right question here. i would love some reference or books that talk about coding controllers and address this kind of problem.

sorry for the long post :)

\$\endgroup\$
1
  • \$\begingroup\$ IMO, you are wasting your time. Use floating point and if you are afraid, then use a MCU with FPU. \$\endgroup\$ Commented Jan 9, 2016 at 20:45

1 Answer 1

1
\$\begingroup\$

There are actually quite a few references out there on converting floating point algorithms to fixed point. Google "convert floating point algorithm to fixed point" for lots of examples. Some software such as MATLAB can help (not cheap though, you'd need a few toolboxes).

The general approach is to scale the numbers at each operation (by shifts) so that you maintain the maximum number of bits (at least "enough" bits anyway) without any chance of overflowing. In some cases (such as integration) where the numbers can grow without bound under certain conditions you may find it useful to use saturating fractional fixed point math rather than the stock integer algorithms you'll find in C or whatever language you are using.

It will not necessarily be much faster than floating point, it depends on the processor the number of bits you need and so on. For example, if you want to multiply a 24-bit number by a scaling coefficient that is close to 1.000 for calibration, you will most likely have to use long long (64 bit integers) in C because you want to have at least 24 bits in each operand and that will result in a product that can be ~48 bits (you could then discard the lower 24 (or so) bits), but if you try to multiply two 24 bit multipicands in 32 bit math you will get overflow. A 32 bit floating point multiply (with a 24 bit mantissa) may execute faster than a 64 bit integer multiply.

You can think of the scaling as manually handling the exponent in a floating point number.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ +1 for fixed point. A neat hack is to write the code using Ada's generics. Since Ada has direct support for fixed point types of any range and resolution, you can instantiate the generic twice, with a floating point type, and any fixed point type you want. Then it's trivial to compare the accuracy of both methods, and pick the right fixed point type. (Especially if you want to test arbitrary word widths, for implementing in hardware.) \$\endgroup\$
    – user16324
    Commented Jan 9, 2016 at 22:35
  • \$\begingroup\$ @BrianDrummond Well that's a splendid suggestion, and I guess it's all included in GNU Ada? As you say that would be excellent for FPGA implementations. \$\endgroup\$ Commented Jan 9, 2016 at 22:45
  • 1
    \$\begingroup\$ It is - not all gcc installs include Gnat, (Gnu Ada Translator) but it's easy to find ones that do. \$\endgroup\$
    – user16324
    Commented Jan 9, 2016 at 22:46
  • \$\begingroup\$ It might be worth adding that more recent versions of GCC C++ support fixed point arithmetic. Ada's support should be better though, because it gives much finer control of number representation. \$\endgroup\$
    – gbulmer
    Commented Jan 9, 2016 at 23:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.