Wednesday, 22 July 2015

Printing/Reading floats on an AVR in Atmel Studio

As part of my lab power supply project I have been coding the control software that runs on the power supply module and drives the DACs/ADCs as well as other things. The plan is to use provide a text based control interface over USB using a USB to UART chip (MCP2200).

I need to print floating point values as strings and parse strings containing floating point values. Turns out this isn't as easy as I hoped!

I am using Atmel Studio 6 and (sensibly) by default it doesn't include code for formatting or parse floats inside printf or scanf. The code to do this is large and would bloat out applications that don't need it.

The way this works is you have to include additional libraries that contain the version of printf and scanf which contain the extra formatting code. So first of all you have to include the libprintf_flt.a and libscanf_flt.a libraries in the linker options. So you right-click your project, choose properties then select the Toolchain tab. Find the AVR/GNU Linker options and select Libraries. Click the gree add icon in the top panel and add printf_flt (the linker adds the lib prefix and .a suffix). Do the same for scanf_flt. If you only need printf and not scanf support you can leave whichever one you don't need out.


When I first did this I found I got link errors like this:


e:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.1061/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.8.1/../../../../avr/lib/avr5\libm.a(mulsf3.o): In function `__mulsf3':
(.text.avr-libc.fplib+0x2): relocation truncated to fit: R_AVR_13_PCREL against symbol `__fp_round' defined in .text.avr-libc.fplib section in e:/program files (x86)/atmel/atmel toolchain/avr8 gcc/native/3.4.1061/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.8.1/../../../../avr/lib/avr5\libm.a(fp_round.o)
  
I searched for quite a bit before I found that the problem is you have to have libm at the BOTTOM of the list. Then it links fine! Thanks for that Atmel!

Then you have to tell the linker to use the float version of the function. For printf you go to the General group under the AVR/GNU Linker and select the last option which is 'Use vprintf library'


For some reason they didn't include a checkbox for scanf. To add scanf you go to Miscellaneous group under the linker options and add the option -Wl,-u,vfscanf manually.



Then you should be able to use printf and scanf with the %f format string and it work correctly.

Why do they make it so hard?

2 comments:

  1. Hello Tom,

    Few days ago I ran into you website which showed the Dave Jones' design of electronic dummy load to be a bit unstable. I am an EE so I have studied about the opamp stability and compensation but it doesn't touches to the practical application of the same.
    I request you to write a blog on finding out what we need to make opamp stable using bode plot be it using some software ? I have seen many videos online explaining what is bode plot but none of them have taken an unstable circuit and walk through every step on how to compensate it ?

    ReplyDelete
  2. I have to say I am far from an expert in this!

    My approach (as I think you saw? here http://wahz.blogspot.com.au/2014/11/constant-current-dummy-load.html) was to model the circuit and any parasitics (like lead inductances) in LTSPICE and then use LTSPICE to plot the open-loop transfer function. From that I could see why the circuit was unstable and then I used ideas from various places I saw on the web to modify it the circuit to get it stable.

    For example this series of videos on op amp loop compensation was excellent. https://www.youtube.com/watch?v=oOsltCa7qBo.
    There are others if you search for this in Google.

    I think there are techniques to measure the open loop transfer function in a real circuit but I've never tried it.

    I'd love to see what you've figured out if you do however!

    Thanks,

    Tom

    ReplyDelete