07 September 2012

Tutorial 19a: SPI Theory

When we looked at the UART, we imagined a setup where two people agreed that at a specific time and at specific intervals, one would send a message to the other one letter at a time. Doing so required both sender and receiver to have an accurate clock to prevent frame errors, or mis-reading the message by skipping or duplicating one of the letters. Using a similar analogy, we can think of the Serial Peripheral Interface as having the two people write a message to each other on a piece of paper, then exchange messages by handing them to each other at the same time. As a serial communication, it's still done letter by letter, though there are variations of SPI that allow for exchanging multiple bits simultaneously. We'll focus on single-bit-at-a-time transmission, since that is the only mode available in the USI and USCI peripherals.
There are 3 basic steps in SPI:
(1) Write bit 7 to the output.
(2) Shift register to the left.
(3) Write the other device's output to bit 0.

Let's say our two devices have 8-bit registers. At a given signal, each writes their most significant bit (bit 7) to their output. At the next signal, each shifts their register up one place, and sets the least significant bit (bit 0) to whatever value is on the other device's output. After 8 cycles, the 8 bit value that was in device A's register is now in device B, while the value that was in device B is now in A. Both read the new value (and probably do something with it), and then perhaps write a new message in their registers for the next exchange. This exchange of information makes it possible to very quickly send data from one device to another.

The key to getting the process to work properly is to have all the shifting occur at the same time--the two devices need to be synchronized. This timing is accomplished by sharing a clock between the two devices; one of the two generates its own clock and includes it as an output for the other device's use. By convention, we refer to the device that generates the clock signal as the "master", and any devices listening in as "slaves". Such nomenclature may seem a little non-politically correct, but at the same time it's a reasonable description of how SPI works. We cannot necessarily deem one device as a "sender" and the other as a "receiver", for example, because both devices are simultaneously sending and receiving. Referring to both as "transceivers" doesn't really work either, because the sending and receiving are in fact the same process. Rather, the devices are "exchangers". One device serves as a control of the exchange, while the other depends on the controller in order to make the exchange. Note that, contrary to the connotation of the nomenclature, the master does not necessarily have to be the device that issues commands, nor does a slave have to only receive instructions. In fact, one could envision a system where the clock is external to both master and slave, and neither device operates entirely independently of the other, but rather a third device mediates the exchange between the two by providing the clock synchronization. Generally, however, it's simpler to let one of the exchanging devices mediate, and that device become designated as the master.

You can imagine that the technique used for the SPI protocol lends itself to many variations. (Eg. do we pass the data starting from most to least significant bit or vice-versa? How many bits do we pass at a time?) Do we start the exchange on a rising edge or a falling edge of the clock? (The edge choice also leads to whether a quiet line idles high or low, of course.) To make it more confusing, for whatever reason various manufacturers have created different naming schemes for the lines between the two devices. In particular for our purposes, TI has the three lines between the devices named as Serial Data In (SDI), Serial Data Out (SDO), and Serial Clock (SCLK). Like for UART, the data in line of one device is connected to the data out line of the other: SDI_A-SDO_B and SDO_A-SDI_B for devices A and B. Note that because we must include the clock, SPI requires three lines (plus one more for ground) between the devices as opposed to two lines (plus ground) in the basic UART. (There are some situations where if one of the devices doesn't need to communicate anything to the other ever you can get away with just two lines, but in general you need three.)

The other common nomenclature for SPI connections was given by Motorola: each device has a Master Out-Slave In (MOSI), and a Master In-Slave Out (MISO) rather than SDI and SDO.  In this nomenclature, you connect like pins rather than opposite pins: MOSI_A-MOSI_B and MISO_A-MISO_B. Other devices use a similar nomenclature to TI, dropping the "D" in the abbreviations: SI and SO, connecting as in the TI scheme. You may also encounter SPSCK and SCK for the clock, and devices enabled with a chip select can be labeled as CS, SS (slave select), or sometimes CE (chip enable). Be certain to verify whether tying this pin high or low enables the device. In this blog, I'll stick with TI's nomenclature, and use SDI, SDO, SCLK, and CE.

SPI can also extend to communication with multiple devices by including a "Chip Select" pin-- a slave will only listen when this pin is high or low, depending on the implementation. Thus other peripherals can be attached, and instructions/data can be exchanged only between the master and the pertinent slave. The disadvantage to this means of multiple-party communication is that it requires one more line for each device that needs to communicate independently.

So how do we know what conventions we should use in our designs? Unfortunately, you need to get familiar with reading data sheets, and my experience has been it takes some practice to read data sheets describing exact communication protocols. In the next tutorial, we'll look at how to implement SPI using the USI peripheral, and delve more into the details of how to determine the particular protocol being used and configure the MSP430 properly.

05 September 2012

Tutorial 19: Going Beyond the UART

We've already looked at asynchronous serial communication, and seen how useful it can be for a scientific instrument as a data logging system. Serial communication has a lot more power, however, especially when we begin looking at the "control" aspect of the microcontroller.

There are a lot of sensors and devices designed to work with microcontrollers that use synchronous communication protocols. The primary difference for these modes of communication are the inclusion of a single clock between the sender and receiver, rather than having to rely on precise and accurate clocks. Having to share a clock limits the separation to a fairly close proximity, but it does simplify the communication process a great deal.

The number of protocols designed for serial communication is quite large, but a few have stood out as standard for many devices. The MSP430 has many devices that, for example, have built-in hardware for communication using the Serial Peripheral Interface (SPI) and the Inter-integrated Circuit Bus (I2C or I2C -- pronounced either as eye-two-see or eye-squared-see, your preference).

Most MSP430 devices have one of two forms of serial communication hardware. The less expensive devices have the Universal Serial Interface (USI), which can do SPI and I2C. Larger devices come with the Universal Serial Communication Interface (USCI), in at least one of two flavors: USCI_A handles asynchronous communication (UART), and USCI_B handles synchronous communication (SPI/I2C). If for any reason you must use a device without either of these modules, you can resort to bit-banging, but aside from the previous tutorial on UART we won't cover that any time soon; most modules have at least USI, and it's far more economical to use the built in hardware.

To work with this tutorial, you'll need at least one of the following:

  • Two devices that communicate via SPI and I2C, such as a serial EEPROM produced by Microchip
  • USB-SPI/I2C interfaces, such as the FTDI devices. (Their chips include one that is great for UART at speeds other than 9600 bps too!)
  • A second MSP430 device.
Owners of a LaunchPad already have two devices that include USI, but keep in mind you'll need a few other components to power the chip off of the LaunchPad. I'll do tutorials that will demonstrate all three methods, but for the beginning I will be working with Microchip serial EEPROM chips. (I will use the 25AA080C for SPI and the 24AA08 for I2C, but any size will do.)

Of the two synchronous protocols used by the MSP430, I2C will likely be the one used most frequently (at least by me), for the reason that the protocol is designed to work with multiple devices on a single communication line. Many sensors and external peripherals are already available that use I2C. However, SPI is a little simpler to understand, and we'll start with that. Once I've gone over the USI peripheral, I'll begin working on a new experiment that will make use of a pressure sensor, and design an MSP430-driven 4-digit LED display. Both will communicate over I2C as a digital pressure gauge. The project will require designing and fabricating a couple of printed circuit boards, so we'll go over a little of that process as well.

New Tutorials are Coming!

Hi everyone; it's great to be back. It's been a crazy few months, what with finishing my Ph.D. and all the other changes in my life. But, it's high time I start learning some new things and building some cool toys. I have a lot in mind for the coming weeks, and hopefully you'll find some of it helpful as well.

These tutorials will be a little different; call them "intermediate-level tutorials" if you will. Mostly, these tutorials will require the use of more parts and tools outside of the LaunchPad, much like the LCM tutorial from before. I'll try to keep the tools I use within a reasonable budget for beginners and amateurs, but some of the parts will probably cost a little more. (I just purchased a sensor for the next project that was $35.) If you have any suggestions or requests for topics, let me know!

Thanks, all of you who read this blog; I have a lot of fun writing this, and I'm glad so many of you have expressed your appreciation for its contribution to the MSP430 community. Let's see what more we can learn!

18 August 2012

Experiment: Battery Profiling Update

I want to get the final results of the Battery Profiling experiment put up for everyone to see, as it came up with an interesting result.

150 Ω Circuit

Average of two runs using matched resistors.
The immediate conclusion is that Duracell does in fact last longer than Energizer. But stopping there doesn't really tell the whole story; yes, the Duracells did maintain a voltage for about 10 hours more time, but look more carefully at the initial period-- the Energizers actually perform better for the first half.  In fact, the Energizers stayed consistently at a higher voltage until around 120 hours, where both batteries were found to be at 1.05 V.  At that point the Energizer drops off quickly, while the Duracell holds on for a little longer. Big deal you say? Well, that depends on how you're using the batteries.

Consider a flashlight as a case example. The higher the voltage, the brighter the light. So the Energizer powered flashlight will stay brighter than the Duracell powered flashlight for a significantly longer time. The Duracell powered light may last longer overall, but how useful is that last 10 hours, really?

This behavior is consistent even at higher power draws:

33 Ω Circuit

Average of two runs using matched resistors.
The same result is found for the higher current case, with the cross again occurring at 1.05 V and the Duracell lasting about 10 hours longer.  This result suggests that the Energizer design optimizes maintaining the higher voltage at the expense of overall lifetime.  Integrating the actual current of each circuit over time gives an average energy capacity of 1380 mAh for Duracell and 1340 mAh for Energizer-- roughly the same!  If the Energizer maintains a higher current for a longer period of time, it would make sense for it to finish draining first as it uses more of its capacity during that initial time.

What we conclude from this is that the brand you choose may depend just on your needs-- specifically on the minimum voltage required in your circuit. If you need the voltage to stay above 1 V to power your application, Energizer will give you that power for a longer time.  If you only need the voltage to be above a threshold below 1 V, go with the Duracell.

What Next?

One reason I'm including these little experiments is as a catalyst for others to start investigating. This simple idea could lead, for example, to an excellent science fair project for a young student. Or perhaps someone is curious enough to justify buying lots of batteries to run through their paces. In any case, here are a few ideas of other questions that could be examined.

  • This experiment used a constant resistance circuit-- how do the lifetimes compare in a constant current application?
  • Is the behavior seen here consistent for other sizes of battery? (Be aware that discharging a D-cell through even 33 Ω may take a while...)
  • Do batteries discharge evenly? What happens if two otherwise identical batteries are placed in series? Measure the voltage at both batteries-- ideally the center voltage should be half of the overall voltage at all times. Is it? Is there any difference if you mix brands together?
  • My measurement of the energy capacity of the two brands shows them as being similar, but the Energizer capacity was lower than the Duracell in both cases. Two measurements is not enough for the difference to be statistically significant-- measuring a larger number of batteries could tell you if Duracell does indeed have just a little more capacity. How many batteries would you need to measure to show that?
  • In this experiment, the circuit was constantly on. What happens if the current is only on intermittently? How much does a battery recover after being used for a while?
  • Both runs were done at room temperature. How much of an affect does temperature have on the battery? Be aware that the temperature difference will change the resistance as well, so that should be accounted in the results.
  • (For those with a lot of time to spare:) People claim that batteries last longer in storage if they are chilled. How quickly does a battery sitting on a shelf decay? How about a battery being stored in a cool environment?
I'm sure there are plenty of others; feel free to add any ideas to the comments!

Disclaimer: Electricity can be dangerous, and you should be aware of the hazards of working with even common alkaline batteries. For example, mixing a drained (or even partially drained) battery with a fresh battery can result in leakage, or possibly fire. The materials inside an alkaline battery are not something to mess with if you're not sure of what you're doing-- so be careful, and if you see anything that looks wrong, stop. If you're young, get help from a parent or teacher. Dispose of waste properly and responsibly.

Any experiments operated using this blog as a basis are done at your own risk and responsibility; I am not liable for any damages that may be caused by duplicating this work or running any experiment derived from this work.  You and you alone are accountable for any consequences of your actions, so if you are unsure about anything, find someone who can help. 

20 June 2012

Experiment: Battery Profiling

Background

Most of us probably purchase batteries with little regard to the brand.  We may purchase whatever is cheapest at the time; we may get a particular brand out of loyalty; we may have just had better luck with one particular brand.  Is there actually any difference between them, though?

I had an experience that  indicates there is, though it may not manifest itself in ways that are apparent to the general consumer.  On a sounding rocket experiment, we had trouble with a particular power supply.  Some investigation revealed that the brand of battery in the supply had problems if it was squeezed in a particular way, shorting out the battery internally.  After taking a few batteries apart, we found that they were, in fact, constructed with slight differences.  How those differences affect performance can be examined using a technique that is ideally suited to a microcontroller.

Here's the idea: run a battery through a particular configuration and monitor its voltage throughout.  In this experiment, I'll keep it simple, but you could easily come up with all kinds of scenarios and configurations in which to compare different batteries.  This demonstration uses only the two major brands, in the AAA form factor, and compares the voltage profile over the lifetime of the batteries at equal current draws.  This is done by having two matched resistors (as measured by a multimeter) draining each battery.  If there is any difference between the two brands, it will be seen by a different discharge rate over time.  Four samples are run, using two resistance values.  Each run uses one of each brand, to eliminate temperature differences.  Two samples are taken at each resistance, swapping the circuits for the two brands in each.  The batteries purchased were selected to have the same expiration date marked on the packages.

Searching online, we find that many people have done a similar experiment, though typically done in ways that are more subjective, such as putting different brands in identical flashlights, see which one gets dim first. Using a microcontroller, we can measure the actual voltage at the battery at specified intervals to get a picture of how the energy is drained from the battery over time.

MSP430 Peripherals Used

  • TimerA with interrupts: Continuous mode, interrupts at CCR0, CCR1, and TAR Rollover
  • ADC10 with interrupts: Sequence Mode, Single Conversion
  • Software UART (Full-Duplex)

Equipment Needed

  • LaunchPad with 32 kHz crystal
  • MSP430G2231 (or any device with ADC10)
  • Computer that can be left on for a few days
  • Multimeter
  • Breadboard
  • 2 single AAA battery holders
  • 2 150 Ω, 1/4 W Resistors
  • 2 33 Ω, 1/4 W Resistors
  • DPST Toggle Switch, rated at least 0.5 A @ 6 V
  • Various Wires

Experiment Design

Schematic for Battery Profiler
The circuit is quite simple: R3, R4, and the LED on P1.6 are built into the LaunchPad.  Q1 is soldered to the LaunchPad and used solely to calibrate the DCO; if this is already done, Q1 is optional.  Remove the jumpers for the Rx, Tx, and LED on P1.0 from the LaunchPad, and jumper Rx to P1.4, Tx to P1.5.

R1 and R2 are matched to be equal resistance, measured with a multimeter.  S1 is a DPST or DPDT toggle switch.  Note that you must use P1.1 and P1.0 to use Sequence Mode for the ADC10 module.

The code for the MSP430G2231 is found in battery_profiler.c.  Most of this code should be straightforward for anyone who has followed through Tutorial 18.  There are a few things to point out, though:

  • Each sample is an average of four measurements.  Since floating point math (particularly division) is a bit expensive in the MSP430, you can use a trick: note that shifting right by one bit is dividing by two. If you are averaging a number of samples equal to a power of 2, you can add the samples together and then shift right by the appropriate number of bits to get division.  Rounding can be done by adding 1 to the highest bit not being included-- in this example, using 4 samples, the second to last bit is the highest not included, so if V holds the sum of  4 measurements, ((V + BIT1) >> 2) gives the rounded average.  Since ADC10 uses only 10 of the 16 bits available in the register, you can average 2, 4, 8, 16, 32, or 64 samples with this technique.  If necessary, floating point numbers and division can be used instead, but it does require more resources of your MSP430 device; plan accordingly.
  • Another issue is transmitting the data; you can transmit the raw bytes back easily, but the data is more easily analyzed afterward if the values are sent in ASCII text.  The MSP430 can use the C printf function in the stdio.h library, but this library is large and increases the size of your code significantly.  This code makes use of a slick scheme to reduce the code size-- the tx_uint() function will transmit a 5 character string corresponding to the zero-padded value of whatever value is passed to it by making use of integer division and modulus operations.  Transmitting the floating point value of the measured voltage is a bit trickier, so the ADC10 conversion is transmitted instead.  These values are converted to a voltage during analysis, using 2.5 V = 1024.
  • The code makes use of the Sequence Mode for the ADC10.  This mode samples each channel starting at that specified by INCH_x in ADC10CTL1, and stepping through to channel A0.  In this example, A1 is measured first, then A0.  This mode operates by waiting for the ENC and SC bits to be set, starting the conversions.  When the first conversion is done, an interrupt is flagged.  In this code, the interrupt resets the flag bit in UART_FG, signaling the code to continue to the next step.  The next channel is sampled when ENC sees another rising edge.  This tripped me up for a while; waiting for a rising edge on ENC allows you to control the timing between samples in the sequence arbitrarily.  If you would rather the ADC10 automatically start the next conversion immediately, you must set the MSC bit in ADC10CTL0 as well when initializing the ADC.  Once the whole sequence is done, ADC10 will wait to have ENC and SC set again to start the next sequence.  This code is timed to do one sequence every 10 seconds.
  • Finally, this code uses all three Timer_A interrupts possible on this device: CCR0, CCR1, and TAR overflow.  This example should help anyone trying to understand the various interrupts that can happen for the Timer_A module.

Results

This experiment takes a good deal of time to finish, and I've decided to post the experiment before getting the actual results.  Here is an example of what we'll be looking at to start-- this is a trial run using two random AAA batteries I had on hand, done just to be certain everything behaved as expected.  As you can see, at 150 Ω it takes days to drain the batteries completely in this setup.  After a few days, I decided to call it a good proof-of-concept, and the experiment is ready to run.  I'll let it run for the next little while, and when I have official results I'll post them here, along with a detailed write-up of what is happening.

Don't worry-- I have two LaunchPads, so I'll be able to post a couple more things while waiting for the experiment to run.

Let me know if you like this post design-- is there any more information that you think would be helpful to have here?

29 May 2012

AdSense

If you haven't already noticed, I've decided to try enabling AdSense on the blog.  I figure I'll give it a shot; if it's not too intrusive I'll leave it there.  Send me feedback and let me know what you think-- there may be better ways to fund my hobby.

25 May 2012

Tutorial 18: Finishing the UART Transceiver

This last tutorial in this series will be fairly short, because there's very little to be done! If we combine tutorial 16f and tutorial 17, we're nearly done building a full-duplex UART transceiver.  There are a few little details that need to be explained in order to get it to work properly, however.

  • A bit counter will be needed for both transmitting and receiving, if you're to be able to do them simultaneously.  This takes another 8 bytes of memory, of course.
  • While not necessary for the UART aspect, this code uses interrupts on two pins of P1. Any output on GPIO, even if interrupts are disabled for the pin, will set the corresponding bit of P1IFG on a rising or falling edge, depending on the setting of the corresponding bit in P1IES. Because the two LEDs are being used, any time the LED is turned on we have a rising edge on that GPIO, which sets the bit in P1IFG. The method used in this code to deal with P1 interrupts fails in those cases, since P1IFG would not be exactly P1RX or BTN1.  To fix this, a mask is introduced so the switch statement in the P1 ISR only considers the bits for P1RX and BTN1, ignoring any others set bits of P1IFG.  There is one disadvantage to this particular scheme: if the UART receives a start bit at the same time as a button press occurs, one or both will be ignored (depending on the order and timing of the two events).
  • A new function is introduced to encapsulate sending a string of characters over UART.  This function makes use of a pointer, allowing us to write new values to the variable message. Be aware that other values in RAM could be overwritten if you're not careful.  Also, the function assumes a message length of exactly 16 characters, and will print garbage (or remnants of the last message) if you write a shorter message.  A longer message will be truncated.
  • Because the DCO is executing commands at a faster rate than the transmission, a short delay of bit_time is added to tx_byte().  This delay lets the transmission start before returning control to the main() function. Without it, the code could call tx_byte() again before transmitting actually starts, changing the value of TXBuffer before it has a chance to get sent.  
The transceiver code can be found in uartTXCVRG2231.c.  I've added a few features to demonstrate the full-duplex capability of the transceiver.  The commands 'r', 'g', and 'z' are retained from the receiver tutorial. To this has been added 'c', which prints a continuous message until another command (eg. 'z' to sleep) is sent.  Note that the command can be sent in the midst of a byte transmission and still work, since the receiver is operating on a separate timer/interrupt configuration.  I verified this to be the case using my logic analyzer, and found that a command was correctly received even while starting in the middle of a transmission.

In addition to the 'c' command, another command is set from a button press (using a non-keyboard ASCII character 0xAF), and can be done at any time, showing that the code can also work with physical interface interrupts as well as the serial transmission of commands.  The button will also stop the continual printing of a 'c' command as well, as it also resets the command variable to 'z'.

Remember to use 9600 baud transmission and to configure CCS to build and link to the header file with the UART calibration, as well as not erase the information memory segment containing the UART DCO calibration.

And with that, we've reached the conclusion of what I'll term as the "basic" tutorials for the MSP430.  A big "Thank you!" to all of you; I've received numerous notes of encouragement from many of my readers, and it's been very helpful.  This project and blog have been a great deal of fun, and wer a key addition to the training I received as a Ph.D. student. This isn't the end of the blog, of course.  I'll be back with more advanced tutorials, and, more importantly, examples of scientific measurements and experiments done with the MSP430.  In fact, my next post will start describing a project I've had in mind for a while.  In the mean time, I will start recompiling these first 18 tutorials into a single volume.  I have as-yet to decide just how it would be distributed, and exactly what form it would take. In any case, I hope all of you stay with me and enjoy exploring the MSP430.