Using a button and a tilt sensor, both on to trigger a servo

Hi guys

I’m doing an Arduino project for a uni project. The Arduino is made of two inputs a button and a tilt sensor, with two outputs, an led and a servo.

The program if it runs right is supposed to work as such…

When you press and hold the button the led comes on.
The tilt sensor is then active (only while the button is pressed)
When the board is shaken, the servo is then supposed to move 180 degrees. Wait 5 secs, then if it’s still shaking, the servo stays in position. Otherwise, if the board is still after 5 secs the servo spins back to 0. Which then becomes a loop, every time you shake the board with the button pressed the servo moves to 180.

So the LED part of the code is working great, but the servo is not moving. When I compiled my code there were no errors, so now I’m scratching my head as to how to trouble shoot further.

I suspect my problem is in the code for the tilt sensor, particularly the line “unsigned char state = 0”.

Any help would be greatly appreciated!

Thanks and here’s my code…

//StarGate Helmet
#include <Servo.h>
const int seatbuttonPin = 2;
const int rideranglePin = 3;
const int enginePin = 13; //engineLED
const int helmetPin = 9;

int seatbuttonState = 0;

unsigned char state = 0; //state of tilt sensor

Servo myservo; //servo library
int pos = 0; //starting pos of servo

//setting Inputs and outputs
void setup(){
  pinMode (seatbuttonPin, INPUT);
  pinMode (rideranglePin, INPUT);
  pinMode (enginePin, OUTPUT);
  pinMode (helmetPin, OUTPUT);
  Serial.begin(9600);
  myservo.attach(9);
  attachInterrupt(1, blink, RISING); //for the tilt sensor
}

//the full prog
void loop(){
  enginecode();
  if (seatbuttonState==HIGH){
    barbieangle();
  }
}

//Making the engine Active
void enginecode(){
  seatbuttonState = digitalRead(seatbuttonPin); //find if Barbie is sitting on the bike
  if (seatbuttonState == HIGH){
    digitalWrite (enginePin, HIGH);
  } else {
    digitalWrite (enginePin, LOW);
  }
}

//Detecting an unsafe angle for Barbie
void barbieangle(){
  if(state!=0){
    state = 0;
    helmetup;
    delay(5000);
  }
  else{
    helmetdown;
}
}

void blink(){
  state++;
}

//turning the servo

//Turning the helmet up
void helmetup() {
  for(pos = 0; pos < 180; pos +=1){
    myservo.write(pos);
    delay(15);
  }
}

//Folding the helmet down
void helmetdown() {
  for(pos = 180; pos>=1; pos-=1){
    myservo.write(pos);
    delay(15);
  }
}

How are the inputs wired ?

Your code looks for HIGH on the setabuttonPin but have you got a pulldown resistor in place to keep it LOW at other times, or is it floating at an unknown, possibly HIGH, state ?

Consider using INPUT_PULLUP in pinMode() to activate the built in pullup resistor, change the circuit to take the input LOW when active and change the program logic to match.

void enginecode(){[color=#222222][/color]
  seatbuttonState = digitalRead(seatbuttonPin); //find if Barbie is sitting on the bike[color=#222222][/color]
  digitalWrite (enginePin, seatbuttonState);[color=#222222][/color]
}

Are you being paid by the line? :smiley:

helmetdown;

What’s that?

helmetup;

Do you mean

helmetup();

?

And ow, state isn't volatile. But I would drop the interrupt altogether. Tilt sensor isn't going to be that fast.

PS I would only make a single check for the button state ans use that throughout.

Untested (but could not help myself)

//StarGate Helmet
#include <Servo.h>
const byte SeatButtonPin = 2;
const byte RiderAnglePin = 3;
const byte EnginePin = 13; //engineLED
const byte HelmetPin = 9;

const unsigned long HelmetThresholdTime = 5000;
const unsigned long ServoInterval = 15;

Servo helmetServo; //servo library
enum helmet_t{HELMET_OFF, HELMET_ON, HELMET_LOCKED};
helmet_t helmetState = HELMET_OFF;

//setting Inputs and outputs
void setup(){
  pinMode (SeatButtonPin, INPUT_PULLUP);
  pinMode (RiderAnglePin, INPUT_PULLUP);
  pinMode (EnginePin, OUTPUT);
  Serial.begin(9600);
  helmetServo.attach(HelmetPin);
}

void loop(){
  //read state once at the start
  const bool SeatState = digitalRead(SeatButtonPin);
  
  //set engine according to SeatState
  digitalWrite(EnginePin, SeatState);
  
  if(SeatState){
    checkRiderAngle();
  }
  else{
    helmetState = HELMET_OFF;
  }
  
  updateHelmet();
}

void checkRiderAngle(){
  static bool previousAngleState = true;
  static unsigned long helmetMillis = 0;
  
  const bool AngleState = digitalRead(RiderAnglePin);
  const unsigned long MillisNow = millis();
  
  //if tilt changed
  if(previousAngleState != AngleState){
    //if is tilted now and helmet is off
    if(helmetState == HELMET_OFF && !AngleState){
      helmetState = HELMET_ON;
      helmetMillis = MillisNow;
    }
    //if tilted back and helmet state isn't locked
    else if(helmetState != HELMET_LOCKED && AngleState){
      helmetState = HELMET_OFF;
    }
  }
  
  //if: - helmet is on but not locked
  //    - still angled
  //    - threshold time passed 
  if( helmetState == HELMET_ON && 
      !AngleState &&
      (MillisNow - helmetMillis >= HelmetThresholdTime))
  {
    helmetState = HELMET_LOCKED;
  }
        
  //save for the next run
  previousAngleState = AngleState;
}

void updateHelmet(){
  static int helmetAngle = 0;
  static unsigned long servoMillis = 0;
  
  if(millis() - servoMillis >= ServoInterval){
    servoMillis = millis();
    
    if(helmetAngle < 180 && helmetState != HELMET_OFF){
      helmetAngle++;
    }
    else if(helmetAngle > 0 && helmetState == HELMET_OFF){
      helmetAngle--;
    }
    
    helmetServo.write(helmetAngle);
  }
}

Thanks for all your replies, particularly septillion! I'm working my way through now.

It's a helmet for a motorbike. My model is the famous Barbie. The project is a sci fi concept applied to everyday. The sci fi concept I chose was Star Gate and the fold out armour the Horus Guards use. I'm applying it to a motorbike helmet.

The led represents the engine and the servo will attach to a fold out helmet made from ping pong balls.

Barbie will be stoked!

Thanks again Septillion. The servo is moving which is great, so I've got the circuit right.

The servo moves as I shake. If I stop it will return to zero straight away. If I keep shaking it will go until it hits 180.

So I'm pretty close with what I want. Ideally what it's supposed to do is with one shake it goes to 180. Once the shaking stops, the servo is then meant to wait 5 secs and return to 0.

I'm still looking through the code and working out how it all works.

I assume that's with my code?

Myansie:
The servo moves as I shake. If I stop it will return to zero straight away. If I keep shaking it will go until it hits 180.

Mm, don't know why it would return to 0 straight away...

The code I made, after what you told, isn't really meant to detect shaking but a steady angle. You can add a time out in detecting a tilt before setting it to HELMET_OFF.

Myansie:
Once the shaking stops, the servo is then meant to wait 5 secs and return to 0.

I thought that you wanted to lock the helmet on (as long as the button is pushed) after it has been tilted (shaked) for 5 seconds. Do you want to lock it? Or just a delay before helmet off after 5 seconds of not shaking?