Tuesday, November 10, 2015

Atollic returns to no code limit

In the year 2011 I was in the search for free programming solutions for the STM32 Discovery boards when I found the Atollic True Studio Lite. It was a very interesting product. Based on Eclipse, it provided all the necessary tools to develop on ARM MCUs. It had some functionality limitations in the free version but It was very good for learning and teaching MCU programming.

That ended at the start of 2012 when Atollic decided to set at 32KB code limit in True Studio Lite. When programming a STM32F4 Discovery board that features 1MB of flash, a code limit of 32KB is a joke. Moreover, it made impossible to integrate an RTOS and some middleware in the code. As I was using ChibiOS at this time, this limitation was very important to me. I complained to Atollic, but, in the end, I found that I was out of the user group that Atollic was targetting. So, I moved on, leaved Atollic alone, and developed my own Eclipse based environment and used it for learning and teaching. That was dificult because the debug was quite difficult to setup at that time and ChibiOS didn't had come with ChibiStudio yet.

Now, at the end of 2015, almost four years after Atollic introduced the code limit in True Studio Lite, Atollic has decided to remove it. That is good news because ST provides examples for True Studio for its evaluation boards so it eases a lot the developement. Perhaps it is time to check again what Atollic has to offer but now there are quite more free options to develop in ARM MCUs that there were at the start of 2012. And now I have my own toolchain.

But for anyone willing to program the cheap evaluation boards that ST and others like Freescale provide,  Atollic True Studio Lite is a free solution that should be taken into account now that the code limit is removed.

Friday, May 29, 2015

LED lights deadbug style

This will be a brief article about building some LED lights to illuminate small things. The objective is to create some lights that can be oriented as needed to iluminate small objets to work on.

Schematic of the circuit

The basic circuit is a constant current driver using a NPN transistor. The 6k8 resistor, the 1N4148 diode and the adjustable resistor set the base voltage at the transistor between about 0.6V and 1.2V. That sets the votage at Re between 0 and 0.6V. The current at the transistor collecto will be between 0 and 0.6V/Re.
For instance, selecting a 15Ohm resistor we can get currents on the LED up to 27mA.

To power the circuit we will use a 2x6 100 mill spaced connector (J1). This connector works in a pseudocoaxial way with ground at the outer pins and +5V at the center. Having two rows enables us to chain several independent LED drive circuits.

The LED is also connected to the circuit using a 3 pin pseudocoaxial connector (J2) with +5V on the outer pin and the drive current on the center.

The circuit is mounted on a scrap piece of two sided copper PCB. The connections are done directly on the copper using deadbug style.

Deadbug circuit

We want the LEDs to be able to be positioned in the position we want. To do that a SMD LED is mounted on a rigid wire soldered to the current pin at  the center of a 3 pin male connector. A second thin wire provides the +5V supply on one of the outer connector pins.

LED connected to a rigid wire
In order to have two independent LED lights I have build two twin circuits.

Twin LED drivers

Next figure shows the detail of the supply J1 connector.

Supply connector
This connector enables us to chain both boards

Chain power to the twin drivers

Now we can put the LEDs on the driver boards

Twin lights
We can also use different LED colors, although this is less usefull.

Green and White lights

That's all for now. This was only a little project to iluminate small spaces. In fact, with the size of the SMD LEDs, we can practically illuminate anything regardless of the space we have to route the lights.

Saturday, January 17, 2015

Fast ADC on Arduino Leonardo

Last December I wrote about generating fast PWM on the Arduino Leonardo board.
This time I will follow my ideas of going beyond stock vanilla Arduino talking about the ADC.

The problem

You can use the Arduino analogRead function to read an analog value on one of the analog enabled pins. On the Arduino Leonardo there are 12 analog inputs. The typical A0 to A5 six standard Arduino inputs and the additional six lines A6 to A11 that correspond to D4, D6, D8, D9, D10 and D12. 
The ADCs contained in the Atmega MCUs used in Arduino boards are 10 bit converters. To do one conversion the analogRead function takes 100us. It is supposed that the MCU needs that much time to give a 10 bit precision conversion. But 100us, for some applications, can be too much time. It limits, in fact, the maximum analog sample frequency to 10kHz and this doesn't take into account the time needed to process the read data.

You can do better. You can do faster. But, as is normal in life, there must be some trade offs. So, if you want to do faster conversions you need to know what are you trading for them.

The ATmega 32u4 ADC

I suspect that other ATmega based Arduinos include a similar ADC, but I don't know for sure. The ADC uses an internal clock that is obtained from the system clock (16MHz on Arduino Leonardo) which is divided by factor between 2 and 128 using an special register setting. 

On the Arduino Leonardo, the divider is set to the maximum 128 value so, at 16MHz master clock frequency we get a 125kHz ADC clock frequency.
To obtain the time needed to do a conversion from the ADC clock frequency we can refer to one table in the ATmega 42u4 datasheet.

Number of cycles to do a conversion
There are three kinds of conversion: First Conversion, Normal Conversions and Auto Triggered Conversion. The ones that apply to analogRead are the two first ones, but the first only applies to the first conversion so we can use the central column (Normal Conversion) as the typical case.

The ADC needs to do two things to provide a conversion: Sample and Hold and SAR Conversion. In the table we find that those needs 1.5 and 13 cycles for a total of 14.4 cycles. As the ADC frequency is 125kHz, the total ADC time is 14.5/125kHz  =  116 us. That's where the about 100us analogRead time comes from.

The MCU datasheet states that we need an ADC frequency between 50kHz and 200kHz to get the maximum 10 bit resolution. With a 200kHz frequency we could shorten the total ADC time to 72,5us. Unfortunately the clock divider option next to 128 is 64 so, we cannot select 200kHz. We can only select 125kHz, 250kHz... Any option beyond 125kHz, using a 16MHz master clock, goes beyond the Atmel recommendations for the MCU.

Separating the two things the ADC does we get 12us Sample and Hold time and 104us SAR Conversion time. If we increase the ADC frequency we could shorten those times but. We know that we won't get maximum resolution but, ¿What are exactly the side effecs?

Sample and Hold

To understand the Sample and Hold we can use one of the figures in the ATmega 32u4 datasheet:

The Sample and Hold (S&H) circuit is composed on a switch, a resistor and a capacitor. At the start of the conversion the switch is closed during the sample time (1.5 ADC clock cycles). After that, the switch is open and the ADC SAR circuit does the real conversion. The S&H circuit is important because the signal should not change during the SAR conversion. That is guaranteed by the fact that the switch is open during the conversion.

One fundamental point about S&H circuits is that the capacitor need to be charged to the input voltage, during the sample time, before the conversion starts. As this is an RC circuit, in theory, the capacitor voltage will never reach the input one. In practice we only need to get as close to the input voltage as is needed for the converter resolution. For a 10 bit ADC, in order to get a negligible error we need to get to 1/2^11 of the ADC reference value that is normally 5V for Arduino boards.

The RC charging, assuming the worst case of capacitor at zero will be modelled by:

In the worst case, the input voltage will be 5V and to meet the required 10 bit precision the input value capacitor value should get to 1/2^11 of the input value.

That will get:

At 125kHz ADC clock operation we know that the sample time is 12us, so the time constant should be 1,57us or less. As the capacitance is 14pF, the total resistance should be below 112 kOhm. As the ADC internal resistance can go up to 100k, that limits the external resistance to about 12kOhm. That is consistent with the fact that the MCU datasheet recommends external resistances to the ADC of 10 kOhm or  less.

The above formula is quite important. When using the ADC. At a 16MHz master frequency the sample time cannot be bigger than 12us so you should not use a total external resistance to the ADC greater than 12 kOhm. Using a greater resistance could limit the ADC resolution lowering the effective number of bits you get from the ADC.

If, for instance, you only need 8 bits because you are discarding the 4 lower bits resulting from the conversion, you only need to have a 5,4 us time constant (sampling time divided by ln(9) ) so, with the same 14pF ADC capacitance you will only need a total resistance below 386k Ohm. Considering the maximum 100k internal ADC resistance you only need to guarantee a maximum of 286k Ohm external resistance.

SAR Conversion

The ATmega 32u4 MCU uses a Succesive Approximation Register (SAR) to do the conversion. This is the most usual kind of converter that can be found on MCUs. These converters get one bit at a time at each clock cycle. So, in order to get a 10bit value, we need 10 clock cycles. From the table found on the datasheet we know that the actual conversion takes 13 cycles. The extra 3 cycles are probably for synchronization tasks.

Increasing the clock frequency during the conversion operation will affect the ADC resolution but the effect is not easy to model although it can be measured. Fortunately someone has done this measurements.

On the Open Music Labs website you can find this two articles:

They are a quite interesting read and they explain more details on the Sample and Hold operation. The links apply to the ATmega 328p but I don't think that the ATmega 32u4 ADC should be much different.

The result is that increasing the ADC frequency reduces the equivalent number of bits (ENOB) of the conversion. Observe that at the minimum stock 125 kHz frequency the ENOB is not 10 bits but something above 9. Also, at 250 and 500 kHz the ENOB is also over 9 but decaying. At 1MHz the ENOB is over 8. For frequencies greater than that the ENOB falls below 8 bits.

Finally we can find the trade offs of using a bigger ADC frequency:
  • The resolution (number of bits) could be limited by the S&H
  • The resolution (number of bits) will be limited during the conversion
The number of bits of an ADC is an integer number, but the Equivalent Number of Bits (ENOB) is not. At 125kHz, if the S&H is not the limiting factor, you will get about 9,5 bits worth of data. That is, the ratio between the maximum value you can convert and the conversion noise will be limited to a 2^9,5 ratio. If you don't need more than 9 bits of real resolution, you can increase the ADC clock frequency up to 500kHz but you must verify that the S&H is also capable to keep with that speed for your ADC external resistance values. For 8 bit operation you could go to 1MHz. That is eight times the original conversion speed.

Example Program

In order to change the ADC speed clock you need to change the ADC Control and Status Register A (ADCSRA).

The 3 lower bits of this register determine the divider used to obtain the ADC clock from the MCU master frequency.

For 111 we get a 128 prescaler that corresponds to the 125 kHz stock Arduino frequency.
For 110 we get a 64 divider that gets a 250kHz clock. For 101 we get 500kHz and for 100 we get 1MHz.

The following example program just does 4 conversions in a row. The first at the stock 125kHz, the second at 250kHz, the third at 500kHz and the last one at 1MHz.

The program also toggles the Arduino pin 3 before and after each call to analogRead so that the total time associated to this function can be measured.

Output at pin 3
From the mesurement we can see how the analogRead function time halves on each call as the ADCSRA register is changed to obtain greater ADC frequencies.

Fortunately the analogRead function itself doesn't modify the ADCSRA register. If that was the case we could not hack the ADC speed without creating a new analogRead function.

Code on Github (11/02/2018)

The  code is now on Github: