Coding

The Stepper and LiquidCrystal libraries of the Arduino software were used in the code. If no cigarette is inserted, only a cigarette counter is shown and some motivational text to encourage people to stop smoking. When a cigarette is inserted, the display changes to allow the user to select the appropriate time to shoot. After shooting by pressing the button, a message is shown depending on whether the ball entered the basket or not. The following code was uploaded to the Arduino:

/* BRUFACE MECHATRONICS 2015 Cigarette Ashtray Game
    Dino, Elie, Marta, Miguel, Pascal
*/
#include <LiquidCrystal.h>
#include <Stepper.h>

#define STEPPER_IN_1 2
#define STEPPER_IN_2 3
#define STEPPER_IN_3 4
#define STEPPER_IN_4 5
#define BUTTON_PIN 7
#define CIGARETTE_SENSOR_PIN A0
#define BASKET_SENSOR_PIN A1
#define IR_SENSOR_PIN A2

Stepper stepper(200, STEPPER_IN_1, STEPPER_IN_2, STEPPER_IN_3, STEPPER_IN_4);
LiquidCrystal lcd(12, 13, 11, 10, 9, 8);

/*
*****************************************************************************
******the following are special characters to be displayed on the LCD********
*****************************************************************************
*/
byte smiley[8] =
{
  B00000,
  B10001,
  B00000,
  B00000,
  B10001,
  B01110,
  B00000,
  B00000
};
byte sad[8] =
{
  B00000,
  B10001,
  B00000,
  B00000,
  B01110,
  B10001,
  B00000,
  B00000
};
byte cross[8] =
{
  B00000,
  B00000,
  B11011,
  B01110,
  B00100,
  B01110,
  B11011,
  B00000
};
byte tick[8] =
{
  B00000,
  B00000,
  B00001,
  B00011,
  B10110,
  B11100,
  B01000,
  B00000
};
byte man_straight[8] =
{
  B00100,
  B01010,
  B00100,
  B11111,
  B00100,
  B00100,
  B01010,
  B10001
};
byte man_down [8] =
{
  B00100,
  B01010,
  B00100,
  B00100,
  B01110,
  B10101,
  B01010,
  B10001
};
byte man_up_r [8] =
{
  B00100,
  B01010,
  B00101,
  B00110,
  B01100,
  B10100,
  B01010,
  B10001
};

byte man_up_l [8] =
{
  B00100,
  B01010,
  B10100,
  B01100,
  B00110,
  B00101,
  B01010,
  B10001
};

// Text to be displayed on the LCD when no cigarette is inserted
String text[5] =
{
  "insert cigarette"
  "smoking kills",
  "smoking is bad",
  "quit smoking",
  "you can do it"
};

bool ins_cig = LOW;
bool cur_cig = LOW;
bool last_cig = LOW;
bool shot_ok = LOW;
bool shot_nok = LOW;
bool forward = HIGH;
bool enable_button = LOW;
bool current_state = HIGH;
bool last_state = HIGH;
byte counter = -1;
byte Speed = 0;
byte steps = 0;
byte t_delay = 50;
byte ran = 4;
byte i = 0;
int cigarette_counter = 0;
unsigned long current_millis = 0;
unsigned long previous_millis = 0;
unsigned long current_millis_motor = 0;
unsigned long previous_millis_motor = 0;
unsigned long current_millis_text = 0;
unsigned long previous_millis_text = 0;

void setup()
{
  //Create the LCD characters declared above
  lcd.createChar(0, smiley);
  lcd.createChar(1, sad);
  lcd.createChar(2, tick);
  lcd.createChar(3, cross);
  lcd.createChar(4, man_straight);
  lcd.createChar(5, man_down);
  lcd.createChar(6, man_up_r);
  lcd.createChar(7, man_up_l);
  stepper.setSpeed(50);
  lcd.begin(16, 2);
  // use the internal pullup resistor in the Arduino
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

// function to debounce the button
boolean debounce(boolean last, int pin)
{
  boolean current = digitalRead(pin);
  if (last != current)
  {
    delay(10);
    current = digitalRead(pin);
  }
  return current;
}

void loop()
{
  // this is used to count each cigarette only once,
  // even if it stays a long time on front of the sensor
  if (analogRead(CIGARETTE_SENSOR_PIN) < 650)
  {
    cur_cig = HIGH;
  }
  else
  {
    cur_cig = LOW;
  }

  // if a cigarette is inserted, enable the button and begin the game
  if ((cur_cig) && (!last_cig))
  {
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("Hit the ");
    lcd.write(byte(2));
    lcd.print(" ");
    lcd.write(byte(0));
    lcd.write(byte(0));
    lcd.write(byte(0));
    cigarette_counter++;
    enable_button = HIGH;
    forward = HIGH;
    counter = -1;
    ins_cig = HIGH;
  }
  last_cig = cur_cig;

  current_millis_text = millis();
  if ((current_millis_text - previous_millis_text) > 1500)
  {
    if (!ins_cig)
    {
      lcd.setCursor(0, 0);
      lcd.print("                ");
      lcd.setCursor(0, 0);
      lcd.print("cigarettes: ");
      lcd.setCursor(12, 0);
      lcd.print(cigarette_counter);
      ins_cig = HIGH;
    }
    if (!enable_button)
    {
      previous_millis_text = current_millis_text;
      lcd.setCursor(0, 1);
      lcd.print("                ");
      lcd.setCursor(0, 1);
      lcd.print(text[i]);
      i++;
      if (i > 4) {
        i = 0;
      }
    }
  }

  // Dancing man on the right cornet of the screen
  if ((current_millis - previous_millis) > 200)
  {
    lcd.setCursor(15, 0);
    ran = random(4, 7);
    lcd.write(byte(ran));
    previous_millis = current_millis;
  }

  current_millis = millis();
  if ((current_millis - previous_millis >= t_delay) && (enable_button))
  {
    previous_millis = current_millis;
    if (forward)
    {
      counter++;
      lcd.setCursor(counter, 1);
      if ((counter == 8) || (counter == 9) || (counter == 7))
      {
        lcd.write(byte(2));
      }
      else
      {
        lcd.write(byte(3));
      }
      if (counter >= 15)
      {
        counter = 16;
        forward = LOW;
      }
    }
    else
    {
      counter--;
      lcd.setCursor(counter, 1);
      lcd.print(" ");
      if (counter <= 0)
      {
        counter = -1;
        forward = HIGH;
      }
    }
  }

  current_state = debounce(last_state, BUTTON_PIN);
  if ((!current_state) & (last_state))
  {
    if (enable_button)
    {
      if ((counter == 8) || (counter == 7) || (counter == 9))
      {
        // accelerate the stepper instead of directly moving at max speed
        // otherwise the motor will not have engough torque to start the movement
        while (Speed <= 150)
        {
          Speed += 15;
          stepper.setSpeed(Speed);
          stepper.step(2);
          steps += 2;
        }
        counter = -1;
        Speed = 0;
        previous_millis_motor = millis();
        enable_button = LOW;
        shot_ok = HIGH;
      }
      else
      {
        // accelerate the stepper instead of directly moving at max speed
        // otherwise the motor will not have engough torque to start the movement
        while (Speed <= 130)
        {
          Speed += 15;
          stepper.setSpeed(Speed);
          stepper.step(3);
          steps += 3;
        }
        counter = -1;
        Speed = 0;
        enable_button = LOW;
        shot_nok = HIGH;
        previous_millis_motor = millis();
      }
    }
    else
    {
      lcd.setCursor(0, 1);
      lcd.print("                ");
      lcd.setCursor(0, 1);
      lcd.print("insert cigarette");
      previous_millis_text = millis();
    }
  }
  last_state = current_state;

  if (shot_nok)
  {
    lcd.clear();
    lcd.print("try next time!");
    lcd.setCursor(0, 1);
    lcd.write(byte(4));
    lcd.write(byte(5));
    lcd.write(byte(7));
    enable_button = LOW;
    shot_nok = LOW;
    ins_cig = LOW;
    i = 0;
    previous_millis_text = millis();
  }

  if (shot_ok)
  {
    if (analogRead(BASKET_SENSOR_PIN) < 1010)
    {
      lcd.setCursor(0, 1);
      lcd.print("                ");
      lcd.setCursor(0, 1);
      lcd.print("you scored! ");
      lcd.write(byte(0));
      score++;
      shot_ok = LOW;
      ins_cig = LOW;
      i = 0;
      previous_millis_text = millis();
    }
  }

  current_millis_motor = millis();
  if ((current_millis_motor - previous_millis_motor) >= 400)
  {
    stepper.setSpeed(40);
    stepper.step(-steps);
    steps = 0;
  }
}