Mirko Pavleski
Published © GPL3+

Arduino hearing test device - Audiometer

An audiometer is a machine used for evaluating hearing acuity.

IntermediateFull instructions provided1,623
Arduino hearing test device - Audiometer

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
WS2812 RGB Led Matrix 8x8
×1
Oled Display SSD1306 128x64
×1
Rotary Encoder with Push-Button
Rotary Encoder with Push-Button
×1
Linear Regulator (7805)
Linear Regulator (7805)
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
×1
LED (generic)
LED (generic)
×1
Through Hole Resistor, 470 ohm
Through Hole Resistor, 470 ohm
×1
PAM8403 D-Class Amplifier module
×1
Battery, 3.7 V
Battery, 3.7 V
×2
Headphones, 20 Hz
Headphones, 20 Hz
×1
Bone conductor hearing oscillator
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Custom parts and enclosures

Led matrix grid

Schematics

Hearing test

Bone conducting Test

Code

Arduino code

Arduino
#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[3][8];
int j=0;
int x=0;
int y=0;
int orecchio=1;
int pos = 1;
char db[9][10]=
{ "0 db",
  "10 db",
  "20 db",
  "30 db",
  "40 db",
  "50 db",
  "60 db",
  "70 db",
  "80 db" 
};
char freq[8][10]
{ "125 Hz",
  "250 Hz",
  "500 Hz",
  "1000 Hz",
  "2000 Hz",
  "3000 Hz",
  "4000 Hz",
  "8000 Hz"  
};

int freqn[8][2]
{
  125, 250, 500, 1000, 2000, 3000, 4000, 8000
};

char ear[3][11]
{ "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[orecchio], 25, 16);
      draw("Freq:", 15, 55);
      draw(db[newPos], 40, 35);
      draw(freq[x], 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[x],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[orecchio][pos]);
  risultati[orecchio][x]=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[j][x]-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[j][x]), 10, 0, 0);
          if ((x==0 or x==2 or x==4 or x==6) and j==2)
            if (strip.getPixelColor((risultati[j][x]-1)+(x*8)) == 0)
              strip.setPixelColor((risultati[j][x]-1)+(x*8), 0, 0, 10);
            else
              strip.setPixelColor((risultati[j][x]-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[j][x])) == 0)
              strip.setPixelColor(((x+1)*8)-(risultati[j][x]), 0, 0, 10);
            else
              strip.setPixelColor(((x+1)*8)-(risultati[j][x]), 10, 0, 10);
          strip.show();
          Serial.print(risultati[j][x]);
          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);
}

Credits

Mirko Pavleski

Mirko Pavleski

147 projects • 1266 followers

Comments