How to use TImer of nrf52480

Why in arduino, after I include the XIAO Nrff52480 board, and the header file
#include <NRF52TimerInterrupt.hpp>
#include <NRF52_ISR_Timer.hpp>
is included, the system still tells me that there is an error.That is

In file included from D:\arduio doucument\hudie\hudie.ino:2:0:
d:\arduio doucument\libraries\NRF52_TimerInterrupt\src/NRF52TimerInterrupt.hpp:86:4: error: #error This code is designed to run on Adafruit or Seeed nRF52 platform! Please check your Tools->Board setting.
   #error This code is designed to run on Adafruit or Seeed nRF52 platform! Please check your Tools->Board setting.
    ^~~~~
In file included from d:\arduio doucument\libraries\NRF52_TimerInterrupt\src/NRF52TimerInterrupt.hpp:118:0,
                 from D:\arduio doucument\hudie\hudie.ino:2:
d:\arduio doucument\libraries\NRF52_TimerInterrupt\src/TimerInterrupt_Generic_Debug.h:42:10: fatal error: Adafruit_TinyUSB.h: No such file or directory
 #include <Adafruit_TinyUSB.h>
          ^~~~~~~~~~~~~~~~~~~~
compilation terminated.

Hi there,

You may have selected the wrong version of the BSP. there are two in the list be sure to pick th ecorrect one, Some LIB’s only work with certain BSP’s (board support package) supplied by the vendors.
With the NRF you the Embed versions 2.9.x and the non-embed versions 1.1.1 for example. Try the other one.

HTH
GL :slight_smile: PJ :v:

common over site… no big deal! :+1:

Thank you for your answer.But I have tried Embed versions 2.9.3、2.9.2、2.9.1,they don’t work.And I didn’t try non-embed versions,because I need to make Something with high power consumption.

Below is my board I selected.


Hi there,

so,

What these libraries do:

  1. NRF52TimerInterrupt
    Lets you create hardware-based timers using the NRF52’s internal timers (TIMER0–4).
    You can set precise periodic interrupts in microseconds or milliseconds.
  2. NRF52_ISR_Timer
    Uses a single hardware timer but allows you to schedule multiple software-based timers, each with its own interval and callback — like a multitimer manager.

Those are compatable with BSP 1.1.1 , Try that first.
then can you post the code you are using, USE the code tags above “</>” paste it in there. You get better reply’s too.

HTH
GL :slight_smile: PJ :v:

doesn’t matter, 1.1.1 will do the same.

Okay,below is the code of .ino,


#include <NRF52TimerInterrupt.hpp>
#include <NRF52_ISR_Timer.hpp>

#include <LSM6DS3.h>


#include "IMU.h"

NRF52Timer ITimer(NRF_TIMER_1);
volatile uint32_t nowtime = 0;//定时器积分参数

#define TIMER0_FREQ_HZ        10000 //定时器定时100us
//IMU积分定时器
void TimerHandler0()
{
  nowtime ++;
  // Doing something here inside ISR
}

//设置速度0-255
void Set_Speed(int PWML,int PWMR)
{
  if(PWML<0)
  {
    analogWrite(8,-PWML);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
  }
  else if(PWML>=0)
  {
    analogWrite(8,PWML);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
  }
    if(PWMR<0)
  {
    analogWrite(9,-PWMR);
    digitalWrite(10, LOW);
    digitalWrite(11, HIGH);
  }
  else if(PWMR>=0)
  {
    analogWrite(9,PWMR);
    digitalWrite(10, HIGH);
    digitalWrite(11, LOW);
  }
}

volatile long encoderCounterL =0; //This variable will increase or decreas depending on the rotation of encoder
volatile long encoderCounterR =0; //This variable will increase or decreas depending on the rotation of encoder

#define encoderPinLA 0
#define encoderPinLB 1
#define encoderPinRA 2
#define encoderPinRB 3

#define xianshu 1024
#define jianshubi 13.5
#define beipin 4

void setup() 
{

  /********
  *端口选择左8 ,AIN16,AIN27
  *右9,BIN110,BIN211
  *
  */
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);

  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
   //编码器输入
   //做点击,0,1
   //右电机, 2,3
  pinMode(encoderPinLA,INPUT);
  pinMode(encoderPinLB,INPUT);
  attachInterrupt(digitalPinToInterrupt(encoderPinLA), doEncoderLA, CHANGE);//B rising pulse from encodenren activated ai1(). AttachInterrupt 1 isDigitalPin nr 3 on moust Arduino.
  attachInterrupt(digitalPinToInterrupt(encoderPinLB), doEncoderLB, CHANGE);

  pinMode(encoderPinRA,INPUT);
  pinMode(encoderPinRB,INPUT);
  attachInterrupt(digitalPinToInterrupt(encoderPinRA), doEncoderRA, CHANGE);//B rising pulse from encodenren activated ai1(). AttachInterrupt 1 isDigitalPin nr 3 on moust Arduino.
  attachInterrupt(digitalPinToInterrupt(encoderPinRB), doEncoderRB, CHANGE);

  //IMU初始化
  IMU_init();
  ITimer.attachInterrupt(TIMER0_FREQ_HZ, TimerHandler0)//imu积分定时器初始化
  delay(20);

  Set_Speed(127,127);//设置初始速度
}
int my_abs(int a)
{
  if(a>0)
  {
    return a;
  }
  else 
  {
    return -a;
  }
}
void loop() {

    if((encoderCounterL*0.667 >=xianshu/jianshubi/beipin)&& (encoderCounterR*0.667 >=xianshu/jianshubi/beipin))
    {
      Set_Speed(-127,-127);
      encoderCounterL = 0;
      encoderCounterR= 0;//计数清0
    }
    else if((encoderCounterL*0.667 <= -xianshu/jianshubi/beipin)&& (encoderCounterR*0.667 <= -xianshu/jianshubi/beipin))
    {
      Set_Speed(127,127);
      encoderCounterL = 0;
      encoderCounterR= 0;//计数清0
    }
}
void doEncoderLA(void)
{
  if (digitalRead(encoderPinLA) == HIGH)//上升沿
   { 

    if (digitalRead(encoderPinLB) == LOW) {  
      encoderCounterL = encoderCounterL + 1;         // CW
    } 
    else {
      encoderCounterL = encoderCounterL - 1;         // CCW
    }
  }
  else   //下降沿                                     
  { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoderPinLB) == HIGH) {   
      encoderCounterL = encoderCounterL + 1;          // CW
    } 
    else {
      encoderCounterL = encoderCounterL - 1;          // CCW
    }
  }

}
void doEncoderLB(void)
{
   if (digitalRead(encoderPinLB) == HIGH)//上升沿
    {   
   // check channel A to see which way encoder is turning
    if (digitalRead(encoderPinLA) == HIGH) {  
      encoderCounterL = encoderCounterL + 1;         // CW
    } 
    else {
      encoderCounterL = encoderCounterL - 1;         // CCW
    }
  }
  // Look for a high-to-low on channel B
  else { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoderPinLA) == LOW) {   
      encoderCounterL = encoderCounterL + 1;          // CW
    } 
    else {
      encoderCounterL = encoderCounterL - 1;          // CCW
    }
  }

}
void doEncoderRA(void)
{
   if (digitalRead(encoderPinRA) == HIGH)//上升沿
   { 

    if (digitalRead(encoderPinRB) == LOW) {  
      encoderCounterR = encoderCounterR + 1;         // CW
    } 
    else {
      encoderCounterR = encoderCounterR - 1;         // CCW
    }
  }
  else   //下降沿                                     
  { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoderPinRB) == HIGH) {   
      encoderCounterR = encoderCounterR + 1;          // CW
    } 
    else {
      encoderCounterR = encoderCounterR - 1;          // CCW
    }
  }
}
void doEncoderRB(void)
{
  if (digitalRead(encoderPinRB) == HIGH)//上升沿
    {   
   // check channel A to see which way encoder is turning
    if (digitalRead(encoderPinRA) == HIGH) {  
      encoderCounterR = encoderCounterR + 1;         // CW
    } 
    else {
      encoderCounterR = encoderCounterR - 1;         // CCW
    }
  }
  else
   { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoderPinRA) == LOW) {   
      encoderCounterR = encoderCounterR + 1;          // CW
    } 
    else {
      encoderCounterR = encoderCounterR - 1;          // CCW
    }
  }
}

HI there,

Ok , so looks like a solid start to something, targeting a real-time control task: motor drive, encoder feedback, and IMU timing — so you’re right to use hardware timers and interrupts.

I don’t have "IMU.h " not sure what you got going on there, but you missed a semicolon in the timer attach
ITimer.attachInterrupt(TIMER0_FREQ_HZ, TimerHandler0); // ← ADD THIS
Also the pins for PWM are not supported on 8 and 9 on BSP 1.1.1 you need to declare them manually for that or
replace analogWrite(pin, val); with analogWrite(PWM_CHANNEL, duty); if using NRF52_PWM library.

I asked our AI , and the interrupts could be an issue at high speed check it out…"
You’re using 4 encoder interrupts (2 per wheel), each running conditional logic and memory writes. That’s acceptable for low RPM, but at higher speed, this could:

  • Starve the CPU
  • Cause missed IMU sampling in TimerHandler0
  • Break BLE, Serial, or other timing-sensitive code

Instead of dual A/B interrupts per encoder, you can reduce to 1 interrupt per wheel (on A) and check B inside the ISR.

For example:

attachInterrupt(digitalPinToInterrupt(encoderPinLA), encoderISR_L, CHANGE);

And inside encoderISR_L():

if (digitalRead(encoderPinLA) == digitalRead(encoderPinLB)) {
  encoderCounterL++;
} else {
  encoderCounterL--;
}

Saves 2 ISR entries per transition = more stable.
YMMV :v:
If using IMU.h from Seeed, confirm you are calling:

IMU.readAcceleration(x, y, z);
IMU.readGyroscope(gx, gy, gz);

I’ll leave it there , I see one or two more optimizations you could make.
Also there is a version of that LIB for embed , if you didn’t know.

HTH
GL :slight_smile: PJ :v:

check out the demo I have on here for Park, Motion, and Fall and also orientation with IMU, It’s an Awesome sensor (search Park IMU) :+1: