Go Down

Topic: How do I make a case statement run constantly until another one is called? (Read 599 times) previous topic - next topic

Abruce11

I am trying to make a remote control fan and so far it works fine. But my problem is I want my cases to run constantly until the next case is called. I am using an IR sensor to take the input from the remote. The problem I have now is once I touch the button on the remote the case only runs once I want it to run continuously until the next case is called. My code is at the bottom does anyone have any suggestions?


Code: [Select]

#include <Servo.h>
#include <IRremote.h>

Servo myservo;  
int pos = 0;  
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
 myservo.attach(9);     // attaches the servo on pin 9 to the servo object
 Serial.begin(9600);
 irrecv.enableIRIn();   // Start the receiver
}

void loop() {
 if (irrecv.decode(&results)) {
   Serial.println(results.value, HEX);
   switch(results.value)
   {
   case 0x800F8401: //Case 1
     // while (results.value == 0x800F8401)
     {
       for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
       {                                  // in steps of 1 degree
         myservo.write(pos);              // tell servo to go to position in variable 'pos'
         delay(0);                       // waits 15ms for the servo to reach the position
       }
       for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
       {                                
         myservo.write(pos);              // tell servo to go to position in variable 'pos'
         delay(0);                       // waits 15ms for the servo to reach the position
       }
     }
     //if (results.value = 0x800F8401){
     break;
     //}
   case 0x800F8402: //Case 2
     {
       //if (results.value == 0x800F8402)
       //while(1)
       //{if (results.value != 0x800F8402)
       {
       for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
       {                                  // in steps of 1 degree
         myservo.write(pos);              // tell servo to go to position in variable 'pos'
         delay(20);                       // waits 15ms for the servo to reach the position
       }
       for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
       {                                
         myservo.write(pos);              // tell servo to go to position in variable 'pos'
         delay(20);                       // waits 15ms for the servo to reach the position
       
         
       }
        (irrecv.decode(&results));
       if (results.value != 0x800F8402)
         {
           break;
         }  irrecv.resume();
       }
       break;
       Serial.println(results.value, HEX);

   case 0x800F8403: //Case 3
     {
       for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
       {                                  // in steps of 1 degree
         myservo.write(pos);             // tell servo to go to position in variable 'pos'
         delay(15);                       // waits 15ms for the servo to reach the position
       }
       for(pos = 180; pos>=1; pos-=1)    // goes from 180 degrees to 0 degrees
       {                                
         myservo.write(pos);              // tell servo to go to position in variable 'pos'
         delay(15);                       // waits 15ms for the servo to reach the position
       }
     }
     Serial.println(results.value, HEX);
     break;
   case 0x800F8404: //Case 4
     {
       for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
       {                                  // in steps of 1 degree
         myservo.write(pos);              // tell servo to go to position in variable 'pos'
         delay(10);                       // waits 15ms for the servo to reach the position
       }
       for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
       {                                
         myservo.write(pos);              // tell servo to go to position in variable 'pos'
         delay(10);                       // waits 15ms for the servo to reach the position
       }
     }
Serial.println(results.value, HEX);
     break;
   }
   irrecv.resume();
 }
   }
 }



Moderator edit:  CODE TAGS, yet again.




AWOL

Code: [Select]
for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
        {                                  // in steps of 1 degree
          myservo.write(pos);             // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
        for(pos = 180; pos>=1; pos-=1)    // goes from 180 degrees to 0 degrees
        {                               
          myservo.write(pos);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
      }

Save yourself some keystrokes - factor all these into a single function.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

wildbill

You're currently only executing your switch statement when something is detected from the remote. Run it unconditionally; you may need to save the response from the remote when you do get it in another variable that drives the switch.

aarondc

State machines are your friend.

Psuedo code:
Code: [Select]

int currentState = 0; // 1..4
int currentPosition; // 1..180
int currentDirection; // -1, 1
int stateDelay[] = {0, 20, 15, 10};


loop: {
   check serial
    if newState sent, currentState = newState
    if currentState != 0 doNextRotationStep
}


void doNextRotationStep {
    currentPosition += currentDirection
    if currentPosition > 180 currentDirection = -1, currentPosition = 180
    if currentPosition < 1 currentDirection = 1, currentPosition = 1

    myservo.write(currentPosition)
    delay(stateDelay[currentState]);
}
Windows serial port monitor: Tellurium | Arduino serial port debugging library: DBG | Cusom LCD char generator | Technical questions will only be answered in forum threads

Abruce11

can some one make this pesudo code into a full code please

int currentState = 0; // 1..4
int currentPosition; // 1..180
int currentDirection; // -1, 1
int stateDelay[] = {0, 20, 15, 10};


loop: {
    check serial
    if newState sent, currentState = newState
    if currentState != 0 doNextRotationStep
}


void doNextRotationStep {
    currentPosition += currentDirection
    if currentPosition > 180 currentDirection = -1, currentPosition = 180
    if currentPosition < 1 currentDirection = 1, currentPosition = 1

    myservo.write(currentPosition)
    delay(stateDelay[currentState]);
}

AWOL

It really isn't all that far from being C.
Why don't you make a start, and get back to us when you get stuck?

Don't forget to use [font=Verdana][[/font]code] [font=Verdana][[/font]/code] tags when you post it.

Some clues: 
These numbers
Code: [Select]
int stateDelay[] = {0, 20, 15, 10}; are found in places like this
Code: [Select]
for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
        {                                  // in steps of 1 degree
          myservo.write(pos);              // tell servo to go to position in variable 'pos'
          delay(20);                       // waits 15ms for the servo to reach the position
        }
in your code.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Abruce11

I do not understnd the Psuedo code. Are there any other methods to get what i want done. i dont understand why i cant use a while 1 loops in each case. could some one give me some explanations please

AWOL

Does this help?
Code: [Select]
void doNextRotationStep ()
{
   currentPosition += currentDirection;
   if (currentPosition > 180) {
     currentDirection = -1;
     currentPosition = 180;
   }  
   if (currentPosition < 1) {
     currentDirection = 1;
     currentPosition = 1;
   }  

   myservo.write(currentPosition);
   delay(stateDelay[currentState]);
}


Compare it to the pseudo code and see if you can fix the rest of it.

Quote
. i dont understand why i cant use a while 1 loops

The function "loop()" already runs in one of those; use that one.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Abruce11

do I have to make if statements for every possible case. I saw youu used delay(stateDelay[currentState]);. is it possible to use something like that in if statements.

AWOL

I'm sorry, I don't understand your question.
There is now very little now for you to write, and most of it could be done by hacking away completely big chunks of your original code.

Edit: The sketch you posted above is about 100 lines long. My guess is that the rewritten one will be no more than about 70 lines. If you get rid of the switch/case and do a table lookup instead, probably fewer than 60 lines.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Abruce11

myservo.write(currentPosition)
    delay(stateDelay[currentState]);
i dont understand what that part of the code does can u explain it. I know i am asking for alot but i am just tring to understand

AWOL

What we're trying to do is to make the system look like it is doing more than one thing at a time, by breaking down what it is doing into tiny steps that individually take a very short time to execute.
So in your original code, the two big for loops could take a maximum of 180 x 2 x 20 milliseconds to execute, or about 7 seconds.
During this time, the system would appear unresponsive, because it would have to complete a movement before it checked the IR input again.
Now, we're going to check the IR input every time through "loop()", but nothing inside "loop()" is going to take more than 20 milliseconds (give-or-take) to execute.
So, we're going to:
check IR,
move a little bit,
check IR,
move a litle bit,
check IR - got something! set a new state (that's is ALL you have to do),
move a little bit.
and so on.

Code: [Select]
myservo.write(currentPosition); 
You know what that does, I'm not going to explain.

Code: [Select]
delay(stateDelay[currentState]);
"currentState" has a value of 0..4 (or however many you want), so we pick a corresponding value from the array "stateDelay" to use as our delay.
For bonus marks later, we're going to get rid of "delay" altogether.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Abruce11

this is what i came up with tell me what you think.
Code: [Select]

int currentState = {1, 2, 3, 4};
int currentPosition; // 1..180
int currentDirection; // -1, 1
int stateDelay[] = {0, 20, 15, 10};
int currentState 1 =  0x800F8401;
int currentState 2 =  0x800F8402;
int currentState 3 =  0x800F8403;
int currentState 4 =  0x800F8404;


loop:() {
  myservo.attach(9);
  Serial.begin(9600);
  irrecv.enableIRIn();
}
{
    if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);(results.value);(results.x800F8401 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}
{
    if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);(results.value);(results.x800F8402 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}

{
    if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);(results.value);(results.x800F8403 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}
{
    if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);(results.value);(results.x800F8404 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}
}


void doNextRotationStep ()
{
    currentPosition += currentDirection;
    if (currentPosition > 180) {
      currentDirection = -1;
      currentPosition = 180;
    }
    if (currentPosition < 1) {
      currentDirection = 1;
      currentPosition = 1;
    }

    myservo.write(currentPosition);
    delay(stateDelay[currentState]);
}

Arrch

Code: [Select]
int currentState 1 =  0x800F8401;
int currentState 2 =  0x800F8402;
int currentState 3 =  0x800F8403;
int currentState 4 =  0x800F8404;


Variables can't have spaces in them.

Code: [Select]
loop:() {
What's with the colon?

Code: [Select]
{
   if (irrecv.decode(&results)) {
   Serial.println(results.value, HEX);(results.value);(results.x800F8401 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}
{
   if (irrecv.decode(&results)) {
   Serial.println(results.value, HEX);(results.value);(results.x800F8402 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}

{
   if (irrecv.decode(&results)) {
   Serial.println(results.value, HEX);(results.value);(results.x800F8403 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}
{
   if (irrecv.decode(&results)) {
   Serial.println(results.value, HEX);(results.value);(results.x800F8404 = results.value);
}
If (results.value) { value != 0 doNextRotationStep()
}
}


None of this code is inside a function and you have no setup function.

Code: [Select]
Serial.println(results.value, HEX);(results.value);(results.x800F8402 = results.value);

Whatever you think this code is doing, it isn't.

Code: [Select]
value != 0 doNextRotationStep()

Same with this.

Your formatting also leaves a lot to be desired.

AWOL

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Go Up