驴友花雕 发表于 5 天前

【Arduino 动手做】评估听力敏锐度的机器:Arduino听力计

该设备通常以不同的频率和强度向测试对象的耳机传输纯音,并记录对象的反应以产生阈值灵敏度的听力图。

听力计是一种用于评估听力敏锐度的仪器。它们通常由一个连接到耳机的嵌入式硬件单元和一个测试对象反馈按钮组成。该设备通常以不同的频率和强度将纯音传输到测试对象的耳机中,并记录对象的响应以生成阈值灵敏度的听力图。我最近在一家专业机构进行了听力测试,并以听力图的形式收到了结果。



驴友花雕 发表于 5 天前

【Arduino 动手做】评估听力敏锐度的机器:Arduino听力计

我决定尝试制作一个类似的设备,因为该设备的工作原理非常简单。在网上搜索了一番后,我发现了一些使用电脑声卡来实现类似功能的应用程序,但我的目标是制作一个实用的独立设备。我在 Arduino 论坛上找到了一位名为“cstram”的用户提出的此类设备的想法,并决定根据我当时的硬件条件进行一些修改。Arduino 是一个输入输出单元,它可以生成不同频率和强度的音调,然后将从被测者那里收到的反馈结果显示在由 64 个 RGB LED 组成的 8 x 8 像素分辨率屏幕上。屏幕上会显示两个不同颜色的图表,分别对应左耳和右耳。

该设备构建起来相对简单,由以下几个组件组成:
   - Arduino Nano 微控制器
   - 8x8 矩阵由 64 个 RGB LED 组成,内置 WS2812 芯片。为了获得更有趣的视觉印象,我制作了一个 3D 打印网格
   - 带有 SSD1306 芯片的 128x64 Oled 显示屏
   - 旋转编码器
   - 按钮
   - 母耳机插孔
   - 和小耳机
   -
该设备由两个串联的锂电池供电,并在其输出端放置了一个 7805 5V 稳压器。这次我忽略了电池控制和充电电路,因为该部分之前已经描述过几次。

如果您想为这个项目或任何其他电子项目制作自己的 PCB,PCBway 是您的绝佳选择。PCBway 是中国在 PCB 原型和制造领域最有经验的 PCB 制造公司之一。他们有一个大型在线社区,您可以在其中找到开源项目,也可以在那里分享您的项目。根据我的个人经验,我可以告诉你,在这个社区你可以找到许多有用的项目,其中有已经设计好的 PCB,你可以直接从那里下订单。

现在让我们看看该设备的实际工作原理:打开设备后,第一个测试频率和以分贝为单位的音量会显示在OLED屏幕上。在矩阵屏幕上,行代表音量(以分贝为单位),列代表给定频率(以赫兹为单位)。现在,我们将耳机戴在一只耳朵上,并使用旋转编码器逐渐增加音量,直到听到声音。此时,我们按下按钮,按钮会记住第一个频率的结果并切换到下一个频率,如此循环至最后。完成最后一个频率的测试后,我们将耳机换到另一只耳朵,并对所有频率重复此过程。此时,二极管将亮起不同的颜色。最后,该设备会分别以红色和蓝色绘制双耳的听力图。显示屏将提供所有必要的信息,告诉您每个频率下的听力质量。红色代表左耳,蓝色代表右耳。需要说明的是,这不是专业设备,可以用于娱乐。然而,如果我们像我一样使用专业设备进行校准,我们就可以对我们的听觉器官的听觉能力有相当深入的了解。





















驴友花雕 发表于 5 天前

【Arduino 动手做】评估听力敏锐度的机器:Arduino听力计

更新:
项目完成几天后,我拿到了用于骨传导测试的骨传导耳机。这是另一种纯音测试,用于测量内耳对声音的响应。测试人员会将一个导体放置在耳后,它会将微小的振动通过骨骼直接传递到内耳。这与传统的利用空气传递可听声音的测试方法不同。如果骨传导测试的结果与纯音听力测试结果不同,您的听力学家可以使用这些信息来确定您的听力损失类型。确定阈值的方法与获取气导阈值的方法相同。骨传导测量通常限制在 250 至 4000 Hz 的频率范围内。我对之前描述的设备进行了小幅修改,扩展了它的功能,之后也可以用它来进行骨传导测试。

由于测试耳机振动器的欧姆电阻只有 4 欧姆,因此只需添加一个小型音频放大器即可。我使用了一个小型廉价的 D 类放大器,带有一个电位器,非常适合此目的。

只需将耳机信号连接到放大器的输入端即可。骨传导耳机通过合适的连接器连接到放大器的输出端。借助电位器,我们可以使用类似的商用设备进行精确校准。正如我之前提到的,测试方法与上一个案例完全相同,只是将骨传导振荡器放置在耳后骨头上,而不是耳机上。最后,将设备安装在一个合适的PVC板盒子中,并用彩色壁纸覆盖。

#include <Volume.h>
#include <RotaryEncoder.h>
#include <Adafruit_NeoPixel.h>
#include <OneButton.h>
#include <U8glib.h>

#define PIN 8
Adafruit_NeoPixel strip = Adafruit_NeoPixel(64, PIN, NEO_GRB + NEO_KHZ800);
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);// I2C / TWI

Volume vol;
// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:neither pin has interrupt capability

// ----- Rotary settings here ----
#define ROTARYSTEPS 1
#define ROTARYMIN 1
#define ROTARYMAX 8
int lastPos = 0;
int exitFlag = 0;
// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);

// Last known rotary position.
// Setup a new OneButton on pin A1.
OneButton button(A1, true);

int risultati;
int j=0;
int x=0;
int y=0;
int orecchio=1;
int pos = 1;
char db=
{ "0 db",
"10 db",
"20 db",
"30 db",
"40 db",
"50 db",
"60 db",
"70 db",
"80 db"
};
char freq
{ "125 Hz",
"250 Hz",
"500 Hz",
"1000 Hz",
"2000 Hz",
"3000 Hz",
"4000 Hz",
"8000 Hz"
};

int freqn
{
125, 250, 500, 1000, 2000, 3000, 4000, 8000
};

char ear
{ "Volume:",
"Vol. Left:",
"Vol. Righ:"
};




void setup() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'

encoder.setPosition(0 / ROTARYSTEPS); // start with the value of 0.

u8g.setColorIndex(1);         // pixel on for Display

button.attachLongPressStop(longPressStop);


vol.begin(); // After calling this, delay() and delayMicroseconds will no longer work
               // correctly! Instead, use vol.delay() and vol.delayMicroseconds() for
               // the correct timing

vol.setMasterVolume(3.00); // Self-explanatory enough, right? Try lowering this value if the speaker is too loud! (0.00 - 1.00)
vol.delay(500);
   
Serial.begin(115200);
Serial.println("Volume test with Encoder:");

}


void loop() {

button.tick();

encoder.tick();

int newPos = encoder.getPosition();
if (pos != newPos) {

    if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;
    } else if (newPos > ROTARYMAX) {
      encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
      newPos = ROTARYMAX;
    }

    Serial.print(newPos);
    Serial.print(", ");
    Serial.print(x);
    Serial.println();

    if (orecchio < 3){
    u8g.firstPage();
    do {
      draw(ear, 25, 16);
      draw("Freq:", 15, 55);
      draw(db, 40, 35);
      draw(freq, 60, 55);
    } while( u8g.nextPage() );
    } else {
      u8g.firstPage();
    do {
      draw("FINAL GRAPH", 0, 20);
      draw("   EXECUTED    ", 0, 50);
    } while( u8g.nextPage() );
    }
   
    pos = newPos;
    vol.tone (freqn,pos);

    if (orecchio < 3)
      for (j=(x*8); j<64;j++)
      strip.setPixelColor(j, 0, 0, 0);
    strip.show();

    if ((x==0 or x==2 or x==4 or x==6) and orecchio==1)
      strip.setPixelColor((pos-1)+(x*8), 10, 0, 0);
    if ((x==1 or x==3 or x==5 or x==7) and orecchio==1)
      strip.setPixelColor(((x+1)*8)-(pos), 10, 0, 0);
    if ((x==0 or x==2 or x==4 or x==6) and orecchio==2)
      strip.setPixelColor((pos-1)+(x*8), 0, 0, 10);
    if ((x==1 or x==3 or x==5 or x==7) and orecchio==2)
      strip.setPixelColor(((x+1)*8)-(pos), 0, 0, 10);
    strip.show();
    }

//vol.delay(10); // solo per test

}



// This function will be called once, when the button1 is released after beeing pressed for a long time.
void longPressStop() {
Serial.print("Button 1 longPress stop, x=");
//scanf("%d", &risultati);
risultati=pos;
x=x+1;
pos=0;
encoder.setPosition(1);
if (x>7 and orecchio == 1) {
    x=0;
    orecchio =2;
    }
    if (x>7 and orecchio == 2) {
    u8g.firstPage();
    do{
      draw("PLEASE WAIT", 0, 20);
      draw("FINAL GRAPH", 0, 50);
      } while( u8g.nextPage() );
      strip.clear();
      for (j=1; j<3;j++) {
      Serial.println();
      for (x=0; x<8;x++) {
          if ((x==0 or x==2 or x==4 or x==6) and j==1)
            strip.setPixelColor((risultati-1)+(x*8), 10, 0, 0);
          if ((x==1 or x==3 or x==5 or x==7) and j==1)
            strip.setPixelColor(((x+1)*8)-(risultati), 10, 0, 0);
          if ((x==0 or x==2 or x==4 or x==6) and j==2)
            if (strip.getPixelColor((risultati-1)+(x*8)) == 0)
            strip.setPixelColor((risultati-1)+(x*8), 0, 0, 10);
            else
            strip.setPixelColor((risultati-1)+(x*8), 10, 0, 10);
          if ((x==1 or x==3 or x==5 or x==7) and j==2)
            if (strip.getPixelColor(((x+1)*8)-(risultati)) == 0)
            strip.setPixelColor(((x+1)*8)-(risultati), 0, 0, 10);
            else
            strip.setPixelColor(((x+1)*8)-(risultati), 10, 0, 10);
          strip.show();
          Serial.print(risultati);
          Serial.print(", ");
          vol.delay(1000);
      }
      
      }
      x=0;
      orecchio = 3;
    }

Serial.println(x);
Serial.print("Ear = ");
Serial.println(orecchio);

} // longPressStop1

void draw(char* parola, int posx, int posy) {
// graphic commands to redraw the complete screen should be placed here
u8g.setFont(u8g_font_unifont);
//u8g.setFont(u8g_font_osb21);
u8g.drawStr( posx, posy, parola);
}


驴友花雕 发表于 5 天前

【Arduino 动手做】评估听力敏锐度的机器:Arduino听力计


驴友花雕 发表于 5 天前

【Arduino 动手做】评估听力敏锐度的机器:Arduino听力计

附录
【Arduino 动手做】用于评估听力敏锐度的机器:Arduino听力计
项目链接:https://hackaday.io/project/187920-arduino-hearing-test-device-audiometer
项目作者:米尔塞姆克 mircemk
项目视频 :https://www.youtube.com/watch?v=H_ecWkNRzCI
项目代码:https://cdn.hackaday.io/files/1879208039969280/CODE%20moj%20za%20128x64.txt
电原理图:https://cdn.hackaday.io/files/1879208039969280/Schematic . jpg
https://cdn.hackaday.io/files/1879208039969280/Schematic%20Bone . jpg





页: [1]
查看完整版本: 【Arduino 动手做】评估听力敏锐度的机器:Arduino听力计