Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

От макетной платы к печатной: игра Simon Says — Часть 1

Компоненты и расходные материалы

Arduino UNO ×1
Макетная плата полноразмерная ×1
Светодиоды (generic) ×4
Тактильные кнопки 12 мм (SparkFun) ×4
Зуммер (buzzer) ×1
Перемычки ×12
Резисторы 10 кОм (pull-down для кнопок) ×4
Резисторы 330 Ом (для LED) ×4
USB-кабель A-B ×1

Приложения и онлайн-сервисы

О проекте

Введение

Все знают старую игру Simon Says — нужно повторять последовательность вспышек, нажимая соответствующие кнопки. Для Hackster Live мы продемонстрировали инструмент проектирования PCB — Upverter. Это веселый и простой проект для создания и превращения в печатную плату. Ниже — базовая версия с железом и кодом.

Серия из трёх частей:

  1. Часть 1: Сборка Simon Says на макетной плате (эта статья)
  2. Часть 2: Проектирование PCB в Upverter на базе этой игры
  3. Часть 3: Фрезеровка собственной PCB по проекту из Upverter на станке с ЧПУ

Чему вы научитесь в этой серии

Программное обеспечение

Если нет Arduino IDE — скачайте последнюю версию для своей ОС здесь.

Сборка оборудования

Ориентировался на пример из SparkFun Inventor's Kit с небольшими изменениями. См. диаграмму Fritzing ниже.

От макетной платы к печатной: игра Simon Says — Часть 1
От макетной платы к печатной: игра Simon Says — Часть 1

Код

В этой игре масса вариаций. Железо базируется на примере SparkFun, код написал с нуля. Если не хотите писать свой — используйте мой ниже, адаптируйте код SparkFun или поищите другие реализации Simon Says под ваше железо.

В коде подробные комментарии и отладочные Serial.print — видно, что происходит в мониторе порта. Видео работы игры ниже!

Видео Simon Says

Примечание: в видео условие победы — 5 правильных повторений подряд. Можно увеличить для сложности, но видео хотел короче :).

Теперь вы готовы превратить макетную плату в PCB! Учимся в Breadboard to PCB Part 2 — Designing a PCB using Upverter.

Код

Simon Says Arduino Code
int ledArray[] = {12, 9, 5, 2};    // 0=зелёный, 1=красный, 2=жёлтый, 3=синий
int buttonArray[] = {13, 10, 6, 3}; // то же соответствие
int pinCount = 4;
int buzzer = 8;
int ledState = 0;
int gameState = 0;
#define NUMBERTOWIN 5  // сколько вспышек повторить для победы — меняйте для сложности
int gameValues[NUMBERTOWIN];
int roundNum = 0;
unsigned long previousMillis = 0;
unsigned long interval1 = 500;

void setLed(int ledNum);
void displayClue(int roundNum);
boolean waitForInput(int buttonNum);

void setup() {
  Serial.begin(9600);
  Serial.println("setup");
  for (int Pin = 0; Pin < pinCount; Pin++) {
    pinMode(ledArray[Pin], OUTPUT);
  }
  for (int Pin = 0; Pin < pinCount; Pin++) {
    pinMode(buttonArray[Pin], INPUT_PULLUP); // используем встроенные pull-up
    // автор добавил внешние 10к после написания кода — можно переделать, но не обязательно
  }
  randomSeed(analogRead(0)); // шум на А0 для случайности
}

void loop() {
  if (gameState == 0) {
    int b0 = digitalRead(buttonArray[0]);
    int b1 = digitalRead(buttonArray[1]);
    int b2 = digitalRead(buttonArray[2]);
    int b3 = digitalRead(buttonArray[3]);
    if (b0 && b1 && b2 && b3) { // ни одна не нажата (pull-up = HIGH)
      pre_game();
    } else {
      Serial.println("button Pressed");
      setLed(-1); // все LED выкл
      roundNum = 0;
      delay(1000);
      gameState = 1;
    }
  }
  if (gameState == 1) gamePlay();
  if (gameState == 2) { // Победа
    delay(500);
    winning_sound();
    winDisplay(); winDisplay(); winDisplay();
    loseDisplay(); // для перехода
    Serial.println("winDisplay");
    delay(1000);
    gameState = 0;
  }
  if (gameState == 3) { // Проигрыш
    delay(500);
    losing_sound();
    loseDisplay(); loseDisplay(); loseDisplay();
    Serial.println("loseDisplay");
    delay(1000);
    gameState = 0;
  }
}

void pre_game() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval1) {
    if (ledState == 0) { Serial.println("pre green"); setLed(0); ledState = 1; }
    else if (ledState == 1) { Serial.println("pre red"); setLed(1); ledState = 2; }
    else if (ledState == 2) { Serial.println("pre yellow"); setLed(2); ledState = 3; }
    else if (ledState == 3) { Serial.println("pre blue"); setLed(3); ledState = 0; }
    previousMillis = currentMillis;
  }
}

void gamePlay() {
  Serial.println("gamePlay");
  for (int i = 0; i < NUMBERTOWIN; i++) {
    gameValues[i] = floor(random(0, 4));
    Serial.println(gameValues[i], DEC);
  }
  Serial.print("Starting Round "); Serial.println(roundNum, DEC);
  for (int r = 0; r < NUMBERTOWIN; r++) {
    displayClue(roundNum);
    for (int i = 0; i <= roundNum; i++) {
      Serial.print("Waiting for input "); Serial.print(i+1, DEC);
      Serial.print(" of "); Serial.print(roundNum+1, DEC); Serial.println("");
      if (waitForInput(gameValues[i])) {
        if (i == roundNum) {
          Serial.println("Correct");
          if (roundNum == NUMBERTOWIN - 1) {
            Serial.println("You Win!");
            gameState = 2; return;
          } else { Serial.println("Continue"); }
        }
      } else {
        Serial.println("You Lose!");
        gameState = 3; return;
      }
    }
    roundNum++;
    delay(1000);
  }
}

void setLed(int ledNum) {
  if (ledNum < 0) {
    for (int i = 0; i < pinCount; i++) digitalWrite(ledArray[i], LOW);
  } else {
    for (int i = 0; i < pinCount; i++) {
      digitalWrite(ledArray[i], (i == ledNum) ? HIGH : LOW);
    }
  }
}

void displayClue(int roundNum) {
  setLed(-1);
  for (int i = 0; i <= roundNum; i++) {
    setLed(gameValues[i]); delay(750);
    setLed(-1); delay(250);
  }
}

boolean waitForInput(int buttonNum) {
  while (true) {
    int b0 = digitalRead(buttonArray[0]);
    int b1 = digitalRead(buttonArray[1]);
    int b2 = digitalRead(buttonArray[2]);
    int b3 = digitalRead(buttonArray[3]);
    if (!b0 || !b1 || !b2 || !b3) { // нажата хоть одна (pull-up = LOW)
      delay(250); // антидребезг
      if (buttonNum == 0) { digitalWrite(ledArray[0], HIGH); delay(250); digitalWrite(ledArray[0], LOW); }
      else if (buttonNum == 1) { digitalWrite(ledArray[1], HIGH); delay(250); digitalWrite(ledArray[1], LOW); }
      else if (buttonNum == 2) { digitalWrite(ledArray[2], HIGH); delay(250); digitalWrite(ledArray[2], LOW); }
      else if (buttonNum == 3) { digitalWrite(ledArray[3], HIGH); delay(250); digitalWrite(ledArray[3], LOW); }
      if (buttonNum == 0 && b0 == 0) { Serial.println("0 Pressed"); return true; }
      else if (buttonNum == 1 && b1 == 0) { Serial.println("1 Pressed"); return true; }
      else if (buttonNum == 2 && b2 == 0) { Serial.println("2 Pressed"); return true; }
      else if (buttonNum == 3 && b3 == 0) { Serial.println("3 Pressed"); return true; }
      else return false;
    }
  }
}

void winDisplay() {
  for (int i = 0; i < 4; i++) {
    digitalWrite(ledArray[i], HIGH); delay(75); digitalWrite(ledArray[i], LOW); delay(75);
  }
  for (int i = 2; i >= 0; i--) {
    digitalWrite(ledArray[i], HIGH); delay(75); digitalWrite(ledArray[i], LOW); delay(75);
  }
}

void winning_sound() {
  Serial.println("buzzer1");
  tone(buzzer, 294, 250); delay(200);
  tone(buzzer, 294, 250); delay(200);
  tone(buzzer, 294, 250); delay(200);
  tone(buzzer, 392, 500); delay(500);
  tone(buzzer, 392, 250); delay(200);
  tone(buzzer, 440, 250); delay(200);
  tone(buzzer, 392, 250); delay(200);
  tone(buzzer, 440, 250); delay(200);
  tone(buzzer, 494, 500);
}

void loseDisplay() {
  for (int i = 0; i < 4; i++) digitalWrite(ledArray[i], HIGH);
  delay(200);
  for (int i = 0; i < 4; i++) digitalWrite(ledArray[i], LOW);
  delay(200);
}

void losing_sound() {
  Serial.println("losing_sound");
  tone(buzzer, 98, 250); delay(250);
  tone(buzzer, 93, 250); delay(250);
  tone(buzzer, 87, 250); delay(250);
}

Схемы

simon_says_fritzing_Yb8EdKPqD4.fzz (файл Fritzing)

Производственный процесс

  1. Создание игры в реальном времени на Arduino Nano с гироскопом MPU-6050 и OLED-дисплеем
  2. Цифровые кости на Arduino: генератор случайных чисел с LCD-дисплеем и кнопкой
  3. Создание рулетки на 37 светодиодов с Arduino Nano
  4. DIY USB-геймпад на Arduino: собственный высокопроизводительный контроллер
  5. Интерактивная игра с джойстиком и LED-обратной связью на Arduino
  6. Портативный дальномер на Arduino Nano: HC-SR04, питание 18650, 3D-корпус
  7. Pixel Chaser: игра на один тап с NeoPixel Ring и Arduino Nano
  8. Медное гальваническое покрытие: умная система на Arduino UNO
  9. Авиастроение для малых цехов: практическое руководство
  10. Полное руководство по производству 4-слойных печатных плат: пошаговый процесс