After setting system time via a call to a real-time-clock (RTC), repeated calls to time() always return the same value. Does the system time actually progress on Arduinos or do I need to continue querying the RTC every time I need the time?
To illustrate:
void InitRTC(void) {
DateTime rtcDT; // type defined by the RTC library
time_t bin_time;
rtcDT = rtc.now();
bin_time = rtcDT.secondstime(); // returns unixlike time
set_system_time(bin_time); //AVR call to set the sys time
}
void Dump(time_t t) {
char debug_log_message[MAX_DEBUG_LENGTH];
sprintf(debug_log_message, " time_t:\t %lu", t);
DebugLog(debug_log_message); //....routine to print to the serial port
}
void setup() {
InitRTC();
time_t now;
while (1) {
now = time(0);
Dump(now);
}
}
(safety checks omitted, serial code omitted).
This simply prints the same time for ever - it never progresses!
The standard library has few platform dependencies, so is very portable. However one of those dependencies is the source for real-time, which is entirely platform dependent, and as such it is common for libraries to leave the function as a stub to be re-defined by the user to suit the specific platform or to implement hook functions or call-backs to run the standard library clock.
With the avr-libc used by AVR based Arduino platformsfFor time() to advance it is necessary to call the hook function system_tick() at 1 second intervals (typically from a timer or RTC interrupt) (refer to the avr-libc time.h documentation. It is also necessary to set the time at initialisation using the set_system_time() function.
Invoking system_tick() from a 1Hz timer will then maintain time(), but it is also possible to use an RTC alarm interrupt, by advancing the alarm match target on each interrupt. So you might for example have:
void rtc_interrupt()
{
// Set next interrupt for 1 seconds time.
RTC rtc ;
int next = rtc.getSeconds() + 1 ;
if( next == 60 )
{
next = 0 ;
}
rtc.setAlarmSeconds( next ) ;
// update std time
system_tick() ;
}
void init_system_time()
{
tm component_time ;
RTC rtc ;
// Get *consistent* time components - i.e ensure the
// components are not read either side of a minute boundary
do
{
component_time.tm_sec = rtc.getSeconds() ;
component_time.tm_min = rtc.getMInutes(),
component_time.tm_hour = rtc.getHours(),
component_time.tm_mday = rtc.getDay(),
component_time.tm_mon = rtc.getMonth() - 1, // January = 0 in struct tm
component_time.tm_year = rtc.getYear() + 100 // Years since 1900
} while( component_time.tm_min != rtc.getMinutes() ) ;
set_system_time( mktime( &component_time ) - UNIX_OFFSET ) ;
// Set alarm for now + one second
rtc.attachInterrupt( rtc_interrupt ) ;
rtc.setAlarmSeconds( rtc.getSeconds() + 1 ) ;
rtc.enableAlarm( rtc.MATCH_SS ) ;
}
An alternative is to override time() completely and read the RTC directly on each call - this has the advantage of not requiring any interrupt handlers for example:
#include <time.h>
extern "C" time_t time( time_t* time )
{
tm component_time ;
RTC rtc ;
// Get *consistent* time components - i.e ensure the
// components are not read either side of a minute boundary
do
{
component_time.tm_sec = rtc.getSeconds() ;
component_time.tm_min = rtc.getMInutes(),
component_time.tm_hour = rtc.getHours(),
component_time.tm_mday = rtc.getDay(),
component_time.tm_mon = rtc.getMonth() - 1, // January = 0 in struct tm
component_time.tm_year = rtc.getYear() + 100 // Years since 1900
} while( component_time.tm_min != rtc.getMinutes() ) ;
return mktime( &component_time ) ;
}
I have assumed that the Arduino library getYear() returns years since 2000, and that getMonth() returns 1-12, but neither is documented, so modify as necessary.
Linking the above function before linking libc will cause the library version to be overridden.
Related
in the ESP-IDF doc about RTC, it says:
This timer allows time keeping in various sleep modes, and can also persist time keeping across any resets
I added the below lines to my main function to test it, but every time after rebooting the ESP(not a hard reset), Each time the code inside the if block is executed.
struct timeval current_time;
// printf("seconds : %ld\nmicro seconds : %ld", current_time.tv_sec, current_time.tv_usec);
struct timeval d_time;
d_time.tv_sec = 1000;
d_time.tv_usec = 120;
struct timezone tz;
gettimeofday(¤t_time, NULL);
if (current_time.tv_sec < 100) {
tz.tz_minuteswest = 210;
tz.tz_dsttime = DST_NONE;
settimeofday(&d_time, &tz);
}
so, what should I do to make it work, I couldn't the problem.
thank you.
I'm trying to implement an error handler using the clock() function from the "time.h" library. The code runs inside an embeeded system (Colibri IMX7 - M4 Processor). The function is used to monitor a current value within a specific range, if the value of the current isn't correct the function should return an error message.
The function will see if the error is ocurring and in the first run it will save the first appearance of the error in a clock_t as reference, and then in the next runs if the error is still there, it will compare the current time using clock() with the previous reference and see if it will be longer than a specific time.
The problem is that the function clock() is always returning -1. What should I do to avoid that? Also, why can't I declare a clock_t variable as static (e.g. static clock_t start_t = clock()?
Please see below the function:
bool CrossLink_check_error_LED_UV_current_clock(int current_state, int current_at_LED_UV)
{
bool has_LED_UV_current_deviated = false;
static int current_number_of_errors_Current_LED_CANNON = 0;
clock_t startTimeError = clock();
const int maximum_operational_current_when_on = 2000;
const int minimum_turned_on_LED_UV_current = 45;
if( (current_at_LED_UV > maximum_operational_current_when_on)
||(current_state!=STATE_EMITTING && (current_at_LED_UV > minimum_turned_on_LED_UV_current))
||(current_state==STATE_EMITTING && (current_at_LED_UV < minimum_turned_on_LED_UV_current)) ){
current_number_of_errors_Current_LED_CANNON++;
if(current_number_of_errors_Current_LED_CANNON > 1) {
if (clock() - startTimeError > 50000){ // 50ms
has_LED_UV_current_deviated = true;
PRINTF("current_at_LED_UV: %d", current_at_LED_UV);
if(current_state==STATE_EMITTING){
PRINTF(" at state emitting");
}
PRINTF("\n\r");
}
}else{
if(startTimeError == -1){
startTimeError = clock();
}
}
}else{
startTimeError = 0;
current_number_of_errors_Current_LED_CANNON = 0;
}
return has_LED_UV_current_deviated;
}
Edit: I forgot to mention before, but we are using GCC 9.3.1 arm-none-eabi compiler with CMake to build the executable file. We have an embedeed system (Colibri IMX7 made by Toradex) that consists in 2 A7 Processors that runs our Linux (more visual interface) and the program that is used to control our device runs in a M4 Processor without an OS, just pure bare-metal.
For a lot of provided functions in the c standard library, if you have the documentation installed (usually it gets installed with the compiler), you can view documentation using the man command in the shell. With man clock, it tells me that:
NAME
clock - determine processor time
SYNOPSIS
#include <time.h>
clock_t clock(void);
DESCRIPTION
The clock() function returns an approximation of processor time used by the program.
RETURN VALUE
The value returned is the CPU time used so far as a clock_t; to get the number of seconds used, divide by
CLOCKS_PER_SEC. If the processor time used is not available or its value cannot be represented, the function
returns the value (clock_t) -1.
etc.
This tells us that -1 means that the processor time (CLOCK_PROCESS_CPUTIME_ID) is unavailable. The solution is to use CLOCK_MONOTONIC instead. We can select the clock we want to use with clock_gettime.
timespec clock_time;
if (clock_gettime(CLOCK_MONOTONIC, &clock_time)) {
printf("CLOCK_MONOTONIC is unavailable!\n");
exit(1);
}
printf("Seconds: %d Nanoseconds: %ld\n", clock_time.tv_sec, clock_time.tv_nsec);
To answer the second part of your question:
static clock_t start_time = clock();
is not allowed because the return value of the function clock() is not known until runtime, but in C the initializer of a static variable must be a compile-time constant.
You can write:
static clock_t start_time = 0;
if (start_time == 0)
{
start_time = clock();
}
But this may or may not be suitable to use in this case, depending on whether zero is a legitimate return value of the function. If it could be, you would need something like:
static bool start_time_initialized = false;
static clock_t start_time;
if (!start_time_initialized)
{
start_time_initialized = true;
start_time = clock();
}
The above is reliable only if you cannot have two copies of this function running at once (it is not re-entrant).
If you have a POSIX library available you could use a pthread_once_t to do the same as the above bool but in a re-entrant way. See man pthread_once for details.
Note that C++ allows more complicated options in this area, but you have asked about C.
Note also that abbreviating "start time" as start_t is a very bad idea, because the suffix _t means "type" and should only be used for type names.
in the end the problem was that since we are running our code on bare metal, the clock() function wasn't working. We ended up using an internal timer on the M4 Processor that we found, so now everything is fine. Thanks for the answers.
I would like to use an arduino to read 433 MHz transmission from multiple Soil Moisture Sensors. Since I can never be sure all transmissions reach the receiver I'd like to set a countdown from the moment the first transmission is received. If another transmission is received, the countdown starts again.
After a defined amount of time (e.g. 10 Minutes) without any more signals or if all signals have been received (e.g 4 Sensors) the receiving unit should stop and come to decision based on the data it got to the point.
For transmitting and receiving I am using the <RCSwitch.h>library.
The loop of the receiving unit and one Sensor looks like this:
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
void Setup(){
Serial.begin(9600);
mySwitch.enableReceive(4);
}
void loop() {
if (mySwitch.available()) {
int value = mySwitch.getReceivedValue();
if (value == 0) {
lcd.clear();
Serial.print("Unknown encoding");
}
else {
Serial.print(mySwitch.getReceivedValue());
Serial.print("%");
}
The full code includes some differentiation mechanism for all sensors but I figured that might not be relevant for my question.
Question:
What's the best way to do this without a real time clock module. As far as I know I can't wait by using delay(...)since then I won't receive any data while the processor waiting.
You can use millis() as a clock. It returns the number of milliseconds since the arduino started.
#define MINUTES(x) ((x) * 60000UL)
unsigned long countStart = 0;
void loop()
{
if (/*read from module ok*/)
{
countStart = millis();
// sanity check, since millis() eventually rolls over
if (countStart == 0)
countStart = 1;
}
if (countStart && ((millis() - countStart) > MINUTES(10)))
{
countStart = 0;
// trigger event
}
}
Arduino's internal timers can also be used in this situation. If a long time period is needed, it's better to use 16bit counter (usually timer1) at 1024 prescaler (largest available). If the largest time interval of timer is greater than time required, then a counter have to be added in order to keep track of 1 minute interval.
For example, for 1-minute interval, initialize registers as:
TCCR1A = 0; //Initially setting every register as 0x0000
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 468750; // compare match register 16MHz/1024/2/frequency(hz)
TCCR1B |= (1 << WGM12); // Timer compare mode
TCCR1B |= (1 << CS10) | (1 << CS10); // 1024 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
These configuration of timer will give interrupt time of 1 minute. And upon timer completion ISR TIMER1_COMPA_vect will be run. You can play around with value of OCR1A for different interrupt periods.
Main advantage of using interrupts is that they don't block any task and can will be executed instantaneously (if interrupts are not disabled explicitly).
I'm looking for a way to obtain a guaranteed-monotonic clock which excludes time spent during suspend, just like POSIX CLOCK_MONOTONIC.
Solutions requiring Windows 7 (or later) are acceptable.
Here's an example of something that doesn't work:
LONGLONG suspendTime, uiTime1, uiTime2;
do {
QueryUnbiasedInterruptTime((ULONGLONG*)&uiTime1);
suspendTime = GetTickCount64()*10000 - uiTime1;
QueryUnbiasedInterruptTime((ULONGLONG*)&uiTime2);
} while (uiTime1 != uiTime2);
static LARGE_INTEGER firstSuspend = suspendTime;
static LARGE_INTERER lastSuspend = suspendTime;
assert(suspendTime > lastSuspend);
lastSuspend = suspendTime;
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
static LONGLONG firstQpc = now.QuadPart;
return (now.QuadPart - firstQpc)*qpcFreqNumer/qpcFreqDenom -
(suspendTime - firstSuspend);
The problem with this (my first attempt) is that GetTickCount only ticks every 15ms, wheras QueryUnbiasedInterruptTime seems to tick a little more often, so every now and then my method observes the suspend time go back by a little.
I've also tried using CallNtPowerInformation, but it's not clear how to use those values either to get a nice, race-free measure of suspend time.
The suspend bias time is available in kernel mode (_KUSER_SHARED_DATA.QpcBias in ntddk.h). A read-only copy is available in user mode.
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
LONGLONG suspendTime, uiTime1, uiTime2;
QueryUnbiasedInterruptTime((ULONGLONG*)&uiTime1);
uiTime1 -= USER_SHARED_DATA->QpcBias; // subtract off the suspend bias
The full procedure for calculating monotonic time, which does not tick during suspend, is as follows:
typedef struct _KSYSTEM_TIME {
ULONG LowPart;
LONG High1Time;
LONG High2Time;
} KSYSTEM_TIME;
#define KUSER_SHARED_DATA 0x7ffe0000
#define InterruptTime ((KSYSTEM_TIME volatile*)(KUSER_SHARED_DATA + 0x08))
#define InterruptTimeBias ((ULONGLONG volatile*)(KUSER_SHARED_DATA + 0x3b0))
static LONGLONG readInterruptTime() {
// Reading the InterruptTime from KUSER_SHARED_DATA is much better than
// using GetTickCount() because it doesn't wrap, and is even a little quicker.
// This works on all Windows NT versions (NT4 and up).
LONG timeHigh;
ULONG timeLow;
do {
timeHigh = InterruptTime->High1Time;
timeLow = InterruptTime->LowPart;
} while (timeHigh != InterruptTime->High2Time);
LONGLONG now = ((LONGLONG)timeHigh << 32) + timeLow;
static LONGLONG d = now;
return now - d;
}
static LONGLONG scaleQpc(LONGLONG qpc) {
// We do the actual scaling in fixed-point rather than floating, to make sure
// that we don't violate monotonicity due to rounding errors. There's no
// need to cache QueryPerformanceFrequency().
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
double fraction = 10000000/double(frequency.QuadPart);
LONGLONG denom = 1024;
LONGLONG numer = std::max(1LL, (LONGLONG)(fraction*denom + 0.5));
return qpc * numer / denom;
}
static ULONGLONG readUnbiasedQpc() {
// We remove the suspend bias added to QueryPerformanceCounter results by
// subtracting the interrupt time bias, which is not strictly speaking legal,
// but the units are correct and I think it's impossible for the resulting
// "unbiased QPC" value to go backwards.
LONGLONG interruptTimeBias, qpc;
do {
interruptTimeBias = *InterruptTimeBias;
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
qpc = counter.QuadPart;
} while (interruptTimeBias != *InterruptTimeBias);
static std::pair<LONGLONG,LONGLONG> d(qpc, interruptTimeBias);
return scaleQpc(qpc - d.first) - (interruptTimeBias - d.second);
}
/// getMonotonicTime() returns the time elapsed since the application's first
/// call to getMonotonicTime(), in 100ns units. The values returned are
/// guaranteed to be monotonic. The time ticks in 15ms resolution and advances
/// during suspend on XP and Vista, but we manage to avoid this on Windows 7
/// and 8, which also use a high-precision timer. The time does not wrap after
/// 49 days.
uint64_t getMonotonicTime()
{
OSVERSIONINFOEX ver = { sizeof(OSVERSIONINFOEX), };
GetVersionEx(&ver);
bool win7OrLater = (ver.dwMajorVersion > 6 ||
(ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 1));
// On Windows XP and earlier, QueryPerformanceCounter is not monotonic so we
// steer well clear of it; on Vista, it's just a bit slow.
return win7OrLater ? readUnbiasedQpc() : readInterruptTime();
}
I am using the MSP430F2274 and trying to understand better the uses of Low Power mode.
In my program I am also using the SimplicTi API in order for two devices (one is the AP which is being connected by the other ,ED) to communicate.
AP - Access Point , which is also connected to a PC via the UART in order to recive a string from the user.
ED - End Device , simply connetes to the AP (with the SimplicTi protocol) and waits for messages form it.
I want to be sure I understand the low power mode uses , and to see how it "comes along" with the SimplicTi API.
The "flow" of the AP is as follows (after it is "linked" to the ED , see the code bellow):
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
// **A)** extract the "RXed" character (8 bits received from user) , use the while
// in order to be sure all the 8 bits are "desirialized" into a byte
while (!(IFG2 & UCA0RXIFG));
input_char = UCA0RXBUF; // input_char is global variable.
// **B)** if we received the "Enter" character , which indicates the
// end of the string
if(input_char == '\r' && input_count > 0)
{
TACCR0 = 10; // **F)**
TACTL = TASSEL_1 + MC_1; // ACLK, up mode
// **E)** Enter LPM3, interrupts enabled !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
__bis_SR_register(LPM3_bits + GIE);
}//end if Enter
// **C)** Any other char of the user's string when we
// have not got more than the maximum amount of bytes(chars)
else if (((FIRST_CHAR <= input_char && input_char <= LAST_CHAR) || ('a' <= input_char && input_char <= 'z')) && (input_count < INPUT_MAX_LENGTH))
{
input[input_count++] = input_char;
}
} //end of UART RX INTERRUPT
The TIMERA0 Interrupt Handler is the following code:
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A(void)
{
if (i == strlen(morse)) // **D)** morse is a global array of chars who holds the string that we wish to send
{
SMPL_Send(sLID[0], (uint8_t*)EOT, 1); // EOT is the last char to send
TACTL = MC_0; //disable TimerA0
}
else if (!letterSpace)
{
char ch = morse[i++];
SMPL_Send(sLID[0], (char*)ch, 1);
switch(ch)
{
case '.':
{
TACCR0 = INTERVAL * 3;
letterSpace = 1;
break;
}
case '-':
{
TACCR0 = INTERVAL * 3 * 3;
letterSpace = 1;
break;
}
} // switch
} // else if
} //end TIMERA0 interrupt handler
The thing is like that:
I use the TIMERA0 handler in order to send each byte after a different amount of type , whether the char was transformed into a "-" or a "."
To do so I set the timer accordingly to a different value ( 3 times larger for "-").
Finnaly when I am done transmitting the whole string (D) , I disable the timer.
NOTE : The following method is performed at the begining of the AP code in order to configure the UART:
void UARTinit()
{
P3SEL = 0x30; // P3.4 and P3.5 as the UART TX/RX pins: P3SEL |= BIT4 + BIT5;
UCA0CTL1 |= UCSSEL_2; // SMCLK
// pre scale 1MHz/9600 =~ 104.
UCA0BR0 = 104;
UCA0BR1 = 0;
// 8-bit character and Modulation UCBRSx = 1
UCTL0 |= CHAR;
UCA0MCTL = UCBRS0;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable UART INPUT interrupt
} // end of UARTinit
So my questions are:
1) Just to be sure, in A) where I am "polling" the Rx buffer of the UART , is it necceary or is it just good practise for "any case" , cause AFAIK the UART handler gets called once the UART module recived the whole BYTE (as I configured it)?
2) In the main program of the AP , the last instruction is the one that "puts" it into LPM0 with interrupts enables : __bis_SR_register(LPM0_bits + GIE);
When for LPM0:
CPU is disable
ACLK and SMCLK remain active
MCLK is disabled
And for LPM3:
CPU is disable
MCLK and SMCLK are disabled
ACLK remains active
As I see it ,I can not enter LPM3 cause the AP needs the SMCLK clock not to be disable? (cause the UART uses it)
Is that correct?
3) In F) , is it a proper way to call the TIMERA0 handler ? I perfrom TACRR0 = 10 , cause it is a small value which the timer will reach "in no time" just so it will enter the TIMERA0 handler to perform the task of sending the bytes of the string.
4) For the "roll back" in the AP: As I see it , the "flow" is like that:
enters LPM0 (main) --> UART gets interrputed --> exit LPM0 and goes to the UART handler --> when it is done reciving the bytes (usually 5) it enters LPM3 --> the timer finishes counting to TACRR0 value (which is 10) --> the TIMERA0 handler gets called --> when the TIMERA0 handler done sending the last byte it disables the timer (TACTL0 = MC_0;) --> we "roll back" to the instruction which got us to LPM3 within the UART handler --> ??
Now , does ?? is "rolling back" to the instrcution which took us to LPM0 within the main program , OR do we "stay here" (in the instruction that entered us to LPM3 within the UART handler E) ?
If we do stay on E) , do I need to change it to LPM0 cause , again, the UART uses the SMCLK which is NOT active in LPM3 but indeed active in LPM0 ?
5) Any other comments will be super !!
Thanks allot,
Guy.
1) This will work
2) When you config this:
UCA0CTL1 |= UCSSEL_2; // SMCLK
This mean that UART used SMCLK, SMCLK will stop when you make MCU turn to LPM3;so that
UART will not work, you should config UART use ACLK, this will make UART work in LPM3 mode.
3) ...
4) ...
5) See 2
I hope this will help you