При обучении игре на гитаре необходимо всегда соблюдать темп игры, поэтому использование метронома для таких занятий просто необходимо. Классические метрономы не всегда удовлетворяют потребностям начинающих гитаристов, и зачастую они не очень удобны в применении. Но всегда можно сделать свой метроном с расширенным функционалом.
В данном проекте мы сделаем электронный метроном своими руками который будет иметь ряд полезных и немного необычных функциональных возможностей:
- Управление жестами рук или даже жестами гитарным грифом
- Легкое увеличение и уменьшение темпа на 5 ударов в минуту
- Возможность записи и отображения времени время игры для каждой тренировки
В качестве элементов данного метронома выступают следующие компоненты:
- Модуль Heltec WiFi Kit 8 (ESP8266 со встроенным OLED-дисплеем 128x32). Но вы можете использовать любую другую плату совместимую с Arduino с внешним OLED-экраном
- Зуммер 5 В
- Датчик жестов PAJ7620U2
- Корпус, распечатанный на 3D-принтере (опционально)
- Гнездовой разъем постоянного тока (опционально), вы также можете запитать устройство помощью любого USB-кабеля
Схема подключения следующая:
Для установки компонентов можно использовать специально разработанный корпус, распечатываемый на 3D принтере (модель можно взять на https://www.thingiverse.com/thing:4810304).
PAJ7620U2 представляет собой весьма интересный компактный датчик от DFRobot. Он может распознавать жесты вправо, влево, вверх, вниз, вперед, назад, по часовой стрелке, против часовой стрелки и различные волновые движения, поэтому его можно использовать для навигации по меню вместо пайки нескольких кнопок. Библиотека DFRobot_PAJ7620U2.h упрощает всю процедуру. Вы просто помещаете этот код в цикл, и все.
DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture();
if(gesture != paj.eGestureNone ){
String description = paj.gestureDescription(gesture);
if (description=="Right"){
// вставить сюда нужный код обработки
}
}
Основная часть этого проекта – вычисление задержки между звуками, и это делается с помощью этой функции:
unsigned long myDelay=(1000)/(bpm/60);
Чтобы увеличить темп метронома, просто сделайте рукой или гитарой жест вверх. Для уменьшения сделайте жест вниз. Вправо для начала и влево для остановки. Полный код для Arduino IDE представлен далее.
#include <DFRobot_PAJ7620U2.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 5, /* data=*/ 4, /* reset=*/ 16);
DFRobot_PAJ7620U2 paj;
int pinBuzzer=D7;
float bpm=100;
int soundOn=0;
int beepFreq=60;
int animation=1;
static const unsigned char logo[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF,
0x1E, 0x1F, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F,
0xFC, 0xFF, 0xFF, 0xFF, 0x1E, 0x0E, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3C, 0x0F, 0x00, 0xB0,
0xC1, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x79, 0xFE, 0xFF, 0xFF, 0xFF,
0x3C, 0x0F, 0x00, 0x18, 0xE3, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF9,
0x7C, 0xE0, 0x03, 0x1F, 0x3C, 0x0F, 0x00, 0x18, 0x63, 0x06, 0x00, 0x00,
0x00, 0x00, 0xF0, 0xF9, 0x7C, 0xE0, 0x03, 0x1F, 0x3C, 0x07, 0x00, 0x0C,
0x66, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x79, 0x3C, 0xE0, 0x03, 0x3F,
0xB8, 0x07, 0x00, 0x0C, 0xE6, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F,
0x3E, 0xE0, 0x03, 0x1F, 0xB8, 0x07, 0x00, 0x06, 0xFC, 0x07, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x3F, 0xFC, 0xE3, 0x07, 0x1E, 0xB8, 0x03, 0x00, 0x07,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F, 0xFC, 0xE3, 0x07, 0x1F,
0xF0, 0x03, 0x00, 0x03, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F,
0xFC, 0xE3, 0x03, 0x1F, 0xF0, 0x03, 0x80, 0x01, 0x3E, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0xF9, 0xFE, 0xE3, 0x03, 0x1F, 0xF0, 0x03, 0x80, 0x01,
0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF9, 0x7C, 0xE0, 0x03, 0x3F,
0xF0, 0x01, 0xC0, 0x80, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF9,
0x3C, 0xE0, 0x03, 0x1E, 0xE0, 0x01, 0xE0, 0xC0, 0xE1, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0xF9, 0x7C, 0xE0, 0x03, 0x3F, 0xE0, 0x01, 0x60, 0x60,
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF9, 0x3E, 0xE0, 0x07, 0x1F,
0xE0, 0x01, 0x30, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF9,
0x7C, 0xE0, 0x03, 0x1F, 0xF0, 0x01, 0x30, 0x00, 0x80, 0x01, 0x00, 0x00,
0x00, 0x00, 0xF0, 0xF9, 0xFC, 0xE3, 0x03, 0x1F, 0xE0, 0x01, 0x18, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F, 0xFC, 0xE7, 0x03, 0x1F,
0xE0, 0x01, 0x1C, 0x88, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F,
0xFE, 0xE3, 0x03, 0x3F, 0xF0, 0x01, 0xFC, 0xFF, 0xFF, 0x07, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x3F, 0xFC, 0xE3, 0x07, 0x1F, 0xE0, 0x01, 0xDC, 0xDD,
0xD7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
//#define 1616724093912_width 32 x 27
static const unsigned char metro1[] = {
0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x20, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x01, 0xE0, 0x03, 0x01,
0x00, 0xE0, 0x87, 0x0F, 0x00, 0x70, 0x87, 0x1F, 0x00, 0x38, 0xEE, 0x1C,
0x00, 0x38, 0xCE, 0x1C, 0x00, 0x1C, 0xDC, 0x0F, 0x00, 0x0C, 0xF8, 0x0F,
0x00, 0x0E, 0x78, 0x07, 0x00, 0x07, 0x78, 0x00, 0x00, 0x07, 0x7E, 0x00,
0x88, 0x03, 0xEE, 0x00, 0xC0, 0x81, 0xCF, 0x00, 0xC0, 0x81, 0xC3, 0x01,
0xC0, 0xE0, 0x81, 0x03, 0xE0, 0x60, 0x00, 0x03, 0x70, 0x00, 0x00, 0x07,
0x38, 0x00, 0x00, 0x0E, 0xB8, 0x73, 0xAE, 0x0F, 0xF8, 0xFF, 0xFF, 0x1F,
0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char metro2[] = {
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
0x20, 0x80, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x40, 0xC0, 0x07, 0x00,
0xF0, 0xC1, 0x07, 0x02, 0xF0, 0xE3, 0x0E, 0x00, 0x38, 0x77, 0x1C, 0x00,
0x38, 0x73, 0x1C, 0x00, 0xF0, 0x3B, 0x38, 0x00, 0xF0, 0x1F, 0x38, 0x40,
0xA0, 0x1F, 0x70, 0x00, 0x08, 0x3E, 0xE0, 0x00, 0x00, 0x7E, 0xE0, 0x00,
0x00, 0xF7, 0xC0, 0x01, 0x00, 0xE3, 0x80, 0x01, 0x80, 0xE3, 0x83, 0x03,
0xC0, 0x81, 0x03, 0x07, 0xC0, 0x01, 0x07, 0x07, 0xE0, 0x00, 0x00, 0x0E,
0x70, 0x00, 0x00, 0x0C, 0x70, 0x53, 0xAE, 0x1D, 0xF8, 0xFF, 0xFF, 0x1F,
0xF8, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
unsigned long start=0;
unsigned long end=0;
void setup()
{
Serial.begin(115200);
delay(300);
Serial.println("Betty started");
u8g2.begin();
u8g2.clearBuffer();
u8g2.drawXBM(0,0, 128, 32, logo);
u8g2.sendBuffer();
delay(3000);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.drawStr(0,10,"Betty Metronome");
u8g2.drawStr(0,20,"Developed by");
u8g2.drawStr(0,30,"@RoniBandini");
u8g2.sendBuffer();
delay(2000);
while(paj.begin() != 0){
Serial.println("PAJ7620U2 failure! Check if all the connections are fine");
delay(500);
}
paj.setGestureHighRate(true);
}
void loop()
{
DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture();
if(gesture != paj.eGestureNone ){
// "None","Right","Left", "Up", "Down", "Forward", "Backward", "Clockwise", "Anti-Clockwise", "Wave", "WaveSlowlyDisorder", "WaveSlowlyLeftRight", "WaveSlowlyUpDown", "WaveSlowlyForwardBackward"
String description = paj.gestureDescription(gesture);
Serial.println(description);
if (description=="Right"){
Serial.print("Start");
soundOn=1;
start = micros();
}
if (description=="Left"){
Serial.print("Stop");
soundOn=0;
}
if (description=="Up"){
Serial.print("Up");
bpm=bpm+5;
}
if (description=="Down"){
Serial.print("Down");
bpm=bpm-5;
}
} // gesture detected
printScreen();
if (soundOn==1){
tone(pinBuzzer, beepFreq);
delay(10);
noTone(pinBuzzer);
}
unsigned long myDelay=(1000)/(bpm/60);
unsigned long time_now;
Serial.println("Delay: "+String(myDelay)+" ms");
time_now = millis();
while(millis() < time_now + myDelay){
// waiting
}
}
void printScreen(){
u8g2.clearBuffer();
u8g2.drawStr(0,10,"Betty Metronome");
u8g2.drawStr(0,20,"Tempo:");
u8g2.drawStr(38,20,String(int(bpm)).c_str());
u8g2.drawStr(60,20,"BPM");
unsigned long delta=0;
if (soundOn==1){
end = micros();
delta = (end - start)/1000000;
Serial.println(delta);
if (animation==1){
u8g2.drawXBM(90,5, 32, 27, metro1);
animation=2;
}
else
{
u8g2.drawXBM(90,5, 32, 27, metro2);
animation=1;
}
}
u8g2.drawStr(0,30,"Playing:");
u8g2.drawStr(50,30,String(delta).c_str());
u8g2.sendBuffer();
}
Вы также можете добавить новые жесты для сброса времени тренировки или увеличения темпа на 10 и т. д.
© digitrode.ru