Operácie

Hra Máš pevnú ruku?

Zo stránky SensorWiki


Záverečný projekt predmetu MIPS / LS2025 - Dávid Jamarik


Zadanie

https://www.makeuseof.com/tag/make-buzz-wire-game-arduino/

Cieľom bolo urobiť hru "Máš pevnú ruku?", zostaviť podstavu na ktorej bude ležať obvod a v ktorom bude trať po ktorej pôjde drôťik

Vývojová doska WS-19287, Arduino-Compatible.

Literatúra:


Analýza a opis riešenia

Pri zostavení projektu som použil:

2x Reproduktor - zapojené bez ohľadu na polaritu

Reproduktor.

Tlačidlo

Tlačidlo.

3x 220 Ohm Rezistor

220 Ohm Rezistor.


Schéma zapojenia:

Schéma zapojenia.
Schéma zapojenia.


Algoritmus a program

Hlavne funkcie ktoré využívam sú: buzz, sing, collison a loop

void buzz(int duration int frequency):

  • duration -> koľko by mala trvať jedna nota
  • frequency -> tón noty
  • long delayValue je 1138, _delay_ms() potreboval konštantu a nemohol byť výpočet, je to spriemerovaná hodnota všetkých 'páuz' aby to znelo rozumne

void sing():

  • millis() je prepísaný aby fungoval v AVRStudio
  • na konci je if ktorý pozerá kde v pesničke sme aby to nadväzovalo na seba a nešlo zase od začiatku

void collision():

  • jednoduchá funkcia ktorá keď sa dotkne drôtik trate tak 3-krát zapípa s krátkou pauzou medzi nimi

void loop():

  • pozerá či bolo stlačené tlačidlo, ak áno začne hru, ak nie tak sa nič nedeje
  • pozerá pokiaľ bol drôtik dotknutý s traťou, pokiaľ áno zavolá collision(), pokiaľ nie nič sa nedeje, a pritom stále hrá pesničku

pitches.h:

  • všetky noty zapísané ako sa volajú namiesto číselný hodnôt v kóde


Výpis kódu:

#define F_CPU 16000000UL

#define TIMER0_COMPARE 249  // 1ms s 64 prescla pri 16MHz

#include "pitches.h"
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define set_bit(ADDRESS, BIT) (ADDRESS |= (1 << BIT))
#define clear_bit(ADDRESS, BIT) (ADDRESS &= ~(1 << BIT))
#define toggle_bit(ADDRESS, BIT) (ADDRESS ^= (1 << BIT))

#define buzz1 PB3   // D11
#define buzz2 PB2   // D10
#define course PB1  // D9
#define button PD2  // D2

volatile unsigned long timer0_millis = 0;

ISR(TIMER0_COMPA_vect) {
  timer0_millis++;
}

unsigned long millis() {
  unsigned long ms;
  cli();
  ms = timer0_millis;
  sei();
  return ms;
}

void setup_timer0() {
  TCCR0A |= (1 << WGM01);                         // CTC mode
  TCCR0B |= (1 << CS01) | (1 << CS00);            // Prescaler 64
  OCR0A = TIMER0_COMPARE;
  TIMSK0 |= (1 << OCIE0A);                        // Enable compare interrupt
  sei();                                          // Enable global interrupts
}

// Music
int songState = 0;

int melody[] = {
  NOTE_F4, NOTE_E4, NOTE_D4, NOTE_CS4,
  NOTE_C4, NOTE_B3, NOTE_AS3, NOTE_A3,
  NOTE_G3, NOTE_A3, NOTE_AS3, NOTE_A3,
  NOTE_G3, NOTE_C4, 0,

  NOTE_C4, NOTE_A3, NOTE_A3, NOTE_A3,
  NOTE_GS3, NOTE_A3, NOTE_F4, NOTE_C4,
  NOTE_C4, NOTE_A3, NOTE_AS3, NOTE_AS3,
  NOTE_AS3, NOTE_C4, NOTE_D4, 0,

  NOTE_AS3, NOTE_G3, NOTE_G3, NOTE_G3,
  NOTE_FS3, NOTE_G3, NOTE_E4, NOTE_D4,
  NOTE_D4, NOTE_AS3, NOTE_A3, NOTE_A3,
  NOTE_A3, NOTE_AS3, NOTE_C4, 0,

  NOTE_C4, NOTE_A3, NOTE_A3, NOTE_A3,
  NOTE_GS3, NOTE_A3, NOTE_A4, NOTE_F4,
  NOTE_F4, NOTE_C4, NOTE_B3, NOTE_G4,
  NOTE_G4, NOTE_G4, NOTE_G4, 0,

  NOTE_G4, NOTE_E4, NOTE_G4, NOTE_G4,
  NOTE_FS4, NOTE_G4, NOTE_D4, NOTE_G4,
  NOTE_G4, NOTE_FS4, NOTE_G4, NOTE_C4,
  NOTE_B3, NOTE_C4, NOTE_B3, NOTE_C4, 0
};

int tempo[] = {
  8, 16, 8, 16,
  8, 16, 8, 16,
  16, 16, 16, 8,
  16, 8, 3,

  12, 16, 16, 16,
  8, 16, 8, 16,
  8, 16, 8, 16,
  8, 16, 4, 12,

  12, 16, 16, 16,
  8, 16, 8, 16,
  8, 16, 8, 16,
  8, 16, 4, 12,

  12, 16, 16, 16,
  8, 16, 8, 16,
  8, 16, 8, 16,
  8, 16, 4, 16,

  12, 17, 17, 17,
  8, 12, 17, 17,
  17, 8, 16, 8,
  16, 8, 16, 8, 1
};

#define MELODY_LENGTH (sizeof(melody)/sizeof(melody[0]))

unsigned long previousMillis1 = 0;
const long interval1 = 1500;
unsigned long previousMillis2 = 0;
const long interval2 = 100;
unsigned long previousMillis3 = 0;
const long interval3 = 1000;

int displayStatus = 0;
int mode = 1;
int countdown = 0;
int count = 20;

void setup() {
  setup_timer0();

  // Set buzzers ako vstupi
  set_bit(DDRB, buzz1);
  set_bit(DDRB, buzz2);

  // Set course wire ako vstup s pull-up
  clear_bit(DDRB, course);
  set_bit(PORTB, course);

  // Set button ako vstup s pull-up
  clear_bit(DDRD, button);
  set_bit(PORTD, button);
}

void buzz(int duration, int frequency) {
  if (frequency == 0) return;

  long delayValue = 1138; // priemer aby to znelo OK

  // vypocet kolko cyclov treba s duration a frequecny
  long numCycles = (long)frequency * duration / 1000;

  for (long i = 0; i < numCycles; i++) {
    set_bit(PORTB, buzz1);  // Turn on buzzer 1
    set_bit(PORTB, buzz2);  // Turn on buzzer 2
    _delay_us(delayValue);  

    clear_bit(PORTB, buzz1); // Turn off buzzer 1
    clear_bit(PORTB, buzz2); // Turn off buzzer 2
    _delay_us(delayValue);   
  }
}

void sing() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis2 >= interval2) {
    previousMillis2 = currentMillis;

    int currentNote = melody[songState];
    int duration = 1000 / tempo[songState];

    buzz(duration, currentNote);  // hraj na oba buzzers
    buzz(10, 0);                  // kratke ticho

    ++songState;

    if (songState > 79) {
      songState = 14;  // Loop 
    }
  }
}

void collision_sound()  {
  for (int i = 0; i < 3; i++) {
    buzz(100, NOTE_E5); // zvuk dotknutia sa
    buzz(100, 0);
  }
}

volatile uint8_t gameRunning = 0;
uint8_t lastButtonState = 1;

void loop() {
  uint8_t currentButtonState = PIND & (1 << button);

  // button stlacenie (rising)
  if (!currentButtonState && lastButtonState) {
    _delay_ms(50);  
    currentButtonState = PIND & (1 << button);
    if (!currentButtonState) {
      gameRunning = !gameRunning;
    }
  }

  lastButtonState = currentButtonState;

  static int wireWasHit = 0;

  if (gameRunning) {
    if (!(PINB & (1 << course))) {  // kabel dotknuty
      if (!wireWasHit) {
        wireWasHit = 1;
        collision_sound();  // hraj koliziu
      }
    } else {
      wireWasHit = 0;  
    }

    sing();  // hrat hudbu ked si zapnuty
  }
}

int main(void) {
  setup();
  while (1) {
    loop();
  }
}
#ifndef PITHCES_H_
#define PITHCES_H_

#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978

#endif /* PITHCES_H_ */

Zdrojový kód: BuzzWire.zip

Overenie

Na použitie stačí zapojiť mikroprocesor, stlačiť tlačidlo, chytiť nevodivú časť drôtika, hrať a nedotknúť sa trate drôtikom

Aplikácia.
Aplikácia.

Video: Vo videu je pár krát počuť 3-krát zapípať keď sa dotknem traťe