Saturday, April 4, 2015

Adafruit BMP183 Sensor and MSP430 using Energia

I finally got the Adafruit BMP183 sensor to work with a MSP-EXP430F5529LP and Energia.  I am using the Adafruit library and it almost works but not quite for the LaunchPad.  The following changes are necessary:
  • As you would expect, it is necessary to change pins for SPI.  I used the following in the test sketch provided as an example by the library:
           #define BMP183_CLK  P4_3
           #define BMP183_SDO  P4_2    // AKA MISO
           #define BMP183_SDI  P4_1     // AKA MOSI
           #define BMP183_CS   P4_0
           Adafruit_BMP183 bmp = Adafruit_BMP183(BMP183_CLK, BMP183_SDO,

               BMP183_SDI,BMP183_CS);
  • The sketch won't compile as is because of a call to _delay_ms in Adafruit.BMP183.cpp provided in the library.  I replaced all instances with the delay function.
  • The sketch won't compile as is because of a call to the pow function in Adafruit.BMP183.cpp.  The offending error is in the altitude calculation and occurs because of a bug in the gcc compiler used by Energia for the MSP430.  Replace pow with powf and it should work.
Follow the link on the Adafruit BMP183 sensor and check out their learning system for a whole lot more information.

Friday, April 3, 2015

Analog Potentiometer

Since I posted some code on a digital potentiometer the other day, I thought I'd go ahead and do the analog.  There is a lot more information on analog potentiometers in the SparkFun Inventor's Kit.  Here is my sketch for the MSP-EXP430F5529LP...

/*
  Control the brightness of a LED with the MSP-EXP430F5529LP LaunchPad
  Reads an analog input from a potentiometer, converts it to voltage, prints the result to
  the serial monitor, and varies the brightness of a LED accordingly

  HARDWARE REQUIRED:
  * MSP-EXP430F5529LP LaunchPad
  * Potentiometer
  * LED
  * 330 Ohm Resistor
 
  CONNECTIONS:
  Potentiometer
  Left pin        3.3 V             Note that potentiometer does not have polarity so flip
                                    the outside leads if you want to change rotation effect
  Center          Pin 6 (P6.6)      Make sure pin can do analog read
  Right pin       GND
 
  LED
  Positive pin    Pin 19 (P2_0)     LED output - make sure pin can do an analog write (PWM)
  Negative pin    330 Ohm    GND    Resistor protects LED

  2 April 2015
  Frank Milburn
  This example code is in the public domain.
*/

// Declarations
const int potPin = 6;                           // Input pin for pot
const int ledPin = 19;                          // Output pin for LED
const int analogRes = 4096;                     // resolution of analog input

int lastReading = -1;                           // Define lastReading for 1st pass
void setup()
{
  Serial.begin(9600);                           // Start serial
  Serial.println("Starting....");
  pinMode(ledPin, OUTPUT);                      // Make the LED pin an output
}

void loop()
{
  int potReading = analogRead(potPin);             // Read the potentiometer setting
   
  // Note that there is some jitter in a potentiometer.  In order to reduce the serial
  // print, a check is made on whether the change is signicant.  Note that a difference
  // in readings of 41 is about a 1% change since the resolution of an analog read
  // is 0 to 4095   
   
  if (abs(potReading - lastReading) > 41)          // if the readings change much
  {                                                // then update and inform of changes
    Serial.print("Raw reading: ");               
    Serial.print(potReading);
  
    float voltage = potReading * 3.3 / analogRes;  // Convert pot reading to voltage
    Serial.print("     Voltage: ");                // and inform the user
    Serial.println(voltage);
  
    int ledBrightness = map(potReading,0,analogRes,0,255);  // map to PWM duty cycle
    analogWrite(ledPin, ledBrightness);            // and adjust LED brigtness
 
    int brightness = (ledBrightness * 100) / 255;  // calculate brightness as percent
    Serial.print("Brightness: ");                  // and inform the user
    Serial.print(ledBrightness);
    Serial.print(" PWM   ");
    Serial.print(brightness);
    Serial.println(" %");
 
    lastReading = potReading;                      // update the last reading
  }
}

TMP36 Temperature Sensor


I wish it were this easy to use all sensors.  I got this TMP36 with a SparkFun SIK Inventor's Kit in 2014.  That kit is well worth it if you are just getting started out.  There is a lot more information and direction on getting this going for an Arduino in the kit.  But we are using the MSP-EXP430F5529 :-)

The TMP36 is a low voltage, precision centigrade temperature
sensor that provides an analog signal that is linearly
proportional to the Celsius (centigrade) temperature.
Accuracy is ±1°C at +25°C and ±2°C over the −40°C to +125°C
temperature range. It provides for single-supply operation
from 2.7 V to 5.5 V maximum. The supply current runs below
50 μA.


Looking at the flat side of the TMP36 the pins are as follows:
Left    Vs   (+2.7 to 5.5V)
Center  Vout (analog output)
Right   GND


The datasheet calls for a 0.1 μF bypass capacitor on the input
(i.e. between Vs on the TMP36 and GND). It specifies a ceramic
type with short leads and located as close as possible to the
temperature sensor supply pin.


Circuit
TMP 36    MSP430F5529
------    ---------------------------------------------------
Vs        3.3V
Vs        0.1uF capacitor to GND
Vout      Pin 6 (P6.6) This must be an analog read pin
GND       GND


Frank Milburn 3 April 2015
*/


const int TMP36Pin = 6;            // pin sensor is connected to
const int analogRes = 4095; // A/D resolution


void setup()
{
  Serial.begin(9600);
  Serial.println("Starting temperature readings...");
}


void loop()
{
  // Get the output from the sensor and multiply it by
  // 3.3 / resolution to get the voltage

  float voltage = (analogRead(TMP36Pin) * 3.3 / analogRes);
 
  // TMP36 datasheet provides the conversion formula
  float degC = (voltage - 0.5) * 100.0;
 
  // and if fahrenheit is desired
  float degF = (degC * 1.8) + 32.0;

 
  // Now the serial output...
  Serial.println("___________________________________________");
  Serial.print("Voltage:         "); Serial.println(voltage,3);
  Serial.print("Temperature (C): "); Serial.println(degC,1);
  Serial.print("Temperature (F): "); Serial.println(degF,1);

  delay(1000);
}

Thursday, April 2, 2015

L293DNE Motor Driver

I used the L293DNE a while back in a prototype robot and thought it might be worthwhile documenting it.  I've since replaced the L293DNE with a Pololu TB6612FNG board and am now using 6V motors instead of the 3V Tamiya models.

Here is a picture of the prototype with a MSP430F5529 on top running things:



Here is the test code and a description of the circuit for those that are interested:

/*
This is a motor control circuit using a TI L293DNE motor
controller used with a MSP432-F5529LP to drive
a toy Tamiya tank with two motors. 


Note that the Tamiya motors operate at 3V and the feed is
routed through LD1117AV33's to get the voltage down. 


Note: Do not use PWM below about 50% or motors can stall -
suggest using PWM to balance motor speed only.

L293DNE
-------
1      MCU 39 (P2.4) - Enable pin
2      MCU 2 (P6.5) - Left Motor Logic pin 1
3      Left Motor Terminal 1
4      Heat sink / ground
5      Heat sink / ground
6      Left Motor Terminal 2
7      MCU 3 (P3.4) - Left Motor Logic pin 2
8      Motor Power Supply - 5.0V reduced to 3.3V for Tamiya
9      MCU 40 (P2.5) - Enable pin
10     MCU 4 (P3.3) - Right Motor Logic pin 1
11     Right Motor Terminal 1
12     Heat sink / ground
13     Heat sink / ground
14     Right Motor Terminal 2
15     MCU 5 (P1.6) - Right Motor Logic pin 2
16     IC Power Supply - 5.0V (used separate supply than LP)


LD1117AV33 - connect all motor terminal through these (4)
----------
1      5.0 V
2      GND
3      3.3 V


Tamiya Motors
-------------
Connect terminals to 3.3 V output from LD1117AV33 above


Capacitors
----------
See LD1117AV33 datasheet
suggests 10uF on output and 100nF on input


Frank Milburn   22 Feb 2015
*/

const int leftMotor1Pin = 2;
const int leftMotor2Pin = 3;
const int leftEnablePin = 39;

const int rightMotor1Pin = 4;
const int rightMotor2Pin = 5;
const int rightEnablePin = 40;

void setup()
{
  pinMode(leftMotor1Pin, OUTPUT);
  pinMode(leftMotor2Pin, OUTPUT);
  pinMode(leftEnablePin, OUTPUT);
  pinMode(rightMotor1Pin, OUTPUT);
  pinMode(rightMotor2Pin, OUTPUT);
  pinMode(rightEnablePin, OUTPUT);
  Serial.begin(9600);
  Serial.println("Starting motor test");
 
}

void loop()
{
  Serial.println("Forward");            // start with left side
  digitalWrite(leftMotor1Pin, LOW);     // set leg 1 of H-bridge low
  digitalWrite(leftMotor2Pin, HIGH);    // set leg 2 of the H-bridge high
  digitalWrite(rightMotor1Pin, LOW);    // now right side  
  digitalWrite(rightMotor2Pin, HIGH);   
  digitalWrite(leftEnablePin, HIGH);    // enable motors on
  digitalWrite(rightEnablePin, HIGH); 
  delay(2000);

  Serial.println("Stop");
  digitalWrite(leftEnablePin, LOW);     // disable the motors
  digitalWrite(rightEnablePin, LOW);
  delay(1000);
 
  Serial.println("Backwards");
  digitalWrite(leftMotor1Pin, HIGH);    // Reverse the motors
  digitalWrite(leftMotor2Pin, LOW);
  digitalWrite(rightMotor1Pin, HIGH);    
  digitalWrite(rightMotor2Pin, LOW);
  digitalWrite(leftEnablePin, HIGH);    // enable motors on
  digitalWrite(rightEnablePin, HIGH);
  delay(2000);
 
  Serial.println("Stop");
  digitalWrite(leftEnablePin, LOW);     // disable the motors
  digitalWrite(rightEnablePin, LOW);
  delay(1000); 
 
  Serial.println("Forward 3/4 speed");
  digitalWrite(leftMotor1Pin, LOW);     // Set both sides forward
  digitalWrite(leftMotor2Pin, HIGH);    
  digitalWrite(rightMotor1Pin, LOW);    
  digitalWrite(rightMotor2Pin, HIGH);
  analogWrite(leftEnablePin, 192);      // enable motors on at reduced speed with PWM
  analogWrite(rightEnablePin, 192);
  delay(2000);
     
  Serial.println("Stop");
  digitalWrite(leftEnablePin, LOW);     // disable the motors
  digitalWrite(rightEnablePin, LOW);
  delay(1000);
}

Piezo Element Buzzer / Songs

OK, here is a sketch and circuit taken from the SparkFun Inventor's Kit (SIK) that plays a song using a piezo buzzer and the MSP-430F5529.

/*
BUZZER
  Use the buzzer to play a song!
  The buzzer in your Inventor's Kit is an electromechanical
  component you can use to make noise. Inside the buzzer is a
  coil of wire and a small magnet. When current flows through
  the coil, it becomes magnetized and pulls towards the magnet,
  creating a tiny "click". When you do this thousands of times
  per second, you create tones.
 
  The LaunchPad has a built-in command called tone() which clicks
  the buzzer at a certain frequency. This sketch knows the
  frequencies of the common notes, allowing you to create songs.
  We're never going to let you down!


Hardware connections:
  The buzzer has two pins. One is positive and one is negative.
  The postitive pin is marked by a "+" symbol on both the top
  and bottom of the buzzer.
 
  Connect the positive pin to Arduino digital pin 19.
  (Note that this must be a analogWrite() / PWM pin.)
  Connect the negative pin to GND.
 
  Tip: if the buzzer doesn't fit into the breadboard easily,
  try rotating it slightly to fit into diagonal holes.


This sketch was written by SparkFun Electronics,
with lots of help from the Arduino community.
(This sketch was originally developed by D. Cuartielles for K3)
This code is completely free for any use.
Visit
http://learn.sparkfun.com/products/2 for SIK information.
Visit
http://www.arduino.cc to learn about the Arduino.
Visit
http://energia.nu/ to learn about Energia
Version 2.0 6/2012 MDG
modified by Frank Milburn for MSP-430F5529LP


This sketch uses the buzzer to play songs.
The Arduino's tone() command will play notes of a given frequency.
We'll provide a function that takes in note characters (a-g),
and returns the corresponding frequency from this table:

  note  frequency
  c     262 Hz
  d     294 Hz
  e     330 Hz
  f     349 Hz
  g     392 Hz
  a     440 Hz
  b     494 Hz
  C     523 Hz

For more information, see http://arduino.cc/en/Tutorial/Tone
*/
 
const int buzzerPin = 19;

// We'll set up an array with the notes we want to play
// change these values to make different songs!

// Length must equal the total number of notes and spaces
const int songLength = 18;
// Notes is an array of text characters corresponding to the notes
// in your song. A space represents a rest (no tone)

char notes[] = "cdfda ag cdfdg gf "; // a space represents a rest
// Beats is an array of values for each note and rest.
// A "1" represents a quarter-note, 2 a half-note, etc.
// Don't forget that the rests (spaces) need a length as well.

int beats[] = {1,1,1,1,1,1,4,4,2,1,1,1,1,1,1,4,4,2};
// The tempo is how fast to play the song.
// To make the song play faster, decrease this value.

int tempo = 150;

void setup()
{
  pinMode(buzzerPin, OUTPUT);
}


void loop()
{
  int i, duration;
 
  for (i = 0; i < songLength; i++) // step through the song arrays
  {
    duration = beats[i] * tempo;  // length of note/rest in ms
   
    if (notes[i] == ' ')          // is this a rest?
    {
      delay(duration);            // then pause for a moment
    }
    else                          // otherwise, play the note
    {
      tone(buzzerPin, frequency(notes[i]), duration);
      delay(duration);            // wait for tone to finish
    }
    delay(tempo/10);              // brief pause between notes
  }
 
  // We only want to play the song once, so we'll pause forever:
  while(true){}
  // If you'd like your song to play over and over,
  // remove the above statement
}


int frequency(char note)
{
  // This function takes a note character (a-g), and returns the
  // corresponding frequency in Hz for the tone() function.
 
  int i;
  const int numNotes = 8;  // number of notes we're storing
 
  // The following arrays hold the note characters and their
  // corresponding frequencies. The last "C" note is uppercase
  // to separate it from the first lowercase "c". If you want to
  // add more notes, you'll need to use unique characters.

  // For the "char" (character) type, we put single characters
  // in single quotes.

  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523};
 
  // Now we'll search through the letters in the array, and if
  // we find it, we'll return the frequency for that note.
 
  for (i = 0; i < numNotes; i++)  // Step through the notes
  {
    if (names[i] == note)         // Is this the one?
    {
      return(frequencies[i]);     // Yes! Return the frequency
    }
  }
  return(0);  // We looked through everything and didn't find it,
              // but we still need to return a value, so return 0.
}


Knock Sensor using Piezo Element

An analog read example using a piezo element out of the SparkFun Inventor's Kit with a MSP-
EXP430F5529LP....

/* Knock Sensor
 
   This sketch reads a piezo element to detect a knocking sound.
   It reads an analog pin and compares the result to a set threshold.
   If the result is greater than the threshold, it writes
   "knock" to the serial port, and toggles the LED on pin 13.
 
   The circuit:
 + connection of the piezo attached to pin 23 (P6.0)
 - connection of the piezo attached to ground
 1-megohm resistor attached from pin 23 (P6.0) to GND

   http://www.arduino.cc/en/Tutorial/Knock
  
   created 25 Mar 20070
   by David Cuartielles <
http://www.0j0.org>
   modified 30 Aug 2011
   by Tom Igoe
   modified 4 Feb 2013
   by Frank Milburn for MSP-EXP430F5529LP
   This example code is in the public domain.
 */

// these constants won't change:
const int ledPin = RED_LED;                  // connected the red LED on the LaunchPad
const int knockSensor = P6_0;                // the pin the piezo is connected to
const int threshold = 20;                    // threshold value to decide when the detected sound is a knock or not
                                             // NOTE: You may need to vary this depending on your sensor
// these variables will change:
int sensorReading = 0;                       // variable to store the value read from the sensor pin
int ledState = LOW;                          // variable used to store the last LED status, to toggle the light

void setup()
{
  pinMode(ledPin, OUTPUT);                   // declare the ledPin as as OUTPUT
  Serial.begin(9600);                        // initiate the serial connection and let the user know we've started
  Serial.println("Starting to listen.... ");
}

void loop()

  sensorReading = analogRead(knockSensor);   // read the sensor and store it in the variable sensorReading:
   
  if (sensorReading >= threshold)            // if the sensor reading is greater than the threshold:
  {   
    ledState = !ledState;                    // toggle the status of the ledPin:           
    digitalWrite(ledPin, ledState);          // and update the LED pin itself:
    Serial.print("Knock! Reading was:");     // let the user know there was a knock and how loud it was
    Serial.println(sensorReading);      
  }
  delay(30);                                 // delay to avoid overloading the serial port buffer
                                             // vary this delay if multiple knocks or no knocks are detected
}


Wednesday, April 1, 2015

MCP41010 Digital Potentiometer

I've been meaning to test out SPI on the LaunchPad for a while, and specifically this digital potentiometer.

Bill of materials:
Breadboard
MSP-EXP430F-5529LP or other LaunchPad
MCP41010 Digital Potentiometer
Jumpers
330 ohm resistor
LED

This is for the single channel version of the chip, there is also a dual channel version labelled the 42xxx series.  There should be enough information here to get that to work - I didn't have any problems with the single channel.  Here is the code and a description of the circuit:

/*
  Digital Pot Control
 
  This example controls Microchip MCP41010 I/P digital potentiometer with a
  MSP-EXP430F5529LP.  The MCP41010 has 1 potentiometer channel with 256 taps.
  
  The MCP41010 is SPI-compatible,and to command it, you send two bytes,
  one with the command selection bits (xxC1xxC2) and one with the data value
  (0-255).  Note there is only one channel on the MCP41010.
 
  C1  C0  Command  Command Summary
  --  --  -------  --------------------------------------------------------
   0   0  None     No command executed
   0   1  Write    Write the date contained in Data Byte to the pot
   1   0  Shutdown Enter shutdown mode.  Data Byte does not matter
   1   1  None     No command executed
  
  P1  P0  Potentiometer Selections
  --  --  ------------------------------------------------------------------
   0   0  Dummy Code - pot not affected
   0   1  Command executed on Pot 0
   1   0  Command executed on Pot 1
   1   1  Command executed on both Pots
 
  Note: Since the MCP41010 only has one channel, P1 above is ignored
 
  MCP41010  Connection
  --------  ----------------------------------------------------------
  1 (CS)    Pin 8 of MSP-EXP430F5529LP  (CS)
  2 (SCK)   Pin 7 of MSP-EXP430F5529LP  (SCK)
  3 (SI)    Pin 15 of MSP-EXP430F5529LP (MOSI)
  4 (GND)   GND
  5 (PAO)   3.3V
  6 (PWO)   330 ohm resistor to LED and GND
  7 (PBO)   GND
  8 (Vdd)   3.3V

  created 10 Aug 2010
  by Tom Igoe
  modified 2 May 2012 - changed SS pin
  by Rick Kimball
  Thanks to Heather Dewey-Hagborg for the original tutorial, 2005
  
  modified 1 April 2014 for EXP430F5529LP and MCP41010 I/P
  by Frank Milburn
*/

#include <SPI.h>
// set pin 8 as the slave select for the digital pot:
const int slaveSelectPin = 8;

void setup()
{
  // set the slaveSelectPin as an output:
  pinMode (slaveSelectPin, OUTPUT);
  SPI.begin();
}

void loop() {
  for (int level = 0; level < 255; level++)
  {
    digitalPotWrite(level);
    delay(20);
  }
  delay(100);             // wait a bit at the top
  digitalPotWrite(0);     // change the resistance from max to min:
  delay(10);  
}

int digitalPotWrite(int value)
{
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, LOW); 
  // give the command to write to pot 1
  byte byte1 = B10001;
  SPI.transfer(byte1);
  // send the pot value
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, HIGH);
}