January 25, 2011
by Linkster
|
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)
|
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
|
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
|
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)
|
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
|
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
|
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
|
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
|
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 |