Saturday, June 15, 2013

Electret Mic with OPA344 1

I wanted to use a small electret mic with a standard OP-AMP to read acoustic data from serial using my ArduinoUNO-R3. This turned out to be more challenging then I was expecting but a lot of good learning happened.

The longterm goal of this project is to build cheap microphone arrays to work on sound source localization project.

First the schematics: (You'll have to excuse my messy routing, it was my first time using gschem.)


This was wired up to ArduinoUNO-R3 as in the following pictures:







Now the Arduino code:

1.) electret mic read


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* 
   Simple code to read the analog signal from an electret mic.
   The digital values are printed to file using python code.
   Commented lines may be uncommented to print digital values 
   converted to voltages. This extra step does slow down audio 
   sampling rate.
*/

// unsigned long time;

void setup() {
  // Begin Serial connection.
  Serial.begin(115200);
}

void loop() {
  // Read analog input from A0
  int micValue = analogRead(A0);

  Serial.print(micValue);
  Serial.print("\n");

  /* // Read microseconds per loop to check sampling rate */
  /* time = micros(); */

  /* // Analog reading goes from 0-1023. Convert to voltage 0V - 5V. */
  /* float micVolt = micValue * (5.0/1023.0); */

  /* // Print the value you read. */
  /* Serial.print(micValue); */
  /* Serial.print("\t"); */
  /* Serial.print(time); */
  /* Serial.print("\n"); */

  // Delay for stability.
  // delay(1);

2.) Python code to read from serial.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/python

# Short program using pySerial module to write Arduino serial 
# data to a file.

import sys
import serial as ser

# Arduino serial port
addr = '/dev/ttyACM0'
baud = 115200
fname = sys.argv[1]
fmode = 'w'
reps = 18000

ard = ser.Serial(addr,baud)

outfile = open(fname,fmode)

for i in range(reps):
    x = ard.readline()
    outfile.write(x)
    # outfile.flush()

outfile.close()

This is called using

>> write_arduino.py filename.dat

and the output text is saved to filename.dat. For reasons that I do not yet understand the entries in the data file sometimes contain arbitrary spaces and unicode characters when they should only contain integers between 0-1023. So at this point you have to go into the text file and fix these parts manually before processing the signal. Any information about this would be most welcome.

3.) MATLAB code to read the digital output data. A graph of the signal is generated and saved, the recorded audio is played, and recorded audio is saved as a *.wav file.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
% M-file to read and view the output of the analog 
% mic reads from the arduino. 

% Open file for reading and read it.
filename = './filename.dat';
fID = fopen(filename);
MicVals = fscanf(fID, '%f',[1,inf]);
MicVals = MicVals';
fclose(fID);

Nsamp = size(MicVals,1)

% End time in milliseconds, approximately .3 milliseconds per sample.
Tend = .3*Nsamp;

time = linspace(0,Tend,Nsamp);

figure(1); clf;
plot(time,MicVals,'-k');
axis([0 Tend 400 1023]);
xlabel('\fontsize{16}milliseconds');
ylabel('\fontsize{16}Digital MIC Read');
title('\fontsize{16}Recording: No Jumps');
saveas(1,'./filename.eps','psc2');

UpSample = zeros(2*Nsamp,1);
UpSample(1:2:(2*Nsamp-1)) = MicVals;
UpSample(2:2:(2*Nsamp)) = MicVals;

% Sampling rate
Fs = 8192/(1.5); 

% Play back the audio
soundsc(UpSample,Fs)

% Write to *.wav file
% First scale data 
AudMed = median(UpSample);
AudScaled = UpSample - AudMed;
AudDev = max(abs(AudScaled));
AudScaled = AudScaled/AudDev;  
wavwrite(AudScaled,Fs,'./filename.wav');

The recording of me saying 'Hello' three times looks like this,

The recording sounds like this...


There are still a few bugs in this project which I would love to get rid of. My next post will be on those.