#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