Digitizing Facial Movement During Singing : Build Progress

This week we focused primarily on gathering our remaining pieces (electrodes, missing chips) and entered round one of the build of physical parts of the testing apparatus—facial geometry element is ready. We had a bit of trouble getting just the right stuff (one of our circuit chips was not available for order and the BMP085 barometric pressure sensor arrived without a breakout board).  That aside, we’re projecting to have the two missing elements with us by Friday. Until then we’re working on building out EMG to -> Arduino circuitry (sans remaining circuit chip):

EMG-circuits

As well as writing preliminary code to read the two physical sensor systems (EMG & BMP085) and print muscle contractions and changes in air pressure and temperature.  Much of the pressure print out code is taken from Jim Lindblom’s BMP085 Barometric Pressure Sensor Quickstart post on Sparkfun and much of the muscle contraction print out code is derived from Brian Kaminski’s USB Biofeedback Game Controller project guide on Instructables. We’ve refined the muscle sensors from five down to four, and with that, the muscle sensing will occupy analog pins 0 through 3 while the pressure/temperature sensor will occupy pins 4 and 5. Additionally we are struggling with determining where/how to find the Reference, Mid and End points of each facial muscle as we’ve never worked with EMGs before.

Code, thus far:
#include <Wire.h>
#define BMP085_ADDRESS 0x77

const unsigned char OSS = 0;
int ac1; int ac2; int ac3;
unsigned int ac4; unsigned int ac5; unsigned int ac6;
int b1; int b2; int mb; int mc; int md;
const int EMG1 = A0; const int EMG2 = A1; const int EMG3 = A2; const int EMG4 = A3;
int sensorValue1 = 0; int sensorValue2 = 0;  int sensorValue3 = 0; int sensorValue4 = 0;
long b5;

void setup(){
  Serial.begin(9600);
  Wire.begin();
  bmp085Calibration();
}

void loop()
{
  float temperature = bmp085GetTemperature(bmp085ReadUT());
  float pressure = bmp085GetPressure(bmp085ReadUP());
  float atm = pressure / 101325;
  sensorValue1 = analogRead(EMG1);
  sensorValue2 = analogRead(EMG2);
  sensorValue3 = analogRead(EMG3);              
  sensorValue4 = analogRead(EMG4);
  Serial.print(“Temperature = “);
  Serial.print(temperature, 2);
  Serial.println(“deg C”);
  Serial.print(“Pressure = “);
  Serial.print(pressure, 0);
  Serial.println(” Pa”);
  Serial.print(“Standard Atmosphere = “);
  Serial.println(atm, 4);
  Serial.print(“Muscle 1 = ” );                       
  Serial.println(sensorValue1);   
  Serial.print(“Muscle 2 = ” );                       
  Serial.println(sensorValue2);   
  Serial.print(“Muscle 3 = ” );                       
  Serial.println(sensorValue3);
  Serial.print(“Muscle 4 = ” );                       
  Serial.println(sensorValue4);
  Serial.println();
  delay(1000);
}

void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}

float bmp085GetTemperature(unsigned int ut){
  long x1, x2;
  x1 = (((long)ut – (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;
  float temp = ((b5 + 8)>>4);
  temp = temp /10;
  return temp;
}

long bmp085GetPressure(unsigned long up){
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;
  b6 = b5 – 4000;
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
  b7 = ((unsigned long)(up – b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;
  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;
  long temp = p;
  return temp;
}

char bmp085Read(unsigned char address){
  unsigned char data;
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 1);
  while(!Wire.available());
  return Wire.read();
}

int bmp085ReadInt(unsigned char address){
  unsigned char msb, lsb;
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 2);
  while(Wire.available()<2);
  msb = Wire.read();
  lsb = Wire.read();
  return (int) msb<<8 | lsb;
}

unsigned int bmp085ReadUT(){
  unsigned int ut;
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();
  delay(5);
  ut = bmp085ReadInt(0xF6);
  return ut;
}

unsigned long bmp085ReadUP(){
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();
  delay(2 + (3<<OSS));
  msb = bmp085Read(0xF6);
  lsb = bmp085Read(0xF7);
  xlsb = bmp085Read(0xF8);
  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
  return up;
}

void writeRegister(int deviceAddress, byte address, byte val) {
  Wire.beginTransmission(deviceAddress);
  Wire.write(address);
  Wire.write(val);
  Wire.endTransmission();
}

int readRegister(int deviceAddress, byte address){
  int v;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(deviceAddress, 1);
  while(!Wire.available()) {
//waiting
  }
  v = Wire.read();
  return v;
}

Those issues established, build for the pressure sensor is super minimal and does not require any extensive set up before we receive the breakout board. BMP085 set up diagram below:

BMP085-hookup

Leave a Reply

Your email address will not be published. Required fields are marked *