icy ZHANG
Published © Apache-2.0

GAME BALL-Yifan

Interactive game ball

BeginnerWork in progressOver 2 days34
GAME BALL-Yifan

Things used in this project

Story

Read more

Schematics

2023-12-10_10_58_27_YBiPsh4MpL.png

Code

Untitled file

C/C++
#include <Servo.h>
#include <Adafruit_NeoPixel.h>

#define SERVO_PIN_1 3
#define SERVO_PIN_2 5
#define ULTRASONIC_TRIGGER_PIN 12
#define ULTRASONIC_ECHO_PIN 11
#define NEOPIXEL_PIN 9
#define NUM_PIXELS 20
bool isReturning = false;

Servo servo1;
Servo servo2;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

enum UltrasonicState1 {
  IDLE_1,
  MOVE_SERVO1
};

enum UltrasonicState2 {
  IDLE_2,
  MOVE_SERVO2
};

UltrasonicState1 currentState1 = IDLE_1;
UltrasonicState2 currentState2 = IDLE_2;
int servo1Angle = 0;
unsigned long lastServoMoveMillis = 0;
unsigned long rainbowStartTime = 0;
bool rainbowTriggered = false;

// 函数原型声明
int measureDistance();

void setup() {
  Serial.begin(9600);
  pinMode(ULTRASONIC_TRIGGER_PIN, OUTPUT);
  pinMode(ULTRASONIC_ECHO_PIN, INPUT);

  strip.begin();
  strip.show();

  servo1.attach(SERVO_PIN_1);
  servo1.write(0);

  servo2.attach(SERVO_PIN_2);
  servo2.write(0);
}

void loop() {
  ultrasonicLoop();
}

void ultrasonicLoop() {
  int distance = measureDistance();
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");

  // 控制第一个舵机
  switch (currentState1) {
    case IDLE_1:
      if (distance < 20) {
        currentState1 = MOVE_SERVO1;
        servo1Angle = 0;
        lightUpStrip();
      } else {
        turnOffStrip();
        servo1.write(0);
        currentState1 = IDLE_1;
      }
      break;
    case MOVE_SERVO1:

  if (millis() - lastServoMoveMillis > 1000) { // 减少时间间隔
    if (servo1Angle < 180 && !isReturning) {
      servo1.write(servo1Angle);
      servo1Angle += 10;  // 增加角度变化量
      if (servo1Angle > 180) {
        servo1Angle = 180; // 防止超过180度
      }
    } else {
      isReturning = true;
      servo1.write(servo1Angle);
      servo1Angle -= 10;  // 减少角度变化量
      if (servo1Angle < 0) {
        servo1Angle = 0; // 防止小于0度
        isReturning = false;
      }
    }
    lastServoMoveMillis = millis();
  }
  break;


  }

  if (distance >= 20) {
    servo1.write(0);
    currentState1 = IDLE_1;
  }

  // 控制第二个舵机
  switch (currentState2) {
    case IDLE_2:
      if (distance < 5) {
        currentState2 = MOVE_SERVO2;
        servo2.write(90);
      } else {
        servo2.write(0);
        currentState2 = IDLE_2;
      }
      break;
    case MOVE_SERVO2:
      if (distance > 9) {
        servo2.write(0);
        currentState2 = IDLE_2;
      }
      break;
  }

  // 当距离在20cm到25cm之间触发彩虹效果
  if (distance >= 20 && distance <= 45) {
   
    if (!rainbowTriggered) {
      rainbowStartTime = millis();
      rainbowTriggered = true;
    }
    rainbowEffect();
  } else {
    rainbowTriggered = false;
     if (distance > 46) {
   digitalWrite(5, LOW); 
   digitalWrite(3, LOW); 
   digitalWrite(9, LOW); 


    //servo1.write(0);
    //servo2.write(0);
    //turnOffStrip();
    return; // 直接返回,不执行其他动作
  }
  }
  
}

void lightUpStrip() {
  for (int i = 0; i < NUM_PIXELS; i++) {
    strip.setPixelColor(i, strip.Color(255, 165, 0)); // 橙色
  }
  strip.show();
}

void turnOffStrip() {
  for (int i = 0; i < NUM_PIXELS; i++) {
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
  strip.show();
}

void rainbowEffect() {
  if (millis() - rainbowStartTime < 5000) {
    for (int j = 0; j < 256; j++) {
      for (int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, Wheel((i + j) & 255));
      }
      strip.show();
      delay(20);
    }
  } else {
    turnOffStrip();
  }
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

int measureDistance() {
  const int sampleSize = 5; // Number of samples to take
  int readings[sampleSize]; // Array to store the readings
  int sum = 0; // Sum of all valid readings
  int validReadings = 0; // Number of valid readings

  for (int i = 0; i < sampleSize; ++i) {
    digitalWrite(ULTRASONIC_TRIGGER_PIN, LOW);
    delayMicroseconds(2);
    digitalWrite(ULTRASONIC_TRIGGER_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(ULTRASONIC_TRIGGER_PIN, LOW);

    readings[i] = pulseIn(ULTRASONIC_ECHO_PIN, HIGH) * 0.034 / 2;
    
    // Simple filter: only accept readings that are not 0
    if (readings[i] != 0) {
      sum += readings[i];
      validReadings++;
    }
    delay(10); // Small delay to prevent echo interference
  }

  if (validReadings > 0) {
    return sum / validReadings; // Return the average of valid readings
  } else {
    return -1; // Return an error value if no valid readings
  }
}

Credits

icy ZHANG
1 project • 0 followers

Comments