Saturday, December 11, 2010

Interfacing TI Launchpad to Digital Caliper

Using msp430 Launchpad to Connect Digital Caliper to RS232 serial port

Caliper and Launchpad
MSP430 Launchpad  from TI is new, very affordable (4.35$), value line development platform. It uses MSP430G2231 - msp430 series mcu and includes everything you'll need to start programming microcontroller. In this article I'll show how to use this development platform to read data from digital caliper and send then to PC RC232 serial port.




You can get digital caliper from ebay.com from about 7$ with shipping. I bought it from this seller, but you can search for Digital Vernier Caliper to find many more. Most of them have small digital port on side, with 4 pins. You could connect data port to  microcontroller and use digital caliper as precise position sensor, for instance.

Taking it Apart

vernier caliper back, break open
Before connecting wires and reading data I wanted to find out "what's inside" and what principle is used to sense position changes. After some struggle with screwdriver and trying to open it up with force, I discovered there 4 screws on back of main unit with display. You just have to take off plastic sticker from back.

calipers body with pealed off plasticWhat I discovered or maybe more correct to say, proved to myself as I have been reading other articles that was talked about this, was that "capacitance" was used to sense movement. PCB that has display had small strips of copper. Similar pattern is on calipers part that moves, the one with units and digits. Basically both of those parts form series of capacitors and when caliper inside part is moved, all those "capacitors" are changing capacitance and from the sequence in what it changes, MCU inside caliper calculates by how far it has moved.





Data Port Pinout and Data Format

Pinout
Digital caliper has small data pot on side, near battery cover. Theoretically you can get cable that connects to this connector, but it is very rear and more expensive than caliper itself, so I just soldered wires directly to contacts of data port.

Pinout of caliper data port is Ground, Data, Clock, +1.5V. Clock is being sent out as series of 24 bit pulses and then silence. Silence (steady signal) between 24 bit bursts is about 115 msec long. Thus, we get position update about 8 times per second.

CLOCK signal is normally high and is taken down on every bit. Thus, you need to read DATA on high-to-low transition. DATA line is taken high or low to signal corresponding bit.

Bits form integer that corresponds to number of 100th of mm in case of metric system. And 2000th of inch in case of measurements in inches. That is, if display reads 3.67mm, you get integer 367. The same reading in inches is 0.1445 and this gives us 289 (0.1445 * 2000). So, in case if caliper is switched to inches, for the same reading, it will send now 289 instead of 367.

First bit from those 24 is ignored and it is also always high. We could call it start bit. Then next bits, starting from second, form bits of number, starting from less significant bits on left. All up to 21st bit, which indicates sign - if it is high, number should be negative. This means that last 3 bits are not used. At least moving my 150mm caliper in both directions full scale I never saw anything there. Maybe working with longer calipers they will get used.
24bit data format
And this is how 3.67 looks on Oscilloscope. Ch 1 is CLOCK directly connected to caliper, Ch2 is DATA. (you should be able to find 367 there or 101101111 reversed)



Connecting to MSP430 Launchpad and Converting from +1.5V to +3V

We want to connect DATA signal to P1.5 on Launchpad, and CLOCK to P1.4. Ground from caliper is connected to ground (pin 20) on Launchpad.

But in order to interface caliper to Launchpad or any other microcontroller, you need to convert voltage signals from 0 - +1.5V range of digital caliper to 0 + 3V range what MSP430 series chip is using. That is because +1.5V what caliper is using to indicate logical 1 is not really 1 for MSP430. It is something in middle and it's not good. One of the ways to do it using simple NPN transistor and pull-up resistor (using internal one built into Launchpad).

Schematics - connecting digital caliper to Launchpad MCU
When there is no signal at DATA line from caliper, Colector-Emiter path is closed for transistor Q1. So, signal on P1.5 is high because of pull-up resistor (need to be enabled in software). When there is signal at DATA line Colector-Emiter path opens basically pulling P1.5 to ground, thus we get logical 0. As you see, signal gets inverted this way and we need to deal with those inverted signals in software. That is - we will fire interrupt on low-to-high transition for CLOCK and will treat low signal on DATA pin as 1 and high signal as 0.

Programming MSP430 Launchpad

I won't go though all source but will try to point out key parts. Basic structure of our application is that we will be mostly sleeping in low power mode and would wake up on two interrupts:

  1. CLOCK pulse interrupt
  2. 32 millisecond timer that helps us detect beginning of CLOCK bursts

Timer is triggering interrupt every 32 milliseconds. If during this time there has not been any CLOCK action, we know we are at idle period and next pulse that we will receive we can interpret as start of 24 bit chunk. In CLOCK interrupt, if we are in state where we know that we are ready for next 24bits, then on every CLOCK interrupt we read DATA pin state and assemble integer from bits read. When we have read all 24 bits, we send integer value our to serial as two single bytes.

Setting up 32 msec timer happens at beginning of main function (we are reusing Watchdog timer as simple timer):
 
   WDTCTL = WDT_MDLY_32;      // default timer 32 msec
   IE1 |= WDTIE;           // Enable WDT interrupt
After this interrupt function
 
   __interrupt void WDT_ISR(void)
will be called every 32 milliseconds.

Setting up CLOCK pin (labeled P1.4, but actually pin6 on chip itself) is done here:
 
   P1DIR &= ~CLOCK;      // sets input direction
   P1OUT |= CLOCK;      // pull-up is selected
   P1REN |= CLOCK;      // pull-up/pull-down enabled
   P1IES &= ~CLOCK;      // interrupt triggered on low-to-high
   P1IFG &= ~CLOCK;      // reset interrupt flag to 0. needs to be reset on start
   P1IE |= CLOCK;         // interrupt enabled for CLOCK
By setting pull-up, we basically say that pin will normally be up and we just need to bring it down (connect to ground, to make it zero). This is important because we connected caliper data and clock lines using transistor. Second important part is that we setup interrupt direction to be fired from low-to-high transition. If we would look at signal direct from caliper it would be high-to-low, but as we inverted it by using transistor, we need to use this other transition.

Now to most important part of our code, Interrupt function PORT1_ISR for CLOCK pin. We need to read DATA pin value as soon as we enter interrupt as if we do this later, DATA pin state might have changed already:
 
   port = P1IN;

Next we check if we are not in middle of clock burst. Ready flag is set by timer if during time interval there have not been any clock action and also it stays true while we are reading current value:
 
   if (ready_for_data)

Next we check "bits read" counter to be between 1 and 16. This way we ignore first bit as it's not relevant. If DATA bit in port is not set, it corresponds to 1 as we have inverted signal. So, if we need 1, we set most significant (the one on most left) bit of value. We had there 0 already as we started with "value" variable at 0. So, we shift all bits to right, this way preparing for next bit. After doing this 16 times, we'll have our integer value formed from bit stream:
 
   if (bits_so_far && bits_so_far <= 16){
      if (!(port & DATA))         // if 0 received, invert = >1
          value |=0x8000;         // then set most significant bit
      value = value >> 1;

We ignore bits above 16 as we have just 16 bit integer, until sign bit. Sign bit is bit nr.21. If it is set, we need to make our integer negative. One way to do it, is by using fact that integer is stored using so called Two's complement notation. So, to invert it you need to invert all bits and add one:
 
   }else if (bits_so_far == 21){     // 21st bit indicates sign (+/-)
   if (!(port & DATA))
      value = (~value)+1;
Last part is detecting when we are done, that is if we successfully received all 24 bits, we have our value in variable "value" and are ready to print it. So, we set ready flag to 0 (timer will set it up again when it detects idle period) and we wake up main function from low power sleep by calling __bic_SR_register_on_exit. When you call this function inside interrupt function it sets flags inside interrupt vector basically waking up main function where it started sleeping with __bis_SR_register(LPM0_bits + GIE);
 
   }else   if (bits_so_far >= 23){            // we're done, got all bits
   ready_for_data = 0;                     // warchdog timer will set it
   __bic_SR_register_on_exit(LPM0_bits);   // wake up main from LPM sleep
}

When main is woken up, it sends value over serial by spiting it into two parts. Also we invert LED pin state, thus blinking LED to give visual feedback that serial transmission is happening. I won't describe serial transmit function in details as that has been described nicely already: here:
 
   TXByte = value >> 8;      // first byte (most significant bits)
   Transmit();
   TXByte = value & 0xFF;   // second byte (least significant)
   Transmit();
   P1OUT ^= LED;            // blink LED

Demo - how to see the number in PC

I'm using nice free terminal program Realterm. When you connect Launchpad to PC over USB, it creates COM port. In my case it was COM9, but you can check device manager to find out what number you have for Launchpad COM port. Start Realterm and connect to port 9, set no parity, 8 data bits, 1 stop bit and Baud to 9600. Everything besides Baud should be at this by default. You can click Open two times to close and open it, just to make sure it's really open.

Besides all else, very useful feature is that you can select how you want data to be interpreted. That is, if you are sending integers, you can select if they are displayed as signed or unsigned, if they are one byte long or two. In our case it is useful as we are sending 16 bit integer (two bytes), signed. And we are just sending binary over serial, first part of integer first, then second. If you select right option (int16), then Realterm will combine those two bytes and display number in nice readable way. So, in our case you should select int16 in Display tab. See picture at the end of post.

Digital Caliper alongside Realterm and breadboard

Now if Launchpad is programmed and caliper connected through transistors as explained above, when you switch ON caliper, you should see instant data flow of numbers from caliper into terminal screen. It should have been easy to write small windows application that reads this serial data stream and displays reading in more user friendly way, but I didn't do it as terminal program was showing it nice enough. If you are interested in Inch measurements, it won't work as well as to get digital caliper readout you will have to divide number from terminal program with 2000.

C Source Code

You can find full source code of project in separate article:
C Source Code of MSP430 Launchpad to Digital Caliper Project

Links, resources


Picture of Result

Realterm terminal program

breadboard  connecting msp430 launchpad and digital caliper
Let me know if you have any questions or comments!

38 comments:

  1. I have the same calipier. I noticed when it is turned off, then the position changed, then turned back on it yields the new position. Is the device measuring absolute capacitance or possibly the calipier is always measuring position, just the display is turned off?

    ReplyDelete
  2. Interesting observation. I just tried this on mine - and if I turn it off and then move (while it's off), it instantly wakes up, shows numbers in display and shows correct measurement. I mean - when waking up from off, it does not miss a single tenth of mm. From this I would guess it is measuring capacitance also while display is off.

    I don't think it can sense absolute capacitance. More likely it is constantly looking for a change in capacitance, even with display off, and as soon as change is detected it uses it to track traveled distance and in my case also to switch on display.

    ReplyDelete
  3. The "power" switch only turns the LCD on and off. The internal processor runs all the time (hence shorter battery life). See http://www.fliptronics.com/tip0006.html for a discussion of this issue and comparison of different button cells.
    Be aware, though, that different caliper models vary in behavior and can reset to zero at odd (i.e., the wrong :-) time.

    ReplyDelete
  4. A quick read of the above article leads me to suspect that Maris has a binary-encoded caliper. Be aware that some, similar calipers use BCD encoding for the data. Check out: http://pcbheaven.com/exppages/Digital_Caliper_Protocol/

    ReplyDelete
  5. Nice links. Looks like mine is in binary encoded category. But what I didn't saw an what all other posts is saying, is two 24 bit bursts. There where only one - relative position from "zero". But this is also enough for any practical application to my mind. Also it looks like data format is slightly different than in article you mention - 3 bits where at least signicifant end and was constant, not noisy. Anyway, I think what this means that chinese manufacturers are "optimizing" their units with time and to be sure that description will fit caliper you buy you need to buy it close to the time when article have been published. Otherwise there might be some nuances that have changed.

    ReplyDelete
  6. Great article! It's nice to see what's inside of there and how it actually works.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. This is a 6" or ~150mm caliper. Are the electronics somehow limited to that maximum value?
    If all 19 data bits were used you could get 799.99mm or 31.496".
    Could I layout a pcb that is 32" long and use the same electronics to measure greater distance? Cheap Digital Readout for a lathe or mill for example.

    ReplyDelete
  9. I think this should work. There are out there longer calipers, and I don't think they use different reading ldc/mcu module. You could copy pattern of PCB under unit bar (I had a picture where I pealed off sticker and I think it should work. This was my idea as well - if I find speed and everything else satisfactory, make it longer. On other hand there are cheap longer calipers aloso on ebay, not that much more expensive. So, that would be othe way to go. Let me know if you do try this out and it works!

    ReplyDelete
  10. Digital Readout, Digital, Readout, givimisure india, Bangalore.


    http://givimisureindia.com

    ReplyDelete
  11. Is there a substitute for that Realterm that works on Win7 64bit? I cant seem to get any output using Putty's serial connection and Ardiuno's serial monitor

    ReplyDelete
  12. Great job! But what is the purpose? just for fun?

    ReplyDelete
  13. Philip - I don't have experience with Win 7 64 bit. Realterm works fine on my 32bit Win7. So, no big help from me on that one.

    Andrei, applications could be many - starting from home made CNC machines (you use this caliper to measure distance and use data in microcontroller that controls servo). More or less in any place where you need to measure distance and do something with it. In my case on of applications where intended to measure travel of suspension of motorcycle and log those data and later analyze data on PC. Caliper appeared to be a bit too slow for that... oh well.

    ReplyDelete
  14. I figured out the problem, Somehow I downloaded an older ver of Realterm and it wasn't working correctly with win7 64bit, but the newer version is. Anyways its been a while since i messed with this but I wasn't having proper results displayed. I either have the other type of chicomm caliper which encodes the data differently or I messed up somehow programming the chip. I would only get a single value displayed over and over again in Realterm and it would never change when the scale was moved. Anyways, whats the best software to use to upload the code to the TI chips? I believe I was trying Code Composer Studio v4 and man its complicated. I've never really used anything but ardiuno software to edit and upload to a MCU and of course a JTAG programmer for pic chips. Anyways, any pointers would be helpful. btw I am actually trying to interface digital read out scales to my pc, not calipers because I need to make a proper digital read out for my milling machine after my DRO350 circuit board died.

    ReplyDelete
  15. In those pics of the circuit on the breadboard, are the emitter and collector switched form what they're supposed to be? Or is the circuit diagram wrong? In any case I've tried it both ways and the only way for my to get any output is reversing the ground and output form what the pics show.

    ReplyDelete
  16. Manufacturer of DROs, Linear Glass / Steel / Magnetic scales and Encoders.

    ReplyDelete
  17. Anyone tried to interface these digital calipers to Google Sketchup? I'm trying to make my life easier as I build 3D models for my 3D printer.

    ReplyDelete
  18. Very good article. The CNC application was an idea I had a long time ago using the digital caliper for absolute positioning.

    Maris, if the reading you were getting from the caliper was too slow, you could try re-clocking the caliper. Use the XTAL or a clock output from the MPS430 as the input clock for the caliper. Desolder or cut the traces on the caliper board for the XTAL.

    I've used this technique when what I'm trying to read data from a source that is either too fast or too slow. Re-clocking always worked for me.

    ReplyDelete
  19. I'm hoping you visit this project again. I am going to try this eventually. Have you looked at the Shumatech article (http://www.shumatech.com/support/chinese_scales.htm)? They mention that there is a "mode" button that isn't found on some of the scales. With "mode", you can select "hold" and "fast read" modes with fast read mode giving, in their case, 50Hz over the normal 3Hz. Of course mode access seems to vary between the chinese scales. Scroll to "Hold and Fast Reading Modes" on the shumatech website for more info.

    ReplyDelete
  20. RE: reclocking - maybe, but somehow not sure if it would be possible to increase the rate by magnitude as probably chip is rated for some frequency.

    Regarding mode button that other articles suggest - yes I tried connecting needed pins, but nothing happened. Apparently this option is working for some but not for all Chinese calipers.

    Now I'm thinking in direction of optical incremental encoders for position sensing... will see.

    ReplyDelete
  21. Manufacturer of DROs, Linear Glass / Steel / Magnetic scales and Encoders.GOODWILL Hydraulics Pvt. Ltd. is situated in Bangalore, is one of the leading manufacturers of Hydraulics fittings, We are providing timely delivery of quality products and services at competitive rates.

    Digital Readout, Digital, Readout, givimisure india, Bangalore.DIGITAL READOUT



    for more details
    please contact
    http://givimisureindia.com

    ReplyDelete
  22. Maris, Can you help please? I am having difficulties setting up caliper i/p on other ports. Works fine on P1.4/5. Although need to declare value as a long int!!
    Would like to use it for XY readout on minimill.Hence need four i/p channels and will use remaing six GPIO for the LCD. LCD works fine.

    Paul

    ReplyDelete
  23. Fixed - problem was LEDs loading caliper signal

    Paul

    ReplyDelete
  24. Hi Maris!

    I'm trying to read the serial output of the following digital Caliper http://www.kingtools.com.br/Listagem.aspx?IdTipoProduto=478&IdCategoria=2447
    I'm still waiting for the specification from the manufacturer...
    I'm not sure if the output is the same as you explained... I 'googled' that there are other 24bits formats for digital calipers...
    Using exactly the way you did, the Realterm display shows only '0' (zeros)... and it displays each value around 8 seconds...
    Is this time interval expected? I fell that is not...
    If I switch Data and Clock pins it displays '256' each 0.5 seconds... Do you think my caliper serial output could have DATA and CLOCK pins the reverse?
    Either way doesn't matter if I change the position, Realterm displays always the same value...
    I appreciate any help!
    Best regards!
    Raphael

    ReplyDelete
  25. I'm just learning CSS(Code Composer Studio) and have limited C comprehension so far(did a lot of ASM for the Z80 in the day) and am have a stumbling block with '#pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)'

    My launchpad came with MSP430G2553 and MSP4302452 chips, have tried using both, and editing code to the best of my ability. Help would be apreciated. Thanks, Fred

    ReplyDelete
  26. oops- compiles fine with msp430g2231 processor. I need to figure out if code can be adapted for msp430g2553 or msp430g2452 or buy 2231. Any help with adaptation would be greatly apprecitated.

    ReplyDelete
  27. Re g2231 vs g2553 - I believe I figured it out, at least it compiles. Will post code after testing.
    Fred

    ReplyDelete
  28. hi, for MSP430G2553 and MSP4302452 chips use
    #include or #include
    and replace

    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)

    for

    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A0 (void)

    i found o big problem with this: int value = 0;

    i replace for

    unsigned int value = 0;

    and work perfect in my MSP430 value line LounchPad

    thanks for the author

    ReplyDelete
  29. This comment has been removed by the author.

    ReplyDelete
  30. for MSP430G2553 and MSP4302452 chips i use
    msp430g2553.h and msp430g2452.h

    ReplyDelete
  31. can this method be used with a single launchpad for multiple calipers? or would this require a launchpad for each caliper?

    ReplyDelete
  32. It could be used with several calipers. You basically have two lines coming from caliper - Data and Clock so you can use more pins on Launchpad to add more calipers. Serial connection would be the same for all calipers. In interrupt code you would need to add additional code to handle correctly data coming in from several calipers.

    ReplyDelete
  33. Thanks for the reply Maris, I'll have a go at doing this!

    ReplyDelete
  34. Don't C source code interfacing mikrokontroller to digital caliper?

    ReplyDelete
  35. Hello

    I have tried your project concenning vernier caliper interface

    I have a electronic rule from a chiness’ caliper and I want to mount it on a little lathe

    But with realterm and other rs232 software I only got “00 00 00 00 00 00 00” and when I invert the source data and clock “FF FF FF FF FF FF FF”

    I have put 2N2222 with 15K resistor , on the scope signals looks good

    I don’t know C language and IAR, just MICROCHIP.

    If you can help me , I will be very happy

    Best Regards

    ReplyDelete