NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Support Forum » Digital Caliper and DRO Schematic

January 25, 2011
by Linkster
Linkster's Avatar

Hi all, I'm having fun with the Nerdkit. Built everything so far but I'm having a bit of a problem with the digital caliper and DRO project. I was wondering if Mike or Humberto could take a look at the schematic I put together. It's actually Mikes work, I just put it all on one diagram. It's been many years since I bread boarded anything and I had some conflicts with the MOSFET diagram. I was hoping you could take a peek and see if I had everything right or any suggestions. I didn't hookup the direction or zero switch so I did't draw them on the schematic. I wired everything and doubled and trippled checked all connections and supply voltage but nothing comes up on the DRO. I'm using the same style digital caliper that was used in the demo. I tryed USB power and seperate power for each but to no avail. I did not change anything in Mikes caliper code. Like all the other projects, I just expected to see it come alive. Here is the link to ImageShack file of the schematic. http://img843.imageshack.us/img843/1273/digitalcaliperatmega168.jpg

BTW. Thanks to Humberto and Mike for the great kit. I'm looking forward to learning a lot from all of you guys. I'll talk about a nother problem in the next post. Gary

January 26, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Linkster,

I don't see anything obviously wrong in your diagram. Are you sure the calipers are actually outputting data? Do you have an oscilloscope around so you can verify data is really coming out of the calipers and it is following the same protocol as the calipers we are using.

Humberto

January 27, 2011
by Rick_S
Rick_S's Avatar

One thing I noticed in your schematic was that you don't have the AVcc line of the micro-controller connected to Vcc. I know according to the datasheet this should be connected whether or not the ADC is used. I have read somewhere... just can't place it right now that it also helps power some of the pins on that side of the chip. This may or may not make a difference, but it could be worth a shot.

Rick

January 27, 2011
by Linkster
Linkster's Avatar

Humberto,
I have an antique single channel buried in the shop. I'll dig it out and see what I can find as far as a signal for the caliper. I did use a logic probe to see if I had pulse output from both the data and clock.
I think Rick might of hit on the problem. I did not have AVCC tied to +5v as per the data sheet for the ATmega168. I'm not sure if that is it but I will give it a try. However, I did try running the signals without the MOSFETS but had no results. Let me solve the new problem with the verification error and then I can get back to the caliper/DRO project.
Thanks Humberto and Rick.
Gary

January 27, 2011
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Hi Gary,

One thing I'd do is just swap the clock and data lines -- I've found it's quite easy to get them mixed up, so whenever my caliper-based circuits aren't working, just try it the other way around and see what happens.

Another thing to try is to write a few lines of code so that the microcontroller copies whatever it sees on those two lines onto another set of two pins, so that you can use an LED to see whether you are getting anything at all.

When you used your logic probe, did you see any activity at all? Were you probing directly at the output of the calipers, or were you looking at the output of the inverter/level-shifter circuits?

Mike

February 26, 2011
by Linkster
Linkster's Avatar

Hi all,
Well, I spent a tremendous amount of time trying to get the DRO Caliper project up and running but still no luck. I re-read the entire article and tried to comprehend every part of the code. So I have a few questions regarding some lines of the code in Mikes DRO project. First let me say that the calipers are very similar to the one that Mike used in his project. Here is what could be of some differences. Some tests that I conducted proved that I can not put the calipers in high speed nor can I zero the calipers from the data and clock output pins. When I placed a logic probe on the data and clock pins, I do get a pulsing signal on both. I then checked the collector of both 2N3904 transistors and they also have pulsing signals. I attempted to check the output voltages of the data and clock signals and the result with a DVM is they are both +1.94dc. My supply voltage to the calipers is 2vdc.
With an old BK 1460 oscilloscope and the help of a Global Specialties 8001 Multiplexer I was able to look at both data and clock signals. At the caliper pins I have approximately +1.5vdc with each pulse of the nibbles dropping to 0vdc. This is the case for both Data and Clock signals. At the collector of each transistor I am seeing approximately +4vdc with the pulse only dropping to +3vdc. I’m thinking this is the problem. I’m only getting a 1 volt drop on my collector when I believe the transistor should be pulling the voltage down to 0vdc for the MCU to be able to detect the pulses. If I force the transistor to change state, the transistor inverts the signal to 0vdc and the pulse goes to almost +5vdc. Again, this is the case for both data and clock signals. (I hope this made since.) Looking closer at the relationship of the signals I see that the Data and clock signals are 6 nibbles each with 4 bits. I can see the changes in the bits when I move the calipers along the scale. The clock signals are always consistent. Because it is an old scope I can not make out much more than the voltages. There seems to be a problem with the stability settings and perhaps calibration of the overall unit. But at least I can verify the clock and data pins of the calipers. As for Mike’s suggestion in writing a couple lines of code to see what the pins are doing, I tried but I’m not sure what to write. I wrote a couple lines to turn on a couple LED’s if a signal is present on the pins. It sometimes seems to work if I force the signal with a jumper but is not always the case. The calipers don’t have any effect at all. So any help on some lines of code for this part would help a lot. Basically I did the same to write to the LCD. Again any help? I removed the mosfets from the board and from the code along with the switch direction button and its code. I think keeping it simple first may be the way to start. Besides, like I said earlier, I don’t think I have Zeroing capabilities on the calipers so I shouldn’t need them.

I included the revised code for you to look at. Please go easy on me. I’m old and still trying to keep the gears going. Here are a couple code questions that I can’t seem to find info on.
What does "break;" do? Is it the same as pause?
What are the two ++ after the i used for? "for(i=0; i<24; i++)" or, how would you explain this line?
What is the part in parenthesis? "return (1L<<30);"

Thank you kindly,
Gary

// calipersrev.c

// for NerdKits with ATmega168

#define F_CPU 14745600

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS:
//
// PB1 -- (inverted) data
// PB2 -- (inverted) clock
// PB3 -- power to calipers
// PC5 -- yellow LED
// PC4 -- red LED

void calipers_power_on() {
  PORTB |= (1<<PB3);
  DDRB |= (1<<PB3);
}

uint8_t read_bit() {
  // wait for rising edge of /CLK
  // then sample /DATA
  // return 0 for true 0 (high voltage on /DATA)
  // return 1 for true 1 (low voltage on /DATA)
  // return 2 for timeout error

  uint8_t attempt_counter=200 ;
  // at 14.7456 MHz and 8 clocks/loop, 200 takes 108us.
  while(--attempt_counter) {
    if((PINB & (1<<PB2)) != 0) {
      // we got rising edge
      break;
    }
  }
    if(attempt_counter==0)
    return 2;  // timeout error

   //sample a bunch of times and take the best guess
  uint8_t samples = 5;
  uint8_t samples_0 = 0;
  uint8_t samples_1 = 0;
  uint8_t i;
  for(i=0; i<samples; i++) {
    if((PINB & (1<<PB1)) != 0) {
      samples_0++;
    } else {
      samples_1++;
    }
  }

  if(samples_0 > samples_1) {
    return 0;
 } else {
    return 1;
  }
}

int32_t read_bits() {
  // read 24 bits
  // LSB first
  // return in a signed int32_t

  uint32_t accumulator = 0;
  uint32_t bitval = 1;
  uint8_t rb;
  uint8_t i;
  for(i=0; i<24; i++) {
    rb = read_bit();
    if(rb==2) {
      // TIMEOUT
      return (1L<<30);
    } else if(rb==1) {
      accumulator |= bitval;
    }
    bitval <<= 1;
  }

  // handle negatives
  if(rb == 1) {
    // the MSB was 1 so we've got a negative number!
    // fill the upper 8-bits of the 32-bit
    accumulator |= 0xFF000000L;
  }

  return accumulator;
}

void wait_for_quiet() {
 // get at least 50us of high on /CLK
 // before returning.
 // not really microseconds -- close enough!
 uint8_t quiet_us = 0;
 while(quiet_us++ < 50) {
   if((PINB & (1<<PB2)) == 0) {
     // /CLK is low -- not quiet!
     quiet_us = 0;
   }
 }
 // we made it through 50!
 return;
}

void wait_for_pulse() {
  // get at least 50us of high on /CLK
  wait_for_quiet();

  // then wait for a falling edge
  while((PINB & (1<<PB2)) != 0) {
    // do nothing
  }
}

int main() {
  // activate pull-ups
  PORTB  |= (1<<PB1) | (1<<PB2) | (1<<PB4) | (1<<PB5);

  // turn on calipers
  calipers_power_on();
  delay_ms(2000);

  // init serial port
  uart_init();
  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

  // lcd
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  lcd_clear_and_home();

  int32_t lastpos, tmpr, refpos = 0;
  double lastpos_inches, lastpos_mm;
  while(1) {
    wait_for_pulse();
    tmpr = read_bits();
    if(tmpr != (1L<<30)) {

      // This is where I started with some code for the pins. don't luagh.

      // check for signal on PB1 & PB2
      // signal from caliper is inverted thru the 3904.
      // PB1 & PB2 is low (0 volts) for true.
      uint8_t signal_1;
      uint8_t signal_2;

       // LED as outputs
       DDRC |= (1<<PC4) |(1<<PC5);

      // Turn on PC4 red LED if signal is detected on PB1.

      signal_1 = ((PINB & (1<<PB1))==0) ? 1 : 0;
      if((PINB & (1<<PB1)) ==0 ){
      PORTC &= ~(1<<PC4);
      }
      else {     
      PORTC |= (1<<PC4);
      }

      // Turn on PC5 yellow LED if signal is detected on PB2. 
      signal_2 = ((PINB & (1<<PB2))==0) ? 1 : 0;
      if((PINB & (1<<PB2)) == 0){
      PORTC &= ~(1<<PC5);
      }
      else {     
      PORTC |= (1<<PC5);
      }

      // calculate position
      lastpos = tmpr - refpos;
      lastpos = -lastpos;

      // translate into inches and mm
      lastpos_inches = lastpos / 20480.0;
      lastpos_mm = lastpos * (25.4 / 20480.0);

      // send over serial port
      printf_P(PSTR("%8ld\t%10.5f\r\n"), lastpos, lastpos_inches);

      // show on LCD
      lcd_line_one();
      fprintf_P(&lcd_stream, PSTR(" Caliper Project "));

      lcd_line_two();
      fprintf_P(&lcd_stream, PSTR("%9.4f inches    "), lastpos_inches);

      lcd_line_three();

      if((signal_1)==1) 
      {
        fprintf_P(&lcd_stream, PSTR("Signal 1 red     YES "));
      } else {
        fprintf_P(&lcd_stream, PSTR("Signal 1 red     No  "));

        lcd_line_four();

      if((signal_2)==1)
      {
        fprintf_P(&lcd_stream, PSTR("Signal 2 yellow  YES"));
      } else {
        fprintf_P(&lcd_stream, PSTR("Signal 2 yellow  No "));

    }
    }
    }

 }

 return 0;

}
February 27, 2011
by Ralphxyz
Ralphxyz's Avatar

Unless you are in your high eighties you are not considered old around here. Some like myself are suffering from the "AGE Virus" but definitely not considered "old".

Therefore we will show no mercy.

Well actually you will find us, like my wife, a very tolerant sort.

re: "I can’t seem to find info on.

What does "break;" do? Is it the same as pause?

 while(--attempt_counter) {
    if((PINB & (1<<PB2)) != 0) {
      // we got rising edge
      break;
    }
  }

  Break literally "breaks" the flow of the while loop, i.e. it ends the loop. Guess what "pause" would do.
 -----------------------------------------------------------------

What are the two ++ after the i used for? "for(i=0; i<24; i++)" or, how would you explain this line?

    for(i=0; i<24; i++) {
    rb = read_bit();
    if(rb==2) {
      // TIMEOUT
      return (1L<<30);
    } else if(rb==1) {
      accumulator |= bitval;
    }
    bitval <<= 1;
  }

Think of i as in "increment", you are in a for loop and gone through all of the steps in that loop once now 
you want to do it 23 more times. The i keeps track of where you are in the loop, how many iterations you 
have completed.
-------------------------------------------------------------------

What is the part in parenthesis? "return (1L<<30);"

 if(rb==2) {
      // TIMEOUT
      return (1L<<30);

The valve to be "returned" to the procedure that preceded or called the if statement. 
In this case I believe it becomes read_bits(1L<<30).
----------------------------------------------------------------------------

Hopefully someone with actual C programing knowledge will clarify/correct all of this further.

You need to Google " C break", "C loops" and "C Increment and Decrement Operators (++, --)"

Ralph

February 27, 2011
by Linkster
Linkster's Avatar

Thanks Ralph,
I've been reprieved from going to the old age home. For now anyways.
So, is the (1L<<30) have something to do with a register? I might need to look again at the spec sheet.
I think I understand the "break;" from what I gather it lets the while statement loop untill it fullfills it's requirements. In this case loop untill ((PINB & (1<<PB2)) != 0). Another words not equal to 0 so it must be a 1 which would be a rising edge and then continue on to the next part of the code.
Am I close??
Thanks for the google tip.
Gary

March 02, 2011
by Linkster
Linkster's Avatar

For mrobbins.
Mike,
Could you give me a little info on how this line of code works for the DRO project? accumulator |= 0xFF000000L; it's the 0xFF000000L part I'm lost on.
I guess I'm also lost on return (1L<<30); the (1L<<30) part of the code. It's used in a couple places.

I difinitely know that I have output from the calipers. I know which is clock and Data. The inverter/level-shifter circuits do have output and are inverted. Data bit pulses are all high when all zeros. I can see the bits go low when I move the caliper. The clock is 6 nibbles each 4 bits. Each of these bits are always high. It's hard with my old scope to guage the voltages or frequencies. If we even need to know the frequency. But, I'm sure we do. I removed the MOSFETs and associated code so I could just concentrate on the actual signals. Not sure if calipers have high-speed. I might have to look for a nother calper if this one does not work. Hate to bother you with this project but it was the sole reason for the kit.

Thanks for any help you can give.
Do I need to start a new topic pertaining to this part of the DRO project?
Gary

Post a Reply

Please log in to post a reply.

Did you know that two resistors can be used to make a voltage divider? Learn more...