Thursday, December 23, 2010

NJC's LaunchScope (A LaunchPad Oscilloscope)

After getting caught up on I am ready to get back to work! For all of you who have been patiently waiting for the final post in the oscilloscope project, it is here. I introduce to you, the LaunchScope. In this post I will present the code for implementing an oscilloscope (a slow oscilloscope) using only the LaunchPad and the MSP430G2231 that comes with it, in addition to providing the source code for the computer application I wrote to go along with the hardware.


I originally built this project a few months ago for the MSP430F5528 for testing my own project which involved data acquisition of biomedical related signals. The 5528 has a built in USB and as such I could use a reasonably high sample rate; when using the LaunchPad though, one is seriously limited by the speeds at which you can transmit data out. As I've mentioned in one of my other posts, it's possible to use the SPI as a quasi-hardware UART for high speed transmission; this would allow you to use a much higher sample rate.

There is very little code on the microcomputer that needs to be added from the last post, all that is missing is the code for continuous reading of the analog channel. In addition to the functions needed for starting and stopping the ADC, the start and stop codes sent to the chip need to be handled.

The last post implemented a speed test which shows you how fast your setup is capable of transmitting data; this value will be used to determine the sample rate of the microcomputer. It is important to not sample at a rate higher than you can process the data because in addition to timing troubles you will end up missing and dropping samples, which could be detrimental depending on the application. Additionally, the code presented in last post can measure a single channel’s voltage using the MSP430F2231; the channels measured were one external channel (A3), the internal temperature sensor, and the internal VCC measure.

I was asked a question in a comment on my previous post, where the analog pin A3 is and I would like to explain that a little bit here before we get started. Almost every pin on all of the MSP430s have multiple functions, these functions can be found in the chips datasheet (not the family guide). For the MSP430F2231 which is the chip used with this series of posts, this can be found on page 6 in the datasheet. Here we can see that in the 14 pin version of the chip pin 5 is not only P1.3, but also ADC10CLK, A3, VREF--, and VEREF. The explanations of each purpose is also included in this table. The datasheet is one of the most useful resources you will have; everyone should have the datasheet and family guide easily accessible during development.

The Computer Application

Find the .zip file of my project here.

Find just the install for the application here. (Note: No promises that this will work for you)

I have decided to post the source code for my computer application since I know how useful it might be to many of you. The reason I was hesitant to post the code is because I do not document and comment my C# code as well as I do my MSP430 code. For anyone who downloads and uses my C# application, please do not expect well documented and commented code, though I will do my best to answer your questions on the Also, as with all of my code I ask anyone who uses it to mention in the code and anywhere it may be published or posted to site my blog and give me credit for whatever I have written. This includes the software UART and any other functions which I have specifically written.

The computer application looks the same as the one I posted previously, except now the streaming buttons are not greyed out. The main difference is the oscilloscope code which will display a waveform in real time on the screen quite beautifully. Back when I needed this code for my own project I was writing my own library for displaying the waveform but was never happy with the results. I found this DAQ32datalogger project online which utilized Berstein's library for real time waveform displays. The first link was for a research project  testing the use of multiple accelerometers for replacing gyroscopes in real world applications. I was very impressed with his code and really recommend that you all take a look at his YouTube video which he links to on his site. The project utilized 32 accelerometer channels and displays all of them in real time on his PC. I emailed the author a few months ago and he is happy that his code is being utilized by others. If you use this code, PLEASE give credit where credit is due, his and Berstein's code is amazingly useful and helpful.

It is important to note that this library has much more potential and can do so much more than I use it for here. Eventually I plan on using this code for monitoring multiple bio-potential signals in real time. The image below is taken from Berstein’s website.

Note: I will not be discussing how this code works because this is a LaunchPad blog and not a C# blog. I am posting this code for those who already know C# or would like to change bits of the source code for their own projects. Keep in mind, this software is far from a polished program, I am using this for my own personal projects and wanted to share it with all of you. 

The Code

Also posted here on github.

Setting up the ADC and the Sample Rate

What will look the most unfamiliar to someone who has followed my blog up till this point is the streaming ADC function Start_Stream(unsigned int chan), here I set all the necessary values for the ADC stream. There should be only two lines which are unfamiliar to you which I used in this function.

ADC10CTL1 = ADC10SSEL_3 + chan + ADC10DIV_7 + CONSEQ_2;

The first line will, turn on the ADC, set the sample and hold time to 64 clock cycles (which can be thought of as yet another divider for the ADC sample rate), sets the device to do multiple samples and conversions, and finally enables the interrupt. The second line selects which clock to use (the SMCLK), sets the channel to use (which is the ‘chan’ input from the function), sets the clock divider to SMCLK/8, and finally tells the ADC to sample a single channel consecutively.

As I already mentioned, it is important to make sure the sampling rate is low enough for the application UART to send every sample to the PC. Using my code the speed test on my application showed 6.21 kbps. Due to the fact that we are using an ADC that has a 10 bit vertical resolutions, we will need to send every sample as two bytes thus sending 16 bits of data per sample. So to calculate our max sample rate (which we should be a bit under just in case), we divide our data rate by our bits needing to be sent per sample, 6.21kbps / 16 bits = 397.44 Hz.

EDIT (01-26-2012): I would like to correct a mistake that was found in the following paragraph by one of my readers. The  problem is with the calculated sample rate. Instead of the equation being SMCLK/8/64/13, it should be SMCLK/8/(64+13). This is because the sample and hold time and the conversion time add together, determining the number of clock samples needed per conversion. This gives us a sample rate of approximately 1.6kHz, a value significantly greater than it should be. That being said, the code will still function, the reasons behind this is a bit complicated and won't be discussed here. Just know that some samples are being dropped and the actual transmission rate is closer to ~450 samples per second. Expect to see a new post in the future with updated code. Sorry for the error!

Our sample rate as set it in the Start_Stream() function is SMCLK/8/64/13. The 8 comes from the clock divider, the 64 comes from the sample and hold time, and the 13 comes from the number of clock cycles it takes to do an actual conversion. This value can be found in the datasheet on page 32 under “10-bit ADC, timing parameters -- MSP430G2x31 only”. SMCLK = 1000kHz (1MHz), so our sample rate is 1000/8/64/13 = 0.150kHz or 150Hz. This is much less than half of our maximum, so we are well within the limit of safety.

ADC10CTL0 &= ~ENC;
ADC10CTL0 &= ~ADC10SC;
ADC10CTL0 &= ~ADC10ON;

These three lines of code are what make up the Stop_Stream() function. It is important to note that ENC needs to be cleared first before any of the other values in ADC10CTL0 can be written. Once that is cleared, the conversion is stopped and the ADC is turned off to save power.

Why Have Commands?

Why not just make the chip constantly send out the data stream of the analog channel conversion results? All we want is an oscilloscope, so why need all of these weird command things? First, if you wanted to do that you would not use an MSP430 but rather you would use a nice and cheap ADC that has a UART out. We also have a built in temperature sensor, and internal VCC measurements which allow us to know almost exactly what voltage is being read by the ADC. Second, it is much easier to interface with a computer application when the program has control over the data flow. Without these commands the application would have a hard time making sure all the data is being received correctly and would not be able to read any of these other nice values the MSP430 can provide.

Improving the Design 

The biggest improvement which I’m sure everyone would like to see is an increase in sampling speed. I will not be doing a post on a faster scope design because it should be very easy to scale this code to faster speeds. If you decide to use an FTDI chip instead of the application UART you can recalculate the maximum speed the software UART can transmit at, then reconfigure the ADC to sample at a certain speed using the method I used in this post. If you would like to use an MSP430F5528 to increase speed, send me an email and I can send you the original source code this project was build from.

Final Thoughts

I hope you all enjoyed this series and find the LaunchScope useful. I have been and will be very busy in the upcoming months since I am leading a “Senior Design” project for my university. The project does utilize multiple MSP430s and I will be doing my best to post more guides on topics which come up during the course of my work.

Before I finish I have an unrelated question for any of my readers which might have experience with Actel FPGAs. I am thinking of using an Actel FPGA for a project and was wondering if anyone has had any experience with Actel FPGAs. I have only used Xilinx and Altera but saw that Actel has very cheap and low powered FPGAs. Any opinion on Actel chips would be greatly appreciated. Email me,

Again, sorry for the delay, but I hope the wait was worth it. When I get around to it, the next post will discuss communication between two (maybe three) LaunchPads using I2C. If you have any simple questions about the post feel free to comment and I will do my best to answer any questions. If you have a complex question or would like some help with your code check out, they have a great forum which I check when I can.

As always, comment away! Let me know what you think of the project. If you used the LaunchScope or the code from this series for anything cool, post a comment about it. Stay tuned, I will be writing more posts.