Digital caliper remote display

Advert

Digital caliper remote display

Home Forums Help and Assistance! (Offered or Wanted) Digital caliper remote display

Viewing 25 posts - 51 through 75 (of 96 total)
  • Author
    Posts
  • #311220
    SillyOldDuffer
    Moderator
      @sillyoldduffer

      More fun due to duff equipment. My oldest oscilloscope probe has an intermittent fault, doh! Very time wasting as I spent an hour looking for a non-existent circuit or caliper fault.

      It appears I have more than one problem. The Arduino isn't catching pulses from the Caliper 100% correctly. For 4.89mm I expect to get 1000 0101 1001. As can be seen from the log below, I quite often do. Unfortunately as can also be seen, it's not unusual to get up to three bits wrong as well.

      1000 0101 1001
      1000 0101 0001
      1000 0101 0000
      1000 0101 0000
      1100 1101 0000
      1000 0101 1000
      1000 1101 0000
      1000 0100 1000
      1000 0101 1000
      1000 0101 0001
      1000 0101 0000
      1000 0101 1001
      1000 0101 1001

      The bit errors are probably due to poorly shaped pulses coming out of the caliper compounded by my simplistic level shifter circuit. It may be possible to fix this in software, otherwise I shall have to install pulse shaping hardware.

      The other problem is that Bob's code doesn't quite match the protocol my caliper is sending. His decode logic assumes the caliper is sending a binary number; mine is sending binary coded decimal. Negatives are handled differently too. I think a few lines of extra code added to Bob's program will fix it for me.

      The way Bob's program works isn't ideal for decoding more than one DRO scale. There are a few places where the code waits for data whilst reading an axis. It means the X axis has to complete before the Y axis gets a chance. This means there's some risk of missing some readings. Adding a Z axis will make this worse. When I've got my caliper decoding correctly I'll give some thought to using interrupts to handle more than one axis safely. (Unless someone else has already done it.)

      Dave

      Edit typos…

      Edited By SillyOldDuffer on 09/08/2017 19:04:31

      Edited By SillyOldDuffer on 09/08/2017 19:05:12

      Advert
      #311238
      Neil Wyatt
      Moderator
        @neilwyatt

        Dave,

        Check out this page on the Shumatech Website, it's where I got my information from when I made my readout.

        It details the differences between the BCD and signed integer formats.

        If your scale sends absolute and relative data, make sure it's reading the right one of the two!

        I wimped and made three units – you could use interrupts but if three pulses arrive together your code would have to be very light-footed (probably written in assembler).

        Neil

        #311261
        SillyOldDuffer
        Moderator
          @sillyoldduffer

          Thanks Neil. Spotted another possibility on the Shumatech pages 'The data and clock pins also function as mode and zero buttons, respectively '. I hadn't thought it might be possible to control the Caliper with an Arduino. Something else to try.

          The protocol used by my Powerfix Caliper seems to be a variant of BCD7. As Les said 'The waveform looks like 7 BCD protocol but the data is inverted.' It sends a single reading in the first five nibbles, each nibble being a Binary Coded Decimal number. The last nibble looks as if it contains the sign, and I'm hoping it decodes as described by Les.

          I agree about interrupts. They're a challenge in lots of ways. Apart from the need to write tight fast code the Uno only supports 2 external interrupt pins, so pin change interrupts will have to be used to take on a third axis caliper. More new territory for me to get lost in!

          Dave

          #311269
          Neil Wyatt
          Moderator
            @neilwyatt
            Posted by SillyOldDuffer on 09/08/2017 21:18:21:

            Thanks Neil. Spotted another possibility on the Shumatech pages 'The data and clock pins also function as mode and zero buttons, respectively '. I hadn't thought it might be possible to control the Caliper with an Arduino. Something else to try.

            I just wired switches across the lines, works fine. Despite what that site says, callipers and scales often have hidden features and mine go into 'fast' mode when you prod the right bits. Although 300ms is fast enough for most things the very brave could use fast mode to implement a closed loop servo CNC system.

            #311271
            Les Jones 1
            Participant
              @lesjones1

              Hi Dave,
              It is only the 2 x 24 bit protocol scales that can be zeroed via the data and clock signals.Also they are the only ones that can be set to fast sample node. (Fast 40 samples per second normal 3 samples per second)
              You need extra hardware in the interface to zero or set fast sample mode on 2 x 24 bit scales. The components in the grey area of my interface schematic are those that are only required to zero or set fast mode of 2 x 24 bit scales. I have only recently noticed that I have not put the resistor values (All 100R) and multiplexor part number (CD4051) on that part of the schematic.

              Here are my notes on 2 x 24 bit protocol.

              ————————————————————————-
              Scale protocol information.

              2 * 24 bit scales

              Data is sent as two groups of 24 bits.
              Each group is a 24 bit binary number. The first bit received is the least significant bit.

              Bits
              are transferred LSB first! Also, data is 2's complement. (ie inverted Data signal at 0 volts = 1 at +1.5 volts = 0)

              Static state of clock signal between frames Low
              Time between start of frames 330 mS Normal mode 25 mS fast mode
              Length of data frame 860 uS
              Length of clock cycle about 14 uS
              Time clock pulse is negative about 7 uS
              Time clock pulse is positive about 7 uS
              Initial high at start of frame about 52 uS
              High in the middle of frame about 110 uS
              High at end of frame about 80 uS

              Clock in the data on the negative going edge.

               

              The first group is the absolute position. It has some arbitary value at power on.
              The second group is the relative position. This will be zero after the zero button is pressed.
              Its value will be the difference between the absolute value when the zero button was pressed and
              and the current absolute value.

              48 bits in a frame of data

              CPI 20480

              ————————————————————————-

               

              Les.

              Edited By Les Jones 1 on 09/08/2017 22:46:02

              Edited By Les Jones 1 on 09/08/2017 22:48:20

              #311272
              Neil Wyatt
              Moderator
                @neilwyatt
                Posted by SillyOldDuffer on 09/08/2017 21:18:21:

                Thanks Neil. Spotted another possibility on the Shumatech pages 'The data and clock pins also function as mode and zero buttons, respectively '. I hadn't thought it might be possible to control the Caliper with an Arduino. Something else to try.

                The protocol used by my Powerfix Caliper seems to be a variant of BCD7. As Les said 'The waveform looks like 7 BCD protocol but the data is inverted.' It sends a single reading in the first five nibbles, each nibble being a Binary Coded Decimal number. The last nibble looks as if it contains the sign, and I'm hoping it decodes as described by Les.

                I agree about interrupts. They're a challenge in lots of ways. Apart from the need to write tight fast code the Uno only supports 2 external interrupt pins, so pin change interrupts will have to be used to take on a third axis caliper. More new territory for me to get lost in!

                Dave

                AVR interrupts are very good, you have lots and they are well behaved, but you do have to manually save and restore any registers you use, it only saves the program counter to the stack automatically. But with lots of registers*, you can use a few for key variables rather than using normal RAM (advantage of assembler over C) and speed things up a lot.

                *They aren't really registers, just privileged memory locations, sort of half way between real registers and the 6502's zero page.

                #311273
                Les Jones 1
                Participant
                  @lesjones1

                  Hi Neil,
                  I like the fact that the AVR chips have vectored interrups so that you don't have to sort out which type of event caused the interrupt as you have to do with a PIC. If you are interested in the source code for my interface that uses an ATtiny4313 then let me know and I will email it to you. (The current version is the one that also works with the Wixey type angle gauges. It supports 2 x 24 bit, 7-BCD, Bin6 and iGaging scales) It also gives the option of enabling fast sample mode on 2 x 24 bit scales.

                  Les.

                  #311488
                  SillyOldDuffer
                  Moderator
                    @sillyoldduffer

                    Another progress report. Yesterday was another baffling waste of time. Despite careful checks of the program and wiring, and trying different ideas, I finished the day still getting incomprehensible readings off the caliper. I went to bed thinking 'very strange' and decided to start again this morning from first principles. Alas, if only I'd done that first! Or taken any notice of the clues!

                    I wrote a simple program this morning to prove that the Arduino was catching the pulses sent by the caliper. It looks like this:

                    pulsecount.jpg

                    The oscilloscope output from the program reveals a big problem:

                    missing.jpg

                    There should be a yellow pulse each time the blue line drops. It can be seen that I got 1,3,2 and 2 yellow pulses rather than 1,4,4,4. Also it can be seen that the first yellow pulse doesn't appear until 9μS after the blue drop that triggered it. The root cause of this failure lies in the speed my particular caliper sends data. Roughly 3 times a second, it sends a frame containing 7 bursts of 4 bits. The whole frame is sent in 780μS and the all important blue pulses are only 6μS long.

                    The problem is that the Arduino digitalRead() function takes about 5μS to do its stuff. As the pulse it's trying to read is only 6μS long, there's a good chance that pulses will be missed. And they are!

                    The good news is that the problem can be circumvented I hope. Turns out that digitalRead() is slow because it hides a lot of complexity from the programmer. 5μS is fast enough for most purposes and the function keeps life simple. However, there are faster alternatives, which is what I need.

                    In general the alternatives to digitalRead are much harder to understand. Assembler, Macros, Bit Twiddling and other advanced under the bonnet stuff. However I've found a library called DigitalIO that looks like a good compromise. Provided the programmer guarantees not to change pin numbers at compile time, PinIO is much faster than digitalRead().

                    The revised program looks like this:

                    fastpulse.jpg

                    Running the PinIO version shows that it's fast enough to keep up with the caliper:

                    hitting.jpg

                    The moral of the story is not to make assumptions. As Bob's caliper is somewhat similar to mine, I assumed that tweaking his logic would work. I also assumed that the Arduino would easily be fast enough to keep up with my caliper. There's nothing wrong with Bob's logic, but using digitalRead() makes it too slow for the protocol used by my Powerfix caliper. No wonder I couldn't understand why nothing I tried worked! Arghh!

                    I've high hopes that my next report will be success. Don't bet the farm on it though, I keep underestimating this problem. It ain't over until the fat lady sings.

                    Dave

                    #311493
                    duncan webster 1
                    Participant
                      @duncanwebster1

                      A different approach might be to read the ports directly. Reading the guff, the A2 pin is bit 2 of PORTC, so putting

                      value = PORTC & 0b00000100

                      will return 0b00000100 if A2 was high and 0 if A2 was low. At least it works with PICs (which I used to mess with), and reading the literature suggests it works in Arduino.

                      Whether this is faster is beyond my pay grade, but actually addressing or reading ports means you can do a lot in one line, and it doesn't make your head hurt once you've got the hang of binary arithmetic

                      I think you can cheat and put

                      value = PORTC & 4

                      and the return would be 4 or 0, but it might be slower, it would have to convert the 4 into binary, and anyway it makes more sense to me the first way.

                      #311509
                      SillyOldDuffer
                      Moderator
                        @sillyoldduffer
                        Posted by duncan webster on 11/08/2017 14:35:05:

                        A different approach might be to read the ports directly. …

                        Hi Duncan,

                        Yes it would be a lot faster but it's not as easy, at least on an Arduino, as your example implies. There are 3 registers to set up with the possibility of squishing something else. (The blurb says 'Note that some bits of a port may be used for things other than i/o; be careful not to change the values of the register bits corresponding to them.' ) Low-level stuff is often a right fiddle to get going and, being lazy, I avoid it if I can.

                        I made much better progress today and can now display caliper values correctly! That fat lady isn't singing though. My sketch loses the most significant digit on readings above 99.99 and can't detect negatives. Sounds like a small bug but I fear it's a nasty one. As the sketch goes wrong reading bits late in the frame I infer the timing is drifting off so that data reads half way through the frame are mistimed. Close but no coconut.

                        This is what the code looks like now:

                        fast_caliper.jpg

                        Just as well I'm busy this weekend. I need to sleep on it.

                        Dave

                        #311973
                        SillyOldDuffer
                        Moderator
                          @sillyoldduffer

                          Just to finish this one off, in case anyone needs such a thing I've put two working Arduino sketches for decoding a BCD7 caliper in this Dropbox folder.

                          caliper_int.ino captures data from the caliper with interrupts generated by the caliper's clock signal. This code is can easily be extended to read more than one axis. (An Arduino Uno has two external interrupt pins, enough for X and Y. If Z (or more) measurements are needed, the easiest solution is to change to an Arduino Mega because it supports 6 external interrupts. )

                          caliper_bob_mcN.ino captures data from the caliper by waiting in a loop until the clock changes. It's based on Bob's program, altered to decode BCD7 protocol.

                          I made a mistake about why 'My sketch loses the most significant digit on readings above 99.99 and can't detect negatives.' Not a timing error as I thought. C programmers will enjoy my discomfort. It was due to writing:

                          value |= 1 << i;

                          when, because value is a long integer, I should have said:

                          value |= 1L << i;

                          Subtle eh. Most C/C++ compilers issue a Warning, the Arduino IDE doesn't. Not sure why not!

                          Dave

                          #311985
                          Ian P
                          Participant
                            @ianp

                            Dave

                            I am very new to Arduino and programming (other than basic Basic) but I am keen to make some displays for calipers. I have a couple of Nano's and this morning the postman brought two of the 2×16 blue LCDs with I2C piggyback boards.

                            Before I damage anything or waste hours I would be grateful if you could outline what libraries or other files have to be present to successfully compile and download to a Nano. I understand that the Nano does not have dedicated pins for serial displays unlike some other Arduino models.

                            Ian P

                            #311991
                            SillyOldDuffer
                            Moderator
                              @sillyoldduffer

                              Hi Ian,

                              Generalising a bit the main difference between a Nano and a Uno is the size of the board and the way the pins are organised.

                              Here's a pin-out diagram for the Nano. A bit intimidating but the most useful information is the lettering running vertically on the board itself D12 to TX1 on the left, D13 to Vin on the right. They're what you connect to.

                              The Nano uses pins A4 and A5 for I2C. A4 is SDA, A5 is SCL. To connect an I2C device, you link GND to GND, 5V to 5V, SDA to SDA and SCL to SCL.

                              Once the Nano and I2C are connected, plug the Nano into a computer with a USB cable. The computer will power the Nano and display.

                              To program the Arduino, download the IDE from here. Fire it up and use the Tools tab to set the Board type to Arduino Nano. Then use the Tools Tab to confirm that the Port is set correctly. (May not get the port right automatically.)

                              Assuming you have a new sketch rather than are modifying an existing one, use the Sketch Tab to select Include Library. Include Library should give you a list with 'Wire' in it. Select it. #include should appear in your source file.

                              Under the File Tab find and open the Examples list. In the 'Examples from Libraries' section you should see a few example sketches showing how to use I2C in the raw. These may be useful later.

                              But if all you want to do with I2C is drive an LCD display, then there's a contributed library called LiquidCrystalI2C. It too can be found and loaded from the Sketch tab.

                              Next is an example of a minimalist 'hello world' program.

                              i2c_hello.jpg

                              In the IDE, type it in, then Verify and Upload using the tick and right arrow buttons. There will be several Warning Messages, but no Errors.

                              If the display doesn't work, and the wiring is OK, the declaration 'LiquidCrystal_I2C lcd( 0x3f, 16, 2 ) is chief suspect. The 16 and 2 must match the number of columns and rows your display has. 16×2 is the most common but you may have bought bigger.

                              The most likely culprit is the 0x3f. It's the address of the I2C hardware and it varies depending on the whim of the supplier, who doesn't always provide documentation. 0x27 and 0x3f are common but other addresses pop up from time to time. If neither work, I provided a link earlier in this thread to a sketch that scans an I2C device and tells you whatever address is being used.

                              Have fun!

                              Dave

                              Edited By SillyOldDuffer on 14/08/2017 16:14:05

                              #311994
                              Bob Mc
                              Participant
                                @bobmc91481

                                Hi Dave/Ian…

                                Dave …. glad to hear you have solved the problem, I was confident you would.

                                Ian… I know you asked Dave and perhaps he will give some advice, however if you are new to Arduino and having got hold of two LCD board I would imagine they are the LCD version 1 as mentioned in https://arduino-info.wikispaces.com/LCD-Blue-I2C.

                                I think it best if you get the LCD display program going first … you need to download the library mentioned at the top of the page of the above website, then there is a small program to download for Version 1.

                                If you have never had a go at these displays previously please note that if you do not see any characters on the display at first or if they seem a bit dull you use the brightness control on the little piggy back I2C board.

                                anyway….best of luck…..Bob..

                                #311995
                                Bob Mc
                                Participant
                                  @bobmc91481

                                  Dave…..you beat me to it….!!!

                                  #311996
                                  Ian P
                                  Participant
                                    @ianp

                                    Dave, Bob

                                    Thanks for the help, I have to go out until this evening but I will try then to get at least the display up and running. I have actually connected it as described and it lights up with the usual top row of solid blocks. Yesterday I checked both the Nano boards using an example LED flash sketch. The only odd thing I dont understand is what one Nano needs Com3 the other one only talks on Com4.

                                    Ian P

                                    #312050
                                    Ian P
                                    Participant
                                      @ianp

                                      Some progress this evening but I'm struggling to compile the hello world example. I took me a while to work out how to add libraries but I have now run the LCD address finder (mine are 0x27) so I must have got something right.

                                      I have actually installed two libraries as the filenames were similar and I was not sure which was the correct one, when the compiler runs it tell me there are two but then uses the liquidcrystal_I2C.h

                                      I get a long list of error messages, probably not right to post them here, but the two lines that look relevant are these,

                                      LCDtest:10: error: 'lcd' was not declared in this scope

                                      'Liquidcrystal_I2C' does not name a type

                                      Ian P

                                      #312052
                                      SillyOldDuffer
                                      Moderator
                                        @sillyoldduffer

                                        Hi Ian,

                                        Doing well if you got something to run! Can you post a copy of what you actually typed for hello world. (it's probably a typo.)

                                        Dave

                                        PS The capitalisation in LiquidCrystal matters!

                                        Edited By SillyOldDuffer on 14/08/2017 21:55:14

                                        #312055
                                        Ian P
                                        Participant
                                          @ianp

                                          This is copied and pasted from the iDE window.

                                          I was surprised earlier but I did discover that case was important!

                                          Thanks for your help

                                          IanP

                                          #include <Wire.h>

                                          #include <LiquidCrystal_I2C.h>

                                          Liquidcrystal_I2C lcd(0x27, 16, 2);

                                          void setup()

                                          {
                                          lcd.init();
                                          lcd.backlight();
                                          }

                                          void loop()
                                          {
                                          lcd.print ("hello&quot;
                                          }

                                          #312056
                                          Ian P
                                          Participant
                                            @ianp

                                            This forum editor is not good for posting code anyway but I have just noticed that I have not put spaces after the lcd.init and the brackets (I presume the space is required)

                                            Ian P

                                            #312057
                                            SillyOldDuffer
                                            Moderator
                                              @sillyoldduffer

                                              Hi Ian,

                                              As you're discovering it's case sensitive!

                                              Liquidcrystal_I2C lcd(0x27, 16, 2);

                                              should be:

                                              LiquidCrystal_I2C lcd(0x27, 16, 2);

                                              The error messages mean 'lcd' didn't get created because there's no such thing as a 'Liquidcrystal_I2C'

                                              Fingers crossed,

                                              Dave

                                              #312058
                                              duncan webster 1
                                              Participant
                                                @duncanwebster1

                                                I've no doubt someone has got in before me, but you've got

                                                Liquidcrystal_I2C lcd(0x27, 16, 2); (3rd line)

                                                which I think should be

                                                LiquidCrystal_I2C lcd(0x27, 16, 2);

                                                Case is very important!

                                                #312059
                                                SillyOldDuffer
                                                Moderator
                                                  @sillyoldduffer
                                                  Posted by Ian Phillips on 14/08/2017 22:06:06:

                                                  This forum editor is not good for posting code anyway but I have just noticed that I have not put spaces after the lcd.init and the brackets (I presume the space is required)

                                                  Ian P

                                                  I see Duncan is helping too.

                                                  Good news – in general white space in C/C++ doesn't matter. Usually…

                                                  #312060
                                                  Ian P
                                                  Participant
                                                    @ianp

                                                    Success!

                                                    I changed the c to C and put spaces before the brackets so now I have an LCD full of hellohellohello

                                                    I really did not realise just how case sensitive it is. Now I can start trying different things.

                                                    Thanks to all

                                                    Ian P

                                                    #312062
                                                    SillyOldDuffer
                                                    Moderator
                                                      @sillyoldduffer

                                                      Hurrah! Don't be afraid to experiment – they're quite hard to damage.

                                                      Cheers,

                                                      Dave

                                                    Viewing 25 posts - 51 through 75 (of 96 total)
                                                    • Please log in to reply to this topic. Registering is free and easy using the links on the menu at the top of this page.

                                                    Advert

                                                    Latest Replies

                                                    Viewing 25 topics - 1 through 25 (of 25 total)
                                                    Viewing 25 topics - 1 through 25 (of 25 total)

                                                    View full reply list.

                                                    Advert

                                                    Newsletter Sign-up