I think about buying an Arduino Due for an inertial motorbike power bench. It's in fact a big roll (around 500 kg) that a bike accelerates... and measuring its acceleration, since we know its inertia, we can compute the power applied by the wheel of the motorbike.
I would need to know how precise is the Master Clock (MCK) of the Due, in ppm or % ?
I would need a precision of at least 0.1 % or better 0.01% (and to be sure of this precision)
The new version of Arduino DUE has an external crystal, unlike the previous ones which have or not the external crystal. This external crystal is more precise than the internal RC oscillator, however even the external crystal is not as stable as a temperature compensated oscillator.
See section PMC of Sam3x datasheet for uc capability to use an external clock input.
Thank's for your answer. It seems that when using peripheral clock for timers, this external clock has to have a 2.5 lower freqeuncy than the peripheral one.
Do I say something wrong by saying : epriphal clock can be set to main clock (Figure 28-2. page 527) with:
CSS = MAINCK
PRES = 1
So could it be correct to plug a TCX0 on XC0 pin to increment Timer0 with a 1/MCK period ? (in fact I would need a lower period, around 1/1MHz)
I found the Due section but isn't it possible to make a research in this to find subjects speaking of Timer Capture ? I am quite new to the forum and surprised not to find this possibility in fact
Here is an example of a Timer Capture to detect frequency and duty cycle of a PWM signal:
// a jumper needs to be installed between pin 7 (PWM output) and pin A7 (TC0 channel 1 TIOA pin)
volatile uint32_t CaptureCountA, CaptureCountB, Period, Duty, TimerCount;
volatile boolean CaptureFlag;
void setup() {
Serial.begin(250000); // initilize serial port to 250000 baud
analogWriteResolution(12); // From 0 to 2exp12 - 1 = 4095
analogWrite(7, 1024); // Duty cycle is 25% with 12 bits resolution
PMC->PMC_PCER0 |= PMC_PCER0_PID28; // Timer Counter 0 channel 1 IS TC1
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKDIS ; // disable internal clocking while setup regs
TC0->TC_CHANNEL[1].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 // capture mode, MCK/2, clk on rising edge
| TC_CMR_ABETRG // TIOA 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_IER |= TC_IER_LDRAS | TC_IER_LDRBS; // Trigger interruption on Load RA and load RB
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger and enable
//NVIC_DisableIRQ(TC1_IRQn);
//NVIC_ClearPendingIRQ(TC1_IRQn);
//NVIC_SetPriority(TC1_IRQn, 0); // Give TC1 interrupt the highest urgency
NVIC_EnableIRQ(TC1_IRQn); // Enable TC1 interrupts
Serial.println("Timer Capture begins");
}
void loop() {
if (CaptureFlag) {
CaptureFlag = 0;
}
}
void TC1_Handler() {
static uint32_t _CaptureCountA = 0;
//Registers A and B (RA and RB) are used as capture registers. They are loaded with
//the counter value TC_CV when a programmable event occurs on the signal TIOA.
// TimerCount = (uint32_t) TC0->TC_CHANNEL[1].TC_CV; // save the timer counter register, for testing
uint32_t status = TC0->TC_CHANNEL[1].TC_SR; // Read & Save satus register -->Clear status register
// If TC_SR_LOVRSRA is set, RA or RB have been loaded at least twice without any read
// of the corresponding register since the last read of the Status Register,
// We are losing some values,trigger of TC_Handler is not fast enough !!
//if (status & TC_SR_LOVRS) abort();
if (status & TC_SR_LDRAS) { // If ISR is fired by LDRAS then ....
CaptureCountA = (uint32_t) TC0->TC_CHANNEL[1].TC_RA; // get data from capture register A for TC0 channel 1
}
else { /*if ((status & TC_SR_LDRBS) == TC_SR_LDRBS)*/ // If ISR is fired by LDRBS then ....
CaptureCountB = (uint32_t) TC0->TC_CHANNEL[1].TC_RB; // get data from caputre register B for TC0 channel 1
CaptureFlag = 1; // set flag indicating a new capture value is present
}
Period = CaptureCountA - _CaptureCountA;
Duty = CaptureCountB - _CaptureCountA;
_CaptureCountA = CaptureCountA;
}
So since my initial wish is to use an external frequence to get more precise time measurements, what I could do is to measure the number of rising edges (I could use TC_CV) of a "perfect" frequence coming from an external device (for example a TCX0) to measure the elapsed time between two instants, isn't it ?
If what I say is true, I just learnt the interest of the counters =)
P.S. In your example code, each rising edge what kind of value is retained by CaptureCountA (timer 0 value or the number of counts) ? If it was the number of counts, Period=CaptureCountA-CaptureCountA variable should always be 1 I think since it is calculated each rising edge. I think there is still something I nee to understand in this example.
I think about buying an Arduino Due for an inertial motorbike power bench. It's in fact a big roll (around 500 kg) that a bike accelerates... and measuring its acceleration, since we know its inertia, we can compute the power applied by the wheel of the motorbike.
I would need to know how precise is the Master Clock (MCK) of the Due, in ppm or % ?
I would need a precision of at least 0.1 % or better 0.01% (and to be sure of this precision)
I thank you a lot for your help,
Ulysse
The original Due derives its 84MHz system clock from a 12MHz quartz crystal multiplied up by a PLL,
so the accuracy depends on that crystal's specs. The phase noise will depend on the on-chip PLL,
should timing jitter matter to you that much.
Typical series resonant crystals used for logic clocks are 50, 30, 20 or 10ppm rated.
MarkT I understand your point of view but I always prefer to know exactly the quality of my hardware, for this reason the TCX0 corresponds to mu need.
ard_newbie, I coded the following, but I still have a problem with the registers parametrization, one line does not compile with the message: "'struct TcChannel' has no member named 'TC_BMR'"
I still have an important question. At this time, I am using 2 external interrupts on my Due. The required treament time is less than 5us for sure, so it is not a big problem if the second interrupt occurs when the first ISR is already running, it can wait 5us.
BUT what happened if one of my external interrupts happens during Serial.print("blabla") ? According to the attached table, I deduce that interrupts on external pins are prioritory, isn't it ?
Thank you,
1 Reset
2 External Interrupt Request 0 (pin D2) (INT0_vect)
3 External Interrupt Request 1 (pin D3) (INT1_vect)
4 Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
5 Pin Change Interrupt Request 1 (pins A0 to A5) (PCINT1_vect)
6 Pin Change Interrupt Request 2 (pins D0 to D7) (PCINT2_vect)
7 Watchdog Time-out Interrupt (WDT_vect)
8 Timer/Counter2 Compare Match A (TIMER2_COMPA_vect)
9 Timer/Counter2 Compare Match B (TIMER2_COMPB_vect)
10 Timer/Counter2 Overflow (TIMER2_OVF_vect)
11 Timer/Counter1 Capture Event (TIMER1_CAPT_vect)
12 Timer/Counter1 Compare Match A (TIMER1_COMPA_vect)
13 Timer/Counter1 Compare Match B (TIMER1_COMPB_vect)
14 Timer/Counter1 Overflow (TIMER1_OVF_vect)
15 Timer/Counter0 Compare Match A (TIMER0_COMPA_vect)
16 Timer/Counter0 Compare Match B (TIMER0_COMPB_vect)
17 Timer/Counter0 Overflow (TIMER0_OVF_vect)
18 SPI Serial Transfer Complete (SPI_STC_vect)
19 USART Rx Complete (USART_RX_vect)
20 USART, Data Register Empty (USART_UDRE_vect)
21 USART, Tx Complete (USART_TX_vect)
22 ADC Conversion Complete (ADC_vect)
23 EEPROM Ready (EE_READY_vect)
24 Analog Comparator (ANALOG_COMP_vect)
25 2-wire Serial Interface (I2C) (TWI_vect)
26 Store Program Memory Ready (SPM_READY_vect)