syouwa-taroのアイコン画像
syouwa-taro 2023年11月06日作成 (2023年11月30日更新) © MIT
製作品 製作品 閲覧数 1351
syouwa-taro 2023年11月06日作成 (2023年11月30日更新) © MIT 製作品 製作品 閲覧数 1351

よく聞こえる静かなスピーカー

よく聞こえる静かなスピーカー

概要

年と共にテレビの音は聞こえるのに内容が聞きづらくなる。テレビの音を大きくすればよいが、周りに喧しく我慢することになる。内容が聞きづらい人に高域をあげたテレビ音声が耳元で聞こえるよう、超指向性スピーカーを正確に自動追尾で人に向ける事により実現した作品である。

仕組みは2Wayスピーカシステムで高域には方向が可変できる超指向性スピーカーを使う。リスナーからリモコンでスキャンコマンドを受けるとリスナーの角度計測しその角度に高域スピーカー向ける。リスナーの所だけ高域が強調された音が聞こえ、周りは静かで聞きやすいスピーカー。

システム構成

  1. 構成はテレビの音を2Wayスピーカーで鳴らしている。中低域スピーカーは固定で、高域スピーカーは指向性のあるパラメトリックスピーカーを使い、正面から左右にサーボで回転。
  2. 人のスキャンはリモコン受光部と赤外線アレーセンサを備え、リモコン信号を一定時間(5秒)受けるとセンサが人の位置を検出し、高域スピーカーがリスナーの正面を向くようサーボが回転する。
    (リモコン信号はどのようなフォーマット キーの種類でも受け付ける。長押しのみ受け付けるので通常のリモコン操作では動かず通常の使い方に支障はなく、新しいリモコンが増えることもない)

動作

  1. リモコン受光ブロックでリモコン信号を受ける。リモコン出力を信号より長い積分定数で積分(1K x10μ)する。これによりどのリモコンフォーマット・コードでもリモコン信号の有無を判別でき5秒以上長押しをカウント。また通常のリモコンの使われ方(5秒以内のキー操作)には反応しない。
    キャプションを入力できます

  2. リモコンを受け付けると、パラメトリックスピーカーに付けられている赤外線アレーセンサ(8x8block)で温度の高い(=人の体温)水平位置を検出。中心Block(=正面)からずれている左右の角度が0度になるようServoを回転させ、中心に来ると回転停止する。

  3. 高域パラメトリックスピーカーが人の正面を向くことにより、人の居るところだけに高域が強調され音が聞きやすく、周りは静かなスピーカーを実現する。

キャプションを入力できます

キーパーツ

部品 備考
NANO Arduino
ParametoricSpeaker 秋月実験KIT
AMG8833 赤外線アレーセンサ スイッチサイエンス
VS18388 赤外リモコン受光ブロック
MG995 Servoモーター : 大き目ですが回転が遅ければ小型SG90などでもよさそうです。
L7805 5V三端子レギュレーター Servo用5V(小型ServoでNANO5V出力が使えれば不要)
SpeakerBOX テレビの音を聞くスピーカーBOX
TPA2006 超小型アンプ 秋月
100K~200KVR 中低域SPの音量調整 高域SPとのバランスをとる

動画

ここに動画が表示されます

感想

テレビ音声の内容が聞きづらい人に、高域強調することで聞きやすくなる?
パラメトリックスピーカーでの実験では多くの人が肯定的であった。作品はリモコン(種類は問わず5秒押し)が送信されるとスピーカーが人を見つけ追尾する電子工作の楽しさがメインでありコストも高く、もっとシンプルにも作れそうです。(例えば 赤外線アレーセンサは高価@¥5000で、リモコン受光ブロック@¥100を扇に並べリモコン信号の来る方向を検知出来れば安価に出来そうです)
家族の中一人聞きづらく困っている人に、このような製品を提供される参考となれば幸いです。

課題

今回使った指向性パラメトリックスピーカーは40Khz超音波を使用しており,出力音圧 視聴時間によっては耳に違和感を生じることもあるというアドバイスをいただいております。本作品はホビー工作としてまだ検証は十分されておりません。実験される場合注意していただくようお願い致します。今後音圧等の検証を進め他の方式も含め、更に完成度の高い”よく聞こえる静かなスピーカー”を目指したいと思っており、またご教授いただけたら幸いです。

遠くでも障害物があってもよく聞こえるバーチャルスピーカー 参考:パラメトリックスピーカー応用作品

超音波の人体への影響について、いろいろ検証されレポートも出ています。規制する法律はなさそうですが、効果が確認出来る範囲で出力を抑えることが望ましいです。
強力超音波の安全な利用に向けて:人体への影響 
超音波が人体に与える影響 
パラメトリックスピーカー

よく聞こえる静かなスピーカー

#include <Wire.h> #define PCTL 0x00 #define RST 0x01 #define FPSC 0x02 #define INTC 0x03 #define STAT 0x04 //SDA #define SCLR 0x05 //SCL #define AVE 0x07 #define INTHL 0x08 #define TTHL 0x0E #define INT0 0x10 #define T01L 0x80 #define AMG88_ADDR 0x68 // IIC68h:default 69h:jumper //temporaryData to buffer sumtotal IIC ADlow68h ADhigh69h int TMPDAT1[65], TMPDAT2[65], TMPDAT3[65], TMPDATS[65]; int TMPVS[8]; //TemperatureVerticalsum=TMPVS[0]:RRRSum ~ TMPVS[7]:LLLLSum int VSmaxH[3] = {4, 4, 4 }; //サーモセンサ正面  verticalSumax HorizontalAngle ([0]:Servo決定 [1]:Buffer [2]:New = 0:RRRR ~4:center~ 8:LLLL) int TMPVSmax = 0 ; int VSmin = 3000 ; int maxmin ; int SA = 45 ; // ServoAngle Left 0~40度 SP正面40~50度 Right 50度~90度 int RS = 1023 ; //RemoconSignal 0(信号有:送信機正面)~ 1023(信号無) int RSTIM = 0 ; //RemoconSignal Timer 信号がある時間カウント int SCANf = 0 ; //ScanFlg Scan終了まで1を維持 #include <Servo.h> // Servoライブラリの読み込み Servo myservo; // Servoオブジェクトの宣言 const int SV_PIN = 7; // サーボモーターをデジタルピン7に const int PIN_ANALOG_INPUT = 7 ; //リモコン入力をアナログピン7に void setup() { Serial.begin(115200); Wire.begin(); //IIC SCL:A5 SDA:A4 AMG8833(Jumperで変更可能) int fpsc = B00000000;// 1fps datasend(AMG88_ADDR, FPSC, &fpsc, 1); int intc = 0x00; // diff interrpt mode, INT output reactive datasend(AMG88_ADDR, INTC, &intc, 1); // moving average output mode active int tmp = 0x50; datasend(AMG88_ADDR, 0x1F, &tmp, 1); tmp = 0x45; datasend(AMG88_ADDR, 0x1F, &tmp, 1); tmp = 0x57; datasend(AMG88_ADDR, 0x1F, &tmp, 1); tmp = 0x20; datasend(AMG88_ADDR, AVE, &tmp, 1); tmp = 0x00; datasend(AMG88_ADDR, 0x1F, &tmp, 1); int sensorTemp[2]; dataread(AMG88_ADDR, TTHL, sensorTemp, 2); myservo.attach(SV_PIN, 500, 2400); // サーボの割当(パルス幅500~2400msに指定) myservo.write(45); //ServoCenter45度にセット delay(5000); //5秒間で確認 pinMode(2, OUTPUT); //LEDをD2pinに(マイコン内部でLED制限抵抗が付けられるが、命令不明でつかわず) digitalWrite(2,LOW); pinMode(3, OUTPUT); //LED GNDをD3pin digitalWrite(3,LOW); } //setup END void loop() { if (SCANf == 0) //ScanFlg=0の時リモコン受信無限LOOPにはいる ScanFlg=1の時は終了までリモコン受信無限LOOPに入らない {remocon() ;} // Wire library cannnot contain more than 32 bytes in bufffer // 2byte per one data // 2 byte * 16 data * 4 times = 2byte*64point int sensorData[32]; for (int i = 0; i < 4; i++) { // read each 32 bytes dataread(AMG88_ADDR, T01L + i * 0x20, sensorData, 32); for (int l = 0 ; l < 16 ; l++) { int16_t temporaryData = (sensorData[l * 2 + 1] * 256 ) + sensorData[l * 2]; // Vertical_Line 温度ヒストグラム //*** TMPDATSUM();*** 温度Datasum 3Frame合計で安定化 3面のDATAを更新 //Serial.print(temporaryData);Serial.print("TMPDAT3");Serial.println(TMPDAT3[i * 16 + l]); TMPDAT3[i * 16 + l] = TMPDAT2[i * 16 + l]; //2面➦3面 TMPDAT2[i * 16 + l] = TMPDAT1[i * 16 + l]; //1面➦2面 TMPDAT1[i * 16 + l] = temporaryData ; // 新➦1面 TMPDATS[i * 16 + l] = TMPDAT1[i * 16 + l] + TMPDAT2[i * 16 + l] + TMPDAT3[i * 16 + l]; //3面SUM Serial.print(" ");Serial.print(TMPDATS[i * 16 + l]); } //for:I15 END Serial.println(""); } //for:i3 END = 1frame X 3面 complete //*** 温度histgram ∑VerticalLineSum (horizontal angle(0 ~ 7) 毎に縦8ブロック合計を計算) TMPVS[0] = 0; TMPVS[1] = 0; TMPVS[2] = 0; TMPVS[3] = 0; TMPVS[4] = 0; TMPVS[5] = 0; TMPVS[6] = 0; TMPVS[7] = 0; for (int m = 0 ; m < 8 ; m++) //m= 0 ~ 7:水平位置毎に縦一列温度(足~頭)合計する { TMPVS[0] = TMPVS[0]+TMPDATS[0 + m * 8]; //LLLL:sensor左方向温度 TMPVS[1] = TMPVS[1]+TMPDATS[1 + m * 8]; //LLL TMPVS[2] = TMPVS[2]+TMPDATS[2 + m * 8]; //LL TMPVS[3] = TMPVS[3]+TMPDATS[3 + m * 8]; //L TMPVS[4] = TMPVS[4]+TMPDATS[4 + m * 8]; //:sensor正面方向温度:SPのangleをServoでここがMAXになるように向けてゆく TMPVS[5] = TMPVS[5]+TMPDATS[5 + m * 8]; //R TMPVS[6] = TMPVS[6]+TMPDATS[6 + m * 8]; //RR TMPVS[7] = TMPVS[7]+TMPDATS[7 + m * 8]; //RRR:sensor右方向温度 } TMPVS[VSmaxH[0]] = TMPVS[VSmaxH[0]] + 20 ; //ヒストグラムでVSmaxH[0]の温度合計max水平位置のTMPVSに+50のヒステリシスを付ける:チャッタ―防止 Serial.println(""); Serial.println(" 温度vs水平角度 サーモヒストグラム"); Serial.println("LLLL      正面 RRR"); Serial.print(TMPVS[0]);Serial.print(" ");Serial.print(TMPVS[1]);Serial.print(" ");Serial.print(TMPVS[2]); Serial.print(" ");Serial.print(TMPVS[3]);Serial.print(" "); Serial.print(TMPVS[4]);Serial.print(" ");Serial.print(TMPVS[5]);Serial.print(" ");Serial.print(TMPVS[6]); Serial.print(" ");Serial.println(TMPVS[7]); //********1frame Data complete********* objectscan() ; //sensor水平範囲(0:左端~7:右端)でVSmax(=人)をさがす 2frame一致H[1]=H[2])(VSmin:maxと差がない時は人がいない) Serial.print(TMPVSmax);Serial.print("VSmaxH[0]");Serial.print(VSmaxH[0]);Serial.print(" [1]");Serial.print(VSmaxH[1]);Serial.print(" [2]");Serial.print(VSmaxH[2]); Serial.print(" VSmin");Serial.print(VSmin);Serial.print("差");Serial.print(maxmin);Serial.print(" SA");Serial.println(SA); //********TMPVSmax が(sensor水平範囲=3:sensor正面)に来るようにservoを回転 servo() ; delay(20); //delay(50); //delay(100)でチャッタ―(scan発振)防止 } //loop END //**************************************************************************************************** //***************************************************************************************************** void remocon() //Remocon信号 (正面 左右) 有無 判別 { RS = analogRead(PIN_ANALOG_INPUT); if(RS > 900) RSTIM = 0 ; // リモコン信号停止(停止実測:analonRead()=982)するとTimerReset(RSTIM=0秒)しリモコン受信無限ループ開始 while(RSTIM < 5) // リモコン信号有が5秒以下は無限ループでリモコンを受け継ずける { while(RS > 900) //リモコン信号がない(RS>900~1034:実測982)時は無限ループでリモコンを受け続ける { RS = analogRead(PIN_ANALOG_INPUT); Serial.print(RS);Serial.print(" ");Serial.println(RSTIM); } RSTIM++ ; //リモコン信号あり 時間カウント(5秒以上あると受信無限ループを抜ける)  delay(1000); } } //リモコン信号5秒以上ありで無限ループから抜ける void datasend(int id, int reg, int *data, int datasize) { Wire.beginTransmission(id); Wire.write(reg); for (int i = 0; i < datasize; i++) { Wire.write(data[i]); } Wire.endTransmission(); } void dataread(int id, int reg, int *data, int datasize) { Wire.beginTransmission(id); Wire.write(reg); Wire.endTransmission(false); Wire.requestFrom(id, datasize, false); for (int i = 0; i < datasize; i++) { data[i] = Wire.read(); } Wire.endTransmission(true); } void objectscan() //Thermosensor縦一列合計のMax Minの値と水平位置(0~7)を特定 { TMPVSmax = 0; VSmaxH[2]=0; VSmin = 3000; //仮初期値設定 for ( int h = 0; h < 8; h++ ) { if (TMPVSmax < TMPVS[h]) {TMPVSmax = TMPVS[h] ; VSmaxH[2] = h ;} //VSmax[2]:NewmaxData if (VSmin > TMPVS[h]) {VSmin = TMPVS[h] ;} //VSmin:NewminData } maxmin = TMPVSmax - VSmin ; if (VSmaxH[1] == VSmaxH[2]) VSmaxH[0] = VSmaxH[1]; //2frame 一致 VSmax[0]に代入 else VSmaxH[1] = VSmaxH[2]; //2frame 一致せず Buffer(=VSmaxH[1])⇐NewData(VSmax[2]) VSmax[0]変更なし } void servo() //Therosensor縦一列合計MaxのSensor水平位置が人の正面(VSmaxH[0]=4)になるようServo angleを向けてゆく { SCANf = 1 ; digitalWrite(2,HIGH); //Scan中は1を立てScan終了までリモコン無限LOOPに入らない LED点灯 if ((maxmin > 30) && (TMPVSmax > 1600)) //ひとがいるmaxmin差>50 and TMPVS>2700 (実測 朝人/3m:1800 1m:昼2700 日差し窓/3m:2000 2300 ) { if (VSmaxH[0] < 4) SA = SA-1 ; //Servo: 人はsensor左 to 人の正面(VSmaxH[0]=4 SA=人のangleまで)へServoで左に向けてゆく else if (VSmaxH[0] >4) SA = SA+1 ; //Servo: 人はsensor右 to 人の正面(VSmaxH[0]=4 SA=人のangleまで)へServoで右に向けてゆく else {SCANf = 0 ; digitalWrite(2,LOW); } //if (VSmaxH[0] == 4 ) //人はsensor正面 SA=人のangle で停止 Scan終了 ScanLED OFF } if (SA <= 0) SA = 0 ; // Servo 0度以下limit :(SP正面-45度左) if (SA >= 90) SA = 90 ; // Servo 90度以上limit:(SP正面+45度右) myservo.write(SA) ; //Servo動かす } //END
1
  • syouwa-taro さんが 2023/11/06 に 編集 をしました。 (メッセージ: 初版)
  • syouwa-taro さんが 2023/11/07 に 編集 をしました。 (メッセージ: Wikipedia情報追加)
  • syouwa-taro さんが 2023/11/07 に 編集 をしました。
  • syouwa-taro さんが 2023/11/07 に 編集 をしました。
  • syouwa-taro さんが 2023/11/07 に 編集 をしました。
  • syouwa-taro さんが 2023/11/07 に 編集 をしました。 (メッセージ: 動作説明追加)
  • syouwa-taro さんが 2023/11/09 に 編集 をしました。
  • syouwa-taro さんが 2023/11/09 に 編集 をしました。 (メッセージ: youtube更新 PP説明追加)
  • Opening
    mipsparcのアイコン画像 mipsparc 2023/11/09

    よく年配の方がテレビを見るときに「うるさい!」ってなるの、あるあるですよね。
    耳元スピーカといった手段もありますが、これはとても面白いです!
    2つのスピーカで音質も配慮している点も良いと思いました。

    syouwa-taroのアイコン画像 syouwa-taro 2023/11/12

    ご感想ありがとうございます。親戚の家では、おばーちゃんの耳が遠くテレビの音がきこえずらく家族は
    テレビが一緒に楽しめないのが、気になっていました。しょうがないと諦めていますがこのようなおうちの助けになる作品が出来ればと思っています。

    1 件の返信が折りたたまれています
  • Opening
    syouwa-taroのアイコン画像 syouwa-taro 2023/11/12

    パラメトリックスピーカーは低域が出ないという課題がありますが、低域スピーカーを加えた2WAYにする事により音質を改善することが出来ました。

    0 件の返信が折りたたまれています
  • syouwa-taro さんが 2023/11/13 に 編集 をしました。 (メッセージ: 読みやすく)
  • syouwa-taro さんが 2023/11/15 に 編集 をしました。
  • syouwa-taro さんが 2023/11/18 に 編集 をしました。 (メッセージ: youtubeに音声例追加)
  • syouwa-taro さんが 2023/11/24 に 編集 をしました。 (メッセージ: youtube 画質/音質 改善)
  • syouwa-taro さんが 2023/11/26 に 編集 をしました。 (メッセージ: 課題追加)
  • syouwa-taro さんが 2023/11/28 に 編集 をしました。 (メッセージ: youtube更新)
  • syouwa-taro さんが 2023/11/30 に 編集 をしました。 (メッセージ: 概要補足)
  • syouwa-taro さんが 2023/11/30 に 編集 をしました。
ログインしてコメントを投稿する