Hi everyone,
I'm implementating a XRF (x-ray fluorecence) mapping method based on Arduino.
Recently I moved to Arduino DUE because I needed a pure analog output but I found that the Arduino UNO program wasnt running any more.
The problem is that the library I used does not support Arduino DUE and so I'm very disappointed.
The program I wrote for Arduino UNO works properly and it have to count digital signal coming from a spectrometer in order to "integrate" the signal.
I post down here the original program.
Now, how can I replace the library FreqCount.h with something similir for Arduino DUE and make the program working again?
I would love to have a good counter up to frequency of 1MHz.
Thanks a lot for who is gonna help me!
#include <FreqCount.h>
unsigned long count = 0;
unsigned long prior_count=0;
int digPin = 5; //pin di trigger
int valPin = 6; //pin su cui sputa la tensione
int trigPin1 = A1; // trigger analogico
unsigned long startTime=0;
int ciclo=0;
float tens=0;
void setup() {
Serial.begin(4800);
FreqCount.begin(100);
pinMode(digPin, INPUT);
pinMode(valPin, OUTPUT);
}
void loop() {
//int trig = digitalRead(trigPin);
int trig1 = analogRead(trigPin1);
//Serial.println(trig1);
if(trig1<100)
{
while(ciclo<1)
{
//Serial.println(ciclo);
startTime = millis();
//Serial.println(startTime);
while(millis()-startTime < 10000)
{
if (FreqCount.available()){
count = count + FreqCount.read();
if (count != prior_count) {
prior_count = count;
//Serial.println(count);
tens = map(count,900,1100,0,255);
//tens=(tens/5)*255;
//Serial.println(tens);
}}
if (millis()-startTime>10000){
break;
}
}
ciclo=1;
Serial.print(count);
Serial.print(" - ");
Serial.println(tens);
analogWrite(valPin, tens);
}}
else if (trig1>100)
{ciclo=0;
count=0;}
}
//else{ciclo=0;
//count=0;}
The library says that it is compatible with all Arduino architectures, but the documentation says that the frequency input pin varies depending on the board and doesn't mention the Due.
You might need to dig into the library code to find out which pin is used.
Thank you for your reply.
I saw this code on the forum but it cant fit for my scope: I need an object that can increment a counter each time a rising edge of a digital signal is registered.
In other words I need something able to "integrate" the digital signals over a fixed period of time.
I dont understand how to fit those function for my scope.
thank you for the time you will spend on this!
@ard_newbie
thank you a lot for the reply.
I tried to figure out how the code is working, I've read the amtel datasheet and everything sound a littler familiar.
this is how i modified it
/*************************************************************************************************/
/* Capture pin A7 (TC0 channel 1 TIOA1 pin) */
/*************************************************************************************************/
int trigPin1 = A1; // trigger analogico
unsigned long startTime=0;
int valPin = 6; //pin su cui sputa la tensione
int ciclo=0;
float tens=0;
void setup() {
Serial.begin(250000);
/* This part is an Input Capture of the PWM frequency */
/************* Timer Counter 0 Channel 1 to capture PWM pulses thru TIOA1 ************/
PMC->PMC_PCER0 |= PMC_PCER0_PID28; // Timer Counter 0 channel 1 IS TC1
TC0->TC_CHANNEL[1].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 // capture mode, MCK/2, clk on rising edge
// | TC_CMR_ABETRG // TIOA1 is used as the external trigger
| TC_CMR_LDRA_RISING // load RA on rising edge of trigger input
| TC_CMR_LDRB_FALLING; // load RB on falling edge of trigger input
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Reset TC1 counter and enable
}
void loop() {
const uint32_t _F_TC1 = F_CPU / 2; //<************ = TC1 clock
uint32_t CaptureCountA, CaptureCountB, CaptureFlag;
register uint32_t _CaptureCountA;
register uint32_t counter=0;
register uint32_t status;
int trig1 = analogRead(trigPin1);
// Serial.println(trig1);
if(trig1<1000)
{
while(ciclo<1)
{
startTime = millis();
while(millis()-startTime < 10000)
{
while (true) {
status = TC0->TC_CHANNEL[1].TC_SR;
if (status & TC_SR_LDRAS) {
CaptureCountA = TC0->TC_CHANNEL[1].TC_RA; // get data from capture register A of TC0 channel 0
counter++;
printf(" Count = %d \n", counter);
_CaptureCountA = CaptureCountA;
}
}
}
if (millis()-startTime>10000){
break;}
ciclo=1;
Serial.print(" - ");
Serial.println(tens);
analogWrite(valPin, tens);
}
}
else if (trig1>100)
{ciclo=0;
counter=0;}
}
I don't understand why it ignore the commands about the trigger value: I want the counter to reset when a digital input comes in and after, it have to start counting for 10seconds and show the result.
It seems like it ignore the first if(trig1<1000).
(I use an external wave generator connected to pin A7 with a pulse height of 3V and various test frequencies)
Any suggestion?
thanks
Hi everybody,
finally solved. I post the code down here.
It's able to count digital signals in a range of period (IntegrationTime) if triggered by a digital signal measured on analog pin A1.
The only problem is that I was beliving Arduino Due were able to count well up to severall MHz but, from my test, it starts to lose counts at around 100kHz. Any suggestion?
Again thanks @ard_newbie for the hints.
/*************************************************************************************************/
/* ATTENZIONE!!!
/* Arduino DUE accetta segnali TTL max 3,3V (5V bruciano la scheda!)
/* Contatore digitale pin A7 (TC0 channel 1 TIOA1 pin)
/* TRIGGER PIN A1 - segnale alto si ferma, basso acquisisce
/* DAC1 forniscer un valore di tensione tra 0,5 e 2,75V
/*************************************************************************************************/
int trigPin1 = A1; // trigger analogico
int valPin = 6; // pin su cui sputa la tensione
unsigned long startTime = 0;
int ciclo = 0;
float tens = 0;
float counter = 0;
int IntTime = 10000; //integration time, in millisecondi
void setup() {
analogWriteResolution(12);
pinMode(trigPin1, INPUT);
Serial.begin(4800);
/* Inizializzazione del modulo Timer Counter 0 Channel 1 */
/* per registrare valori digitali attraverso TIOA1 */
PMC->PMC_PCER0 |= PMC_PCER0_PID28; // Timer Counter 0 channel 1 IS TC1
TC0->TC_CHANNEL[1].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 // capture mode, MCK/2, clk on rising edge
// | TC_CMR_ABETRG // TIOA1 is used as the external trigger
| TC_CMR_LDRA_RISING // load RA on rising edge of trigger input
| TC_CMR_LDRB_FALLING; // load RB on falling edge of trigger input
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Reset TC1 counter and enable
}
void loop() {
const uint32_t _F_TC1 = F_CPU / 2; //<************ = TC1 clock
uint32_t CaptureCountA;
register uint32_t _CaptureCountA;
register uint32_t status;
int trig1 = analogRead(trigPin1);
//Serial.println(trig1); //Abilitare questa riga per valutare su che sogli impostare il trigger
if (trig1 < 10) //valore di trigger da aggiustare (0V-->0, 3.3V-->1022)
{ while (ciclo < 1)
{ startTime = millis();
while (millis() - startTime < IntTime)
{ status = TC0->TC_CHANNEL[1].TC_SR;
if (status & TC_SR_LDRAS) {
CaptureCountA = TC0->TC_CHANNEL[1].TC_RA; // get data from capture register A of TC0 channel 0
counter++;
_CaptureCountA = CaptureCountA;
}
if (millis() - startTime > IntTime) {
break;
}
}
ciclo = 1;
tens = map(counter, 0, 1000000, 0, 4096); //mappare il valore di tensione in uscita nel range migliore possibile
Serial.print(counter); //tra un lowValue, maxValue per avere la risoluzione migliore possibile
Serial.print("..."); //utilizzati 12bit quindi mapping tra 0 e 4096
Serial.println(tens);
analogWrite(DAC1, tens);
}
}
else if (trig1 > 10)
{ Serial.println(".");
ciclo = 0;
counter = 0;
}
}
I imagine you have already solved your problem, but in any case, you might have look to tc_lib for measuring a digital signal using timer TC modules available in DUE's ATSAM3X8E microcontroller. You can find the library here: https://github.com/antodom/tc_lib.
@HermannSW has done some nice work measuring tc_lib's limits in this post: here