In the same manner as their MSP430 development board, Texas Instruments also have another LaunchPad board with their powerful Stellaris LM4F120H5QR microcontroller. It’s an incredibly powerful and well-featured MCU – which offers an 80 MHz, 32-bit ARM Cortex-M4 CPU with floating point, 256 Kbytes of 100,000 write-erase cycle FLASH and many peripherals such as 1MSPS ADCs, eight UARTs, four SPIs, four I2Cs, USB & up to 27 timers, some configurable up to 64-bits.
That’s a bucket of power, memory and I/O for not much money – you can get the LaunchPad board for around $15. This LaunchPad has the in-circuit debugger, two user buttons, an RGB LED and connectors for I/O and shield-like booster packs:
and the other side:
However the good news as far as we’re concerned is that you can now use it with the Energia Arduino-compatible IDE that we examined previously. Before rushing out to order your own Stellaris board, install Energia and examine the available functions and libraries to make sure you can run what you need. And if so, you’re set for some cheap Arduino power.
Installation
Installation is simple, just get your download from here. If you’re running Windows 7 – get the USB drivers from here. When you plug your LaunchPad into the USB for the first time, wait until after Windows attempts to install the drivers, then install drivers manually after download via Device manager … three times (JTAG, virtual serial port and DFU device). Use the debug USB socket (and set the switch to debug) when installing and uploading code. If you get the following warning from Windows, just click “Install this driver software anyway”:
Once the drivers are installed, plug in your LaunchPad, wait a moment – then run Energia. You can then select your board type and serial port just like the Arduino IDE. Then go ahead and upload the “blink” example…
Awesome – check out all that free memory space. In the same manner as the MSP430, there are some hardware<>sketch differences you need to be aware of. For example, how to refer to the I/O pins in Energia? A map has been provided for front:
… and back:
As you can imagine, the Stellaris MCUs are different to an AVR, so a lot of hardware-specific code doesn’t port over from the world of Arduino. One of the first things to remember is that the Stellaris is a 3.3V device. Code may or may not be interchangeable, so a little research will be needed to match up the I/O pins and rewrite the sketch accordingly. For example, instead of digital pins numbers, you use PX_Y - see the map above. So let’s say you want to run through the RGB LED… consider the following sketch:
int wait = 500;
void setup()
{
// initialize the digital pin as an output.
pinMode(PF_1, OUTPUT); // red
pinMode(PF_3, OUTPUT); // green
pinMode(PF_2, OUTPUT); // blue
}
Which simply blinks the red, green and blue LED elements in series. Using digital inputs is in the same vein, and again the buttons are wired so when pressed they go LOW. An example of this in the following sketch:
void setup()
{
// initialize the digital pins
pinMode(PF_1, OUTPUT); // red
pinMode(PF_3, OUTPUT); // green
pinMode(PF_2, OUTPUT); // blue
pinMode(PF_4, INPUT_PULLUP); // left - note _PULLUP
pinMode(PF_0, INPUT_PULLUP); // right - note _PULLUP
}
void loop()
{
if (digitalRead(PF_4)==LOW) { blinkslow(); }
if (digitalRead(PF_0)==LOW) { blinkfast(); }
}
And for the non-believers:
Where to from here?
Sometimes you can be platform agnostic, and just pick something that does what you want with the minimum of time and budget. Or to put it another way, if you need a fast CPU and plenty of space but couldn’t be bothered don’t have time to work with Keil, Code Composer Studio, IAR etc – the Energia/Stellaris combination could solve your problem. There’s a growing Energia/Stellaris forum, and libraries can be found here. At the time of writing we found an I2C library as well.
However to take full advantage of the board, consider going back to the TI tools and move forward with them. You can go further with the tutorials and CCS etc from Texas Instruments own pages.
In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.
Over the last year or so Texas Instruments have been literally pushing their MSP430 development platform hard by offering an inexpensive development kit – their LaunchPad. For around ten dollars (not everyone could get it for $4.30) it includes a development board with flash emulation tool and USB interface, two of their microcontrollers, crystal, USB cable and some headers. It was (is?) a bargain and tens of thousands of LaunchPads were sold. Happy days.
However after the courier arrived and the parcel was opened, getting started with the LaunchPad was an issue for some people. Not everyone has been exposed to complex IDEs or university-level subjects on this topic. And to get started you needed to use a version of Code Composer Studio or IAR Embedded Workbench IDEs, which scared a few people off. So those LaunchPads went in the cupboard and gathered dust.
Well now it’s time to pull them out, as there’s a new way to program the MSP430 using a fork of the Arduino IDE – Energia. Put simply, it’s the Arduino IDE modified to compile and upload code to the LaunchPad, which makes this platform suddenly much more approachable.
Getting Started
You’ll need to download and install the appropriate USB drivers, then the IDE itself from here. To install the IDE you just download and extract it to your preferred location, in the same manner as the Arduino IDE. Then plug your LaunchPad into the USB. Finally, load the IDE. Everything is familiar to the Arduino user, except the only surprise is the colour (red as a nod to TI perhaps…):
Looking good so far. All the menu options are familiar, the files have the .ino extension, and the preferences dialogue box is how we expect it. Don’t forget to select the correct port using the Tools > Serial port… menu. You will also need to select the type of MSP430 in your LaunchPad. At the time of writing there is support for three types listed below (and the first two are included with the LaunchPad v1.5):
MSP430G2553 - <=16 MHz, 16KB flash, 512b SRAM, 24 GPIO, two 16-bit timers, UART, SPI, I2C, 8 ADC channels at 10-bit, etc. Cost around Au$3.80 each**
MSP430G2452 - <=16 MHz, 8KB flash, 256b SRAM, 16 GPIO, one 16-bit timer, UART, I2C, 8 ADC channels, etc. Cost around Au$2.48 each**
MSP430G2231 - <=16 MHz, 2KB flash, 128b SRAM, 10 GPIO, one 16-bit timer, SPI, I2C, 8 ADC channels, etc. Cost around Au$3.36 each**
** One-off ex-GST pricing from element14 Australia. In some markets it would be cheaper to buy another LaunchPad. TI must really be keen to get these in use.
There are some hardware<>sketch differences you need to be aware of. For example, how to refer to the I/O pins in Energia? A map has been provided for each MSP430 at the Energia wiki, for example the G2553:
As you can imagine, MSP430s are different to an AVR, so a lot of hardware-specific code doesn’t port over from the world of Arduino. One of the first things to remember is that MSP430s are 3.3V devices. Code may or may not be interchangeable, so a little research will be needed to match up the I/O pins and rewrite the sketch accordingly. You can refer to pins using the hardware designator on the LaunchPad (e.g. P1_6) or the physical pin number. For example – consider the following sketch:
void setup() {
// initialize the digital pins as an output.
pinMode(P1_0, OUTPUT); // LED 1
pinMode(P1_6, OUTPUT); // LED 2
}
You could have used 2 (for physical pin 2) instead of P1_0 and 14 (physical pin … 14!) instead of P1_6. It’s up to you. Another quick example is this one – when the button is pressed, the LEDs blink a few times:
const int redLED = P1_0;
const int greenLED = P1_6;
const int button = P1_3; // button S2 (on the left)
Due to the wiring of the LaunchPad, when you press the button, P1_3 is pulled LOW. For the non-believers, here it is in action:
So where to from here? There are many examples in the Energia IDE example menu, including some examples for the Energia libraries. At the time of writing there is: Servo, LiquidCrystal, IRremote, SPI, wire, MSPflash and Stepper. And as the Energia project moves forward more may become available. For help and discussion, head over to the 4-3-Oh forum and of course the Energia website. And of course there’s the TI MSP430 website.
Conclusion
Well that was interesting to say the least. If you have a project which needs to be low-cost, fits within the specifications of the MSP430, has a library, you’re not hung up on brand preference, and you just want to get it done – this is a viable option. Hopefully after time some of you will want to work at a deeper level, and explore the full IDEs and MSP430 hardware available from TI. But for the price, don’t take my word for it – try it yourself.
In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.
The first chapter is here, the complete series is detailed here. Please note from November 1, 2010 files from tutorials will be found here.
[Updated 10/01/2013]
Today we are going to continue learning about the I2C bus and how it can work for us. If you have not already, please read and understand the first I2C article before continuing.
First of all, there are some limitations of I2C to take into account when designing your projects. One of these is the physical length of the SDA and SCL lines. If all your devices are on the same PCB, then there is nothing to worry about, however if your I2C bus is longer than around one metre, it is recommended that you use an I2C bus extender IC. These ICs reduce electrical noise over the extended-length bus runs and buffer the I2C signals to reduce signal degradation and chance of errors in the data. An example of such an IC is the NXP P82B715 (data sheet). Using a pair of these ICs, you can have cable runs of 20 to 30 metres, using shielded twisted-pair cable. Below is a good example of this, from the aforementioned NXP data sheet:
Several applications come to mind with an extended I2C bus, for example remote temperature monitoring using the the ST Microelectronics CN75 temperature sensor from part one; or controlling several I/O ports using an I2C expander without the expense or worry of using a wireless system. Speaking of which, let’s do that now…
Example 21.1
A very useful and inexpensive part is the PCF8574 I/O expander (data sheet.pdf). This gives us another eight outputs, in a very similar method to the 74HC595; or can be used as eight extra inputs. In fact, if you were to use more than one 74HC595 this IC might be preferable, as you can individually address each chip instead of having to readdress every IC in line as you would with shift registers. So how do we do this? First, let’s consult the pinout:
There should not be any surprises for you there. A2~A0 are used to select the last three bits of the device address, P0~P7 are the I/O pins, and INT is an interrupt output which we will not use. To address the PCF8574 we need two things, the device address, and a byte of data which represents the required output pin state. Huh? Consider:
So if we set pins A0 to A2 to GND, our device address in binary will be 0100000, or 0×20 in hexadecimal. And the same again to set the output pins, for example to turn them all on we send binary 0 in hexadecimal which is 0; or to have the first four on and the second four off, use 00001111 which is Ox0F. Hopefully you noticed that those last two values seemed backwards – why would we send a zero to turn all the pins on?
The reason is that the PCF8574 is a current sink. This means that current runs from +5v, through into the I/O pins. For example, an LED would have the anode on the +5V, and the cathode connected to an I/O pin. Normally (for example with a 74HC595) current would run from the IC, through the resistor, LED and then to earth. That is a current source. Consider the following quick diagram:
In the example above, please note that the PCF8574N can take care of current limitation with LEDs, whereas the 74HC595 needs a current-limiting resistor to protect the LED.
Luckily this IC can handle higher volumes of current, so a resistor will not be required. It sounds a bit odd, but like anything is easy once you spend a few moments looking into it. So now let’s use three PCF8574s to control 24 LEDs. To recreate this masterpiece of blinkiness you will need:
Eight each of red, green and yellow (or your choice) LEDs, each with a current draw of no more than 20mA
Two 4.7 kilo ohm resistors
Hook-up wires
Three 0.1 uF ceramic capacitors
Here is the schematic:
… and the example board layout:
and the example sketch. Note that the device addresses in the sketch match the schematic above. If for some reason you are wiring your PCF8574s differently, you will need to recalculate your device addresses: (download sketch)
/*
Example 21.1
Texas Instruments PCF8574N demonstration sketch
element-14 part number 7527718; RS part number 517-0687
http://tronixstuff.com/tutorials > chapter 21
CC by-sa v3.0
*/
#include "Wire.h"
#define redchip 0x20 // device addresses for PCF8547Ns on each LED colour bank
#define yellowchip 0x22 // addresses in this example match the published schematic in the tutorial
#define greenchip 0x21 // you will need to change addresses if you vary from the schematic
int dd=20; // used for delay timing
void setup()
{
Wire.begin();
allOff(); // the PCF8574N defaults to high, so this functions turns all outputs off
}
// remember that the IC "sinks" current, that is current runs fro +5v through the LED and then to I/O pin
// this means that 'high' = off, 'low' = on.
void loop()
{
for (int z=0; z<10; z++)
{
testfunc();
}
for (int z=0; z<10; z++)
{
testfunc2();
}
for (int z=0; z<10; z++)
{
testfunc3();
}
}
And finally our demonstration video:
That was a good example of controlling many outputs with our humble I2C bus. You could literally control hundreds of outputs if necessary – a quite inexpensive way of doing so. Don’t forget to take into account the total current draw of any extended circuits if you are powering from your Arduino boards.
The next devices to examine on our I2C bus ride are EEPROMs - Electrically Erasable Programmable Read-Only Memory. These are memory chips that can store data without requiring power to retain memory. Why would we want to use these? Sometimes you might need to store a lot of reference data for use in calculations during a sketch, such as a mathematical table; or perhaps numerical representations of maps or location data; or create your own interpreter within a sketch that takes instruction from data stored in an array.
In other words, an EEPROM can be used to store data of a more permanent use, ideal for when your main microcontroller doesn’t haven enough memory for you to store the data in the program code. However, EEPROMs are not really designed for random-access or constant read/write operations – they have a finite lifespan. But their use is quite simple, so we can take advantage of them.
EEPROMS, like anything else come in many shapes and sizes. The model we will examine today is the Microchip 24LC256 (data sheet.pdf). It can hold 256 kilobits of data (that’s 32 kilobytes) and is quite inexpensive. This model also has selectable device addresses using three pins, so we can use up to eight at once on the same bus. An example:
The pinouts are very simple:
Pin 7 is “write protect” – set this low for read/write or high for read only. You could also control this in software if necessary. Once again we need to create a slave I2C device address using pins 1, 2 and 3 – these correlate to A2, A1 and A0 in the following table:
So if you were just using one 24LC256, the easiest solution would be to set A0~A2 to GND – which makes your slave address 1010000 or 0×50 in hexadecimal. There are several things to understand when it comes to reading and writing our bytes of data. As this IC has 32 kilobytes of storage, we need to be able to reference each byte in order to read or write to it. There is a slight catch in that you need more than one byte to reference 32767 (as in binary 32767 is 11111111 0100100 [16 bits]).
So when it comes time to send read and write requests, we need to send two bytes down the bus – one representing the higher end of the address (the first 8 bits from left to right), and the next one representing the lower end of the address (the final 8 bits from left to right) – see figure 6.1 on page 9 of the data sheet.
An example – we need to reference byte number 25000. In binary, 25000 is 0110000110101000. So we split that up into 01100001 and 10101000, then covert the binary values to numerical bytes with which to send using the Wire.send(). Thankfully there are two operators to help us with this. This first is >>, known as bitshift right. This will take the higher end of the byte and drop off the lower end, leaving us with the first 8 bits. To isolate the lower end of the address, we use another operator &, known as bitwise and. This unassuming character, when used with 0XFF can separate the lower bits for us. This may seem odd, but will work in the examples below.
Writing data to the 24LC256
Writing data is quite easy. But first remember that a byte of data is 11111111 in binary, or 255 in decimal. First we wake up the I2C bus with
Wire.beginTransmission(0x50); // if pins A0~A2 are set to GND
then send down some data. The first data are the two bytes representing the address (25000) of the byte (12) we want to write to the memory.
Wire.write(25000 >> 8); // send the left-hand side of the address down
Wire.write(25000 & 0xFF); // send the right-hand side of the address down
And finally, we send the byte of data to store at address 25000, then finish the connection:
Wire.write(12);
Wire.endTransmission();
There we have it. Now for getting it back…
Reading data from the 24LC256
Reading is quite similar. First we need to start things up and move the pointer to the data we want to read:
Wire.beginTransmission(0x50); // if pins A0~A2 are set to GND
Wire.write(25000 >> 8); // send the left-hand side of the address down
Wire.write(25000 & 0xFF); // send the right-hand side of the address down
Wire.endTransmission();
Then, ask for the byte(s) of data starting at the current address:
Wire.beginTransmission(0x50); // if pins A0~A2 are set to GND
Wire.requestFrom(0x50,1);
Wire.read(incomingbyte);
In this example, incomingbyte is a byte variable used to store the data we retrieved from the IC.
Example 21.2
Now we have the theory, let’s put it into practice with the test circuit below, which contains two 24LC256 EEPROMs. To recreate this you will need:
and the example sketch. Note that the device addresses in the sketch match the schematic above. If for some reason you are wiring your 24LC256s differently, you will need to recalculate your device addresses. To save time with future coding, we have our own functions for reading and writing bytes to the EEPROM – readData() and writeData(). Consider the sketch for our example: (download sketch)
/*
Example 21.2
Reading and writing data to Microchip 24LC256 EEPROMS over I2C
tronixstuff.com/tutorials > Chapter 21
CC by-sa v3.0
*/
#include // for I2C
#define chip1 0x50 // device address for left-hand chip on our breadboard
#define chip2 0x51 // and the right
// always have your values in variables
unsigned int pointer = 69; // we need this to be unsigned, as you may have an address > 32767
byte d=0; // example variable to handle data going in and out of EERPROMS
void setup()
{
Serial.begin(9600); // for screen output
Wire.begin(); // wake up, I2C!
}
void writeData(int device, unsigned int add, byte data)
// writes a byte of data 'data' to the chip at I2C address 'device', in memory location 'add'
{
Wire.beginTransmission(device);
Wire.write((int)(add >> 8)); // left-part of pointer address
Wire.write((int)(add & 0xFF)); // and the right
Wire.write(data);
Wire.endTransmission();
delay(10);
}
byte readData(int device, unsigned int add)
// reads a byte of data from memory location 'add' in chip at I2C address 'device'
{
byte result; // returned value
Wire.beginTransmission(device); // these three lines set the pointer position in the EEPROM
Wire.write((int)(add >> 8)); // left-part of pointer address
Wire.write((int)(add & 0xFF)); // and the right
Wire.endTransmission();
Wire.requestFrom(device,1); // now get the byte of data...
result = Wire.read();
return result; // and return it as a result of the function readData
}
Although the sketch in itself was simple, you now have the functions to read and write byte data to EEPROMS. Now it is up to your imagination to take use of the extra memory.
Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.
RT @MakerFaireMel: Ammon, James and Paul have been working on another event in Nov 2013. You can check out what we've been up to here: htt… 9 hours ago