Thursday, May 21, 2015

Addicore Joystick with Push Button

Here is a nice little joystick from Addicore with push button action.  It's easy to use on the MSP430F5529LP.  It uses dual potentiometers for the x and y axis.  Note that there is a commented out line that you can use if desired to change the numeric value for the y axis so that zero voltage is down instead of up.  The x axis goes from zero at left to 4095 at right.  The F5529 has analog resolution of 4096 - you will need to change this to 1023 for Arduino or lower resolution MSP430s.



The Energia sketch below demonstrates how it works.

 /*
 Read Joystick and Push Button - display to Serial Monitor
 Tested with MSP540F5529LP
 Addicore joystick with push button
 https://www.addicore.com/Dual-Axis-XY-Joystick-Module-with-Push-Button-p/139.htm

 F. Milburn 5/19/2015

 Joystick  MSP430F5529LP
 --------  -------------
 GND       GND
 +5V       3V3
 VRX       P6.0
 VRY       P6.1
 SW        P3.4

 */

 int xPin = P6_0;           // x direction potentiometer pin
 int yPin = P6_1;           // y direction potentiometer pin
 int pushPin = P3_4;        // Push button pin
 int xValue = 0;            // x direction potentiometer value (0 to 4095)
 int yValue = 0;            // y direction potentiometer value (0 to 4095)
 int pushState = 0;         // Push button state (0 or 1)

 void setup()
 {
   Serial.begin(9600);
   Serial.println("Starting...");
   pinMode(pushPin, INPUT_PULLUP);
 }

 void loop()
 {
   // Read joystick position
   xValue = analogRead(xPin);         // Read x     (x0 left)
   yValue = analogRead(yPin);         // Read y     (y0 top)
   // yValue = abs(4095 - yValue);    // Reverse y direction  
  
   Serial.print("X = ");
   Serial.print(xValue);
   Serial.print("   ");
   Serial.print("Y = ");
   Serial.print(yValue);
   Serial.print("   ");
  
   // Read button status
   pushState = digitalRead(pushPin);  // See if joystick has been pushed in
  
   Serial.print("Joystick is ");
   if (pushState == 0)
   {
     Serial.println("pushed in");
   }
   else
   {
     Serial.println("not pushed");
   }
  
   delay(200); 
 }

Addicore 20 x 4 Serial LCD using I2C and BS170 MOSFETs

This is a very nice 20 column, 4 line display from Addicore - big and easy to read.  I've ordered several things from them recently and have been pleased.  They have free mailing in the U.S. for orders over $25 and are quick and responsive.  Recommended....

Here is what it looks like when up and running on the MSP430F5529 LaunchPad.



Note that this is a 5V device!  I've translated signals using BS170 MOSFETs and the following circuit.



I got it up and running easily using a library from DFRobot.

Here is the test code running in the display above.

//Using library from DFRobot.com
//Compatible with the Arduino IDE 1.0
//Library version:1.1
/*
 * 20x4 Serial LCD from Addicore
 * https://www.addicore.com/2004-20x4-Character-LCD-with-I2C-backpack-p/157.htm
 * Tested on MSP430F5529LP
 * NOTE: This is a 5V device!
 * Need to translate 3V3 <---> 5V (used two BS170 MOSFETs)
 * F Milburn   21 May 2015
*/
#include <Wire.h>
#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd(0x27,20,4);  // set for a 20 character 4 line display

void setup()
{
  lcd.init();                      // initialize the lcd
  // LINE 0
  // Print a message to the LCD.
  lcd.backlight();
  lcd.print("First line");
}

void loop()
{
  // LINE 1 - Number of columns
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  lcd.print("Second line");
 
  // LINE 2 - ENERGIA
  lcd.setCursor(0, 2);
  lcd.print("Third line");
 
  // LINE 3 - Count seconds
  lcd.setCursor(0, 3);
  lcd.print("Time since reset:");
  // print the number of seconds since reset:
  lcd.print(millis()/1000);
}

Wednesday, April 8, 2015

DHT 22 Humidity and Temperature Sensor

I bought a DHT 22 a while back from Adafruit for use on the Arduino and just got around to trying it on the MSP-EXP430F5529LP.  They supply a good write-up and a library for using it as well but it is another one of those libraries that almost, but not quite, works with Energia.  To make it work you need to do the following:

Inside the sketch itself you will need to adjust the "threshold for cycled for cycle counts".  The remarks state that the default is 6 which works with a 16mhz AVR.  It definitely does not work with the 430F5529.  I played around and ended up assigning with the following statement and seemed to get good results:

DHT dht(DHTPIN, DHTTYPE, 12);

It does bother me that I'm not really sure what this is doing or how it impacts results.  I compared it to what my local weather station was reporting and was within 1% but that is just one data point.

You will also need to make a change to DHT.cpp in the library.  There are function that attempt to return NAN (not a number).  The gcc compiler for the 430 does not like this.  I fixed it in a way I'm not too proud of.  Instead of return NAN, I used return 0/0 which of course is "not a number".  I could have used a negative number outside of normal values but that didn't seem right either since I didn't explore what the consequences of that might be.  This code needs to be cleaned up.

The Adafruit library does not calculate dew point and I wanted that.  It can be calculated from the August-Roche-Magnus approximation as follows:

td =243.04*(logf(h/100)+((17.625*t)/(243.04+t)))/(17.625-logf(h/100)-((17.625*t)/(243.04+t)));

Where:

td = dew point, degrees C
h = relative humidity, % from the DHT 22
t = air temperature, degrees C from the DHT 22





Sunday, April 5, 2015

Adafruit TSL2591 Lux Sensor

This post is about the Adafruit TSL2591 Lux Sensor which I have also used with the Arduino.  Adafruit has a good write-up and it ports very easily to the MSP-EXP430F5529.  I am using the Adafruit library, however there is one thing that keeps their library from compiling on the LaunchPads...

In the Adafruit library for the TL2591, the cpp file (Adafruit_TSL2591.cpp)has a preprocessor directive for delay.h.  Either remove it or comment the line out.

One thing the example code Adafruit supplies does not do is auto-range the gain on the sensor.  If the light is too bright it can saturate and if too dim you may not get good readings.  I've written a function named  configureSensor(void) below.  The magic numbers are experimental results that seem to work well for me.  It needs an iteration or two to make this adjustment.  I've not added code to discard bad readings but that could be easily done.

Here is the sketch...

/*
PURPOSE:

  This sketch uses the Adafruit TLS2591 light sensor to display lux values
  on the serial monitor.  It also "autoranges" the gain and time photons
  are collected on the sensor to keep the sensor in range.  In order to
  get a good reading after a bad reading due to a drastic light change it
  will be necessary to let it iterate two times or so.  Try covering the
  sensor and watching what happens.  Then remove the cover and shine a
  bright light on it.


PORT TO MSP-EXP430F5529:

  In order for this to compile, comment out or remove the following
  line of Adafruit_TSL2591.cpp in the library
  =========================================================================
  #include <util/delay.h>           
  =========================================================================


SENSOR:
  TSL2591 Digital Light Sensor
  Dynamic Range: 600M:1
  Range: 188 ulux up to 88,000 lux

  The lux (symbol: lx) is the SI unit of illuminance and luminous emittance,
  measuring luminous flux per unit area. It is equal to one lumen per square
  meter.  The table below gives examples:
 
               0.0001   lux   Moonless, overcast night sky (starlight)
               0.002    lux   Moonless clear night sky with airglow
               0.27–1.0 lux   Full moon on a clear night
               3.4      lux   Dark limit of civil twilight under a clear sky
              50.       lux   Family living room lights
              80.       lux   Office building hallway/toilet lighting
             100.       lux   Very dark overcast day
         320–500.       lux   Office lighting
             400.       lux   Sunrise or sunset on a clear day.
            1000.       lux   Overcast day; typical TV studio lighting
     10000–25000.       lux   Full daylight (not direct sun)
    32000–100000.       lux   Direct sunlight
   
    Source: Wikipedia


HARDWARE AND CONNECTIONS:

  Adafruit TLS2591 connections for MSP-EXP430F5529LP
  ======================================================================
  SCL to Pin 14 (P3.1)                  Must be I2C Pin
  SDA to Pin 15 (P3.0)                  Must be I2C Pin
  connect Vin to 3.3 DC
  GND to common ground
  3Vo (no connection)
  Int (no connection)
*/

 
//============================ G L O B A L ============================
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_TSL2591.h"

Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);  // sensor identifier

float luxVal = 10000;  

                          
void setup(void)
{
  //============================== S E T U P =============================
  Serial.begin(9600);
 
  Serial.println("Starting Adafruit TSL2591 Test!"); 
  if (tsl.begin())
  {
    Serial.println("Found a TSL2591 sensor");
  }
  else
  {
    Serial.println("No sensor found ... check your wiring?");
    while (1);
  }
 
  /* Display some basic information on this sensor */
  displaySensorDetails();

}

void loop(void)
{
  //============================== L O O P ==================================
 
  configureSensor();
  unifiedSensorAPIRead();
  delay (1000);
 
}


void unifiedSensorAPIRead(void)
{
  //============== U N I F I E D   S E N S O R   A P I   R E A D =============
  //  Performs a read using the Adafruit Unified Sensor API
  //  Updates the lux value in the global variable luxVal
  //  Get a new sensor event
 
  sensors_event_t event;
  tsl.getEvent(&event);
 
  if ((event.light == 0) |
      (event.light > 4294966000.0) |
      (event.light <-4294966000.0))
  {
    // If event.light == 0 lux the sensor is probably saturated
    // and no reliable data could be generated!
    // if event.light is +/- 4294967040 there was a float over/underflow
    Serial.println("Invalid data - auto adjusting gain gain and timing)");
    luxVal = 10000.0;    // Set luxVal to get minimum time and gain for next pass
                         // so as to get a valid starting point
  }
  else
  {
    int f;            // format number for decimal places in the print statement
    if (luxVal >= 100.0)
    {
      f = 0;
    }
    else if (luxVal < 100.0 && luxVal >= 100.0)
    {
      f = 1;
    }
    else if (luxVal < 100.0 && luxVal >= 1.0)
    {
      f = 2;
    }
    else
    {
      f = 3;
    }
          
    Serial.print(event.light,f);     Serial.println(" lux");
    Serial.println("------------------");
    Serial.println("");

    luxVal = event.light;
  }
}


void displaySensorDetails(void)
{
  //============= D I S P L A Y   S E N S O R   D E T A I L S ================
  // Displays some basic information on this sensor from the unified
  // sensor API sensor_t type (see Adafruit_Sensor for more information)
  sensor_t sensor;
  tsl.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" lux");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" lux");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" lux"); 
  Serial.println("------------------------------------");
  Serial.println("");
 
  delay(2000);
}


void configureSensor(void)
{
  //================== C O N F I G U R E   S E N S O R    =====================
  //
  //  Configures the gain and integration time for the TSL2561 depending  

  //  on luxVal
  //  NOTE:  The variable luxVal is global.  The following calls are valid:
  // 
  //  Set gain according to the light level
  //  tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
  //  tsl.setGain(TSL2591_GAIN_MED);    // 25x gain
  //  tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
  //  tsl.setGain(TSL2591_GAIN_MAX);    // 9876x gain (extremely low light)
  //
  //  Changing integration time gives you a longer time over which to sense light
  //  Longer timelines are slower, but improve accuracy in low light situations
  //  tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
  //  tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
  //  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
  //  tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
  //  tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
  //  tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)
  //
  //  The values used below are empirical ones that seemed to get things in
  //  a good range for accurate measurement...  F Milburn
  //
  Serial.println("------------------");
  Serial.print  ("Gain: ");
  if (luxVal > 200.0)
  { 
    tsl.setGain(TSL2591_GAIN_LOW);              
    tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);
    Serial.println("1x (Low)");
    Serial.println("Timing: 100 ms");
  }
  else if (luxVal <=200.0 && luxVal > 40.0)
  {
    tsl.setGain(TSL2591_GAIN_MED);                
    tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
    Serial.println("25x (Med)");
    Serial.println("Timing: 200 ms");
  }
  else if (luxVal <=40.0 && luxVal > 10.0)
  {
    tsl.setGain(TSL2591_GAIN_MED);                
    tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);
    Serial.println("25x (Med)");
    Serial.println("Timing: 600 ms");
  }
  else if (luxVal <=10.0 && luxVal > 0.1)
  {
    tsl.setGain(TSL2591_GAIN_HIGH);                
    tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);
    Serial.println("428x (High)");
    Serial.println("Timing: 600 ms");
  }
  else
  {
    tsl.setGain(TSL2591_GAIN_MAX);                
    tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);
    Serial.println("9876x (Max)");
    Serial.println("Timing: 600 ms");
  }
}

HC-543 Keypad

This post is about a nice little keypad I bought on Amazon.  I can't remember which vendor but you can get them for 2-3$ US.  I usually buy from Amazon Prime vendors if I can.  Here is a photo:

They are very easy to connect up using this library.  Here is a sketch that works on a MSP-EXP430F5529LP.

/*
||
|| Modified for HC-543 keypad and TI MSP-EXP430F5529LP.
|| Demonstrates changing the keypad size and key values.
||
|| Credit for original code:
|| @author Alexander Brevig
|| @contact
alexanderbrevig@gmail.com
||
|| Frank Milburn
|| 19 Feb 2015
||
|| Connections:
|| As you look at the HC-543 keypad, the first lead on the
|| left is the first row.  The 5th lead over to the right
|| is the first column.

*/
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the symbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {10, 9, 8, 7}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 5, 4, 3};  //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

void setup(){
  Serial.begin(9600);
  Serial.println("Starting keypad...");
}
 
void loop(){
  char customKey = customKeypad.getKey();
 
  if (customKey){
    Serial.println(customKey);
  }
}

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
  }
}