Hi, I am trying to use hardware timer to generate PPS every 1s, with 100ms pulse High and 900ms pulse low. The pulse generate at beginning of every second.
I first check Martin's suggestion for interrupt each 1s. I did a little change, my code is below. Basicly, just add ROS to time message and add pulse generation at TC4_Handler.
#define USE_USBCON
#include <ros.h>
#include <std_msgs/Header.h>
#define PPS_TRIGGER_PIN 16 // pps not stable
ros::NodeHandle nh;
std_msgs::Header header;
ros::Publisher timer("timer", &header);
volatile boolean isRead = false;
// Set timer TC4 to call the TC4_Handler every second
void setup() {
nh.initNode();
nh.advertise(timer);
pinMode(PPS_TRIGGER_PIN, OUTPUT);
digitalWrite(PPS_TRIGGER_PIN, LOW);
// Set up the generic clock (GCLK4) used to clock timers
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK4
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Feed GCLK4 to TC4 and TC5
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TC4 and TC5
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK4 to TC4 and TC5
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_TC4_COUNT16_CC0 = 0xB71A; // Set the TC4 CC0 register as the TOP value in match frequency mode
while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization
//NVIC_DisableIRQ(TC4_IRQn);
//NVIC_ClearPendingIRQ(TC4_IRQn);
NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC)
REG_TC4_INTFLAG |= TC_INTFLAG_OVF; // Clear the interrupt flags
REG_TC4_INTENSET = TC_INTENSET_OVF; // Enable TC4 interrupts
// REG_TC4_INTENCLR = TC_INTENCLR_OVF; // Disable TC4 interrupts
REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz
TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode
TC_CTRLA_ENABLE; // Enable TC4
while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization
}
void loop() {
while(!isRead); // Block until the trigger() function returns
isRead = false; // Reset the count read flag
timer.publish( &header );
nh.spinOnce();
}
void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4
{
// Check for overflow (OVF) interrupt
if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF)
{
// Put your timer overflow (OVF) code here:
// ...
header.stamp = nh.now();
isRead = true;
digitalWrite(PPS_TRIGGER_PIN, HIGH);
delayMicroseconds(100000);
digitalWrite(PPS_TRIGGER_PIN, LOW);
REG_TC4_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag
}
}
The output time are shown below:
secs: 1617982338
nsecs: 583847082secs: 1617982339
nsecs: 484847082secs: 1617982340
nsecs: 385847082secs: 1617982341
nsecs: 583608999secs: 1617982342
nsecs: 484608999secs: 1617982343
nsecs: 385608999
So the timer is seems like interrupt as 900ms, 900ms, 1200ms, 900ms, 900ms... It's definitely related to my generated pulse which is about 100ms. When I remove those pulse generation line, timer works fine.
Any suggestions will be grateful, thanks.