Go Down

Topic: Fast Low frequency measurement with Due (Read 7159 times) previous topic - next topic

Magician

Quote
Thank you,I didn't see that, but it doesent work. I upload sketch but on serial it doesent print anything
Based on response, I'd expect library can't make any difference.
I don't mind if someone implemented a code in another library, just don't know how to send to github.
There is some nuances, that have to be considered. Code partly rely on Atmel's ASF and  I ca't see, that arduino IDE is included all hardware :

Quote
adc.h can.h dacc.h efc.h emac.h gpbr.h interrupt_sam_nvic.h pio.h pio_it.h pmc.h pwmc.h rstc.h rtc.h rtt.h spi.h ssc.h tc.h timetick.h trng.h twi.h udp.h udphs.h uotghs_device.h uotghs_host.h usart.h USB_device.h USB_host.h wdt.h
There is no issue with tc.h, but I remember, that I can't compile ssc.h Could someone confirm what hardware is in the list of arduino DUE board definition for compiler, and what is not? And if tc.h is in the list today, would it be there in next release of IDE? 

BlackT

I'm the author of FreqMeasure.  So far, nobody has figured out the proper timer defines to make it work on Due.  Or at least nobody has done so and shared them.  If anyone does get it working, I'd be happy to include the defs.

As you can see on the FreqMeasure library page, if you scroll down to "FreqCount vs FreqMeasure", there's 2 basic approaches to measuring digital frequencies.  Counting cycles only works well for higher frequencies.  For low frequencies, measuring cycle time is what you need.

A software-only approach, like the code in #13, can work for very low frequencies.  But it will have small errors due to interrupts, and the limited resolution of the timing functions like millis().  It also can't properly measure while doing other things, like printing to Serial.

I designed FreqMeasure to solve all those problems.  Timer input capture allows very precise measurement, with resolution limited only to the maximum clock speed of the hardware timer.  It also allows each cycles to be measured and stored in a buffer while your sketch does other work, like printing to Serial, so you never lose any input.  Especially for very low frequencies where you must wait for a long cycle to get another measurement, automatically capturing every cycle with hardware and interrupts lets your program be as responsive as possible.

Unfortunately all this great capability does require expert-level knowledge to create the timer defs.  If you're not very experienced with the Due hardware timers (I am not... I know them well on AVR and Kinetis chips, but not SAM3), your best option for high accuracy would be to switch to a board that is well supported.  Or find an expert and convince them to make these defs, and hopefully contribute them so everyone else can use them too.
hello, as I can see your desing  of freq measure is good exacly what I looking for. But problem is I cant compile any off your libary in arduino IDE, for me is no problem to use AVR board i have arduino nano 328u. Then I can send data true rx/tx port on due.

Rufe0

This seems to work for me, use Pin 11.

Code: [Select]
unsigned long lastB;
unsigned long B;
void setup() {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)TC0_IRQn);
pmc_enable_periph_clk((uint32_t)TC8_IRQn);
PIO_Configure(PIOD,PIO_PERIPH_B,PIO_PD8B_TIOB8,PIO_DEFAULT);
PIO_Configure(PIOD,PIO_PERIPH_B,PIO_PD7B_TIOA8,PIO_DEFAULT);
REG_TC2_WPMR=0x54494D00;
TC_Configure(TC2, 2,!TC_CMR_WAVE|TC_CMR_TCCLKS_TIMER_CLOCK1|TC_CMR_LDRB_RISING|TC_CMR_LDRA_FALLING);
TC2->TC_CHANNEL[2].TC_IER=TC_IER_LDRBS;
TC2->TC_CHANNEL[2].TC_IMR=TC_IMR_LDRBS;
TC_Start(TC2, 2);
NVIC_EnableIRQ(TC8_IRQn);
Serial.begin(9600);
}

void loop() {
Serial.println(42000000/(B - lastB));
delay(500);
}

void TC8_Handler()
{
TC_GetStatus(TC2, 2);
lastB=B;
B = TC2->TC_CHANNEL[2].TC_RB;
}

BlackT

Thank you, your sketch is fast and acurrate. But it have one problem, when there is no signal is keep printing the last save signal. And can you modify it to count 2-3 signals

antodom

Hi there,

I have recently announced a library for using the TC modules (Timer Modules) channels of DUE's Atmel ATSAM3X8E micro-controller. You have the announce in this post:

 https://forum.arduino.cc/index.php?topic=144446.msg2562995#msg2562995

The name of the library is tc_lib, and is available at: https://github.com/antodom/tc_lib

The TC module channels available in the ATSAM3X8E working in capture mode can measure duty and period of digital signals directly on hardware. The capture objects available on tc_lib abstract the use of TC module channels in capture mode.

Using a tc_lib capture object is easy, just have a look to the capture_test.ino example that comes with the library. The example measures a PWM signal generated on pin 7 with analgoWrite(). I think the example is self-explaining but if there is any doubt just tell me.

I have check the library with plenty of signals so @Yossi  I think you should not have any problem to get the frequency and duty of a digital signal in the interval of 1-200 Hz that you want. In its present version capture objects can measure signals of a maximum period of about 102 seconds.

I hope it helps.
------------
antodom

Rufe0

antodom's library looks good, but if you still wanted to use mine then this would average 3 samples.
Code: [Select]

const int sampleSize = 3;
const int Max = 42000000/500; //Filter errors Max 500Hz measurment
int samples[sampleSize];
unsigned long lastB;
unsigned long B = 0;
int c = 0;
int i = 0;
int num = 0;
int total;
void setup() {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)TC0_IRQn);
pmc_enable_periph_clk((uint32_t)TC8_IRQn);
PIO_Configure(PIOD,PIO_PERIPH_B,PIO_PD8B_TIOB8,PIO_DEFAULT);
PIO_Configure(PIOD,PIO_PERIPH_B,PIO_PD7B_TIOA8,PIO_DEFAULT);
REG_TC2_WPMR=0x54494D00;
TC_Configure(TC2, 2,!TC_CMR_WAVE|TC_CMR_TCCLKS_TIMER_CLOCK1|TC_CMR_LDRB_RISING|TC_CMR_LDRA_FALLING);
TC2->TC_CHANNEL[2].TC_IER=TC_IER_LDRBS;
TC2->TC_CHANNEL[2].TC_IMR=TC_IMR_LDRBS;
TC_Start(TC2, 2);
NVIC_EnableIRQ(TC8_IRQn);
Serial.begin(9600);
}

void loop() {
total = 0;
num = 0;
for (i = 0; i < sampleSize; i = i + 1) {
if(samples[i]>0){
total += samples[i];
samples[i] = 0;
num++;
}
}
Serial.println(total/num);
delay(500);
}

void TC8_Handler()
{
TC_GetStatus(TC2, 2);
lastB=B;
B = TC2->TC_CHANNEL[2].TC_RB;
if((B - lastB)>Max&&(B - lastB)<42000000){
samples[c] = 42000000/(B - lastB);
c ++;
if(c>sampleSize){
c = 0;
}
}
}

BlackT

Hi there,

I have recently announced a library for using the TC modules (Timer Modules) channels of DUE's Atmel ATSAM3X8E micro-controller. You have the announce in this post:

 https://forum.arduino.cc/index.php?topic=144446.msg2562995#msg2562995

The name of the library is tc_lib, and is available at: https://github.com/antodom/tc_lib

The TC module channels available in the ATSAM3X8E working in capture mode can measure duty and period of digital signals directly on hardware. The capture objects available on tc_lib abstract the use of TC module channels in capture mode.

Using a tc_lib capture object is easy, just have a look to the capture_test.ino example that comes with the library. The example measures a PWM signal generated on pin 7 with analgoWrite(). I think the example is self-explaining but if there is any doubt just tell me.

I have check the library with plenty of signals so @Yossi  I think you should not have any problem to get the frequency and duty of a digital signal in the interval of 1-200 Hz that you want. In its present version capture objects can measure signals of a maximum period of about 102 seconds.

I hope it helps.
Thank you for your response, unfortunately i can't complie it




antodom's library looks good, but if you still wanted to use mine then this would average 3 samples.
Code: [Select]

const int sampleSize = 3;
const int Max = 42000000/500; //Filter errors Max 500Hz measurment
int samples[sampleSize];
unsigned long lastB;
unsigned long B = 0;
int c = 0;
int i = 0;
int num = 0;
int total;
void setup() {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)TC0_IRQn);
pmc_enable_periph_clk((uint32_t)TC8_IRQn);
PIO_Configure(PIOD,PIO_PERIPH_B,PIO_PD8B_TIOB8,PIO_DEFAULT);
PIO_Configure(PIOD,PIO_PERIPH_B,PIO_PD7B_TIOA8,PIO_DEFAULT);
REG_TC2_WPMR=0x54494D00;
TC_Configure(TC2, 2,!TC_CMR_WAVE|TC_CMR_TCCLKS_TIMER_CLOCK1|TC_CMR_LDRB_RISING|TC_CMR_LDRA_FALLING);
TC2->TC_CHANNEL[2].TC_IER=TC_IER_LDRBS;
TC2->TC_CHANNEL[2].TC_IMR=TC_IMR_LDRBS;
TC_Start(TC2, 2);
NVIC_EnableIRQ(TC8_IRQn);
Serial.begin(9600);
}

void loop() {
total = 0;
num = 0;
for (i = 0; i < sampleSize; i = i + 1) {
if(samples[i]>0){
total += samples[i];
samples[i] = 0;
num++;
}
}
Serial.println(total/num);
delay(500);
}

void TC8_Handler()
{
TC_GetStatus(TC2, 2);
lastB=B;
B = TC2->TC_CHANNEL[2].TC_RB;
if((B - lastB)>Max&&(B - lastB)<42000000){
samples[c] = 42000000/(B - lastB);
c ++;
if(c>sampleSize){
c = 0;
}
}
}

At first view program looks good :) with 200 delay it count good till 25 hz,that is 0.2 sec resposne. For me enought.  I will test it later in My main program(with display) ande come here with feedback :)

antodom

Hi @BlackT,

As you are using Arduino IDE 1.6.5, maybe you have not activated -std=gnu++11 flag in DUE's platform file. As commented in tc_lib's README.md:

Quote
For using it you just have to copy the library on the libraries folder used by your Arduino IDE, the folder should be named "tc_lib".

In addition you must add the flag -std=gnu++11 for compiling. For doing that add -std=gnu++11 to the platform.txt file, concretely to compiler.cpp.flags. In Arduino IDE 1.6.6 and greater versions this flag is already set.
I suspect/guess that's the reason it is not compiling. In any case if you can provide me with the whole output of the compilation process, I could give you more specific help.
------------
antodom

BlackT



here is a full error message
https://www.dropbox.com/s/0uwbc5a2scb2yt0/erorr%20program%20antodom.txt?dl=0


is this correct?

antodom

Hi there @BlackT,

As you can see in your compilation output:

Quote
...
In file included from c:\users\audi\appdata\roaming\arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\arm-none-eabi\include\c++\4.8.3\cstdint:35:0,
                 from C:\Program Files (x86)\Arduino\libraries\tc_lib/tc_lib.h:39,
                 from capture_test.ino:35:
c:\users\audi\appdata\roaming\arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\arm-none-eabi\include\c++\4.8.3\bits\c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
...
You must set flag -std=gnu++11 in compiler.cpp.flags:

Quote
compiler.cpp.flags=-c -g -Os -std=gnu++11 {compiler.warning_flags} -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -MMD
Take into account that the platform.txt file you must modify is the one for the DUE, you should find it in "c:\users\audi\appdata\roaming\arduino15\packages\arduino\hardware\sam\1.6.4\cores\arduino".


------------
antodom

BlackT

@antodom I tested your program and for now is doing job perfect, even with lot of function in my program with display. Thank you very much :)
@Rufe0 thank you too :)

antodom

@BlackT, I am glad you found tc_lib useful, thanks for using it :)
------------
antodom

Go Up