![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
scaven92
Joined: 06 Oct 2006 Posts: 44
|
Encoder to PIC interfacing |
Posted: Fri Oct 06, 2006 8:18 pm |
|
|
I was hoping someone could shed some insight on the software needed to interface a US Digital LS7266 (Encoder to Microprocessor Interface) chip. You can see the product here: http://www.usdigital.com/products/ls7266/ .
I am new to embedded design and was hoping someone has some software they have used for this chip that I can learn from. I am using a PIC18F452 with a transmisive optical encoder.
Thanks in advance for your help and suggestions. |
|
![](templates/subSilver/images/spacer.gif) |
bsodmike
Joined: 05 Aug 2006 Posts: 52
|
|
Posted: Sat Oct 07, 2006 1:25 am |
|
|
Looks like a fun project. Most of it seems more or less straight forward. The key is to reading over the datasheet and communicating with it as described.
What you should do is come up with some code and if you have issues, post back - this would be the best way to learn rather than having someone else do it all for you ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sat Oct 07, 2006 3:05 am |
|
|
I have used the 7166 (the single channel version), some time ago, and it really is fairly simple. You read it just like a memory (select 'read', select 'data', lower the CS, and read a byte). If you write '3' to the master control register, it resets the read counter, and copies the current 'count', into the output register. The counter for the output, automatically increments, so three reads, give the full 24bit value. If you are handling potentially 'large' counts, you need to have a interrupt driven off the carry/borrow pins, and increment/decrement your own carry register.
It is a very easy way of handling fast/large encoder counts. :-)
As bsodmike says, have a little 'try', work out which pins are connected to what on your processor, and try a simple program to just read the value every few seconds. This can be done in only a few dozen lines of code, and if you get problems, post back, and I'll try to remember how I did it, and help. :-)
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
jbmiller
Joined: 07 Oct 2006 Posts: 73 Location: Greensville,Ontario
|
LS7266 |
Posted: Sat Oct 07, 2006 5:58 am |
|
|
US Digital makes great shaft encoders and interface chips. I used a lot of them when I worked for Quanser( www.quanser.com). We developed a series of robotics learning products for universities.
The US digital encoders are far superior to the HP types. FAR easier o install and replace when damaged(see the 'pendulums' at quanser).
I still have code on this hard drive that may help.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
scaven92
Joined: 06 Oct 2006 Posts: 44
|
|
Posted: Sat Oct 07, 2006 1:38 pm |
|
|
Alright, I think you guys are right. I will try to write some code and post it for some help. Thanks! I'll try to get it back to you guys to look at tonight!
I appreciate all of your comments |
|
![](templates/subSilver/images/spacer.gif) |
scaven92
Joined: 06 Oct 2006 Posts: 44
|
|
Posted: Sat Oct 07, 2006 3:30 pm |
|
|
Ok, here is what I have come up with so far. I do have some questions. First off, this encoder will be for wheel position. Will it count negative values, telling me that the position is behind the start position? Also, I do not need to use the XFLAG, YFLAG pins do I? How do I deal with FCLK? Also am I reseting the counter correctly? I am only using this encoder to tell me position as feedback for a controller. I believe all I will need to do it have the ability to resest both counters and read the two counters. Can anyone think of other features I should implement? Thanks so much for your help and time! Dont hold back on your comments or criticism, thats how I learn!
Code: |
#include <18F452.h>
#include <stdio.h>
#include <math.h>
#FUSES NOWDT, XT, NOPROTECT, BROWNOUT
#use delay(clock=4000000)
//Data Pins
#define DATA PORTB
#define DATA_SELECT PIN_D2
#define WRITE PIN_D3
#define CS PIN_D4
#define READ PIN_D5
#define X_OR_Y PIN_D6
#define FCLK PIN_D7
#define CHIP_ON 0
#define CHIP_OFF 1
#define X 0
#define Y 1
#define RESET 0b00000011 // Resets the Counter using RLD, selectable by X_OR_Y, from page 2 of datasheet
// Reads the 24 bit Count from either X or Y Channels
long Read_Position( int axis ) { // read position of encoder
long position;
output_bit(READ, CHIP_ON); // Select READ Mode
output_bit(CS, CHIP_ON); // Select Chip Select On
output_bit(DATA_SELECT, CHIP_ON); // Select Data Mode
output_bit(X_OR_Y, axis); // Selects X or Y Channel
position = (long)input_b(); // least significant byte
position += (long)input_b() << 8; // mid
position += (long)input_b() <<16; // most significant byte
output_bit(CS, CHIP_OFF); // Select Chip Select Off
return position;
}
// Reset either X or Y Channel Counter
void Reset_Count( int axis )
{
output_bit(WRITE, CHIP_ON); // Select READ Mode
output_bit(CS, CHIP_ON); // Select Chip Select On
output_bit(DATA_SELECT, CHIP_ON); // Select Data Mode
output_bit(X_OR_Y, axis); // Selects X or Y Channel
output_b(RESET); // Write a '3' to reset Counter selected by axis
output_bit(CS, CHIP_OFF); // Select Chip Select Off
}
void main( void )
{
long count = 0;
//Init_Chip();
//Init_Encoder();
count = Read_Position( X ); // Read count of X Channel
Reset_Count( X );
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Oct 08, 2006 3:11 pm |
|
|
You need to use an int32, not a 'long'. Long in CCS, is only 16 bits.
You need to reset the byte counter (which also latches the current position), _before_ reading the bytes. Doing this afterwards, would mean that the data you read next time, could be several counts 'out of data'.
No, the counter will not itself handle negative values. The readout will wrap, to return a maximum value, and a carry bit gets set. You have two choices (depending on how large the values are likely to get). The first is to set the counter to 0x800000, when you wake the encoder up, and then anything below this corresponds to a reverse movement. The second is to use a signed int32, and handle the overflow bit.
_You_ need to handle the control transactions for each byte (CS/RD etc.).
The sequence will be something like:
Code: |
//Data Pins
#define DATA PORTB
#define DATA_SELECT PIN_D2
#define WRITE PIN_D3
#define CS PIN_D4
#define READ PIN_D5
#define X_OR_Y PIN_D6
#define FCLK PIN_D7
#define SETUP_REGISTERS(register) DATA_SELECT=(register & 1);\
X_OR_Y = (register & 2)
void output_data_byte(int8 val,int8 register) {
SETUP_REGISTERS(register);
DATA=val;
WRITE=0;
CS=0;
delay_cycles(1);
CS=1;
WRITE=1;
}
int8 input_data_byte(int8 register) {
temp rval;
SETUP_REGISTERS(register);
READ=0;
rval=DATA; //ensure port is set to input _before_ selecting chip...
(assuming 'standard_io' - otherwise you need to set the tris).
CS=0;
delay_cycles(1);
rval=data;
CS=1;
READ=1;
}
// Reads the 24 bit Count from either X or Y Channels
int32 Read_Position( int axis ) { // read position of encoder
int32 position;
axis<<=1; //using 'X/Y in second bit
output_data_byte(0x81, axis+1); //reset pointer;
position = input_data_byte(axis); // least significant byte
position += (long)input_data_byte(axis) << 8; // mid
position += (long)input_data_byte(axis) <<16; // most significant byte
return position;
}
|
No guarantees, but is should be getting close.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
scaven92
Joined: 06 Oct 2006 Posts: 44
|
|
Posted: Sun Oct 08, 2006 4:47 pm |
|
|
Thanks for your help! Alright I have taken your code and tried to understand it a bit better and have come up with this. Since I don't need the full range of the counter I am going to center is at 0x800000 and then subtract that value from the int32 that I read from the chip. Then value will be a signed int32 so I can have posivitve and neg values.
Please let me know if I have created the Reset_Counter function correctly. I don't have an encoder nor counter yet, so I cannot implement and test yet. Thank again for your time and help!
I am having trouble posting the code, it is clipping it so I'll post it next... |
|
![](templates/subSilver/images/spacer.gif) |
scaven92
Joined: 06 Oct 2006 Posts: 44
|
|
Posted: Sun Oct 08, 2006 5:09 pm |
|
|
Here is the first half of the code... (it won't let me post it all at once, it overlaps when submitted)
Code: |
#include <18F452.h>
#include <stdio.h>
#include <math.h>
#FUSES NOWDT, XT, NOPROTECT, BROWNOUT
#use delay(clock=4000000)
//Data Pins
#define DATA input_b()
#define DATA_SELECT(value) output_bit(PIN_D2, value)
#define WRITE(value) output_bit(PIN_D3, value)
#define CS(value) output_bit(PIN_D4, value)
#define READ(value) output_bit(PIN_D5, value)
#define X_OR_Y(value) output_bit(PIN_D6, value)
#define FCLK(value) output_bit(PIN_D7, value)
#define SETUP_REGISTERS(register1) DATA_SELECT(register1 & 1);\
X_OR_Y(register1 & 2)
#define CHIP_ON 0
#define CHIP_OFF 1
#define X 0b00000000
#define Y 0b00000010
#define RESET_BP 0b10000001
void output_data_byte(int8 val,int8 register1)
{
SETUP_REGISTERS(register1);
output_b(val);
WRITE(0);
CS(0);
delay_cycles(1);
CS(1);
WRITE(1);
}
int8 input_data_byte(int8 register1)
{
int8 rval;
SETUP_REGISTERS(register1);
READ(0);
rval=DATA; //ensure port is set to input _before_ selecting chip...(assuming 'standard_io' - otherwise you need to set the tris).
CS(0);
delay_cycles(1);
rval=DATA;
CS(1);
READ(1);
return rval;
}
// Reads the 24 bit Count from either X or Y Channels
int32 Read_Position( int axis ) { // read position of encoder
int32 position;
axis<<=1; //using 'X/Y in second bit
output_data_byte(RESET_BP, axis+1); //reset byte pointer (x and y);
position = (int32)input_data_byte(axis); // least significant byte
position += (int32)input_data_byte(axis) << 8; // mid
position += (int32)input_data_byte(axis) << 16; // most significant byte
return position;
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
scaven92
Joined: 06 Oct 2006 Posts: 44
|
|
Posted: Sun Oct 08, 2006 5:09 pm |
|
|
and here is the last part...
Code: | // Reset either X or Y Channel Counter
void Reset_Count( int axis )
{
int32 preset = 0x800000; // Middle value.
output_data_byte(RESET_BP, axis+1);
output_data_byte(preset, axis);
output_data_byte(preset >> 8, axis);
output_data_byte(preset >> 16, axis);
}
void main( void )
{
int32 count = 0;
signed int32 true_count = 0;
count = Read_Position( X ); // Read count of X Channel
true_count = count - 0x800000;
Reset_Count( X );
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Oct 09, 2006 8:59 am |
|
|
You don't want to keep resetting the count. Remember that the chip is potentially counting all the time. If you read, then reset, if a count has occured between these moments, it'll be lost.
You reset at the start of the program only.
Then the question is just how large your counts may become?. This will depend on how far your shaft can turn, and the resolution of the coupler involved. If the likely count will fit in a signed int32, then breath a sigh of relief, use this, and 'sign extend' the 24bit value. You can do this, if it is declared as a signed int32, by simply subtracting 0x800000 after the value is retrieved.
If it won't fit into an int32, then you will need to have custom arithmetic routines to handle larger values.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|