This link leads to an example for TI MSP430 and CC3200 LaunchPads that read a card number
using a RC522 MIFARE module and Energia.
Tested with Energia V16 on:
MSP-EXP430G2 LaunchPad
MSP-EXP430F5529 LaunchPad
MSP-EXP430FR5969 LaunchPad
CC3200
Learning to use microcontrollers with an emphasis on the Texas Instruments Launchpads / Energia
Wednesday, December 2, 2015
Saturday, August 8, 2015
Color Sensor TCS230/TCS3200
I got this sensor off Amazon. It was fun to play with but surprisingly difficult to get meaningful results from. The difficulty is primarily due to sensor limitations. There are quite a few sites with Arduino code for this sensor, I am using a MSP432 LaunchPad here. I wanted to keep it simple and use the pulseIn() function. It works with the MSP432, but not so well with the F5529. A better approach would be to use a timer and count interrupts from the pulses.
See my git repository here for the pin connections, code, and a deeper discussion.
The following is a photo of the sensor I'm using and some examples of what you might expect:
See my git repository here for the pin connections, code, and a deeper discussion.
The following is a photo of the sensor I'm using and some examples of what you might expect:
Tuesday, July 14, 2015
BerkeleyX: EE40LX Electronic Interfaces Module 1
I just started the Berkley edX course on Electronic Interfaces. The ultimate goal is to build a small robot and they give you latitude along the way on how to build it. At the end of Module 1 (just before the quiz) you put together a voltage regulator to power the MSP430G2 from a battery. Here is mine, running the hello world sketch:
Their design calls for a 9V battery and a LM1086 3.3V voltage regulator. I'm using a LD1117AV33 and a 4xAA switched battery pack because that is what I happen to have on hand. I made 100 on the quiz. So far, so good...
Their design calls for a 9V battery and a LM1086 3.3V voltage regulator. I'm using a LD1117AV33 and a 4xAA switched battery pack because that is what I happen to have on hand. I made 100 on the quiz. So far, so good...
Thursday, July 9, 2015
Stripped down Stand-alone M430G2553
It is amazing how easy and inexpensive it is to program a MSP430G2553 (or any number of other chips in the value line series) and then run it as a stand-alone microcontroller. The photo below shows a MSP430G2553 being programmed with a MSP-EXP430G2 LaunchPad. The LaunchPad costs $9.99 at Mouser. The MSP430G2553 costs $2.80 as a single, $2.25 if you buy in lots of 10.
This is a minimal setup to program the chip. Once it is programmed, you can remove the TEST and RST jumpers.
Thanks to Kerry Wong for his write-up here that I used to get started. I've simplified his set-up by leaving off RXD and TXD, and taking the pins directly to the LaunchPad. I took off the jumpers on the LaunchPad and hooked-up to the pins on the LaunchPad the same as Kerry.
Here it is blinking "hello world" from a battery pack.
This is a minimal setup to program the chip. Once it is programmed, you can remove the TEST and RST jumpers.
Thanks to Kerry Wong for his write-up here that I used to get started. I've simplified his set-up by leaving off RXD and TXD, and taking the pins directly to the LaunchPad. I took off the jumpers on the LaunchPad and hooked-up to the pins on the LaunchPad the same as Kerry.
Here it is blinking "hello world" from a battery pack.
Friday, June 26, 2015
RGB Strip LED
For my sound level project I am considering using inexpensive RGB Strip LEDs. So to try some code out I did a trial from this Adafruit post:
https://learn.adafruit.com/rgb-led-strips/overview
The differences are:
* used Adafruit's circuit for the TIP120 except except that I used 5mm LEDs to stand in for the strip (also put a resistor in front of each LED so it wouldn't burn out)
* used Adafruit's sketch except I substituted pins 11, 12, and 13 for the Arduino PWM (used a MSP430G2553)
* used a 4.5V battery pack for external power to the LEDs
It is working:
For my project I am thinking I'll need at least 2 strips running 2 different colors so 6 TIP120s. I only have 5. Even better would be to have 3 strips and 3 colors - then I'll have the added complication of not enough PWM pins. It looks like there is another order in my future.
https://learn.adafruit.com/rgb-led-strips/overview
The differences are:
* used Adafruit's circuit for the TIP120 except except that I used 5mm LEDs to stand in for the strip (also put a resistor in front of each LED so it wouldn't burn out)
* used Adafruit's sketch except I substituted pins 11, 12, and 13 for the Arduino PWM (used a MSP430G2553)
* used a 4.5V battery pack for external power to the LEDs
It is working:
For my project I am thinking I'll need at least 2 strips running 2 different colors so 6 TIP120s. I only have 5. Even better would be to have 3 strips and 3 colors - then I'll have the added complication of not enough PWM pins. It looks like there is another order in my future.
Wednesday, June 24, 2015
Saturday, June 20, 2015
Friday, June 19, 2015
Rainfall Gauge using Hall Sensor
This is one I was working on a while back but have put on hold. I have a working prototype so will post it anyway - maybe it will inspire me to finish it up. Find photos below and preliminary code here at github.
The sensor works by collecting rain in the funnel as shown in the top photographs. The funnel has a known diameter and thus area.
The rain then collects in the rocking mechanism in the middle photograph. The pivot point for the mechanism is better seen in the top photo. The volume collected can be calibrated by moving the adjustment screws up and down. The hall sensor is the device that has been attached with yellow wire. It is opposite the South pole of a small round magnet in the middle photo.
When the tipping mechanism fills it tips as shown in the bottom photo. The hall sensor loses contact with the magnet and reports the change to the MSP430F5529 microcontroller. The water then drains out the bottom of the sensor through holes.
The sensor works and appears to be accurate and repeatable. I have not kept it in service long enough to comment on how reliable it might ultimately be. I need to go back and clean up the design a bit and incorporate it into the larger weather station vision I have.
The sensor works by collecting rain in the funnel as shown in the top photographs. The funnel has a known diameter and thus area.
The rain then collects in the rocking mechanism in the middle photograph. The pivot point for the mechanism is better seen in the top photo. The volume collected can be calibrated by moving the adjustment screws up and down. The hall sensor is the device that has been attached with yellow wire. It is opposite the South pole of a small round magnet in the middle photo.
When the tipping mechanism fills it tips as shown in the bottom photo. The hall sensor loses contact with the magnet and reports the change to the MSP430F5529 microcontroller. The water then drains out the bottom of the sensor through holes.
The sensor works and appears to be accurate and repeatable. I have not kept it in service long enough to comment on how reliable it might ultimately be. I need to go back and clean up the design a bit and incorporate it into the larger weather station vision I have.
Credit to msuzuki77, the Lazy Old Geek http://www.instructables.com/id/Arduino-Weather-Station-Part3-Rain/ for the inspiration for my version
Tuesday, June 16, 2015
Vibration Sensors SW-18015P and SW-18020P
There is a post on how to use these simple vibration sensors with a LaunchPad here on github. They act like open switches that close momentarily when shaken or bumped. I got mine at Addicore.
Saturday, June 13, 2015
Addicore 20 x 4 Serial LCD using I2C and Addicore Bi-Directional Level Converter
This post uses the same Addicore 20x4 Serial LCD that I used in this post. However, this time I used an Addicore Level Converter instead of creating a circuit. The Level Converter is easy to use, reasonably priced, and has 4 channels should you need them. I've also posted an I2C library with it that was obtained from the DFRobot.com site. The library, example code, and circuit are located here on github. The example demonstrates how to define special characters and also simple animation.
I tested the sketch with the F5529, CC3200, and the MSP432P410R. It should work with a 2 line LCD as well but I haven't tried that since I don't have one with I2C.
Monday, June 8, 2015
Sharp GP1S53VJ000F PhotoInterrupter
I recently got a Sharp GP1S53VJ000F photointerrupter from Mouser and successfully tested it with a Texas Instruments EXP-430F5529 LaunchPad with Energia and on an Arduino Uno. It should work with most LaunchPads using Energia. Non-transparent objects passing through the "slot" are detected.
The sensor consists of an infrared LED emitter and a phototransistor detector opposite each other in a case. When the transmission between them is blocked the digital pin will go high. The sketch will then send a message to the serial monitor.
When tested it gave a very reliable response, even in bright sunlight with the sensor unshielded.
The circuit and sketch can be found here at Github.
The sensor consists of an infrared LED emitter and a phototransistor detector opposite each other in a case. When the transmission between them is blocked the digital pin will go high. The sketch will then send a message to the serial monitor.
When tested it gave a very reliable response, even in bright sunlight with the sensor unshielded.
The circuit and sketch can be found here at Github.
Friday, June 5, 2015
HC-SR04 Ultrasonic Distance Sensor
Here's a simple sketch that shows how to use the HC-SR04 ultrasonic distance sensor. I bought this one from Addicore. They are inexpensive and work well for what they are, especially for the cost. They are easy to get going and fun to play with. The code is here on Github.
Here it is, measuring the distance from my laptop to the wall...
Here it is, measuring the distance from my laptop to the wall...
Tuesday, June 2, 2015
CNY70 Tachometer
Here are some photographs of a CNY70 Reflective Optical Sensor mounted on a little board for use as a tachometer.
In the photograph below the reflector can be seen. It is simply a piece of white paper glued to the fan rotor.
Here it is with the MSP-EXP430F5529 spitting out RPM values to the serial monitor. I've turned the fan off and it is slowing down.
The code and schematic can be found here on Github. It includes a discussion of how the sensor works and modifying it to work on an Arduino Uno.
In the photograph below the reflector can be seen. It is simply a piece of white paper glued to the fan rotor.
Here it is with the MSP-EXP430F5529 spitting out RPM values to the serial monitor. I've turned the fan off and it is slowing down.
The code and schematic can be found here on Github. It includes a discussion of how the sensor works and modifying it to work on an Arduino Uno.
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);
}
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);
}
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
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");
}
}
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);
}
}
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:
#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);
- 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_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.
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
}
}
/*
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);
}
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.
}
/*
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
}
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);
}
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);
}
Subscribe to:
Posts (Atom)