Go Down

Topic: Crossplatform timer api for ChipKIT and Arduino (Read 321 times) previous topic - next topic

sadr0b0t

Aug 23, 2017, 11:44 pm Last Edit: Sep 03, 2017, 09:05 am by sadr0b0t Reason: updated installation instructions
Hello, this is my very simple lib to access timer interrupts API on ChipKIT/PIC32MX and Arduino/AVR without dealing with platform-specific headers and registers.
https://github.com/sadr0b0t/arduino-timer-api

to install

Code: [Select]

cd ~/Arduino/libraries/
git clone https://github.com/sadr0b0t/arduino-timer-api.git


or on github page click Clone or download > Download ZIP, then install arduino-timer-api-master.zip ZIP via Arduino library installation menu.

restart IDE, examples would appear in File/Examples/arduino-timer-api menu

Basic example:
Code: [Select]

#include"timer-api.h"

void setup() {
    Serial.begin(9600);

    // freq 5Hz == 5 ops per second <=>
    // timer period = 200ms
    timer_init_ISR_5Hz(TIMER_DEFAULT);

    // freq 50Hz == 50 ops per second <=>
    // timer period = 20мс
    //timer_init_ISR_50Hz(TIMER_DEFAULT);
  
    pinMode(13, OUTPUT);
}

void loop() {
    Serial.println("Hello from loop!");
    delay(5000);

    // any code here: blocking or non-blocking
}

void timer_handle_interrupts(int timer) {
    static unsigned long prev_time = micros();

    unsigned long _time = micros();
    unsigned long _period = _time - prev_time;
    prev_time = _time;
  
    static int count = 5;

    // print message every 5th interrupt call
    // (with interrupt freq 5Hz - print once per second)
    if(count == 0) {
        Serial.print("goodbye from timer: ");
        Serial.println(_period, DEC);
      
        digitalWrite(13, !digitalRead(13));
      
        count = 5;
    }
    count--;
}


Procedure timer_handle_interrupts would be called with chosen frequency no matter what the main loop contains and doing, so this is a kind of specific multitasking in the same sketch.

Most common frequencies are available with corresponding calls in a cross-platform way:

Code: [Select]

void timer_init_ISR_100KHz(int timer);
void timer_init_ISR_50KHz(int timer);
void timer_init_ISR_20KHz(int timer);
void timer_init_ISR_10KHz(int timer);
void timer_init_ISR_5KHz(int timer);
void timer_init_ISR_2KHz(int timer);
void timer_init_ISR_1KHz(int timer);
void timer_init_ISR_100Hz(int timer);
void timer_init_ISR_50Hz(int timer);
void timer_init_ISR_20Hz(int timer);
void timer_init_ISR_10Hz(int timer);
void timer_init_ISR_5Hz(int timer);


You can also provide your own frequency setting by setting custom timer, prescaler and timer compare adjuster value

Code: [Select]

#include"timer-api.h"

void setup() {
    Serial.begin(9600);

    // http://www.robotshop.com/letsmakerobots/arduino-101-timers-and-interrupts
    // 1. CPU frequency 16Mhz for Arduino
    // 2. maximum timer counter value (256 for 8bit, 65536 for 16bit timer)
    // 3. Divide CPU frequency through the choosen prescaler (16000000 / 256 = 62500)
    // 4. Divide result through the desired frequency (62500 / 2Hz = 31250)
    // 5. Verify the result against the maximum timer counter value (31250 < 65536 success) if fail, choose bigger prescaler.
  
    // Arduino 16МГц
    // Настроим и запустим таймер с периодом 20 миллисекунд (50 срабатываний в секунду == 50Гц):
    // prescaler=1:8, adjustment=40000:
    // 16000000/8/50=40000 (50Hz - срабатывает 50 раз в секунду, т.е. каждые 20мс)
    // Обработчик прерывания от таймера - функция timer_handle_interrupts
    // (с заданными настройками будет вызываться каждые 20мс).
    //timer_init_ISR(TIMER_DEFAULT, TIMER_PRESCALER_1_8, 40000-1);
  
    // ChipKIT PIC32MX 80МГц
    // Настроим и запустим таймер с периодом 20 миллисекунд (50 срабатываний в секунду == 50Гц):
    // prescaler=1:64, adjustment=25000:
    // 80000000/64/25000=50 (срабатывает 50 раз в секунду, т.е. каждые 20мс)
    // Обработчик прерывания от таймера - функция timer_handle_interrupts
    // (с заданными настройками будет вызываться каждые 20мс).
    timer_init_ISR(TIMER_DEFAULT, TIMER_PRESCALER_1_64, 25000-1);
  
    pinMode(13, OUTPUT);
}

void loop() {
    Serial.println("Hello from loop!");
    delay(5000);

    // any code here: blocking or non-blicking
}


/**
 * Процедура, вызываемая прерыванием по событию таймера с заданным периодом.
 */
void timer_handle_interrupts(int timer) {
    static unsigned long prev_time = micros();

    unsigned long _time = micros();
    unsigned long _period = _time - prev_time;
    prev_time = _time;

    static int count = 50;

    // печатаем статус каждые 50 вызовов прерывания,
    // на частоте 50Гц - 1 раз в секунду
    if(count == 0) {
        Serial.print("goodbye from timer: ");
        Serial.println(_period, DEC);
      
        digitalWrite(13, !digitalRead(13));
      
        count = 50;
    }
    count--;
}


But your code might lose cross-platformity in this case.

pert

A lot of Arduino users are not familiar with Git and prefer to install libraries via Library Manager if possible, otherwise by the Clone or download > Download ZIP button on GitHub and then Sketch > Include Library > Add .ZIP Library.... This is only possible if the library is located in the root of the repository. So if you want to make installation as easy as possible I would recommend that you consider moving your library to the repository root folder. These installation methods also eliminate the need to restart the IDE, making the installation process even more simple.

Also, the current installation instructions assumes that the user has their sketchbook folder at ~/Arduino/libraries but this location is OS specific and the sketchbook location can be changed in File > Preferences so you have no assurance this is correct.

sadr0b0t

A lot of Arduino users are not familiar with Git and prefer to install libraries via Library Manager if possible, otherwise by the Clone or download > Download ZIP button on GitHub and then Sketch > Include Library > Add .ZIP Library.... This is only possible if the library is located in the root of the repository. So if you want to make installation as easy as possible I would recommend that you consider moving your library to the repository root folder. These installation methods also eliminate the need to restart the IDE, making the installation process even more simple.

Also, the current installation instructions assumes that the user has their sketchbook folder at ~/Arduino/libraries but this location is OS specific and the sketchbook location can be changed in File > Preferences so you have no assurance this is correct.
Thank's for feedback, I have rapacked repository, so it can be cloned directly to Arduino/libraries dir or installed via ZIP library installation option. Updated initial post.

Also added another example sketch to rotate stepper motor (connected via step-dir driver interface) in background with timer:
https://github.com/sadr0b0t/arduino-timer-api/blob/master/examples/timer-api-stepper/timer-api-stepper.ino

sadr0b0t

added support for Arduino Due (SAM, 32-bit ARM 84MHz)

Go Up