This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <M5StickC.h> | |
#include <driver/i2s.h> | |
#include "arduinoFFT.h" | |
#include <WiFi.h> | |
#include <WiFiClient.h> | |
#define PIN_CLK 0 | |
#define PIN_DATA 34 | |
#define READ_LEN (2 * 1024) | |
#define GAIN_FACTOR 10 | |
#define SAMPLING_FREQUENCY 44100 | |
uint8_t BUFFER[READ_LEN] = {0}; | |
uint16_t oldy[160]; | |
int16_t *adcBuffer = NULL; | |
//for FFT | |
const uint16_t FFTsamples = 512; // サンプル数は2のべき乗 | |
double vReal[FFTsamples]; // vReal[]にサンプリングしたデーターを入れる | |
double vImag[FFTsamples]; | |
arduinoFFT FFT = arduinoFFT(vReal, vImag, FFTsamples, SAMPLING_FREQUENCY); // FFTオブジェクトを作る | |
unsigned int sampling_period_us; | |
float dmax = 10000.0; | |
int bell_start_counter = 0; | |
int not_bell_counter = 0; | |
float max_d=0; | |
int max_band=0; | |
int bell_state = 0; | |
const char* ssid = "**************"; | |
const char* password = "**************"; | |
String makerEvent = "*************"; // Maker Webhooks | |
String makerKey = "***************"; // Maker Webhooks | |
const char* server = "maker.ifttt.com"; // Server URL | |
WiFiClient client; | |
int btn_state = 0; | |
unsigned long last_bell_time = 0; | |
void i2sInit() | |
{ | |
i2s_config_t i2s_config = { | |
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM), | |
.sample_rate = SAMPLING_FREQUENCY, | |
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB | |
.channel_format = I2S_CHANNEL_FMT_ALL_RIGHT, | |
.communication_format = I2S_COMM_FORMAT_I2S, | |
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, | |
.dma_buf_count = 2, | |
.dma_buf_len = 128, | |
}; | |
i2s_pin_config_t pin_config; | |
pin_config.bck_io_num = I2S_PIN_NO_CHANGE; | |
pin_config.ws_io_num = PIN_CLK; | |
pin_config.data_out_num = I2S_PIN_NO_CHANGE; | |
pin_config.data_in_num = PIN_DATA; | |
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); | |
i2s_set_pin(I2S_NUM_0, &pin_config); | |
i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); | |
} | |
void mic_record_task (void* arg) | |
{ | |
size_t bytesread; | |
while(1){ | |
i2s_read(I2S_NUM_0,(char*) BUFFER, READ_LEN, &bytesread, (100 / portTICK_RATE_MS)); | |
adcBuffer = (int16_t *)BUFFER; | |
showSignal(); | |
fft(); | |
vTaskDelay(100 / portTICK_RATE_MS); | |
} | |
} | |
void fft(){ | |
for (int i = 0; i < FFTsamples; i++) { | |
unsigned long t = micros();// | |
vReal[i] = adcBuffer[i]; | |
vImag[i] = 0; | |
} | |
FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD); // 窓関数 | |
FFT.Compute(FFT_FORWARD); // FFT処理(複素数で計算) | |
FFT.ComplexToMagnitude(); // 複素数を実数に変換 | |
int nsamples = FFTsamples/2; | |
max_d = 0; | |
max_band = 0; | |
for (int band = 0; band < nsamples; band++) { | |
float d = vReal[band] / dmax; | |
if(band > 2 && max_d < d){ | |
max_d = d; | |
max_band = band; | |
} | |
} | |
if(max_band == 10){//0.88khz(G#5)が2回ほど見つけたらstate移動 | |
bell_start_counter++; | |
not_bell_counter = 0; | |
if(bell_start_counter >= 2){ | |
bell_state = 1; | |
} | |
}else if(max_band == 8 && bell_state == 1){//0.69khz(E5)を見つける&前回の条件を達成している | |
bell_state = 2; | |
sendMsg(); | |
}else{//リセット | |
not_bell_counter++; | |
if(not_bell_counter > 2){//リセット | |
bell_state = 0; | |
} | |
} | |
} | |
void setup() { | |
M5.begin(); | |
M5.Lcd.setRotation(3); | |
M5.Lcd.fillScreen(WHITE); | |
M5.Lcd.setTextColor(BLACK, WHITE); | |
M5.Lcd.setTextSize(2); | |
i2sInit(); | |
Serial.begin(115200); | |
delay(100); | |
WiFi.begin(ssid, password); | |
while (!checkWifiConnected()) { | |
WiFi.begin(ssid, password); | |
} | |
sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY)); | |
xTaskCreate(mic_record_task, "mic_record_task", 2048, NULL, 1, NULL); | |
} | |
void showSignal(){ | |
M5.Lcd.setCursor(0,0); | |
M5.Lcd.print(max_band); | |
M5.Lcd.print(":"); | |
M5.Lcd.print((max_band * 1.0 * SAMPLING_FREQUENCY) / FFTsamples / 1000); | |
M5.Lcd.print("kHz : "); | |
M5.Lcd.println(max_d); | |
M5.Lcd.print("state : "); | |
M5.Lcd.println(bell_state); | |
} | |
bool checkWifiConnected() { | |
// attempt to connect to Wifi network: | |
while (WiFi.status() != WL_CONNECTED) { | |
Serial.print("."); | |
// wait 1 second for re-trying | |
delay(1000); | |
} | |
Serial.print("Connected to "); | |
Serial.println(ssid); | |
return true; | |
} | |
void sendMsg() { | |
if(abs(micros() - last_bell_time) < 7000000 ){//7秒以内になっていたら何もしない | |
return; | |
}else{ | |
last_bell_time = micros(); | |
} | |
while (!checkWifiConnected()) { | |
Serial.print("Attempting to connect to WiFi"); | |
WiFi.begin(ssid, password); | |
} | |
Serial.println("\nStarting connection to server..."); | |
if (!client.connect(server, 80)) { | |
Serial.println("Connection failed!"); | |
} else { | |
Serial.println("Connected to server!"); | |
// Make a HTTP request: | |
String url = "/trigger/" + makerEvent + "/with/key/" + makerKey; | |
client.println("GET " + url + " HTTP/1.1"); | |
client.print("Host: "); | |
client.println(server); | |
client.println("Connection: close"); | |
client.println(); | |
Serial.print("Waiting for response "); //WiFiClientSecure uses a non blocking implementation | |
int count = 0; | |
while (!client.available()) { | |
delay(50); // | |
Serial.print("."); | |
} | |
// if there are incoming bytes available | |
// from the server, read them and print them: | |
while (client.available()) { | |
char c = client.read(); | |
Serial.write(c); | |
} | |
// if the server's disconnected, stop the client: | |
if (!client.connected()) { | |
Serial.println(); | |
Serial.println("disconnecting from server."); | |
client.stop(); | |
} | |
} | |
} | |
void loop() { | |
vTaskDelay(1000 / portTICK_RATE_MS); // otherwise the main task wastes half of the cpu cycles | |
if(digitalRead(M5_BUTTON_HOME) == LOW && btn_state == 0){ | |
M5.Axp.ScreenBreath(0); | |
btn_state = 1; | |
while (digitalRead(M5_BUTTON_HOME) == LOW) ; | |
}else if(digitalRead(M5_BUTTON_HOME) == LOW && btn_state == 1){ | |
M5.Axp.ScreenBreath(10); | |
btn_state = 0; | |
while (digitalRead(M5_BUTTON_HOME) == LOW) ; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment