Thursday, December 23, 2010

NJC's LaunchScope (A LaunchPad Oscilloscope)

After getting caught up on 43oh.com 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.

Background

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 43oh.com/forum. 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.

ADC10CTL0 = ADC10ON + ADC10SHT_3 + MSC+ ADC10IE;
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, webmaster@msp430launchpad.com.

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 43oh.com/forum, 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.

34 comments:

  1. The Berstein's library was new to me. I've to take a look at it. Thanks for the plug.

    Good luck on your project!

    ReplyDelete
  2. I agree about the dataflow, where the computer issues commands. We have had a similar problem at work. What we ended up doing is keep the command set, but create a special "stream" command that would stream data in and would interrupt on a receive command - normal commands can then follow. Is this possible here.?

    ReplyDelete
  3. bluehash: Yes, that is how this works. When the LaunchPad is streaming data you can stop the stream by clicking the stop button on the GUI, then you can send any command. Your question made me realize that I should have greyed out the other buttons in the GUI while the device is streaming. Oh well, maybe in another release.

    ReplyDelete
  4. Nice work! Very similarly DC could be used for data loging some analog signal, like position sensor made of potentiometer. I'd we curious to see some articles on FPGA - this some field I have hear a lot about but have't read any easy to follow tutorial style guides.

    ReplyDelete
  5. I am having trouble getting the code to compile in VS Express. I am completely unfamiliar with C#, so it is probably me, but which IDE did you write the code in?

    ReplyDelete
  6. I'm getting an exception from the C# application, the line in question is:

    this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

    If I comment it down, the next exception happens at: Application.Run(new Form1());

    Any ideas? - Why use C#? - You don't even have error handling, the given executables just crash miserably...

    ReplyDelete
  7. MIL & Anonymous: I provided the code only as a favor to my usual readers. This is not a C# blog, and I do not claim to write professional C# code. What I did works for me. If you look at the previous post where I first provided the executables, I lay no claim to them even working. I'm sorry that you two are both having trouble though with the code.

    To answer your question MIL, I used Visual Studio 2010 Professional.

    ReplyDelete
  8. @NJC: I have been somewhat successful with your code. I have used a tone generator program, that I am using on a trial basis, as an input signal. I am not happy with the scope trace that I see. It doesn't seem to matter whether I used a sine, square or triangular waveform, it never quite looks like any of those but at least I get something.
    All things considered, you have provided us with an interesting project that doesn't require a lot of resources.
    Thanks!

    ReplyDelete
  9. Glad you got the code working to some extent! My guess for the reason you are not seeing the correct waveform on the scope, is due to the frequency of the signal you are sending in. If your input signal is over 50Hz you will not see anything resembling the input. This is due to aliasing. You can read more about this on wikipedia if you are curious. http://en.wikipedia.org/wiki/Nyquist_frequency
    If you are feeding in a sine wave at 30Hz or lower you should be able to see quite a good waveform.

    Note: The sample frequency can be increased if you use a faster method to send data to the computer.

    ReplyDelete
  10. This code has provided me with great insight into using the launchpad to transmit and receive data via the PC's USB (ie COM) port. I was able to get your code working in a couple of hours. Looks like I need to order a few more launchpads. Thank you!

    ReplyDelete
  11. I was having trouble getting your application to run on my laptop as well. I ended up getting it to compile by removing the icon(from Form1.resx) and about box image(from AboutBox.resx) resources, and it compiled with no errors, and runs just fine.

    I have no idea why it didn't like those resources (the image and icon were both there as far as I could see) but that's all I had to do to get it to run.

    ReplyDelete
  12. A nice option would be to have an 8 bit mode. You would loose some resolution but you could double the sampling rate.

    ReplyDelete
  13. whats the pinout?

    ReplyDelete
  14. I was just wondering if the launchscope you made would be able to measure negative voltages. I mean you are using either Vcc/Vss or Vref/Vss pairs. Now I cannot give a negative Vref so I see no way that this would enable me to measure negative voltages. Can you help me with this confusion?

    ReplyDelete
  15. @Anonymous - The pinout is the same as the LaunchPad, I have not added any extra hardware to make this work.

    @rick2047 - The quick answer is no, it cannot. The detailed answer is, it's complicated.

    Voltage is relative. Though you cannot measure voltages smaller than VSS, you can trick any microcomputer into measuring "negative" voltages.

    For example, let's say you want to measure a sensor which has a negative voltage output. You can create a "virtual ground" for this sensor at VCC/2 using an op-amp and voltage divider. The lower voltage rail will be VSS and the upper rail will be VCC. The MSP430 does not ever see a negative voltage, but it can read voltages which the sensor considers "negative".

    Sorry if that answer is not very concise since I think that this concept deserves its own blog post.

    Hope that helps!

    ReplyDelete
  16. Excellent reading, and great project!
    Need to try this soon. But so many projects, so little time... ;)

    Cheers!
    MarkoeZ

    ReplyDelete
  17. Great job, greetings from Colombia!

    Thank you very much.

    ReplyDelete
  18. Excellent project!
    A question:

    The conversion of the measure of the voltage is done in this way:

    vccBox.Value = (decimal) (2*value * 2.5/ADCBitSize);
    vMeasureBox.Value = (decimal) (value * ((double) vccBox.Value)/ADCBitSize);

    Could it be better?

    vMeasureBox.Value = (decimal)(2.5*value/ref);

    ReplyDelete
  19. Great project, it's been really helpful for me. But I was trying to make some changes at the both programs to make them work for two channels and I am having some problems with that. Any tips?

    ReplyDelete
    Replies
    1. The way I would go about adding two channels would be to add another byte to each samples transmission. This byte can represent a channel number which then can be filtered out by the C# software. Also, if you are using a 10-bit or 12-bit ADC, the remaining bits in the upper byte can be used to specify which channel the data came from. Best of luck.

      Delete
  20. Great project! I would like to know if is possible to make some modifications to your code to run it under MSP430F2132 using UART instead of bit banging and publish it at my blog (www.microembebidos.wordpress.com) for tutorial purposes (always mention your blog as the original source). Thanks!

    ReplyDelete
    Replies
    1. Go for it! I will enjoy reading your post on it. Thank you for the comment.

      Delete
  21. y cant this project be done using arduino code?...
    using C# it looks hard to understand...........

    ReplyDelete
    Replies
    1. First, let me start off by saying that almost any MSP430 project could be done using the Arduino (and vica versa). The C# code in this project is actually not meant to run on a microcontroller at all, it runs on a Windows PC. The C code provided here is what runs on the MSP430.

      For most hobby projects, the reason a person chooses one microcontroller over another is purely based on their preferences and what they are most comfortable with. Each microcontroller has it's own advantages and disadvantages. The MSP430 is VERY low power, and the Arduino is VERY easy to program.

      I hope that answered your question.

      Delete
    2. Thats exact my opinion. I use the MSP 430 because it is a real low power microcontroller. And it i s not easy for me as a beginner to understand how it works. With Arduino i get things working in a few minutes where i need a long time to do the same on an MSP. But i really understand what happens there when i am ready and dont only use libs that are like using magic. For understanding how the things work i love the MSP.

      Delete
  22. Hi, thank you very much for your work
    I wonder if the problem of sampling rate will be limited using the
    LM4f120 stellaris launchpad. it has 80MHz 32-bit ARM Cortex-M4 CPU and the controller has ADC sampling rate of 1000 kSPS
    http://www.ti.com/ww/en/launchpad/stellaris_head.html
    it cost 12$

    have a good day, Francesco

    ReplyDelete
    Replies
    1. Thank you for your comment. I agree, it would be VERY cool to see this code ported to the Stellaris LaunchPad. While it is on my list of things to do, it is too far down for me to get to it anytime soon. In the coming months, I will most likely release a new version of the PC program (in Python) to interface both with my new Bluetooth Low Energy breakout board.

      Delete
    2. Thank you for your reply...
      I will follow the development of your projects with interest..

      Delete
    3. Nice project. Even I am interested on porting to Stellaris LaunchPad as it has fast ADC and higher resolution than MSP430. I ported MSP430 code to Stellaris LaunchPad, but still few TODOs are pending. Details are here https://github.com/harischandraprasad/Stellaris-LaunchPad-Oscilloscope

      Delete
  23. Hi . I modified your code and I made it to get bursts of 220 integers continously with the fastest rates (no divider) and without software intervention for each sample (using the DTC that comes with the msp430g2553) and I can see 4Khz sinusoidal signals , beyond that it doesn't looks well . but I think it is a great option and more realistic for oscilloscope-like jobs .
    I am making a user on 43oh forum so I'll post it there

    ReplyDelete
    Replies
    1. Hi! Can you share this project?

      Delete
    2. Has anyone found the code for this scope converted to g2553 on 43oh-forum. Have just searched that forum but could not find it. rgds

      Delete
  24. to which input must be connected an external signal?

    ReplyDelete
    Replies
    1. INCH_3, which corresponds to A3. This is the same pin as P1.3 on the MSP430G2231.

      Delete