Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
8 years, 1 month ago.
Strange behavior
I am using a ticker to move a stepper and there is something very strange happening that I cant find why. Can someone please take a look and help me? (Disregard the portions concerned with TFT output)
My code is
#include "mbed.h" #include "TFT_LCD.h" //ALL these related with display extern uint8_t SmallFont[]; extern uint8_t BigFont[]; BusOut myBusOut(PB_0,PB_1,PB_2,PB_3,PB_4,PB_5,PB_6,PB_7,PB_8,PB_9,PB_10,PB_11,PB_12,PB_13,PB_14,PB_15); TFT_LCD myScreen(ILI9325C,PC_7,PC_1, PC_6, PC_0,&myBusOut); //end of display /* The Pins for the Stepping Motor are: * * A -> PA_9 * ~A -> PA_10 * B -> PA_11 * ~B -> PA_12 */ #define MASK (0x1E00) // the pins above defined PortOut stepMotor(PortA,MASK); Ticker step_ticker; uint16_t sequence[8]={0x0200,0x0A00,0x0800,0x0C00,0x0400,0x1400,0x1000,0x1200}; uint8_t seq_i=0; #define WAVE_INC 2 uint8_t seq_increment=WAVE_INC; int n_steps; int direction; bool moving=false; void step_motor() { // static int n=0; stepMotor=sequence[seq_i]; seq_i+=(seq_increment*direction); seq_i&=0x07; // myScreen.printNumI(n_steps, LEFT, 70, 10, ' '); if(--n_steps<=0){ n_steps=0; moving =false; step_ticker.detach(); } } void wave_drive(int dir, int ns) { direction=dir; n_steps=ns; step_ticker.attach(&step_motor,0.050); //toggle at 50ms moving=true; } int main() { //display wait(3); myScreen.InitLCD(); myScreen.setBackColor(BLACK); myScreen.setColor(BLACK); myScreen.clrScr(); myScreen.setColor(GREEN); myScreen.setFont(SmallFont); myScreen.print("Stepper Motor Program",LEFT, 10); //display while (true) { myScreen.print("Wave Drive ->> ", LEFT, 50); wave_drive(1,200); // while(n_steps>0){ while(moving){ myScreen.printNumI(n_steps, LEFT, 90, 10, ' ');//<-----HERE IT WORKS } // stop while moving myScreen.print("Wave Drive <<- ", LEFT, 50); wave_drive(-1,200); // while(n_steps>0){ while(moving){ // myScreen.printNumI(n_steps, LEFT, 90, 10, ' '); //strange it does not work when commented in ; } // stop while moving }//while true }
As you can see I put a "while(moving)" clause to wait for the ticker to be detached. but it waits for ever!!! (except when I put a totally unrelated instruction there....
that does not make sense. How can I know that a process has been detached???
Thank you for any help you can give me
Question relating to:
2 Answers
8 years, 1 month ago.
The compiler may do some unexpected optimisations when you use a variable (moving) in your while loop that is modified in an interrupt. Try
volatile bool moving=false;
The attach/detach may also be tricky and cause timing issues when the ticker is running at a relatively high rate. You may simply keep the ticker and the attached call to step_motor() going and add a test on the 'moving' variable inside the step_motor() function to decide whether or not a next step is needed.
8 years, 1 month ago.
Start by defining moving as 'volatile', so volatile bool moving = false;. The problem is (well there could also be other issues) that the compiler does not realise moving can be changed in the interrupt. So it optimizes your while loop to check a copy of 'moving' in its register, while the interrupt will change it in the SRAM. Normally when something has been changed, the compiler will make sure it retrieves latest version of this variable, but the compiler does not realise it can be changed.
Adding volatile forces it to always retrieve the data from the SRAM.