/*
 * =====================================================
 * TEDDY BEAR WAVE CONTROLLER
 * =====================================================
 *
 * Description: Makes a teddy bear's arm wave for 10 seconds
 *              when a button is pressed
 *
 * Components:
 *   - Arduino Uno (or compatible)
 *   - Servo motor (SG90 or similar)
 *   - Push button (momentary)
 *   - Jumper wires
 *
 * Connections:
 *   - Button: Pin 2 and GND
 *   - Servo Signal: Pin 9
 *   - Servo Power: 5V
 *   - Servo Ground: GND
 *
 * =====================================================
 */

#include <Servo.h>

// ============ PIN CONFIGURATION ============
const int BUTTON_PIN = 2;        // Push button input
const int SERVO_PIN = 9;         // Servo motor control

// ============ SERVO SETTINGS ============
const int ARM_DOWN = 0;          // Servo angle when arm is down/rest
const int ARM_UP = 90;           // Servo angle when arm is up/waving
const int WAVE_SPEED_MS = 500;   // Milliseconds per wave cycle (adjust for faster/slower)

// ============ TIMING SETTINGS ============
const unsigned long WAVE_DURATION_MS = 10000;  // 10 seconds total wave time

// ============ OBJECTS & VARIABLES ============
Servo armServo;                  // Servo object
bool isCurrentlyWaving = false;  // Tracks if wave is in progress
unsigned long waveStartTime = 0; // Records when wave started
bool lastButtonState = HIGH;     // Previous button state (for edge detection)
bool currentButtonState = HIGH;  // Current button state

// ============ SETUP ============
void setup() {
  // Initialize serial communication for debugging
  Serial.begin(9600);
  Serial.println("Teddy Bear Wave Controller - Ready!");
  Serial.println("Press button to make teddy wave!");

  // Configure button pin with internal pull-up resistor
  // This means button reads HIGH when not pressed, LOW when pressed
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  // Attach servo to pin and set initial position
  armServo.attach(SERVO_PIN);
  armServo.write(ARM_DOWN);

  // Small delay to let servo reach position
  delay(500);
}

// ============ MAIN LOOP ============
void loop() {
  // Check button state
  checkButton();

  // If waving is active, perform wave motion
  if (isCurrentlyWaving) {
    performWave();
  }

  // Small delay for stability
  delay(10);
}

// ============ BUTTON CHECK FUNCTION ============
void checkButton() {
  // Read current button state
  currentButtonState = digitalRead(BUTTON_PIN);

  // Detect button press (HIGH to LOW transition)
  // Only start wave if not already waving
  if (currentButtonState == LOW && lastButtonState == HIGH && !isCurrentlyWaving) {
    startWaving();
  }

  // Update last button state
  lastButtonState = currentButtonState;
}

// ============ START WAVING FUNCTION ============
void startWaving() {
  Serial.println("Button pressed! Starting wave sequence...");
  isCurrentlyWaving = true;
  waveStartTime = millis();
}

// ============ PERFORM WAVE FUNCTION ============
void performWave() {
  // Calculate how long we've been waving
  unsigned long currentTime = millis();
  unsigned long elapsedTime = currentTime - waveStartTime;

  // Check if wave duration is complete
  if (elapsedTime >= WAVE_DURATION_MS) {
    stopWaving();
    return;
  }

  // Calculate current position in wave cycle
  unsigned long cyclePosition = elapsedTime % WAVE_SPEED_MS;

  // Create smooth back-and-forth motion
  int servoAngle;

  if (cyclePosition < WAVE_SPEED_MS / 2) {
    // First half: Move from down to up
    servoAngle = map(cyclePosition, 0, WAVE_SPEED_MS / 2, ARM_DOWN, ARM_UP);
  } else {
    // Second half: Move from up to down
    servoAngle = map(cyclePosition, WAVE_SPEED_MS / 2, WAVE_SPEED_MS, ARM_UP, ARM_DOWN);
  }

  // Move servo to calculated angle
  armServo.write(servoAngle);
}

// ============ STOP WAVING FUNCTION ============
void stopWaving() {
  Serial.println("Wave complete! Arm returning to rest position.");
  isCurrentlyWaving = false;
  armServo.write(ARM_DOWN);
}

// ============ END OF CODE ============
