8 years, 8 months ago.

Conflicts between Ticker, Analog In, Timer, USB HID, Serial Port?

I'm trying to use a FRDM-KL25z to acquire a voltage signal at 1 KHz. To ensure the timing I tried to use an interruption (Ticker). Around 150 us are needed to get a conversion from ai.read_u16(), so there is plenty time in between interruptions to do other stuff (dividing the number in two separate bytes, placing both in an array, when the array is full sending it to the PC, ...)

My question is if there is any conflict using a Ticker, Analog In and a Timer altogether in the same program (do they share counters)? I tried to acquire known low frequency squares, ramps and sines but the results are not right. I send the acquired data through USB HID (with hid.sendNB) or through serial (with printf).

I tried both options: placing the code to read the ADC inside the function attached to the ticker, and also just using it to set a flag and reading the ADC on the main. Both worked, but as I said, the acquired data shows there's a timing error on the acquisition.

Maybe it is better to use an external clock and use an external interrupt? Or do you suggest any other path?

1 Answer

8 years, 8 months ago.

AnalogIn can be a pain to get stable readings. I tend to use an average of 100 readings otherwise the results will drift around quite a bit. But that does depend how 'clean' vrefh is. The FRDM board does not have enough filtering for this.

I don't think the Ticker or anything else will cause a problem, only vrefh. The other consideration is not to run any code in the callback. The code bellow is similar to what I use and get a stable reading down to 0.001 V using my own board with a clean vrefh voltage.

snip, untested

#include "mbed.h"

AnalogIn Vcc(PTA9);

Timer readVcc;

float Vcc;
int readVcc;

void IRQ_callback()
{
    readVcc=1;
} 

void getpower()
{    
    float zVcc=0;int n=0;
    Vcc=0;
    while(n<100)     // get 100 readings
        {        
        Vcc = (Vcc1.read()*3.314);  // vrefh voltage          
        zVcc=zVcc+Vcc;
        n++;
        }    
    Vcc=zVcc/100;  // average of the 100 readings.
}


int main()
{

     readVcc.attach(& IRQ_callback, 0.001);

     while(1)
        {

        if(readVcc)
           {
           getpower();
           readVcc=0;
           }


           // rest of you code
        
        
        }
 }

I finally found the problem, which was unexpected for me, source of a lot of headhaches. I was developing my code over the one I imported from an example on this site, about USB. Turns out that the mbed library included in that project was messing things up. After deleting mbed.bld, and importing it again with the Wizard, everything started to work!! I discovered just now that you can switch the mbed library revision used in the project (I was using revision 60 and the current one is revision 118).

On the code you posted I would be careful because to acquire 100 points could take too much time, conflicting with the following callback (it depends on the board used, I guess), or even distorting the signal if it is a fast one. (Also, a timer and an int variable share the same name).

Thank you Paul for your answer, you were right, there was no conflict between peripheral libraries! Saludos!

posted by Diego Fainstein 14 Apr 2016