Hello,
I am looking for information and example on programing a led that's is on / off every second, based on a 'timer' interrupt. So far I found very few information on timers.
By the way I am programing in C.
Hello,
I am looking for information and example on programing a led that's is on / off every second, based on a 'timer' interrupt. So far I found very few information on timers.
By the way I am programing in C.
An actual timer interrupt in Linux using C is not trivial. See for example "man timer_create".
You could simply make a never-ending loop (like Arduino) and sleep 1 second every loop. That means your program has just that one function, though. (Of course you could do other things instead of sleeping.)
If you want easy and reliable timer interrupts to do simple hardware things, use a microcontroller like the Pico, not a full Linux Raspberry Pi.
You could always use the poll() function, though the advisability of this depends on what else the program is doing apart from making an LED blink.
For instance, if poll() watches stdin and has a timeout value of 1 second, it would be trivial to use poll() to turn the LED on for a second, then off for a second until a key is hit, and then to write "Exiting NOW" to stdout and exit.
IME its useful to understand how to use poll(). This is because writing and debugging a program that uses it to handle input from several files is a lot simpler and less error-prone than using threads to do the same thing.
sleep()
e.g. #include<stdio.h>
main() { printf("Sleeping for 1 second.\n"); sleep(1); return 0; }
also see usleep() and nanosleep() despite being obsolete they may do what you want if available.
Not strictly true. Windows has never supported nanosleep. On Posix, although deprecated, these days the OS actually translates it as
1000 * nanosleep (which is very much current).
Is interruptible and therefore may terminate early (same applies to poll and almost anything else you can use in C). If it doesn't terminate early it /will/ be late by whatever delay process switching and system load imposes.
There is no really correct way to do this because Linux is not a real time OS - but you can come close[1] on a reasonably quiet system by using nanosleep, checking the time when it returns and either acting or calculating the new interval until you should wake up.
[1] Almost certainly close enough for visual steadiness.
Many thanks, but for the moment I m only testing /evaluating possibilities. I often use timer wile programing microcontrolers (Atmel) but here poll doesn't fit because the target is free running procces in backgound supposed to take some action every second?.
I originally wrote these for an Arduino but it works fine on any Linux computer. It is to be used in a processing loop (eg.. Arduino). It is written in C++ but easy enough to change them to C. The timer uses very little processor and unless you need microsecond accuracy it works fine.
/* * timer.h * * written by: knute johnson - 13 September 2021 * */
#undef FOR_ARDUINO // this code is not for arduino
#ifndef TIMER_H #define TIMER_H
#ifdef FOR_ARDUINO #include <Arduino.h>
#endif
class timer { private: // last time triggered unsigned long last_triggered; // period between triggers unsigned long period; // method to calculate time difference between two millis() readings unsigned long diff(unsigned long, unsigned long); #ifndef FOR_ARDUINO // a millis() function for non-Arduinos unsigned long millis(); #endif // flag is inverted during check() if period has been reached bool flag = false;
public: // create a new timer timer(unsigned long); // check to see if it is later than last trigger plus period bool check(); // reset the last trigger to now void reset(); // gets the status of the flag bool get_flag(); };
#endif /* timer.h */
-----------------------------------------------------------------------------------------------
/* * timer.cpp * * written by: Knute Johnson - 13 September 2021 * * This method is NOT thread safe, all calls to the constructor and the public * methods must be from the same thread. * */
#include "timer.h"
#ifndef FOR_ARDUINO #include <sys/time.h>
#include <cstddef>
#endif
// construct new timer // per - timer period in milliseconds timer::timer(unsigned long per) { period = per; last_triggered = millis(); }
#ifndef FOR_ARDUINO // a millis() function for non-arduino // returns - unsigned long of milliseconds since program started unsigned long timer::millis() { struct timeval tp;
gettimeofday(&tp,NULL); return tp.tv_sec * 1000 + tp.tv_usec / 1000; } #endif
// calculate elapsed time between two millis() readings // returns - unsigned long difference in milliseconds between two millis() // readings unsigned long timer::diff(unsigned long a, unsigned long b) { return a > b ? a - b : b - a; }
// check that the current time has surpassed the last trigger plus period // returns - true if it has been period milliseconds since timer was last // triggered bool timer::check() { unsigned long now = millis();
if (diff(now,last_triggered) >= period) { last_triggered = now; flag = !flag; return true; }
return false; }
// reset the last trigger to now void timer::reset() { last_triggered = millis(); }
// get the state of the flag bool timer::get_flag() { return flag; }
-------------------------------------------------------------------------------------------
Simple test program: #include <stdio.h>
#include <unistd.h>
#include "timer.h"
int main() { timer test(1000); // create a new timer with 1 second timeout int n = 0;
while (1) { if (test.check()) printf("%d:%s\n",n++,test.get_flag() ? "true" : "false"); usleep(100); // sleep for 100us } }
That would be sleep(), then, or possibly usleep() if you want to keep exact clock time by reducing the wait time my the number of microseconds the code in your loop takes to execute. However, don't forget that Linux is NOT a real-time OS and so your program may get suspended or slowed down while a system process executes.
The poll() and the earlier select() library functions are designed to support asynchronous i/o - the function typically watches several channels, which may be character oriented or buffered files. If the timeout is unset, poll() waits until data is received on one of the channels its watching, when it executes code associated with the channel that received the data before going back to waiting for a input on one of the channels. It uses no cpu time while waiting for a event.
If a timeout value is set, if nothing happens until timeout expiry, when poll() exits. When that happens you'd normally normally do any required housekeeping and then call poll() again or, if a 'stop' command is received on stdin, the program might release any resources it holds and exit.
As others have said, if all you want is to stop execution for a fixed amount of time, there are other library functions such as sleep() to do that. sleep() delays by whole seconds but there are other functions that are finer grained down to intervals measured in microseconds and nanoseconds.
If you haven't found them yet, you really need to get to know the 'apropos' and 'man' commands, which are used to search for and display manual pages for everything in Linux from commands to library functions.
If you're new to Linux, you may also want to find a copy of "UNIX Systems Programming" by David Curry - it covers all aspects of writing C programs to run under any of the *nix operating systems. There's a lot in it, but its well organised, well written and contains excellent example code.
-- Martin | martin at Gregorie | gregorie dot org
Just make sure you check that whatever sleep function you are using in whatever language, is doing what you expect for sub-second values, by timing how long it takes do to a few thousand calls.
For example sleeps of down to 1ms may sleep for the expected time, but under that it may either return straight away causing the loop to run too fast, or always sleep for a minimum of 1ms, causing the loop to be too slow.
I've seen this change from platform to platform, and language to language, including on Windows differences between Python 2 (<1ms returned immediately) and Python 3 (minimum sleep of 1ms).
---druck
IIUIC you can set up a timer alarm to send a signal to process after a predetermined time.
Interrupts are kernel space, not user space, so cannot be utilised directly.
>
Why? Linux can do multithreading.
I wouldn't know what windows does. I'm a unix (now linux) user since the 1980s. And AFAIK Pi's don't run windows.
I don't think Microsoft support the Pi, but people seem to find ways
zeneca,
A word of warning :
Most of the people here have adviced to use sleep(). There is something you should be aware of when you chose to use that method :
The distance between two code executions seperated by sleep()s is whatever time you set sleep() to *plus* the time your code takes to do its thing (and before you ask : trying to recalculate the sleep time each step to account for the code-execution delay comes with its own problems).
Opposed to that an event from a system timer will /allways/ be the set time apart [1], regardless of how much time the fired-up code takes.
[1] even though the to-be-fired-up code may be delayed due to another processes timeslice still running.Ofcourse, this is also a timers drawback : if the fired-up code takes more than the set time the next iteration of the fired-up code will start to run when the last one has not yet finished. And that can give .... interresting results. :-)
Bottom line: Using Sleep()s in a loop works good enough when the timing isn't all that important.
Regards, Rudy Wieser
Unless the process gets a signal and doesn't ignore it, in which case the sleep returns as soon as the signal handler is done. Sleep can return early or late, it will never return on time.
Sure. I guess that is why they asked about timer interrupts. But can you give an example of how to use timer interrupts (hardware or otherwise) using C on Raspberry Pi OS? Easy enough on a microcontroller, but ...
As I said already, you need to set a signal and let the kernel return a signal to your process after a timeout. You cannot access interrupts directly from user space in Linux...
Yes, but I wanted to hear Rudy say that. Also, it's still not trivial, is it? It has been too long since I did it, or tried it.
Well handling a timer interrupt in a multitasking environment ain't trivial either.
In essence I think - and I haven't time to try it - its a matter of:
- setting a timer to return a signal after a certain time. (Not sure the exact syntax)
- suspending the thread to wait for the signal. ( use pause() or sigwait() )
In essence signals are the asynchronous message from kernel to user space I guess. Not hardware interrupts!
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.