Improvements in led indication with RTOS code - c

I want to make certain effects with RGB led which changes colour using PWM signals.
|¯¯¯¯¯¯¯¯¯¯||¯¯¯¯¯¯¯¯¯¯||¯¯¯¯¯¯¯¯¯¯|
| Green || Yellow || Pink |
|__________||__________||__________|
15ms 10ms 25ms
|¯¯¯¯¯¯¯¯¯¯||¯¯¯¯¯¯¯¯¯¯||¯¯¯¯¯¯¯¯¯¯|
| Blue || Magneta || Blue |
|__________||__________||__________|
20ms 10ms 20ms
Based on interrupt, these led colours should be displayed on LED.
I made a task specifically for this purpose and running these effects on that task.
while(1)
{
if (indication_type == event_a)
{
led_color_green();
osDelay(15);
led_color_yellow();
osDelay(10);
led_color_pink();
osDelay(25);
}
else if (indication_type == event_b)
{
led_color_blue();
osDelay(20);
led_color_magneta();
osDelay(10);
led_color_blue();
osDelay(20);
}
else
..
..
}
Code is working but there are two issues
Each led effect is visible for 50ms and if an event change has occurred, the led keeps on executing the previous state and a new state is showed after it has exited if-else condition with delay as per current implementation. How can I change the led indication immediately after receiving an interrupt?
I think there should be some clean way to make such effects especially with led. How can I improve this code? Any code reference you can share?
I am using STM32F4 and CMSIS RTOS v2

You need to be able to make a decision about the "indication type" at every time quanta (tick), and switch the sequence immediately.
The following is an outline of one way to do that:
// Color/time descriptor for each sequence
static const struct
{
void (*setcolor)(void) // Pointer to color set function
int showtime ; // Time to display color
} indication_descriptor[][3] =
{
{ {led_color_green, 15}, {led_color_green, 15}, {led_color_green, 15} }, // event_a sequence
{ {led_color_blue, 15}, {led_color_magneta, 15}, {led_color_blue, 15} }, // event_b sequence
...
} ;
// Sequence control variables
int last_indication_type = indication_type - 1 ; // force "change" on first iteration
int current_indication = 0 ;
int current_step = 0 ;
int step_time = 0 ;
while(1)
{
// On indication change...
if( indication_type != last_indication_type )
{
// Set the indication descriptor...
if( indication_type == event_a )
{
current_indication = 0 ;
}
else if( indication_type == event_b )
{
current_indication = 1 ;
}
...
last_indication_type = indication_type ;
// Set initial indication color and time for this sequence
current_step = 0
step_time = indication_descriptor[current_indication][0].showtime ;
indication_descriptor[current_indication][0].setcolor() ;
}
// Wait one tick
osDelay(1) ;
// Decrement time in step
step_time-- ;
// If end of step...
if( step_time == 0 )
{
// Set colour and time for next step
current_step == (current_step % 3) ;
step_time = indication_descriptor[current_indication][current_step].showtime ;
indication_descriptor[current_indication][current_step].setcolor() ;
}
}
It is likely that further improvements can be made, but from the fragment you have provided it is not possible to advise. For example the data type and range of indication_type, event_a etc are not shown - it is possible that a switch-case or lookup table or even arithmetic could replace the if/else if/.../else selection block, but more information would be required.
If you need faster and more deterministic sequence interruption than 1ms you'd have to use an osTimer, with a callback function that sets a thread flag and have the task wait on a thread flag rather than osDelay(). The interrupter can then set a different thread flag to wake the task to abort the timer and switch indication. That is somewhat more complex however and likely not necessary in this case. A pattern that is useful for when hard-real-time response at the microsecond order is required. If you did that the sequence code might change thus:
...
// Set initial indication color and time for this sequence
current_step = 0
osTimerStart( step_timer, indication_descriptor[current_indication][0].showtime ) ;
indication_descriptor[current_indication][0].setcolor() ;
}
// Wait for timer expiry or event
uint32_t flags = osThreadFlagsWait( STEP_COMPLETE_FLAG | SEQUENCE_CHANGE_FLAG, osFlagsWaitAny, step_time ) ;
// If end of step...
if( (flag & STEP_COMPLETE_FLAG) != 0 )
{
// Set colour and time for next step
current_step == (current_step % 3) ;
step_time = indication_descriptor[current_indication][current_step ].showtime ;
indication_descriptor[current_indication][current_step].setcolor() ;
}
else
{
osTimerStop( step_timer ) ;
}
It has the advantage of having far fewer task context switches which may be useful if you need to reduce CPU load to achieve real-time deadlines or reduce power consumption by entering sleep for longer periods.

osWait allows you to wait for either an event or a timeout. So if you can generate a proper signal when you have an interrupt, the thread will wake-up and you can immediately switch LED state.
See https://www.keil.com/pack/doc/cmsis/RTOS/html/group__CMSIS__RTOS__Wait.html#details

Put the RTOS to work and use an RTOS timer. From the interrupt that triggers the change in indication_type, you can call your function to set the color and then start the timer for the desired color duration (this can also be done in a task context after the interrupt notifies the task). On the timeout, set the next color and restart the timer with the next color duration. When indication_type changes, you can simply set the color again and restart the timer with the new indication_type color pattern.

Related

How to increment or decrement a 7-segment display 00-99 using button

i'm using code composer studio and data signals(D0-7) are obtained from tms320f28335
i have incremented and decremented specific led on 7-segment using switch statement. but that is kind if manual incrementing( where i already provide values as shown below)
void display(void)
{
B1 +=1;
if(B1 > B1_lim) { B1 = 0; }
switch(B1)
{
case 0: Display[0] = 0xf7; break; //9
case 1: Display[0] = 0xfF; break; //8
case 2: Display[0] = 0xf0; break; //7
case 3: Display[0] = 0x9F; break;
}
i have also tried to run counter but it never comes out of the loop because of while(1) statement and then i cant use other buttons, the code is shown below it works for 00-99 with never ending. furthermore, i tried to use button in below code but it loops like button can just start the increment/decrement process
void display(void)
{
unsigned char a[]={0xfb,0xb0,0xeD,0xf5,0xb6,0xd7,0x9F,0xf0,0xfF,0xf7}; //[0,1,2,3,4,5,6,7,8,9]
unsigned char b[]={0xfb,0xb0,0xeD,0xf5,0xb6,0xd7,0x9F,0xf0,0xfF,0xf7}; //[0,1,2,3,4,5,6,7,8,9]
int k,j;
while(1)
{
Display[0] = 0xfb;
Display[1] = 0xfb;
DELAY_US(200000L);
for(j=0;j<=9;j++)
{
Display[1]=b[j];
led_display(0x00); DELAY_US(200000L);
for(k=0;k<=9;k++)
{
Display[0] = a[k];
led_display(0x00); DELAY_US(200000L);
DELAY_US(2L);
}
}
}
}
on my 7-segment driver board, I have 4 buttons, and i want to use two of them for incrementing and decrementing.
I would like to know if there is any logical way to use a switch statement such that for each button press I can increment or decrement.
the simplest way show increment is shown in above code but i want to using second code.
I think you should use interrupt for button, don't use while(1) in your function.
Create a function to update value for 7-segment. When you press button, interrupt function will call. In this, you update your value to display.
First of all you need a coherent design following the tight cohesion, loose coupling principles. Your display function is attempting to doo too much - it is not cohesive - it contains logic related to your specific application and unrelated to display. It should do only what its name suggests and display a desired value. For example:
void display( uint8_t value )
{
// 0 1 2 3 4 5 6 7 8 9
static const uint8_t digits[]={0xfb,0xb0,0xeD,0xf5,0xb6,0xd7,0x9F,0xf0,0xfF,0xf7};
if( value < 100 )
{
uint8_t display[2] = {0,0} ;
display[0] = value % 10u ; // least significant digit
display[1] = value / 10u ; // most significant digit
led_display( 0x00 ) ;
}
}
Then let's assume (because you have not told us) that you have some GPIO input for the button and a clock source, hypothetically I will call these getSwitchState() and getClockMillisec(), then you might have a button state function something like:
bool getButtonState()
{
static const uint32_t DEBOUNCE_MILLIS = 20 ;
static uint32_t timestamp = getClockMillisec() ;
static bool debounced_button_state = getSwitchState() ;
uint32_t now = getClockMillisec() ;
uint32_t button_state = getSwitchState() ;
if( now - timestamp > DEBOUNCE_MILLIS &&
button_state != debounced_button_state )
{
debounced_button_state = button_state ;
timestamp = now ;
}
return debounced_button_state ;
}
Then you will want to act only on a button change of state, so you might have:
bool isButtonDownEvent()
{
static bool button_state = getButtonState() ;
bool button_down_event = false ;
// On change of state
if( getButtonState() != button_state )
{
button_state = !button_state ;
// True if button change was released to pressed (down event)
button_down_event = button_state ;
}
return button_down_event ;
}
Then your application loop can be built from those primitives thus:
uint8_t num = 0 ;
for(;;)
{
display( num ) ;
if( isButtonDownEvent() )
{
num++ ;
num %= 99 ;
}
}
Clearly if you have more than one button for separate increment/decrement that will need some modification to handle separate buttons, but since you have provided no information on the button hardware or software interface to it, I'll leave that to you to consider.
Also of course that is not the only possible solution to button input and debounce - you may already have suitable code. Usefully perhaps this method does not need a dedicated h/w timer or interrupt. It does however require regular polling to avoid missing events.
Critically note that the solution has no delays and no blocking, you can do other useful work in the loop whilst maintaining the display (so long as that too is non-blocking and does not take excessive CPU time such that button events might be missed.

is there a way to wait for something without interrupt the execution of other code?

i have to write a function that, by calling it only a single time, have to:
turn on an output pin
the pin stays high for 200mS
at the end of the timer the pin need to be low again.
the pin stays low for 200mS
at the end of the timer the function can be called again.
to turn on and off an output pin I already have wrote and tested the funcions:
outOn(pin_id);
outOff(pin_id);
now, i am trying to write the function that does the above mentioned actions and this is what l've come out with so far:
void outOnT02(enum e_outs ou){
outOn(ou);
gu_RegTim.BTime[BTIM_FUNCT].Timer = O_SEC01*2;
if(gu_RegTim.BTime[BTIM_FUNCT].b.Stato == O_EndTimer) {
outOff(ou);
}
}
the function is named outOnT02 because:
it is an output;
after calling it, the pin became high;
T02 because the pin stays high for 0.2 Seconds.
outOn(ou); makes the pin go high,
outOff(ou); makes the pin go low,
gu_RegTim.BTime[BTIM_FUNCT].Timer = O_SEC01*2;
starts a 200mS timer,
and gu_RegTim.BTime[BTIM_FUNCT].b.Stato == O_EndTimer is true when the timer has run out.
it works but, as you can tell, I have to put it in a cycle otherwise gu_RegTim.BTime[BTIM_FUNCT].b.Stato == O_EndTimer will never be true and so,the pin will stay high forever.
this is where i am stuck. i can't use a SLEEP(200); because i can't interrupt the execution of the code.
the language is C, the ide is MPLAB X IDE v6.00, the compiler is XC8 v2.31 and the cpu is a PIC16F15355.
This post is a little old but it is worth to answer since it is both a good question and a common problem. Now this problem is very common in embedded world when we develop applications that has to run on only one CPU. Hence there is no real parallelism in the workflow. Also since the application will not run on top of any OS, there will be no scheduler, no timers, no threads etc. Especially in small scaled microcontrollers there is no way to run many of the true RTOSs.
But this shouldn't be an obstacle for developing applications that runs tasks concurrently. We can develop an application using some tricks so that it runs the tasks concurrently and behave as a small OS. Running concurrently means that no task blocks the CPU using busy waiting checks or something alike but we block a task that needs to wait some event to occur.
When we block a task, the specific data and the next execution point on that task must be preserved so that it can continue from where it should in the next execution. Knowing what we need to preserve helps us to create a thread-like structures that executes until it has to wait some event to occur (eg. time delay). When it has to wait (means that it will be blocked) the next state of it must be preserved and it exits to give the control to the CPU so that it executes other tasks.
When we need to deal with periodic tasks as in the question, it is relatively easier to implement without blocking the CPU execution and meanwhile handle other tasks. Moreover no interrupt usage needed for this type of tasks unless the tasks are extremely time sensitive.
Well, enough with the story part, let's get into it. I will base the examples on the OP's output flashing problem. However the same techniques can be applied for other situations like I/O events, hardware events etc.
Let's sum up the requirement briefly, we have a task that runs atomically. That is, when it is called it must run to completion so that it can be called again (this is what I understand from the OP's requirement):
Turns on an output pin for 200ms
Then turns off the pin for 200ms
Once turned off and 200ms time has elapsed it can be executed again.
Note Some functions in this example are not implemented since they can be application or microcontroller specific.
Task-like Functions
Let's assume we want to schedule the following two task-like functions each of which keeps track of its execution continuation points.
The static cp variables are declared in each function so that they remember where to continue whenever they are called. The content of cp variable will not be destroyed by the compiler when the function returns since we declare it as static. The cp needs to be updated upon the expected events occur in order to proceed to the next step whenever it is called.
Note that in outputTask, the call source must be known to control its atomic behaviour. Since the requirement for this task is that once it triggered or called, it must run to completion. So we have to know where the task is called from, in order it to decide what to do on each call. If it has been triggered from another task, it can't be triggered anymore until it completes its flashing prosess. If it is called from the scheduler (main loop) it knows it is a periodic call and will keep track of the time. This control is achieved using a parameter called periodic. When it is called from the scheduler this parameter must be set to 1, and 0 for the calls other than the scheduler.
/*
* This task-like function performs what the OP wants to achieve
*/
void outputTask(unsigned char periodic) {
static unsigned char cp = 0; // Continuation Point holder
static unsigned char currentMillis;
/*
* Check whether it is a periodic call or a new output signal call.
* If it is a periodic call and signalling has been initialized,
* proceed for time keeping.
* If it is a new signalling call and the task hasn't completed yet,
* simply ignore and return.
*/
if(!periodic && cp != 0) {
return;
}
switch(cp) {
case 0:
outOn(pin_id); // Turn on the output
cp = 1; // Next execution point
currentMillis = 200; // Load the 200ms counter for time keeping
break;
case 1:
currentMillis--;
if(currentMillis == 0) {
// 200ms time for output high has elapsed, proceed to next step
outOff(pin_id); // Turn off the output
currentMillis = 200; // Reload the counter value
cp = 2; // Proceed to the next step
}
break;
case 2:
currentMillis--;
if(currentMillis == 0) {
// 200ms time for output low has elapsed, proceed to next step
cp = 0; // Last step is done, reset the state for new calls
}
break;
default:
// For anything else, reset the task state to the initials
cp = 0 // Reset the task state to zero so that it accepts new calls
}
}
/*
* Let's say this task will wait for a button press event and will
* trigger the outputTask upon the event occurs
*/
void outputTriggerTask() {
static unsigned char cp = 0;
static unsigned char currentMillis;
switch(cp) {
case 0:
if(isButtonPressed()) { // Platform specific function
// A button press has been detected, debounce first
currentMillis = 50;
cp = 1; // Next step, check for the elapsed time
}
else {
break;
}
case 1:
currentMillis--;
if(currentMillis == 0) {
// Check whether the button press is consistent
if(isButtonPressed()) {
// Yes still consistent, handle the button press by triggering the output task
outputTask(0); // Not a periodic call
cp = 2; // Next step is to check whether button is released
}
else {
cp = 0; // Reset the task state
}
}
break;
case 2:
if(isButtonReleased()) { // Platform specific function
currentMillis = 50; // Reload the time counter
cp = 3;
}
else {
break;
}
case 3:
currentMillis--;
if(currentMillis == 0) {
// Check whether the button release is consistent
if(isButtonReleased()) {
// Yes still consistent, handle the button release if needed
cp = 0; // Reset the task to its initial state
}
}
break;
default:
cp = 0; // Reset to initials
}
}
Scheduling Approches
The following approches are for non RTOS small embedded systems. They are suitable for wide range of 8-bit microcontrollers.
Approach 1 - Create Delay Based Timebase to Schedule Tasks
Scheduling using CPU blocking delay is suitable for hobby and educational purposes while it is not suitable for real projects. This example uses a platform specific delay_ms function (or can be a macro) to create a 1ms heartbeat for the application so that the tasks can keep track of time.
void main(void) {
systemInit(); // Platform specific function
// maybe some more init functions go here
// Application's infinite scheduler loop
while(1) {
// The first thing we do is to create a 1ms timebase using delay.
// This is the heartbeat for the application
delay_ms(1000); // Platform specific function
// 1ms has elapsed check the tasks
outputTriggerTask(); // Check whether any button press event has occured
outputTask(1); // It is a periodic call for the output task
// Maybe more tasks go here...
}
}
Approach 2 - Create Hardware Timer Based Timebase
void main(void) {
systemInit(); // Platform specific function
// Setup a hardware timer for 1ms overflow without interrupt
initTimerForOneMs(); // Platform specific function
// maybe some more init functions go here
// Application's infinite scheduler loop
while(1) {
// Wait for the timer to overflow
while(!isTimerOverflow()) // Platform specific function
;
// Timer has overflowed, reload and check tasks
reloadTimer(); // Platform specific function
// 1ms has elapsed check the tasks
outputTriggerTask(); // Check whether any button press event has occured
outputTask(1); // It is a periodic call for the output task
// Maybe more tasks go here...
}
}
Approach 3 Put the Processor to Sleep for 1ms Timebase
void main(void) {
systemInit(); // Platform specific function
// maybe some more init functions go here
// Application's infinite scheduler loop
while(1) {
// Put the Processor to sleep along with a watchdog timer to wake it up
clearWatchdogTimer(); // Platform specific function
sleep(); // Platform specific function
// CPU slept for 1ms and woke up, handle the periodic tasks
outputTriggerTask(); // Check whether any button press event has occured
clearWatchdogTimer(); // Platform specific function
outputTask(1); // It is a periodic call for the output task
clearWatchdogTimer(); // Platform specific function
// Maybe more tasks go here...
}
}
And Last But not Least Time Checking Approach
In this approach the tasks will be keeping the time by checking better say comparing the elapsed time to the desired time to delay tasks without blocking the CPU. For this, we will need to use a free running timer. This will be like the millis function of the Arduino API.
Rewriting the Tasks for the Time Checking Approach
/*
* This task-like function performs what the OP wants to achieve
*/
void outputTask(unsigned char periodic) {
static unsigned char cp = 0; // Continuation Point holder
static unsigned short currentMillis; // 16 bit millisecond holder
/*
* Check whether it is a periodic call or a new output signal call.
* If it is a periodic call and signalling has been initialized,
* proceed for time keeping.
* If it is a new signalling call and the task hasn't completed yet,
* simply ignore and return.
*/
if(!periodic && cp != 0) {
return;
}
switch(cp) {
case 0:
outOn(pin_id); // Turn on the output
cp = 1; // Next execution point
currentMillis = getCurrentMillis(); // Platform specific function
break;
case 1:
if(getCurrentMillis() - currentMillis >= 200) {
// 200ms time for output high has elapsed, proceed to next step
outOff(pin_id); // Turn off the output
currentMillis = getCurrentMillis(); // Reload the counter value
cp = 2; // Proceed to the next step
}
break;
case 2:
if(getCurrentMillis() - currentMillis >= 200) {
// 200ms time for output low has elapsed, proceed to next step
cp = 0; // Last step is done, reset the state for new calls
}
break;
default:
// For anything else, reset the task state to the initials
cp = 0 // Reset the task state to zero so that it accepts new calls
}
}
/*
* Let's say this task will wait for a button press event and will
* trigger the outputTask upon the event occurs
*/
void outputTriggerTask() {
static unsigned char cp = 0;
static unsigned short currentMillis;
switch(cp) {
case 0:
if(isButtonPressed()) { // Platform specific function
// A button press has been detected, debounce first
currentMillis = getCurrentMillis(); // Platform specific function
cp = 1; // Next step, check for the elapsed time
}
else {
break;
}
case 1:
if(getCurrentMillis() - currentMillis >= 50) {
// Check whether the button press is consistent
if(isButtonPressed()) {
// Yes still consistent, handle the button press by triggering the output task
outputTask(0); // Not a periodic call
cp = 2; // Next step is to check whether button is released
}
else {
cp = 0; // Reset the task state
}
}
break;
case 2:
if(isButtonReleased()) { // Platform specific function
currentMillis = getCurrentMillis();
cp = 3;
}
else {
break;
}
case 3:
if(getCurrentMillis() - currentMillis >= 50) {
// Check whether the button release is consistent
if(isButtonReleased()) {
// Yes still consistent, handle the button release if needed
cp = 0; // Reset the task to its initial state
}
}
break;
default:
cp = 0; // Reset to initials
}
}
Scheduler for Time Checking Approach
void main(void) {
systemInit(); // Platform specific function
initMillisTimerWithInterrupt(); // Platform specific function
// maybe some more init functions go here
// Application's infinite scheduler loop
while(1) {
// Now that we use a free running millis timer no need to block the CPU to create a timebase
// Just call tasks sequentially. Each task will know what to do individually
outputTriggerTask(); // Check whether any button press event has occured
outputTask(1); // It is a periodic call for the output task
// Maybe more tasks go here...
}
}

how to stop looping and wait until different value received from serial

hi i planning to made a multiple servo controlling with serial as control trigger signal on AVR with C and codevision
but when the trigger is true, the servo running in crazy loop, it back to original position (0 degree) instead of stay on desired position, my tutor give me hint to use "wait ... until" statement with the old data comparison but i'm not found the way to utilize it yet on google
because utilizing break; at the end of the if left the chip freeze until it reset
and the old code(it runs the servo forth and back continously)
while (1)
{
while(UCSRA & (1<<RXC))
{
// Place your code here
//data=UDR;
PORTC=UDR;
data=UDR;
//PORTB=data;
} ;
if (data== 0x0A || data== 0x0B)
{
if (data== 0x0A)
{
old_data=data;
PORTA=0x00;
PORTA.1=1;
movservo0(90,7);
movservo1(15,3);
}
if (data== 0x0B)
{
old_data=data;
PORTA=0x00;
PORTA.1=1;
movservo0(15,3);
movservo1(90,7);
}
}
}
as for movservo0 (another movservo() almost had same code)
void set_servo1(unchar derajat)
{ unchar n;
servo2=1;
delay_us(750);
for(n=0; n<derajat; n++)
{
delay_us(12);
};
servo2=0;
delay_ms(10);
}
void movservo0(unsigned char sudut, unsigned char speed)
{
unchar i;
set_servo1(sudut);
for (i=1;i<=sudut;i+=speed){
set_servo1(i);
delay_ms(100/speed);
}
}
This new code is a bit better.
The top of the while(UCSRA & (1<<RXC)) loop is fine this way. The loop body will only be entered if there is a character to be read. (Although, I'm not sure why you are expecting to read '\n' or vertical tab.)
A minor problem is the way the UDR is read. The act of reading UDR erases the contents. So you should be using
data=UDR;
PORTC=data;
The jumping of the servos appears to be in the moveservo() function. This function always sets the angle to 1 and then gradually increases the angle of the servo until it reaches the desired angle.
setservo() appears to be an attempt to perform PWM to drive a servo, but it doesn't work correctly. To keep the servo at a desired angle, you have to keep switching the pin from 0 to 1 at the correct times, not just once like this function does. Have you looked at the PWM functions of the timers? You just set these up and they run in the background. An alternative is to use a timer to set an interrupt to wake up and toggle the pins as you need.
If you want to do the switching of the pins without interrupts, then you should be using delays in the while(1) loop itself. Just use the setservo() functions to change some variables.
while(1)
{
// read the UART if ready and set the target values
// this part only runs occasionally
while(UCSRA & (1<<RXC))
{
// etc
}
// The rest of the loop body runs every time
// adjust the servo values toward the target values
// use a counter to determine if to adjust during this loop iteration
// e.g., a slow speed counts to a higher number before adjusting
delay(750);
for(int i = 0; i < NUM_INTERVALS; ++i)
{
// decide whether to set pins to 1 or 0 based on the servo values
delay(INTERVAL);
}
}
I don't know about your particular servos, but they typically have a period where most of the time the pin is 0, and then a short time in the period where the pin is 1. You will need to adjust NUM_INTERVALS and INTERVAL and 750 to add up to the correct length of time.
There is so much wrong with this snippet, it is hard to start. It is difficult to say why the servo is moving, as it is only ever "moved" to the same value every time. (Unless, you have omitted some code that sets it to some other value.)
Typically, when receiving UART, the processor should wait until the character is received. This is accomplished by this
while(UCSRA & (1<<RXC) == 0);
Note the ; creating an empty body of the while loop. This is probably what your tutor meant. When the flag is set, then the loop exits and the data is ready to be read.
while(UCSRA & (1<<RXC) == 0);
data = UDR;
Next, you have a block which looks like you meant to be part of a while loop, but it isn't. The body of the loop is the single statement abbove it. The block gets executed every time.
{
if(data=0x0a)
{
olddata=data;
movservo0(90,7); //move servo to certain degree
}
}
Another error is the condition in the if statement. It looks like you are trying to test if data is 0x0A, but that is not what is happening. Instead, you set data to be 0x0A, and then execute the inner part every time. The condition you probably want is if(data == 0x0A). Note the == instead of =.
So your code is equivalent to
while(1)
{
while(ucsra & (1<<RXC)) data=udr; // maybe read UDR into data
data=0x0a; // set data anyway
olddata=data;
movservo0(90,7); //move servo to certain degree
}
Again, for the jumping servo, I suspect some code that is omitted here that is also runs every time. Or else, the moveservo() function has a problem itself.

opencv circle detection with video

is there a way to wait until something happens(while loop) or wait wait 10 seconds before doing a circle detection, but still displaying the video. i have tried it with while loop but if condition is not met, frames will not be displayed as code does not get the cvShow\iamge().
Yes, it's possible, but you will have to use threads. Declare a global variable bool exec_circle_detection = false; and start a 2nd thread. On this thread, call sleep(10) to wait for 10 seconds and then change exec_circle_detection to true.
In the main thread, inside the frame grabbing loop, you check if the boolean variable is set to true, and in case it isn't, you won't process the frame. This part would look something like this (in C):
char key = 0;
while (key != 27) // ESC
{
frame = cvQueryFrame(capture);
if (!frame)
{
fprintf( stderr, "!!! cvQueryFrame failed!\n" );
break;
}
if (exec_circle_detection)
{
// execute custom processing
}
// Display processed frame
cvShowImage("result", frame);
// Exit when user press ESC
key = cvWaitKey(10);
}
If you plan to do the circle detection once every 10 seconds, you will need to change exec_circle_detection to false after you execute the custom processing. On the secondary thread, adjust your code so there is a while loop changing exec_circle_detection to true every 10 seconds.
You can simply run the detection every X frames. Add a frame counter in your code, restarting to 0 when detection is perform, increase by one at each grabbed new frame, and perform detection when the counter is equal to 300 considering your video is displayed at 30 fps. You will get your 10 seconds delay between each detections.

Using timers in ARM embedded C programming

I'm writing a pong-type game in C, which will run on an ARM board over an LCD screen. Part of the requirements for the game is something called 'magic time'.
A "magic time" period occurs at random intervals between 5 and 10 seconds - i.e, between 5 and 10 seconds after the last "magic time" period, and lasts for a random duration of 2 to 10 seconds.
I don't really understand your question (do you execute this code every second via timer interrupt, or?), but there are some errors that I see on the first sight:
while (magicTime == true) {
magicTimeLength++;
magicTime == magicTimeLength;
}
Last line (magicTime == magicTimeLength;) don't do anything - it simply evaluates if magicTime is equal to the magicTimeLength, so you will enter dead-loop.
I think that you want to do this:
Init magicTimeOccurence with random value within 5 and 10.
Init magicTimeLength with random value within 2 and 10.
Every second, if magicTimeOccurence is greater than 0, decrease
its value by one.
Once magicTimeOccurence hits 0, decrease magicTimeLength value
by one.
Check if magicTimeLength is greater than 0. If it is, it is magic
time period (so, set the magicTime flag to true). Decrement
magicTimeLength.
If magicTimeLength, set magicTime to false and go to step 1.
You should initialize your timer0 interrupt with period of 1s. I think that you accomplished it with
/* Set timer 0 period */
T0PR = 0;
T0MR0 = SYS_GetFpclk(TIMER0_PCLK_OFFSET)/(TIMER0_TICK_PER_SEC);
but make sure that is triggered every second.
Here is sample code, it should show you what I mean.
/* In void InitTimer0Interrupt() */
...
T0TCR_bit.CE = 1; /* Counting Enable */
magicTimeOccurence = 5+(rand()%5);
magicTimeLength = 2+(rand()%8);
magicTime = false;
__enable_interrupt();
}
/* In void Timer0IntrHandler (void) */
void Timer0IntrHandler (void) {
/* clear interrupt */
T0IR_bit.MR0INT = 1;
VICADDRESS = 0;
if(magicTimeOccurence > 0)
{
magicTimeOccurence--;
}
else if(magicTimeLength > 0){
magicTime = true;
magicTimeLenght--;
}
else{
magicTime = false;
magicTimeOccurence = 5+(rand()%5);
magicTimeLength = 2+(rand()%8);
}
/* take action on timer interrupt */
}

Resources