Skip to content

Instantly share code, notes, and snippets.

@nyarurato
Created May 1, 2020 13:15
Show Gist options
  • Save nyarurato/bd4a89e94c3b2be6cccf90de0420c229 to your computer and use it in GitHub Desktop.
Save nyarurato/bd4a89e94c3b2be6cccf90de0420c229 to your computer and use it in GitHub Desktop.
#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