Friday 13 April 2012

Saying Measurements

One more post about the speak jet and an intro to the compass. Plan is to take measurements and then read them out. Before doing this I decide to try and create an Arduino library to manage the speak jet interface. Doing this was a nightmare in the Arduino IDE, but after bit of coding and a lot of messing around I had this interface:


class CSpeakJet
{
public:


  CSpeakJet(uint8_t receive_pin, uint8_t transmit_pin, uint8_t is_speaking_pin);
  
  void Begin();
  void SetVolume(int lVol);
  void SetPitch(int lPitch);
  void SetSpeed(int lSpeed);
  void SetBend(int lBend);
  void Play(uint8_t* data, int len, bool wait);
  void Play(int id, bool wait);
  void PlayNumber(int number, bool wait);
  void AddByte(uint8_t data);
  void Wait();
  
private:
  SoftwareSerial mSerial;
  uint8_t mSpeakingPin;
};


This class provides functions to set volume/pitch/speed/bend, and a 2 ways to play a sound. The first simply sends a series of bytes to the speech jet. However the second takes an index into a hard coded list of sounds:



enum ESpeech
{
 SPEECH_HELLO,
 SPEECH_YOUR,
 SPEECH_ENGINE,
 SPEECH_IS,
 SPEECH_BOUNCY,
 SPEECH_I,
 SPEECH_CAN,
 SPEECH_SEE,
 SPEECH_YOU,
 SPEECH_DEGREES,
 SPEECH_ANGLE,
 SPEECH_DISTANCE,
 SPEECH_0,
 SPEECH_1,
 SPEECH_2,
 SPEECH_3,
 SPEECH_4,
 SPEECH_5,
 SPEECH_6,
 SPEECH_7,
 SPEECH_8,
 SPEECH_9,
 TOTAL_SPEECH 
};

In amongst these are the numbers 0 to 9. All that needs to happen now is a simple function to extract the digits of a number and say them, rather like converting numbers to strings. After a bit of fiddling I come up with this, which could be better but does the job for now:

void CSpeakJet::PlayNumber(int number)
{
  int orignumber = number;
  if(orignumber >= 1000)
    Play(int(SPEECH_0+number/1000));
  number = number % 1000;
  if(orignumber >= 100)
    Play(int(SPEECH_0+number/100));
  number = number % 100;
  if(orignumber >= 10)
    Play(int(SPEECH_0+number/10));
  number = number % 10; 
  Play(int(SPEECH_0+number/1));
}

Next up it's time to connect the CMP03 electronic compass. I introduced this device in the Bob The Boe Bot post earlier. However it wasn't massively useful, as it communicated using pulse width modulation which was too slow. This time we'll be hooking it up via an I2C Bus, as shown below.


Compass with I2C connection

Developed by Philips, this clever system is a common way for multiple devices to communicate with a microcontroller, normally in master/slave configuration. The master can choose to send a message to one of the devices on the network and sends it's address down the data line, followed by the data. It then waits while the slave sends a response. It's too much to explain right now but there's lots of info here. If you're starting to robot you'll need this soon.

Compass connected to I2C via Analog pins

The Arduino has built in support for I2C and can act as master or slave. On the Uno this is done using  Analog Pins 4 and 5, along with a library to send and receive data through it.

Arduino devices, now with CMP03 Compass

Here you see the circuit from the last blog which includes PING, Motion and Speak Jet, now with an added Compass connected via I2C to Analog In 4+5 on the Arduino. Using the Wire library we can then communicate with the compass using a hardcoded address that the sensor stores.


//read value from 0 to 359 degrees

#define ADDRESS 0x60 //defines address of compass


int readCompass(){
  byte highByte;
  byte lowByte;
  
   Wire.beginTransmission(ADDRESS);     //starts communication with cmps03
   Wire.write(2);                       //Sends the register we wish to read
   Wire.endTransmission();
   Wire.requestFrom(ADDRESS, 2);        //requests high byte
   
   while(Wire.available() < 2);         //wait for 2 bytes
   
   highByte = Wire.read();              //reads the bytes as a integers
   lowByte = Wire.read();
   return ((highByte<<8)+lowByte)/10;   //combine and return 16 bit integer
}



With a bit of work, I plug all the bits together to get:

  • Wait until button clicked
  • Read compass and ping sensor
  • Say 'Compass'
  • Using PlayNumber function I wrote earlier to say the compass reading
  • Say 'Distance'
  • Use PlayNumber again to say the distance reading

And here's a little video of it in action (if vid doesn't work, check on you tube here):


And there you have it - the Arduino using a SpeakJet to read out measurements from a compass and ultra sound sensor when 

No comments:

Post a Comment