参考
x 過去ログをみよ
x 3.1.1
x モノラルである
x マイクは、SPV1840LR5H-B
目的
マイクを使ったサウンドオシロスコープを作る。
速度は、音声程度で特に同期は、していないである。
モノラルである。
入力は、GPIOの1である。
平均してマイナス側は、カットである。
ある。ある。である。
いろいろ
デジタル信号の基本的な操作が入っている。
レベルカットや平均化、0点調整、ゲイン
まとめて、デジタルフィルター処理で昔は、
専用のDSP(デジタルシグナルプロセッサ)で
行っていて、現在、DSPは、絶滅危惧種
理由は、CPUの速度向上の為。
デジタル信号処理の講師の人もあの東芝を
追い出されたと言っていた。
オペアンプ反転増幅の例 各自、ネットで確認の事
結果
プログラム
//秋月のOLEDとアイテンドウのOLEDのアドレスは3C
//ssd1306_Sound_Oscilloscope_point_mic_p1_S3_1
//ヘッダー
#include <Arduino.h>
#include <Wire.h>
//定義
#define MAX_PAGE (7)
#define MAX_COL (127)
#define COMMAND_MODE 0x80 // continuation bit is set!
#define DATA_MODE 0x40
#define SET_COLUMN_ADDRESS 0x21 // takes two bytes, start address and end address of display data RAM
#define SET_PAGE_ADDRESS 0x22 // takes two bytes, start address and end address of display data RAM
#define SET_MEMORY_ADDRESSING_MODE 0x20 // takes one byte as given above
#define HORIZONTAL_ADDRESSING_MODE 0x00
//I2Cに配列を転送する
void write_s(uint8_t *str1, uint8_t len1) {
Wire.beginTransmission( 0x3c );
for (int ii = 0; ii < len1; ii++) {
//一文字出力
Wire.write(*str1 ++);
}//for
Wire.endTransmission();
}//write_s
//セットページアドレス
void setPageAddress(uint8_t start, uint8_t end)
{
uint8_t databytes[6] = {COMMAND_MODE, SET_PAGE_ADDRESS, COMMAND_MODE, start, COMMAND_MODE, end};
write_s(databytes, 6);
}//setPageAddress
//セットカラムアクセス
void setColumnAddress(uint8_t start, uint8_t end)
{
uint8_t databytes[6] = {COMMAND_MODE, SET_COLUMN_ADDRESS, COMMAND_MODE, start, COMMAND_MODE, end};
write_s(databytes, 6);
}//setColumnAddress
//セットメモリーアドレシングモード
void setMemoryAddressingMode()
{
uint8_t databytes[4] = {COMMAND_MODE, SET_MEMORY_ADDRESSING_MODE, COMMAND_MODE, HORIZONTAL_ADDRESSING_MODE};
write_s(databytes, 4);
}//setMemoryAddressingMode
//座標
int SO_X = 0;
int SO_Y = 0;
//8ドット分のデータ
char dot_1ch[8];
char dot_2ch[8];
//ブロックカウント
char b_count = 0;
//パターンRAMの内容を液晶に転送
void Sound_Oscilloscope(int L1, int L2) {
if (SO_Y >= 64) {
//範囲の設定 (OLED内部のx,yカウンターを初期化してホームポジション0,0に)
setPageAddress(0, MAX_PAGE); // all pages
setColumnAddress(0, MAX_COL); // all columns
SO_Y = 0;
//while(1){} //debug
}//end if
dot_1ch[b_count] = L1;
dot_2ch[b_count] = L2;
b_count++;
//b_count = 7; //debug
if (b_count > 7 ) {
//L1 L1 L1 vL1 L1 L1 L1 L1 L1
int a; //一時
//データの配列の定義
uint8_t databytes[2] = {DATA_MODE, 0x00};
for (int x = 0; x < 64; x++) {
//dot8[0]=0;dot8[1]=8;dot8[2]=16;dot8[3]=32;
//dot8[4]=0;dot8[5]=9;dot8[6]=16;dot8[7]=32;
a = 0;
if(dot_1ch[0] == x ) {a = a | 0b00000001;}
if(dot_1ch[1] == x ) {a = a | 0b00000010;}
if(dot_1ch[2] == x ) {a = a | 0b00000100;}
if(dot_1ch[3] == x ) {a = a | 0b00001000;}
if(dot_1ch[4] == x ) {a = a | 0b00010000;}
if(dot_1ch[5] == x ) {a = a | 0b00100000;}
if(dot_1ch[6] == x ) {a = a | 0b01000000;}
if(dot_1ch[7] == x ) {a = a | 0b10000000;}
databytes[1] = a;
write_s(databytes, 2);
b_count = 0;
}//for x
//L2 L2 L2 L2 L2 L2 L2 L2 L2
for (int x = 0; x < 64; x++) {
//dot8[0]=0;dot8[1]=8;dot8[2]=16;dot8[3]=32;
//dot8[4]=0;dot8[5]=9;dot8[6]=16;dot8[7]=32;
a = 0;
if(dot_2ch[0] == x ) {a = a | 0b00000001;}
if(dot_2ch[1] == x ) {a = a | 0b00000010;}
if(dot_2ch[2] == x ) {a = a | 0b00000100;}
if(dot_2ch[3] == x ) {a = a | 0b00001000;}
if(dot_2ch[4] == x ) {a = a | 0b00010000;}
if(dot_2ch[5] == x ) {a = a | 0b00100000;}
if(dot_2ch[6] == x ) {a = a | 0b01000000;}
if(dot_2ch[7] == x ) {a = a | 0b10000000;}
databytes[1] = a;
write_s(databytes, 2);
b_count = 0;
}//for x
}//end if b_count
SO_Y++;
}//Sound_Oscilloscope
//SSD1306の初期化
void display_begin(void) {
//I2Cの初期化
Wire.begin(); //C011
delay(200);
//SSD1306の初期化スペル(魔法)
//0x80,0x8D,0x80,0x14,0x80,0xAF
write_s( (uint8_t*) "\200\215\200\024\200\257", 6);
delay(100);
//セットメモリーアドレシングモード (画面の終端に来たら画面の先頭に)
setMemoryAddressingMode();
//範囲の設定 (OLED内部のx,yカウンターを初期化してホームポジション0,0に)
setPageAddress(0, MAX_PAGE); // all pages
setColumnAddress(0, MAX_COL); // all columns
}//display_begin
//初期化
void setup() {
//SSD1306の初期化
display_begin();
}//setup
//メインループ
void loop() {
//static int L1 = 0;
//L1 = L1 + ( random(16) - 8 );
//if ( L1 < 0 ) {L1 = 0;} else if ( L1 > 64 ) {L1 = 64;}
//L1 = 32;
//static int L2 = 0;
//L2 = L2 + ( random(16) - 8 );
//if( L2 < 0 ) {L2 = 0;} else if ( L2 > 64 ) {L2 = 64;}
// //L1 = 32;
int L1; //値 L ch
int L2; //値 R ch
float s; //input
float cl = 0.0f; //L ch
float cr = 0.0f; //R ch
//L1
for(int i=0;i<2;i++){ //平均化する
//センサー入力する
s = ((float)analogRead(1)); //センサーの値
s = s * (3.3f / 4096.0f); //電圧こと
cl = cl + s;
}
cl = cl / 2;
cl = cl - 1.650f; //中心にする
if(cl < 0) {cl = 0;} //マイナス側のカット(マイクだから+-あり)
cl = cl * 128; //倍率を掛ける(好みで変える)
if(cl > 63) {cl = 63;} //MAXを超えた物をカット
L1 = (int)cl; //キャストして転記
//モノラル時 #ifで処理をコメントアウト
#if 0
//L2
for(int i=0;i<2;i++){ //平均化する
//センサー入力する
s = (float)(analogRead(2)); //センサーの値
s = s * (3.3f / 4096.0f); //電圧こと
cr = cr + s;
}
cr = cr / 2;
cr = cr - 1.650f; //中心にする
if(cr < 0) {cr = 0;} //マイナス側のカット(マイクだから+-あり)
cr = cr * 128; //倍率を掛ける(好みで変える)
if(cr > 63) {cr = 63;} //MAXを超えた物をカット
L2 = (int)cr; //キャストして転記
#else
L2 = L1; //モノラルの時
#endif
Sound_Oscilloscope(L1, L2); //画面の再表示
//delay(1000); //1秒待つ debug
}//loop