214Views16Replies

Author Options:

Arduino code help? Answered

I'm really new to the arduino and I'm struggling to get this code working. I'm trying to have a servo continuously go back and forth until I change its state, which result on the servo to stop at its current position. However, it gets stuck on that for loop and i can't change its state. I assume this is caused by the delay, but I am not sure how to make it so it works without delays, unless there is another way.My code is right here:
{edited}

const int Button = 2; //This is interrupt 0
int Pos;
const int button2=14;
volatile int sweep = HIGH; //Our state variable, initialise so we always sweep
#include <Servo.h>
Servo servo1;
int buttoncount=1;
int lastbuttonstate=0;
const int led_1=7;


void setup()
{

servo1.attach(10);
pinMode(Button, INPUT);
pinMode(button2,INPUT);
pinMode(led_1,OUTPUT);
Serial.begin(9600);

attachInterrupt(0, Isweep, CHANGE);

}

void loop()

{
Serial.println(buttoncount);
switch(buttoncount){
case 1:
servo1.write(0);
digitalWrite(led_1, LOW);
break;
case 2:
    Pos=0;
while (Pos<180 & sweep==true)
{servo1.write (Pos);
Pos++;
delay(10);
}
while (Pos>0 & sweep==true)
{servo1.write(Pos);
Pos--;
delay(10);
}
break;
case 3:
digitalWrite(led_1,HIGH);
break;
default:
Serial.println("error");
}


//both these whiles will terminate and not do anything if sweep is true.
}

void Isweep() //Interrupt routine
{
int buttonstate=digitalRead(Button);
if (buttonstate !=lastbuttonstate){
   if (buttonstate==HIGH){
     buttoncount++;
   }
}
lastbuttonstate=buttonstate;
if (buttoncount==4){
   buttoncount=1;
  }
sweep = !sweep;
while (digitalRead(Button)==true); //change state only once when button is pressed
}

18 Replies

user
steveastroukBest Answer (author)2014-07-27

What's the point of buttoncount ?


Select as Best AnswerUndo Best Answer

user
cmasuo (author)steveastrouk2014-07-27

I need to change the switch case with a button, and the way i know it involves making a button counter.

Select as Best AnswerUndo Best Answer

user
steveastrouk (author)cmasuo2014-07-27

The state is either sweeping or fixed. If the button has been pressed, its fixed. What stops the servo being fixed ? Another press ?

Select as Best AnswerUndo Best Answer

user
cmasuo (author)steveastrouk2014-07-27

if it worked, that is what I want it to do. I tried using breaks on the for loop and using a if(digitalRead(button)==HIGH){break;}

but that ended up being buggy and weird.

Select as Best AnswerUndo Best Answer

user
steveastrouk (author)cmasuo2014-07-27

Breaks are to be avoided. The for loop is not really the right
structure for this.You just need a simple loop, but put the button in an
interrupt routine.

I don't know which arduino you have, but you can try putting something like this - just check which pins can interrupt you.

int Button = 13; //This is interrupt 0

volatile int sweep = HIGH; //Our state variable, initialise so we always sweep

void setup()

{

servo1.attach(10);
pinMode(Button, INPUT);
Serial.begin(9600);

attachInterrupt(0, Isweep, CHANGE);

}

void loop()

{ Pos=0;
while (pos<180) & (sweep==true) {servo.write (pos);pos++;delay(10)};
while (Pos>0) & (sweep==true) (servo.write(pos);pos--;delay(10)};

//both these whiles will terminate and not do anything if sweep is true.
}

void Isweep() //Interrupt routine

{
sweep = !sweep;
while digitalread(button)==TRUE; //change state only once when button is pressed
}

Select as Best AnswerUndo Best Answer

user
cmasuo (author)steveastrouk2014-07-27

Thanks! it works, but how do I make it so I can do this in a switch case where it will have an initial position, then make it so it it goes back and forth until i hit the button again, and it will go on another case to do something else like start an led. But otherwise that, this is exactly what I need.

Select as Best AnswerUndo Best Answer

user
steveastrouk (author)cmasuo2014-07-27

When asking a question, give a full description of the problem, the answer would be different to the one I've given.

Select as Best AnswerUndo Best Answer

user
cmasuo (author)steveastrouk2014-07-27

I'm very sorry to bother you again, but I really have no idea how to get this working. I uploaded the new code. I'm basically having the same issue again, except this time i have to hold the button to make the servo to go back and forth. Sometimes when i hit the button again, it will go to case 3, which is good, except for the part that it is really random. I tried using another button, but it seems to not work. If you can see what I clearly did wrong feel free to correct me.

Select as Best AnswerUndo Best Answer

user
cmasuo (author)cmasuo2014-07-27

If you are wondering what I'm doing, I'm trying to make some soccer arcade game where it has a servo to make it go back and forth, and then once it stops, led lights will turn on in a sequence and you hit the button and, and if all led or most are on it kicks the ball with a motor.

That is why I'm trying to use a switch case for this.

Select as Best AnswerUndo Best Answer

user
steveastrouk (author)cmasuo2014-07-27

Add a counter IN THE INTERRUPT, and use that number in an external switch. enum a series of states, sweep, flash_leds, kick, and transition between the states depending on the value of the counter.

Don't forget to vote the best answer.

Select as Best AnswerUndo Best Answer

user
cmasuo (author)steveastrouk2014-07-27

one last question. I'm kind of stupid, but when you mean add a counter in the interrupt, you mean the void Isweep() or is it something else?

Select as Best AnswerUndo Best Answer

user
steveastrouk (author)cmasuo2014-07-27

Yes, that's right, in lsweep

Select as Best AnswerUndo Best Answer

user
cmasuo (author)steveastrouk2014-07-27

Thanks again for the help! I will try this out. I'm really new to this, so hopefully I can do this haha

Select as Best AnswerUndo Best Answer

user
steveastrouk (author)2014-07-27

Forget the switch statement. It doesn't need breaks in it anyway, but "if" statements are much clearer.

Should be

attachInterrupt(0, Isweep, FALLING);//assumes button input is tied high

Lsweep

{ //button has been pressed, it must be LOW to trigger the interrupt, so increment the counter
buttoncount++;
if (buttoncount>=4) buttoncount=0; //never use "==", it might fail
while (digitalRead(Button)==true); //change state only once when button is pressed
}

void loop()

{

if (buttoncount==1)
{servo1.write(0);
digitalWrite(led_1, LOW);
}

if (buttoncount==2)
{Pos=0;
while (Pos<180 & sweep==true)
{servo1.write (Pos);
Pos++;
delay(10);
}
while (Pos>0 & sweep==true)
{servo1.write(Pos);
Pos--;
delay(10);
}

if (buttoncount==3) digitalWrite(led_1,HIGH);

}

Select as Best AnswerUndo Best Answer

user

There are better ways, but this section should be as below.

if (buttoncount==2)
{Pos=0;
while ((Pos<180) & (buttoncount==2))
{servo1.write (Pos);
Pos++;
delay(10);
}
while ((Pos>0) & (buttoncount==2))

{servo1.write(Pos);
Pos--;
delay(10);
}

Delete the "sweep" variable

Select as Best AnswerUndo Best Answer

user
cmasuo (author)steveastrouk2014-07-28

sweet, it almost works, I'm not sure, but i think the button count jumps, should I add some sort of debounce code?

Select as Best AnswerUndo Best Answer

user
steveastrouk (author)cmasuo2014-07-28

put a few msec delay in the interrupt routine

Select as Best AnswerUndo Best Answer