As stated in stackoverflow-17135805 the millis() function does not return the correct time, if the interrupts where disabled, while Arduino had to detect an overflow of timer0.
I have a time critical program that uses a lot of functions which have to disable the interrupts. So my program runs 1:30 while it thinks it was running only for 1:00.
Is there another timer that I can use to avoid this problem?
It happens to me when I use the GSM Module:
// startpoint
unsigned long t = 0;
unsigned long start = millis();
while ( (millis()-start) < 30000 ){
//read a chunk from the gprs module
for (int i=0;i<8;i++)
client.read();
//do this loop every 10ms
while( (millis()-start) < t*10 ){};
t++;
}
//endpoint
From the startpoint to the endpoint it should take 30 seconds. Instead it takes 65 seconds.
If you have to disable interrupts so often and so long your best bet would be to use an external timer. I highly recommend DS3231. Since it has a build in crystal it is easier to setup than a 1307 and it is also significantly more accurate.
You could use one of the other hardware timers
to keep track of the time. For example, on the Leonardo Timer 1 is a 16 bit timer.
To set it up directly (this obliterates code portability) there are a couple steps.
TCCR1A = 0;
this puts the timer in "normal" mode, meaning it just runs to 0xFFFF and wraps back to 0x0000.
TCCR3B = 0;
TCCR3B = _BV(CS11) | _BV(CS10);
this starts the timer and sets it to use a clock/64 prescale, which equates to 1 tic every 4us.
To check the time:
long time; // declared somewhere in scope.
time = TCNT1; // this reads the timer count register
time *= 4; // this multiplies time by 4 to give you us.
As mentioned earlier, TCNT1 wraps around at 0xFFFF = 65536. So, with the pre-scaler set as above, that gives you about 65536 * 4E-6 = .262 seconds of counting before your program needs to put the data into a bigger variable (assuming you care). Hopefully it isn't a problem to poll things more often than 4 times a second, which gets you away from interrupts.
Several arduino core functions utilize these timers, so you'll need to verify that the core functions you need don't depend on the timer you choose. For example, doing the above will break analogWrite() on certain pins.
Related
I'm making an LED control program (using FastLED, of course) and using Serial (with the Serial monitor) to control it. I just connected it via USB and for the most part it works just fine. However, I noticed with the long, flashing routines that I couldn't stop them and make the LEDs do something else. The flash routine in my code is very simple:
void flash(CRGB color, int count, int del){
for(int i = 0; i < count; i++){
if(pause){
break;
}
fillLeds(color.r, color.g, color.b);
milliDelay(del);
fillLeds(0,0,0);
milliDelay(del);
}
}
With fillLeds(r,g,b) being a for loop, looping through and setting all LEDs to a certain color, and milliDelay is just delay() using millis and not the delay() function.
I need to be able to pause not just this, but other functions as well (probably using break;) and then execute other code. It seems easy, right? Well, I've noticed that when I send a byte over Serial, it goes into this "queue," if you will, and then is sequentially read.
I can’t have this happen. I need the next byte entering Serial to activate some kind of event that pauses the other flash() function running, and then be used. I have implemented this like:
void loop()
{
if (Serial.available() > 0)
{
int x = Serial.read();
Serial.print(x);
handleRequest(x);
}
FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
}
Where handleRequest(x); is just a long switch statement with calls to the flash method, with different colors being used, etc.
How can I make the Arduino pause other loops whenever a new byte is received, instead of adding it to this "queue" to be acted upon later? If this is not possible thanks for reading anyway. I've tried using serialEvent() which doesn't appear to work.
I think you need two loops. You have one, which is your main loop, and you can add another (like a multi threading) with the TimerOne library. Like this:
Timer1.initialize(your desired delay in this loop);
Timer1.attachInterrupt(your desired function in this loop);
So maybe you can add an if statement with a variable in your second loop to prevent some function and update the variable in your first loop or something like that.
Presuming you want interrupt-like functionality when a new byte arrives:
Unfortunately, serialEvent() is not a true interrupt. It only runs at the end of loop(), if there is serial data available.
However, serialEvent() is just a function, and there isn't any reason why you can't call it in your code as often as you like. This is effectively polling for new serial data as often as possible. So, while your loops are running, call serialEvent() during your delays and handle the serial data there.
You may need to restructure your code to avoid recursion though. If flash calls serialEvent(), which calls flash, which calls serialEvent, etc... then you may end up overflowing the stack.
I'm new at arduino, Here is a problem in inputting data from multiple pins and writing in to other pins, The input comes from transmitter's reciever and it writes data to KK board pins.The code is simple however when it takes an input from one pin the other pin is disabled and the button is not working. Here is the code:
Servo ale, ele;
Void setup()
{
ale.attach(11);
ele.attach(12);
........
.....
}
Void loop()
{
a = pulseIn(6, HIGH, 20000);
b = pulseIn(7, HIGH, 20000);
ale.writeMicroseconds(a);
ele.writeMicroseconds(b);
..........
......
}
Is there something that i'm doing wrong?
The pulseIn function waits for the pin to go high, than waits for the pin to go low and only then it returns and the execution of the program continues for the next line.
If you want to be able to receive input from several pins concurrently, you need to simulate pulseIn behavior over several cycles of loop function.
There are two options (simplified pseudo code):
For each pin separately, every loop cycle you read pin value, if it is transitioning from low to high, a flag a set and you save the current millis. When it goes low again, you measure the current millis and subtract the previous reading. This will give you the a or b.
Same as 1 but instead of checking every loop cycle, you can attach interrupts for low to high and high to low transitions.
I have a problem with arduino due timers. First let me explain what i know of them.I don't know if there is a way to solve this issue for general timers. Due timers features:
1) They always start from zero,
2) They work as UP-COUNTING or UP-DOWN counting timers,
3) Each timer has two compare registers.
My project involves cases to work in sampled times(period), i.e. timer runs for a sampled time and based on values in compare registers the outputs TIOA and TIOB toggles.I am working in up-down mode. Now the problem is when I have zero in a compare register I expect a zero output (on TIOA and TIOB) for whole period. But the timer is toggling output for zero comparison also. i.e. instead of getting a zero always i am getting a square wave with (2*period) as its time period. Is this common problem for other timers also?
Can you guys suggest me a workaround for this problem?
Thanks in advance.
#include <AdvaDueTC.h>
int default_clock = 1;
int RCcntS = 2187*2;
int period0 = 65536;
int a = 2180;
int b = 0;
void subrtn()
{
changeTC_TC3_Period(RCcntS); // loading sampler TC3 with RCcntS
changeTC_TC0_Period(RCcntS/2,a,b); // loading timer TC0 with RCcntT
}
void setup() {
setupTC3_Interrupt(period0,default_clock ,subrtn);//setup sampler interrupt
setupTC_TC0_Timing(period0, default_clock);
}
void loop() {
// put your main code here, to run repeatedly:
}
functions used are :
Here TC3 is in UP mode and TC0 is in UPDOWN mode of operation. TIOA0 and TIOB0 are used for obtaining toggling output.(i.e. in REG_TC0_CMR0, ACPA,BCPB are set to 3). Here TIOB0 is toggling and I want to stay at one valve (0 or 3.3v) for whole period.
Thanks for your suggestion.
when I have zero in a compare register I expect a zero output
i expect the output to be triggered two times (UP and DOWN) every tick (i think you call it period), because the timer is overflowing EVERY tick.
Solution is turn off the timer comparison.
this seems to me a PWM, maybe you'll get better result using the dedicated HW
Yes what you said is correct. At first I couldn't get it but this MCU timer has option to set or clear the timer output value for whole period. so without going for TOGGLE always, I used these options to get desired operation.
A lot of hardware comes with a Tx/Rx status LED, but what if your hardware doesn't and you want to see if data is transmitting? If you just set the LED to the value of the line it may go on and off before you even see it (<1/100th of a sec.).
My question is, how do I write an interrupt driven function to drive the LED state? I've searched the internet and found nothing and I could use a counter with a modulus, but that seems clunky. Any other ideas?
PS - I'd like to use this in either Arduino or Mbed, but I doubt it makes a difference to the question as to which one...
void receive_or_transmit_interrupt()
{
g_traffic = true;
/* other stuff. */
}
void timer_that_fires_every_100_milliseconds()
{
if ( led == ON)
{
led = OFF;
g_traffic = false;
}
else if ( g_traffic )
{
led = ON;
}
}
If you don't want the timer to always be firing even when there's not traffic, you could change the receive_or_transmit_interrupt to enable the timer, and the timer could disable itself when it turns off the LED.
A simple way is to switch the LED on in the Tx/Rx interrupt and initiate a timer of say 200ms (long enough to perceive). You then switch the LED off in the timer ISR.
That way the indicator is extinguished 200 ms after the last tx/rx activity. If the activity is sustained, the indicator will remain illuminated.
If the tx/rx bursts are intermittent with greater than 200ms gaps, the indicator will flicker. So the states of off, on and flickering give a broad indication of the data activity.
I have a GPU with CC 3.0, so it should support 16 concurrent kernels. I am starting 10 kernels by looping through clEnqueueNDRangeKernel for 10 times. How do I get to know that the kernels are executing concurrently?
One way which I have thought is to get the time before and after the NDRangeKernel statement. I might have to use events so as to ensure the execution of the kernel has completed. But I still feel that the loop will start the kernels sequentially. Can someone help me out..
To determine if your kernel executions overlap, you have to profile them. This requires several steps:
1. Creating the command-queues
Profiling data is only collected if the command-queue is created with the property CL_QUEUE_PROFILING_ENABLE:
cl_command_queue queues[10];
for (int i = 0; i < 10; ++i) {
queues[i] = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE,
&errcode);
}
2. Making sure all kernels start at the same time
You are right in your assumption that the CPU queues the kernels sequentially. However, you can create a single user event and add it to the wait list for all kernels. This causes the kernels not to start running before the user event is completed:
// Create the user event
cl_event user_event = clCreateUserEvent(context, &errcode);
// Reserve space for kernel events
cl_event kernel_events[10];
// Enqueue kernels
for (int i = 0; i < 10; ++i) {
clEnqueueNDRangeKernel(queues[i], kernel, work_dim, global_work_offset,
global_work_size, 1, &user_event, &kernel_events[i]);
}
// Start all kernels by completing the user event
clSetUserEventStatus(user_event, CL_COMPLETE);
3. Obtain profiling times
Finally, we can collect the timing information for the kernel events:
// Block until all kernels have run to completion
clWaitForEvents(10, kernel_events);
for (int i = 0; i < 10; ++i) {
cl_ulong start;
clGetEventProfilingInfo(kernel_event[i], CL_PROFILING_COMMAND_START,
sizeof(start), &start, NULL);
cl_ulong end;
clGetEventProfilingInfo(kernel_event[i], CL_PROFILING_COMMAND_END,
sizeof(end), &end, NULL);
printf("Event %d: start=%llu, end=%llu", i, start, end);
}
4. Analyzing the output
Now that you have the start and end times of all kernel runs, you can check for overlaps (either by hand or programmatically). The output units are nanoseconds. Note however that the device timer is only accurate to a certain resolution. You can query the resolution using:
size_t resolution;
clGetDeviceInfo(device, CL_DEVICE_PROFILING_TIMER_RESOLUTION,
sizeof(resolution), &resolution, NULL);
FWIW, I tried this on a NVIDIA device with CC 2.0 (which should support concurrent kernels) and observed that the kernels were run sequentially.
You can avoid all the boilerplate code suggested in the other answers (which are correct by the way) by using C Framework for OpenCL, which simplifies this task a lot, and gives you detailed information about OpenCL events (kernel execution, data transfers, etc), including a table and a plot dedicated to overlapped execution of said events.
I developed this library in order to, among other things, simplify the process described in the other answers. You can see a basic usage example here.
Yes, as you suggest, try to use the events, and analyze all the QUEUED, SUBMIT, START, END values. These should be absolute values in "device time", and you may be able to see if processing (START to END) overlaps for the different kernels.