DSA00211720

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 40

a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Interfacing the ADMC401 to the


Stegmann SINCOS® Encoder With

AN401-20

© Analog Devices Inc., January 2000 Page 1 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Table of Contents

SUMMARY...................................................................................................................... 3

1 ENCODERS ............................................................................................................. 3

1.1 Standard Sinusoidal encoders .......................................................................................................................3

1.2 Stegmann’s SINCOS® Encoder with Hiperface®.......................................................................................5

1.3 Encoder Interface Unit (EIU) on the ADMC401 .........................................................................................6

1.4 Required calculations .....................................................................................................................................6

2 HARDWARE ............................................................................................................ 7

2.1 Analogue Circuitry .........................................................................................................................................7


2.1.1 ADC input................................................................................................................................................7
2.1.2 EIU input .................................................................................................................................................8

2.2 Communication Circuitry..............................................................................................................................8

3 THE STEGMANN HIPERFACE® ENCODER ROUTINES ...................................... 9

3.1 Using the Stegmann Hiperface® Encoder Application Routines ...............................................................9

3.2 MathEX.h......................................................................................................................................................11

3.3 Stegmann.h....................................................................................................................................................13

3.4 Stegmann.dsp ................................................................................................................................................27

4 SOFTWARE EXAMPLE: OBTAINING POSITION INFORMATION ...................... 34

4.1 The main program: Main.dsp .....................................................................................................................35

4.2 The main include file: main.h ......................................................................................................................37

4.3 Changing to a 1024-line encoder .................................................................................................................37

5 TESTING THE ACCURACY................................................................................... 38

5.1 DSP results ....................................................................................................................................................38

5.2 Overall System Results.................................................................................................................................39

6 IMPROVEMENTS AND FURTHER WORK............................................................ 40

© Analog Devices Inc., January 2000 Page 2 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Summary
This application note describes how the ADMC 401 may be used solely for the purpose of calculating
position and speed information with the Stegmann SINCOS® Encoder. This application note uses the
Stegmann SCM 60 as the encoder for all calculation and hardware requirements, but any of the Stegmann
SINCOS® encoders may be used, with the relevant changes in the code.
The application note also includes all relevant software modules for serial communications with the
encoder using the Stegmann Hiperface® protocol.

1 Encoders
1.1 Standard Sinusoidal encoders
Sinusoidal encoders encode position information by providing a pair of quadrature sine and cosine signals
as the shaft is rotated. The signals may be generated by optical or magnetic means and typically produce
512 or 1024 cycles per mechanical revolution. For noise immunity the signals are typically transmitted
differentially from the encoder to the sensor interface electronics. A typical interface configuration is
shown in Figure 1.
Differential
Line Receiver
Comparators
+
+ EIA
DSP
- SIN
- Quadrature
Counter
+
+ EIB
- COS
-
Midpoint
SHA

+ Vsin
-
ADC
+ Vcos
-

Figure 1: Typical Sinusoidal Encoder Interface

In order to extract reliable position and speed information from the sinusoidal encoder signals, a certain
amount of pre-conditioning of the analogue signals must be implemented. As a first stage, the differential
SIN and COS signals (typically 1Vpp input signal range) from the sinusoidal encoder must be applied to
input differential amplifiers. This ensures maximum noise immunity and may also be used to
appropriately amplify and level shift the resultant single-ended SIN and COS signals for later input to the
Analogue to Digital Converter (ADC) stage. Next, the SIN and COS signals of Figure 1 are applied to
comparators that generate square-wave, TTL-level signals (EIA & EIB) that are synchronized to the SIN
and COS signals respectively. The relationship between the SIN, COS, EIA and EIB signals is illustrated
in Figure 2.

© Analog Devices Inc., January 2000 Page 3 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

SIN COS

EIA

EIB

EIUCNT N+7 N+6 N+5 N+4 N+3 N+2 N+1 N

ARCTAN Result

Figure 2: Signals Produced by the Sinusoidal Interface

The analogue SIN and COS signals are also fed to dual sample and hold amplifiers (SHA) for subsequent
conversion to digital and post-processing in the digital signal processor (DSP). The signals EIA and EIB
are typically applied to the internal quadrature counter of a dedicated digital Encoder Interface Unit
(EIU)1 as illustrated in Figure 1. The resultant parallel word in the quadrature counter provides the crude
position estimate from the sinusoidal encoder. There are four counts per cycle of the sinusoidal
waveforms (SIN and COS) as seen in Figure 2, and so for a 512 line encoder the maximum count value is
2047 (4*512-1) which provides 11 bits of crude position information. In the case of a 1024-line encoder
the maximum count is 4095 which provides 12 bits of resolution. In the case where the EIB signal leads
the EIA signal, the encoder is determined to be rotating in the reverse direction and the quadrature count
value (EIUCNT) is decremented at each edge of the EIA and EIB signals, as seen in Figure 2. Naturally,
when EIA leads EIB, the quadrature count value is incremented at each event.
Fine position resolution is obtained by further processing the digitized SIN and COS signals to provide
much finer granularity between the EIA and EIB events, as illustrated by the lower waveform of Figure 2.
In some applications, it is necessary to know the initial position of the rotor following power up. There
are different techniques used to obtain this information depending on the particular encoder design. Some
encoder designs provide an alternative pair of sine and cosine signals that provide one cycle per
mechanical revolution, from which it is possible to derive an initial position estimate. Alternatively, some
modern sinusoidal encoders now provide a dedicated serial interface that can be used to extract the initial
position following power up.
During normal operation, the complete position information must be constructed from both the crude and
fine position information. The crude information contains the cycle identification information, which,
depending on the encoder used, can be 11 or 12 bits. The fine information is the result of the calculation
from the sinusoidal signals. With high-resolution analogue to digital conversion of 12 bits on the SIN and
COS, position information to 23/24 bit can be achieved. Since the crude position information is a
quadrature value, the 2 least significant bits (LSB) are the same as the 2 most significant bits (MSB) of
the fine data. Thus, only the 9 MSBs of the crude information are used in the case of a 512-line encoder.
In the case of a 1024 line encoder the first 10 bits are used. The construction of the final position data is
illustrated in Figure 3 for a 512-line encoder.

1
See section 1.3 for information on the operation of the EIU block.

© Analog Devices Inc., January 2000 Page 4 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

N-1 N N+1 N+2

COS SIN

Crude Position Data from EIU


10 0

Overlap Bits
Fine Position Data from SIN/COS Signals
15 0

24 0

Figure 3: Diagram of the relationship between encoder cycles and the position information

1.2 Stegmann’s SINCOS® Encoder with Hiperface®


Stegmann’s Hiperface®2 compatible encoders differ slightly from this configuration as they only output
the 512/1024 SINCOS® waveforms and transmit the other waveform information as digital position
instead. Depending on the encoder, it is possible to obtain up to 15 bits of digital position information. In
the case of the multi-turn encoders it is possible to get 12 bits of multi-turn information, i.e. the number of
complete revolutions. This is seen in the diagram below, Figure 4.

Figure 4:Diagram of the multiturn information supplied by the Stegmann encoder SCM60

The 9 bits plus the first two bits of the 5 bits of information are used to initialise the EIU count value. The
12-bit section contains the multiturn information, which is simply discarded in this example. Finally the
6-bit section contains all zero and is simply padding to fill the 32 bits.
Once this is done the analogue signals are fed into the analogue to digital converter. They are
simultaneously sampled, divided and the result is used in the ARCTAN calculation. The final result is

2
See the Stegmann’s HIPERFACE® Parameter channel booklet for more information on HIPERFACE®

© Analog Devices Inc., January 2000 Page 5 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

combined with the EIU count value giving a 25 bits position information, as seen in Figure 5, where the
final 7 bits are padding zeros to make up the 32 information block.

Figure 5: Diagram of the 32 bit position information supplied by the ADMC401

1.3 Encoder Interface Unit (EIU) on the ADMC401


The encoder interface unit consists of three blocks, the Encoder Loop Timer, Encoder Event Timer Block
and the Encoder Interface Block as labelled in Figure 6. In this example the EIU is used with all the
defaults, and so no set-up is required other than the initialisation of EIUMAXCNT. This is required to
start the EIU. As indicated in the ADMC401 datasheet the value to be written to this register is 4N-1,
where N is the number of lines on the encoder. In this case N is 512 and so the value written is 2047. It is
possible to set-up filtering on the input to the interface by increasing the value of EIUFILTER. This
defaults to the smallest value, zero, on reset. As the signal is already processed externally there is no need
for software filtering.
Encoder Loop Timer Encoder Event Timer Block
Clock Divider EETDIV(15::0)
Encoder Event EETSTAT(0)
EIUSCALE (7:0) Time Out Timer
EETT(15::0)
EIUTIMER (15:0) Pulse
Decimator EETDELTAT(15::0)
EIUPERIOD(15:0)
EETN(7::0)
Quadrature Signal
Direction

EETCNT(15...0)
EIA A EIUCNT(15...0)
16-bit Quadrature EIUMAXCNT(15…0)
EIB B UP/DOWN Counter EIUCTRL(8...0)
PROGRAMMABLE EIUSTAT(7...0)
NOISE
EIZ FILTERING EISLATCH(15…0)
Z
Encoder Counter EIZLATCH(15...0)
EIS S
Control EIUFILTER(5...0)

Encoder Interface Block

Figure 6: The EIU block diagram for the ADMC401

1.4 Required calculations


Once the initial position is obtained, the EIU is used to keep track of which cycle of the 512/1024 the
encoder is in. The analogue signals are converted (digitised), divided (SINCOS®) which results in the
TAN(θ) as Equation (1) illustrates.

V 
θ fine = tan −1  sin  (1)
 Vcos 

© Analog Devices Inc., January 2000 Page 6 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

An ARCTAN calculation is carried out and the result of combined with the EIU value to produce position
information.

2 Hardware
The following describes the additional hardware necessary to 1) process the analogue signals produced by
the encoder and 2) to communicate with the encoder using the Hiperface® protocol. The analogue
hardware on the ADMC401-PB (processor board) is not discussed in this application note. To fully
understand this application note it is necessary to first read and understand the working of the analogue to
digital converter. This is explained in the Application Note: ADC-system on the ADMC401, number
AN401-53.

2.1 Analogue Circuitry

2.1.1 ADC input

Figure 7: Analogue differential, gain and TTL configuration of the encoder signals

The analogue signals4, (sin, cos, refsin, refcos), produced by the encoder are differential, 1 volt peak to
peak waveforms. Thus, a differential amplifier (AD8044AR5) is required to convert them to single ended

3
This document may be download from the Analog Devices Inc. website.
4
See the Stegmann’s SCM60 datasheet at www.Stegmann.com for further information about the signals
produced by the encoder.
5
See the Analog Devices Inc. datasheet on the AD8044AR for further information.

© Analog Devices Inc., January 2000 Page 7 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

signals suitable to feed into the ADMC401. These signals are amplified to approximately 4 volts peak to
peak to obtain the best resolution from the A/D converter. The resulting waveforms are fed into IF2A PIN
1 (Sin) and IF2A PIN 5 (Cos). See Figure 7 for the recommended circuitry. The circuit contains two
variable resistors. These are used to ensure that the sin and cos peak to peak voltages are the same and
less than or equal to 4 volts peak to peak. They should be calibrated using an oscilloscope before the
program is run.
It is possible to digitally filter the signals by making use of the fact that the ADMC401 permits 4 pairs of
signals to be simultaneously sampled. If one wishes to do this it is necessary to feed the Sin signal into
PINS 2,3,4 of IF2A and the Cos signal into PINS 6,7,8 of IF2A. Then at the very simplest, one could
acquire the average by adding the results and shifting right by 2 in the shifter block. This process has its
problems.
If the motor is running at 3000 rpm, then the encoder is producing 1536000 cycles of both Sin and Cos
waves per minute. Which is equivalent to 25.6 kHz. It takes 1.88 µs to convert all 8 A/D channels. The
time between the first sample and hold and the last is 1 µs, which means that the cycle has moved through
9.2 electrical degrees. These samples may be too far apart to be used as an average for the filter
depending on the application. In this application note it was decided not to implement this type of filter,
instead it uses only the signals samples at pins 1 and 5 of IF2A with no filtering.

2.1.2 EIU input


The Sin and Cos waveforms are fed into a comparator, the output of which is fed into the EIU interface
on the ADMC401-CB (connector board) through pins 9-IF3A and 9-IF3B. The EIU takes two square
wave signals 90 degrees out of phase and counts the number of edges. Therefore, with the Stegmann
SCM60 which has 512 SINCOS® cycles per revolution will produce an EIU count of (512*4) 2048.
There are two ways to reset the EIU count value. The first involves a north marker. This is a signal, which
occurs once per revolution, indicating the start of a new revolution. The second involves a software reset.
There is no north marker signal on the encoder so pin 9 of IF3C on the ADMC401-CB is connected to
ground. The software reset will be explained later.
The ADMC401-CB contains a differential line receiver (DS26LS32) which is also connected directly to
the pins used above. Since this circuitry bypasses this chip it necessary to lift legs 3,5 and 11 and so break
the connection. This is done to prevent the chip from introducing noise into the system.

2.2 Communication Circuitry


To communicate with the encoder one needs a differential line transceiver suitable for high-speed bi-
directional data communication. The ADM485AN6 was chosen in this case. The pin outs for the
ADM485 are as follows.

ADM485AN Connection
Pin 1 Pin 26 and Pin 27 of IF1A of ADMC401
Pin 2 Pin 25 of IF1A of ADMC401
Pin 3 Pin 2 of ADM485AN
Pin 4 Pin 28 of IF1A of ADMC401

6
See the Analog Devices Inc. datasheet on the ADM485AN for further information.

© Analog Devices Inc., January 2000 Page 8 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Pin 5 Gnd
Pin 6 Data Positive of the encoder
Pin 7 Data Negative of the encoder
Pin 8 5 volts

Figure 8: Communication configuration between the Encoder and the ADMC401


Figure 8 shows the recommended communication circuitry for the Stegmann Hiperface® Encoder. Note
the 130Ω terminating resistor.

3 The Stegmann Hiperface® Encoder Routines


3.1 Using the Stegmann Hiperface® Encoder Application Routines
These application routines provide various functions that configure and enable the ADMC401 to obtain
position information from the Encoder. With the use of ADIs Standard Motor Control Library (see
Library Documentation File) an example is given which demonstrate position and speed calculation. The
position information is treated as an unsigned fraction, which goes from 0x0 to 0xFFFFFF80 representing
0 to 360 degrees. In addition, the UART interface routines from the standard library are required for serial
communication7.
The routines are developed as easy-to-use blocks, which must be linked with the used library functions to
build the complete application software. The routines for this application consist of five files.
File name Usage
Main.dsp (dsp,h) Set up interrupt structure and makes use of the application routines
Stegmann (dsp, h) Stegmann Hiperface® Encoder Application Routines
MathEx (h) Additional Macros for Bit-Manipulation

Table 1: Files used with the Stegmann Hiperface® Encoder application routines

7
AN401-08: Using Serial Port 0 of the ADMC401 as a UART Interface

© Analog Devices Inc., January 2000 Page 9 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

As with the structure from the ADIs Standard Motor Control Library, macros are defined. For this
application three macros are used for configuration and update in the code. The following table
summarises the set of macros that are defined in “stegmann.h”.

Macro name Function

Stegmann_Init_Total_Pos Initialize the encoder and position variables at startup


Stegmann_GetPosition Get the encoder position
Stegmann_GetSpeed Get the encoder speed

Table 2:Macros ultilised in the main.dsp file


The following Table 3 provides a list of functions implemented in Stegmann.h and their relevant
command number. Not all the Stegmann encoders provide all these functions. For more information on
their use and structure consult the Stegmann’s Encoder datasheet. Only one of these functions is used in
the Stegmann.dsp library namely Stegmann_read_Enc_Pos.
Macro name Encoder Command Function
Code
Stegmann_read_Enc_Pos 42H Read encoder position
Stegmann_Set_position 43H Set encoder position
Stegmann_Read_Analogue_value 44H Read analogue value
Stegmann_Read_Counter 46H Read counter
Stegmann_Increment_Counter 47H Increment counter
Stegmann_Clear_Counter 49H Clear counter
Stegmann_read_data 4AH Read data
Stegmann_store_data 4BH Store data
Stegmann_status_data 4CH Determine status of a data field
Stegmann_create_data 4DH Create a data field
Stegmann_available_memory 4EH Determine available memory
Stegmann_change_acc_code 4FH Change access code
Stegmann_encounter_status 50H Read encoder status
Stegmann_read_type_lable 52H Read type label
Stegmann_reset 53H Reset encoder
Stegmann_allocate_Address 55H Allocate encoder address
Stegmann_read_Serial_No_and_Prog_Ver 56H Read serial number and program version

© Analog Devices Inc., January 2000 Page 10 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Stegmann_Configure_Serial_Interface 57H Configure serial interface


Stegmann_Output_Ref_Signal 5FH Output reference signal repeatedly

Table 3: Implemented Macros and code numbers

As will be seen in Section 4.2, these routines require a configuration constant, which is declared in a
dedicated section of the main include-file "main.h". If a routine requires internal configuration constants
they are declared in the associated include-file "stegmann.h". The following section will explain each of
the routines in details linked with the relevant segments of code that are found in any of the files
described in Table 3.

3.2 MathEX.h
Due to the need to calculate the parity (Check Sum) of all data sent via the serial interface to the
encoder, a library file that incorporates three XOR macros is provided.
The macro MathsEX_XORMATH2n is used to XOR two numbers or registers, and place the result in the
third parameter, usually the data memory address of Check Sum. The second macro takes one number or
register and XOR’s it with a data memory and places the result in the third parameter. The final macro takes
two data memory address and places the result of the XOR operation in the data memory address indicated
by the final parameter.
{***************************************************************************************
* *
* Library: Macros for the Stegmann Encoder *
* *
* File: MathEx.h *
* *
* Description: Math XOR library *
* Purpose : Additional XOR macros to aid in check sum calculations *
* *
* Author : JB *
* Version : 1.0 *
* Date : January 2000 *
* Modification History: None *
* *
* Embedded Control Systems *
* Analog Devices Inc. *
***************************************************************************************}
{***************************************************************************************
* *
* Other Libraries Required by this Module: *
* *
* none *
***************************************************************************************}

#ifndef mathsEx_included
#define mathsEx_included

{***************************************************************************************
* Routines Defined in this Module *
***************************************************************************************}

{ None }

{***************************************************************************************
* Global Variables Defined in this Module *
***************************************************************************************}

{ None }

{***************************************************************************************

© Analog Devices Inc., January 2000 Page 11 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

* *
* Type: Macro *
* *
* Call: MathsEX_XORMATH2N(%0,%1,%2); *
* *
* Get the encoder position *
* *
* Inputs : %0: Number or register *
* %1: Number or register *
* *
* Ouputs : %2: Data memory pointer (Checksum) *
* *
* Modified: AX0, AY0, AR *
* *
***************************************************************************************}

.MACRO MathsEX_XORMATH2N(%0,%1,%2);
AX0=%0;
AY0=%1;
AR=AX0 XOR AY0;
DM(%2)=AR;
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: MathsEX_XORMATH1N(%0,%1,%2); *
* *
* Get the encoder position *
* *
* Inputs : %0: Number or register *
* %1: Data memory pointer *
* *
* Ouputs : %2: Data memory pointer (Checksum) *
* *
* Modified: AX0, AY0, AR *
* *
***************************************************************************************}

.MACRO MathsEX_XORMATH1N(%0,%1,%2);
AX0=%0;
AY0=DM(%1);
AR=AX0 XOR AY0;
DM(%2)=AR;
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: MathsEX_XORMATH0N(%0,%1,%2); *
* *
* Get the encoder position *
* *
* Inputs : %0: Data memory pointer *
* %1: Data memory pointer *
* *
* Ouputs : %2: Data memory pointer (Checksum) *
* *
* Modified: AX0, AY0, AR *
* *
***************************************************************************************}

.MACRO XORMATH0N(%0,%1,%2);
AX0=DM(%0);
AY0=DM(%1);
AR=AX0 XOR AY0;
DM(%2)=AR;
.ENDMACRO;
#endif

© Analog Devices Inc., January 2000 Page 12 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

3.3 Stegmann.h
This library includes all the macros for communicating with the Stegmann Encoder, as well as
some additional macros for manipulating some of the results.
{***************************************************************************************
* *
* Library: Macros for the Stegmann Encoder *
* *
* File: stegmann.h *
* *
* Description: Stegmann include file *
* Purpose : Macros for the Stegmann Encoder *
* *
* Author : JB *
* Version : 1.0 *
* Date : January 2000 *
* Modification History: None *
* *
* Embedded Control Systems *
* Analog Devices Inc. *
***************************************************************************************}
This constant is the address of the encoder that you wish to communicate with. 0x40 is the default address of
all Stegmann encoders.
{***************************************************************************************
* *
* Constants that need to be defined in main.h: *
* *
* .CONST addressOfEncoder = 0xxx; !The serial address of the encoder *
***************************************************************************************}

{***************************************************************************************
* *
* Other Libraries Required by this Module: *
* *
* uart0.dsp *
* adc401.dsp *
* trigono.dsp *
***************************************************************************************}

#ifndef stegmann_included
#define stegmann_included

#include <mathsEx.h>;

The two external definitions will be explained later in Stegmann.dsp. It is enough for now to say that
Stegmann_getAnalogPosition is a macro, that when called, places the analogue position value in the AR
register. The function Stegmann_Init sets up all the relevant parameters so that the ADMC401 and the
Stegmann encoder are ready to produce position information.
{***************************************************************************************
* Routines Defined in this Module *
***************************************************************************************}

.EXTERNAL Stegmann_GetAnaloguePosition_;
.EXTERNAL Stegmann_Init_;
The variable checkSum is used to hold the value of the check sum value. This is the final packet of data sent
to the encoder at the end of each instruction. It consists of all the previous packets in that instruction XORed.
{***************************************************************************************
* Global Variables Defined in this Module *
***************************************************************************************}

.EXTERNAL checkSum;
.EXTERNAL digitalPosMSB;
.EXTERNAL digitalPosLSB;
This macro combines the cycle information with the fine analogue information. Since there is a slight time
delay between getting the simultaneous samples and the getting of the EIU count, under certain conditions

© Analog Devices Inc., January 2000 Page 13 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

combining the two words of position information would result in getting the wrong answer. For instance,
assume the encoder is moving in the forward direction and at a point where it is moving from one cycle of the
512 to another. If the analogue position is taken and lets say the result is 0x7FAA. Next the EIU count value
is read, but by now the encoder is in the new cycle and the value would be 0X0A8. Combining this
information would result in the wrong answer. This is corrected for in the algorithm as follows. The
analogue information is the most accurate and most up to date and so is not altered. Instead 1 is added to the
EIU count value that lags the analogue value. Visa versa 1 is subtracted from the EIU count that leads the
analogue value.
{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_GetPosition(MSB,LSB); *
* *
* Get the encoder position *
* *
* Inputs : none *
* *
* Ouputs : %0:MSB of the mechanical position in 0.16 format(direction is clock wise)*
* %1:LSB of the mechanical position *
* *
* Modified: AX0, AX1, AY0, AY1, AR, AF, SR0, SR1 SI, SE MR0, MR1, *
* MX1, MY0, MY1, MF, I5, M5, L5 *
* *
***************************************************************************************}
.MACRO Stegmann_GetPosition(%0,%1);
.local crude_one;
.local fine_fb_zero;
.local end_of_alignment;

CALL Stegmann_GetAnaloguePosition_;
AX0 = AR;
SI=DM(EIUCNT);
SR=ASHIFT SI by -2 (hi);

AX1 = SR0;
AY1 = SR1;

AF=tstbit 15 of AX0;
IF EQ jump fine_fb_zero; !First bit of the analogue position information is zero check
AF=tstbit 14 of AX0;
IF NE jump crude_one; !Second bit of the analogue position information is one check
jump end_of_alignment; ! If neither are true then alignment is OK jump to end

crude_one:
AF=tstbit 15 of AX1; !Test first bit of the cycle information
IF NE jump end_of_alignment; !If equal to one finished, jump to end
AR=AY1-1; !If equal to zero then the cycle position is ahead,
!and must be aligned.
AY1=AR;
jump end_of_alignment; !jump to end

fine_fb_zero:
AF=tstbit 14 of AX0; !test the second bit of analogue information
IF NE jump end_of_alignment; !If equal to one jump to end of alignment
AF=tstbit 15 of AX1; !test the first bit of the cycle information
IF EQ jump end_of_alignment; !If equal to one jump to the end of alignment
AR=AY1+1; !Otherwise align by adding one to the cycle information
AY1=AR;

end_of_alignment:

AR=AX0;
SR=LSHIFT AR by 7 (lo); !Shift the analogue position information by 7 (9(2^9=512)-
2(unused))
DM(%1)=SR0; !place the lower half of the position information into the
!second parameter

© Analog Devices Inc., January 2000 Page 14 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

SI=AY1; !place the cycle information in a shiftable register


SR=SR OR LSHIFT SI by 7(hi); !shift the cycle information by 7 so align with analogue
!signal and OR it with the previous result
DM(%0)=SR1; !Store the answer in the first parameter

.ENDMACRO;
The Stegmann_GetSpeed result is computed as a simple position difference between sample instants, in other
words, the 32-bit difference between the current and previous position information. It is left to the user to
scale the result to the appropriate format. It should be noted that a more comprehensive speed routine maybe
required, has this routine does not account for the roll over between cycles.
{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_GetSpeed(New_Pos_MSB,New_Pos_LSB,Old_Pos_MSB,Old_Pos_LSB, *
* speed_MSB,speed_LSB); *
* *
* Calculates the speed *
* *
* Inputs : %0:New position information MSB (Data Memory) *
* %1:New position information LSB (Data Memory) *
* %2:Old position information MSB (Data Memory) *
* %3:Old position information LSB (Data Memory) *
* *
* Ouputs : %4:Speed information MSB (Register) *
* %5:Speed information LSB (Register) *
* *
* Modified: AX0,AX1,AY0,AY1,AR, *
* *
***************************************************************************************}

.MACRO Stegmann_GetSpeed(%0,%1,%2,%3,%4,%5);
.local Back_dir;
.local forward_dir;
.local endspeed;

{store the previous and present position and subtract them => speed}

AX0=DM(%1);
AX1=DM(%0);
AY0=DM(%3);
AY1=DM(%2);
AR=AX0-AY0;
AR=DM(EIUCTRL);
AR=tstbit 0 of AR;
IF EQ jump forward_dir;
Back_dir:
AR=AY0-AX0;
%5=AR;
AR=AY1-AX1+C-1;
%4=AR;
jump endspeed;
forward_dir:
AR=AX0-AY0;
%5=AR;
AR=AX1-AY1+C-1;
%4=AR;
endspeed:
nop;
.ENDMACRO;

Stegmann_Init_Total_Pos is used to initialise the position information. The first time, due to the length of the
algorithm it is necessary to prevent the PWM interrupt from interrupting the initialisation of the EIU count
value and communication with the encoder. This is the only time serial communication is done with the
encoder.

© Analog Devices Inc., January 2000 Page 15 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_Init_Total_Pos(New_Pos_MSB,New_Pos_LSB); *
* *
* This macro gets the inital position of the encoder at startup. The encoder must be at*
* rest in order for this routine to work. *
* *
* Inputs : none *
* *
* Ouputs : %0:The initial position information MSB *
* %1:The initial position information LSB *
* *
* Modified: AX0, AX1, AY0, AY1, AR, AF, SR0, SR1, SE, SI CNTR, MR0, MR1, MF, *
* MX1, MY0, MY1, I5, M5, L5 *
* *
***************************************************************************************}

.MACRO Stegmann_Init_Total_Pos(%0,%1);

{to avoid the interupt routine been called before the


setup is complete mask interupt IRQ2}

AR=IMASK;
AR=CLRBIT 9 of AR;
IMASK =AR;

CALL Stegmann_Init_;
DM(%1)=AX0;
DM(%0)=AR;

{Re-enable the interupt routine}

AR=IMASK;
AR=SETBIT 9 of AR;
IMASK =AR;

.ENDMACRO;
Since all communication is done in 8 bit format, storing this information in 8-bit format
would be wasteful. Stegmann_PutTogetherDM combines two on these data blocks into a single 16 bit word.
{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_putTogetherDM(DM_memory,DM_memory,DM_memory); *
* *
* Since all communication is done in 8 bit format, storing this information in 8-bit *
* format would be wasteful. putTogetherDM put two on these data blocks together. *
* *
* Input: %0:data memory address or flag *
* %1:data memory address or flag *
* *
* output: %2:data memory address or flag *
* *
* Modified: SI,SR,AR,AY0 *
* *
***************************************************************************************}

.MACRO Stegmann_putTogetherDM(%0,%1,%2);
SI=DM(%0);
SR=lshift SI by 8 (LO);
AY0=DM(%1);
AR=SR0+AY0;
DM(%2)=AR;
.ENDMACRO;

© Analog Devices Inc., January 2000 Page 16 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

The following is the implementation of functions offered by the Stegmann Encoder range. Not all the
Stegmann encoders provide all these functions. For more information on their use and structure consult the
Stegmann’s Encoder datasheet. Only one of these functions is used in the Stegmann.dsp library namely
Stegmann_read_Enc_Pos. This function is explained below. Table 3 is provided in section 3.1 which lists the
functions implemented in Stegmann.h and their relevant command number.
Stegmann_Read_Enc_Pos takes one parameter, the encoder address, which in this case is the constant
defined at the bottom of the Main.h file addressOfEncoder. First the address packet is sent. Next the
command packet is sent i.e. 0x42. Finally the checkSum packet is sent. The program then waits for the
encoder to return the encoder position 4 packets of 8 bits. This information is stored in Data Memory
address return3 through return6. Note that each time UART0_ Read_ is called AX0 holds the result. In this
case the first two calls are not stored, as they have no relevant information. The first call being the encoder
address and the second the command sent to the encoder. The final UART0_ Read_ call is not stored. It
contains the returned CheckSum value. If error checking were to be implemented then it would be necessary
to store this information. Finally, to save on space the first two packets are combined and placed in Data
Memory address digitalPosMSB, The second two packets are combined and placed in digitalPosLSB. (Note
no further macros are explained in this section. Section 3.4 is the next segment of explained code.)
{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_set_position(encoder address,upper position bits,lower position bits);*
* *
* see the Stegmann data sheet for the relevant format of the position *
* *
* Inputs : %0:encoder address *
* %1:upper position bits *
* %2:lower position bits *
* *
* Ouputs : none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0 SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_set_position(%0,%1,%2);
DM(checkSum)=0;
MathsEX_XORMATH2N(%0,0x43,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X43; !Command
Call UART0_Write_;
AR=%1;
SR=ASHIFT AR by 8 (lo);
AX0=SR1; !Byte 0
MathsEX_XORMATH1N(AX0,checkSum,checkSum);
Call UART0_Write_;
AX0=SR0; !Byte 1
MathsEX_XORMATH1N(AX0,checkSum,checkSum);
Call UART0_Write_;
AR=%2;
SR=ASHIFT AR by 8 (lo);
AX0=SR1; !Byte 2
MathsEX_XORMATH1N(AX0,checkSum,checkSum);
Call UART0_Write_;
AX0=SR0; !Byte 3
MathsEX_XORMATH1N(AX0,checkSum,checkSum);
Call UART0_Write_;
AX0=0; !Code 0
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;

Call UART0_Read_; !Address


Call UART0_Read_; !Command
Call UART0_Read_; !Check Sum
.ENDMACRO;

© Analog Devices Inc., January 2000 Page 17 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_allocate_Address(Old address, New address) *
* *
* Allocates a new address to the encoder *
* *
* Inputs : %0:encoders old address *
* %1:encoders new address *
* *
* Ouputs : none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_allocate_Address(%0,%1);
MathsEX_XORMATH2N(%0,0X55,checkSum);
MathsEX_XORMATH1N(%1,checkSum,checkSum);
MathsEX_XORMATH1N(0x55,checkSum,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X55; !Command
Call UART0_Write_;
AX0=%1; !new address
Call UART0_Write_;
AX0=0x55; !code zero
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;

Call UART0_Read_; !Address


Call UART0_Read_; !Command
Call UART0_Read_; !Check Sum

.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_Read_Analogue_Value(encoder address, channell, data memory flag) *
* *
* Inputs : %0:encoder address *
* %1:channel that must be converted *
* *
* Ouputs : %2:memory address to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR, I0, M0 *
* *
***************************************************************************************}

.MACRO Stegmann_Read_Analogue_Value(%0,%1,%2);
MathsEX_XORMATH2N(%0,%1,checkSum);
MathsEX_XORMATH1N(0x44,checkSum,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X44; !Command
Call UART0_Write_;
AX0=%1; !Channel
Call UART0_Write_;
AX0=DM(checkSum);
Call UART0_Write_;
I0=^%2;
M0=1;
Call UART0_Read_; !Address
Call UART0_Read_; !Command
Call UART0_Read_; !Channel

© Analog Devices Inc., January 2000 Page 18 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Call UART0_Read_; !High Byte


DM(I0,M0)=AX0;
Call UART0_Read_; !Low Byte
DM(I0,M0)=AX0;
Call UART0_Read_; !Check Sum

.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_read_Type_Lable(encoder address, data memory flag) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:data memory address to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR, I0, M0 *
* *
***************************************************************************************}

.MACRO Stegmann_read_Type_Lable(%0,%1);
I0=^%1;
M0=1;
MathsEX_XORMATH2N(%0,0x52,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X52; !Command
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;

Call UART0_Read_; !Address


Call UART0_Read_; !Command
Call UART0_Read_; !Mode_RS485
DM(return3)=AX0;
Call UART0_Read_; !Type
DM(return4)=AX0;
Stegmann_putTogetherDM(return3,return4,return1); !ar = return1;
DM(I0,M0)=AR;
Call UART0_Read_; !EEPR_Size
DM(return5)=AX0;
Call UART0_Read_; !Options
DM(return6)=AX0;
Stegmann_putTogetherDM(return5,return6,return2); !ar = return2;
DM(I0,M0)=AR;
Call UART0_Read_; !Check Sum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_reset(encoder address) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO stegmann_reset(%0);
MathsEX_XORMATH2N(%0,0X53,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X53; !Command
Call UART0_Write_;
AX0=DM(checkSum); !Check sum

© Analog Devices Inc., January 2000 Page 19 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Call UART0_Write_;
!No return
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_read_Serial_No_and_Prog_Ver(encoder address, data memory flag) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:data memory flag to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR, I0, M0 *
* *
***************************************************************************************}

.MACRO Stegmann_read_Serial_No_and_Prog_Ver(%0,%1);
.local END_READ_SERIAL_NO;
I0=^%1;
M0=1;
MathsEX_XORMATH2N(%0,0X56,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X56; !Command
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;

Call UART0_Read_; !Address


Call UART0_Read_; !command
CNTR=15;
do END_READ_SERIAL_NO until CE;
Call UART0_Read_;
DM(return3)=AX0;
Call UART0_Read_;
DM(return4)=AX0;
puttogetherDM(return3,return4,return3); !ar=retunr3
DM(I0,M0)=AR;
END_READ_SERIAL_NO:
nop;
Call UART0_Read_;
DM(return5)=AX0; !checkSum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_Output_Ref_Signal(encoder address) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_Output_Ref_Signal(%0);
MathsEX_XORMATH2N(%0,0X54,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X54; !Command
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;
!No return
.ENDMACRO;

© Analog Devices Inc., January 2000 Page 20 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_Clear_Counter(encoder address) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_Clear_Counter(%0);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X49; !Command
Call UART0_Write_;
AX0=0x55; !Zero Code
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;

Call UART0_Read_; !Address


Call UART0_Read_; !Command
Call UART0_Read_; !Check Sum

.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_Increment_Counter(encoder address) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_Increment_Counter(%0);
MathsEX_XORMATH2N(%0,0x47,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X47; !Command
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;

Call UART0_Read_; !Address


Call UART0_Read_; !Command
Call UART0_Read_; !Check Sum

.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_Read_Counter(encoder address, data memory flag) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:data memory flag to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR, I0, M0 *
* *

© Analog Devices Inc., January 2000 Page 21 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

***************************************************************************************}

.MACRO Stegmann_Read_Counter(%0,%1);
MathsEX_XORMATH2N(%0,0x46,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X46; !Command
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;
I0=^%1;
M0=1;
Call UART0_Read_; !Address
Call UART0_Read_; !Command
Call UART0_Read_; !Byte 0
DM(I0,M0)=AX0;
Call UART0_Read_; !Byte 1
DM(I0,M0)=AX0;
Call UART0_Read_; !Byte 2
DM(I0,M0)=AX0;
Call UART0_Read_; !Check Sum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_read_Data(encoder address, datafield, start address, number, code, *
* flag to the block of memory) *
* *
* Inputs : %0:encoder address *
* %1:datafield *
* %2:start address *
* %3:number of blocks *
* %4:access code *
* *
* Ouputs : %5:Data memory flag to the block of memory to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR, I0, M0 *
* *
***************************************************************************************}

.MACRO Stegmann_read_Data(%0,%1,%2,%3,%4,%5);
.local read_data_loop;

MathsEX_XORMATH2N(%0,0x4A,checkSum);
MathsEX_XORMATH1N(%1,checkSum,checkSum);
MathsEX_XORMATH1N(%2,checkSum,checkSum);
MathsEX_XORMATH1N(%3,checkSum,checkSum);
MathsEX_XORMATH1N(%4,checkSum,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X4A; ! read data
Call UART0_Write_;
AX0=%1; ! data field
Call UART0_Write_;
AX0=%2; ! start address
Call UART0_Write_;
AX0=%3; ! number
Call UART0_Write_;
AX0=%4; ! code
Call UART0_Write_;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;

Call UART0_Read_; !1 !Address


Call UART0_Read_; !2 !read data
Call UART0_Read_; !3 ! data field
Call UART0_Read_; !4 ! start address
Call UART0_Read_; !5 ! number

© Analog Devices Inc., January 2000 Page 22 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

CNTR=%3;
I0=^%5;
M0=1;
do read_data_loop until ce;
Call UART0_Read_; !6
DM(I0,M0)=AX0;
read_data_loop:
nop;
Call UART0_Read_; !7

.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_store_Data(encoder address, datafield, start address, number, code, *
* flag to the block of memory) *
* *
* *
* Inputs : %0:encoder address *
* %1:datafield *
* %2:start address *
* %3:number of blocks *
* %4:access code *
* *
* Ouputs : %5:Data memory flag to the block of memory to hold the answer *
* *
* Modified: AX0, AX1, AY0, AY1, AR, AF, SR0, SR1, SE, SI CNTR, MR0, MR1, MF, *
* MX1, MY0, MY1, I5, M5, L5 *
* *
***************************************************************************************}

.MACRO Stegmann_store_Data(%0,%1,%2,%3,%4,%5);
.local store_data_loop;
!not implemented

MathsEX_XORMATH2N(%0,0x4B,checkSum);
MathsEX_XORMATH1N(%1,checkSum,checkSum);
MathsEX_XORMATH1N(%2,checkSum,checkSum);
MathsEX_XORMATH1N(%3,checkSum,checkSum);
MathsEX_XORMATH1N(%4,checkSum,checkSum);

AX0=%0; !Address
Call UART0_Write_;
AX0=0X4B; !store data
Call UART0_Write_;
AX0=%1; ! data field
Call UART0_Write_;
AX0=%2; ! start address
Call UART0_Write_;
AX0=%3; ! number
Call UART0_Write_;
AX0=%4; ! code
Call UART0_Write_;
CNTR=%3;
I0=^%5;
M0=1;
do store_data_loop until ce;
AX0=DM(I0,M0);
MathsEX_XORMATH1N(AX0,checkSum,checkSum);
Call UART0_Write_; !6
store_data_loop:
nop;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;

Call UART0_Read_; !1 !Address


Call UART0_Read_; !2 !store data
Call UART0_Read_; !3 ! data field
Call UART0_Read_; !4 ! start address

© Analog Devices Inc., January 2000 Page 23 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Call UART0_Read_; !5 ! number


Call UART0_Read_; !6 !check sum

.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_status_Data(encoder address, datafield, flag to the block of memory) *
* *
* Inputs : %0:encoder address *
* %1:datafield *
* *
* Ouputs : %2:Data memory flag to the block of memory to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_status_data(%0,%1,%2);
MathsEX_XORMATH2N(%0,0x4C,checkSum);
MathsEX_XORMATH1N(%1,checkSum,checkSum);

AX0=%0; ! Address
Call UART0_Write_;
AX0=0X4C; ! status data
Call UART0_Write_;
AX0=%1; ! data field
Call UART0_Write_;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;

Call UART0_Read_; !1 ! Address


Call UART0_Read_; !2 ! status data
Call UART0_Read_; !3 ! data field
Call UART0_Read_; !4 ! status
DM(%2)=AX0;
Call UART0_Read_; !5 ! check sum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_create_Data(encoder address, datafield, status, code) *
* *
* Inputs : %0:encoder address *
* %1:datafield *
* %2:status *
* %3:access code *
* *
* Ouputs : none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_create_data(%0,%1,%2,%3);
MathsEX_XORMATH2N(%0,0x4D,checkSum);
MathsEX_XORMATH1N(%1,checkSum,checkSum);
MathsEX_XORMATH1N(%2,checkSum,checkSum);
MathsEX_XORMATH1N(%3,checkSum,checkSum);

AX0=%0; !Address
Call UART0_Write_;
AX0=0X4D; ! create data
Call UART0_Write_;
AX0=%1; ! data field
Call UART0_Write_;
AX0=%2; ! status

© Analog Devices Inc., January 2000 Page 24 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Call UART0_Write_;
AX0=%3; ! code
Call UART0_Write_;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;

Call UART0_Read_; !1 ! Address


Call UART0_Read_; !2 ! create data
Call UART0_Read_; !3 ! data field
Call UART0_Read_; !4 ! status
Call UART0_Read_; !5 ! check sum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_available_memory(encoder address, flag to the block of memory) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:Data memory flag to the block of memory to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR, I0, M0 *
* *
***************************************************************************************}

.MACRO Stegmann_available_memory(%0,%1);
MathsEX_XORMATH2N(%0,0x4E,checkSum);

AX0=%0; !Address
Call UART0_Write_;
AX0=0X4E; ! available data memory
Call UART0_Write_;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;
I0=^%1;
M0=1;
Call UART0_Read_; !1 ! Address
Call UART0_Read_; !2 ! available data memory
Call UART0_Read_; !3 ! availsize
DM(I0,M0)=AX0;
Call UART0_Read_; !4 ! def_Nr
DM(I0,M0)=AX0;
Call UART0_Read_; !5 ! check sum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_change_Acc_Code(encoder address, code_Nr, old code, new code) *
* *
* Inputs : %0:encoder address *
* %1:coder Nr *
* %2:old code *
* %3:new code *
* *
* Ouputs : none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_change_Acc_Code(%0,%1,%2,%3);
MathsEX_XORMATH2N(%0,0x4F,checkSum);
MathsEX_XORMATH1N(%1,checkSum,checkSum);
MathsEX_XORMATH1N(%2,checkSum,checkSum);
MathsEX_XORMATH1N(%3,checkSum,checkSum);

AX0=%0; !Address

© Analog Devices Inc., January 2000 Page 25 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Call UART0_Write_;
AX0=0X4F; ! change acc code
Call UART0_Write_;
AX0=%1; ! code_Nr
Call UART0_Write_;
AX0=%2; ! old code
Call UART0_Write_;
AX0=%3; ! new code
Call UART0_Write_;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;

Call UART0_Read_; !1 ! Address


Call UART0_Read_; !2 ! change acc code
Call UART0_Read_; !3 ! code_Nr
Call UART0_Read_; !4 ! check sum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_encoder_Status(encoder address,flag to data memory to hold the answer)*
* *
* Inputs : %0:encoder address *
* *
* Ouputs : %1:flag to data memory to hold the answer *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_encounter_Status(%0,%1);
MathsEX_XORMATH2N(%0,0x50,checkSum);

AX0=%0; !Address
Call UART0_Write_;
AX0=0X50; ! encounter status
Call UART0_Write_;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;

Call UART0_Read_; !1 ! Address


Call UART0_Read_; !2 ! encounter status
Call UART0_Read_; !3 ! error
DM(%1)=AX0;
Call UART0_Read_; !4 ! check sum
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_read_Enc_Pos(encoder address) *
* *
* Inputs : %0:encoder address *
* *
* Ouputs : none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_read_Enc_Pos(%0);
MathsEX_XORMATH2N(%0,0x42,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0x42; !read position
Call UART0_Write_;
AX0=DM(checkSum); ! check sum
Call UART0_Write_;

© Analog Devices Inc., January 2000 Page 26 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Call UART0_Read_;
Call UART0_Read_;
Call UART0_Read_;
DM(return3)=AX0;
Call UART0_Read_;
DM(return4)=AX0;
Call UART0_Read_;
DM(return5)=AX0;
Call UART0_Read_;
DM(return6)=AX0;
Call UART0_Read_;
DM(return7)=AX0;
Stegmann_putTogetherDM(return3,return4,digitalPosMSB);
Stegmann_putTogetherDM(return5,return6,digitalPosLSB);
.ENDMACRO;

{***************************************************************************************
* *
* Type: Macro *
* *
* Call: Stegmann_Configure_Serial_Inferface(encoder address, Mode_485, code) *
* *
* Inputs : %0:encoder address *
* %1:Mode_485 information *
* %2:zero code *
* *
* Ouputs : none *
* *
* Modified: AX0, AY0, AY1, AR, MR0, MR1, SR0, SR1, CNTR *
* *
***************************************************************************************}

.MACRO Stegmann_Configure_Serial_Interface(%0,%1,%2);
MathsEX_XORMATH2N(%0,0X57,checkSum);
MathsEX_XORMATH0N(%1,checkSum,checkSum);
MathsEX_XORMATH0N(%2,checkSum,checkSum);
AX0=%0; !Address
Call UART0_Write_;
AX0=0X57; !Command
Call UART0_Write_;
AX0=DM(%1); !Mode_485
Call UART0_Write_;
AX0=DM(%2); !code zero
Call UART0_Write_;
AX0=DM(checkSum); !Check sum
Call UART0_Write_;

Call UART0_Read_; !Address


Call UART0_Read_; !Command
Call UART0_Read_; !Mode_485
DM(%1)=AX0;
Call UART0_Read_; !Check Sum

.ENDMACRO;
#endif

3.4 Stegmann.dsp
The following code contained in the file “Stegmann.dsp” defines the two routines mentioned in the
previous section.
The functions are declared as globally accessible to other applications.
.MODULE/RAM/SEG=USER_PM1 encoder_functions;

{***************************************************************************************
* *
* Library: Communication Library for the Stegmann Encoder *

© Analog Devices Inc., January 2000 Page 27 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

* *
* File: Stegmann.dsp *
* *
* Description: Stegmann Code File *
* Purpose : Library Routines for Stegmann Encoder Operation *
* *
* Author : JB *
* Version : 1.0 *
* Date : January 2000 *
* Modification History: None *
* *
* Embedded Control Systems *
* Analog Devices Inc. *
***************************************************************************************}

#include <main.h>;
#include <admc401.h>;
#include <uart0.h>;
#include <adc401.h>;
#include <mathsEx.h>;
#include <trigono.h>;
#include <stegmann.h>;

{***************************************************************************************
* Calculate Configuration Register Contents from Parameters *
***************************************************************************************}
{None}

{***************************************************************************************
* Constants Defined in the Module *
***************************************************************************************}
{None}

{***************************************************************************************
* Routines Defined in this Module *
***************************************************************************************}

.ENTRY Stegmann_GetAnaloguePosition_;
.ENTRY Stegmann_Init_;
.ENTRY CheckSum;

{***************************************************************************************
* Global Variables Defined in this Module *
***************************************************************************************}

.VAR/RAM/DM/SEG=USER_DM3 digitalPosMSB; !Encoder digital Position MSB


.Global digitalPosMSB;

.VAR/RAM/DM/SEG=USER_DM3 digitalPosLSB; !Encoder digital Position LSB


.Global digitalPosLSB;

{***************************************************************************************
* Local Variables Defined in this Module *
***************************************************************************************}

.VAR/RAM/DM/SEG=USER_DM3 SINVALUE; !Sin value read in


.VAR/RAM/DM/SEG=USER_DM3 COSVALUE; !Cos value read in

.VAR/RAM/DM/SEG=USER_DM3 SINVALUESH; !Sin shifted value


.INIT SINVALUESH :0; !Set init sin shift to zero
.VAR/RAM/DM/SEG=USER_DM3 COSVALUESH; !Cos shifted value
.INIT COSVALUESH :0; !Set init cos shift to zero

.VAR/RAM/DM/SEG=USER_DM3 cosSinZero; !Status bits of Sin and Cos


!bit 3 sin = zero
!bit 2 cos = zero
!bit 1 sin positive
!bit 0 cos pos

.VAR/RAM/DM/SEG=USER_DM3 checkSum; !The check sum for data packet to be sent

© Analog Devices Inc., January 2000 Page 28 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

.VAR/RAM/DM/SEG=USER_DM3 offSetSin; !The offset of the Sin waveform


.INIT offSetSin :0; !Default offset set to zero

.VAR/RAM/DM/SEG=USER_DM3 offSetCos; !The offset of the Cos waveform


.INIT offSetCos :0; !Default offset set to zero

.VAR/RAM/DM/SEG=USER_DM3 sinAmpComp; !Correct for different amplitude between Sin


and Cos.
.INIT sinAmpComp :1; !Default gain correction factor set to one

.VAR/RAM/DM/SEG=USER_DM3 return1; !Temporary variables


.VAR/RAM/DM/SEG=USER_DM3 return2;
.VAR/RAM/DM/SEG=USER_DM3 return3;
.VAR/RAM/DM/SEG=USER_DM3 return4;
.VAR/RAM/DM/SEG=USER_DM3 return5;
.VAR/RAM/DM/SEG=USER_DM3 return6;
.VAR/RAM/DM/SEG=USER_DM3 return7;

Since the encoder may not be ideal and produce perfect Sin and Cos waveforms, it may be necessary to
correct offsets and amplitude differences. This application note does not provide the software for calculating
the offsets and amplitude errors, instead the user is expected to calibrate the system. One method is to create
a large data memory block and store successive position information. Using this data calculate the Max and
Min of each wave. Once the Max and Min are known then the offsets are calculated as follows:
SinMax − SinMin
→ offsetSin (1)
2
CosMax − CosMin
→ offsetCos (2)
2
Next, the amplitude compensation factor can be calculated. It is necessary to correct only one of the
waveforms. The sin waveform is corrected by multiplying the digitised sin value by the amplitude correction
factor. This factor is calculated using the following equation,
CosMax − CosMin
→ SinAmpComp (3)
SinMax − SinMin
For simplicity the offsets are set to zero and the amplitude compensation factor is set to one.
The task of the first routine is to get the initial position from the encoder. The encoder supplies this
information in four packets of 8 bits giving 32 bits of multi-turn position information. As explained in section
1.2 the first 6 bits are leading zero and the next 12 bits are multi-turn information. The next 9 bits plus 2 bits
of the cycle information make up the EIU count initial value.
In order to start the EIU block the EIUMAXCNT must be set. The value is 4*N-1 where N = number of lines
on the encoder.
Due to the way the encoder is designed, it is necessary to do an initial alignment of the analogue information
with the digital information. This is explained in detail in the encoder datasheet and a suggested algorithm is
also supplied, see Figure 9. This algorithm is implemented in this routine.
if (analogue angle < 180°) and (quadrature counter < 180°) Then no need to synchronise
if (analogue angle > 180°) and (quadrature counter > 180°) Then no need to synchronise

if (analogue angle >= 180°) and (quadrature counter < 180°) Then
diff = (analogue angle) - (quadrature counter)
if (diff < 180°) Then add 90° to quadrature counter // 0.. 179°, analogue angle preceding
else subtract 90° from quadrature counter // 0 .. -179°

else
diff = (quadrature counter)- (analogue angle)

© Analog Devices Inc., January 2000 Page 29 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

if (diff < 180°) Then subtract 90° from quadrature counter // 0.. 179°, period counter preceding
else add 90° to quadrature counter // 0 .. -179°

Figure 9: Alignment algorithm for analogue and digital position information.

{***************************************************************************************
* *
* Type: Routine *
* *
* Call: call Stegmann_Init_; *
* *
* Initializes the variables for the Stegmann Encoder Routines. *
* *
* Inputs : None *
* *
* Ouputs : AX0: MSB of initial position *
* AR: LSB of initial position *
* *
* Modified: AX0, AX1, AY0, AY1, AR, AF, SR0, SR1, SE, SI CNTR, MR0, MR1, MF, *
* MX1, MY0, MY1, I5, M5, L5 *
* *
***************************************************************************************}

Stegmann_Init_:
{
Set up EIU
In order of the EIU to start it my get an initial value for EIUMAXCNT
}
Setup_EIU:
AR=0X7FF; !512*4-1=2048-1 =>0x800-1=0X7FF see ADMC401 datasheet pages 36/37
DM(EIUMAXCNT)=AR;
Setup_Encoder:
{
The segment of code communicates with the encoder and retrieves the initial position
information. The information is shift first to find a value for the EIUCNT and then
to find the 5 bits of angle information.
}

Stegmann_read_Enc_Pos(addressOfEncoder);
AR=DM(digitalPosLSB);
AY0=0x3FFF;
AR=AR and AY0;
SR=ASHIFT AR by -3(lo);
DM(EIUCNT)=SR0;
SR=ASHIFT AR by -5(hi);
DM(return3)=SR0;

{
The analogue position is got and aligned with the digital position initial value.
}

CALL Stegmann_GetAnaloguePosition_;
The Stegmann alignment algorithm starts here.
AY0 = DM(return3);
AX0 = AR;
AR=AR XOR AY0;
AF=tstbit 15 of AR;
IF EQ jump end_of_alignment;
AF = tstbit 15 of AX0;
IF EQ jump Analog_less_oneeighty;
AX1=AY0;
AR=tstbit 15 of AX1;
IF NE jump Analog_less_oneeighty;
MY0=1;
AR=AX0;

© Analog Devices Inc., January 2000 Page 30 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

MR=AR * MY0 (uu);


MY0=AY0;
MR=MR-MX0*MY0(uu);
AF=tstbit 0 of MR1;
IF NE jump diff_less_one;
SR0=DM(EIUCNT);
SR=ASHIFT SR0 by 5 (lo);
AY1=B#100000;
AR=SR0+AY1;

!at this point you could handle complete cycle turn over.

SR=ASHIFT AR by -5 (lo);
DM(EIUCNT)=SR0;
jump end_of_alignment;
diff_less_one:
SR0=DM(EIUCNT);
SR=ASHIFT SR0 by 5 (lo);
AY1=B#100000;
AR=SR0-AY1;

!at this point you could handle complete cycle turn under.

SR=ASHIFT AR by -5 (lo);
DM(EIUCNT)=SR0;
jump end_of_alignment;

Analog_less_oneeighty:
MY0=1;
AR=AY0;
MR=AR * MY0 (uu);
MY0=AX0;
MR=MR-MX0*MY0(uu);
AF=tstbit 0 of MR1;
IF EQ jump diff_less_two;
SR0=DM(EIUCNT);
SR=ASHIFT SR0 by 5 (lo);
AY1=B#100000;
AR=SR0+AY1;

!at this point you could handle complete cycle turn over.

SR=ASHIFT AR by -5 (lo);
DM(EIUCNT)=SR0;
jump end_of_alignment;

diff_less_two:
SR0=DM(EIUCNT);
SR=ASHIFT SR0 by 5 (lo);
AY1=B#100000;
AR=SR0-AY1;

!at this point you could handle complete cycle turn under.

SR=ASHIFT AR by -5 (lo);
DM(EIUCNT)=SR0;
jump end_of_alignment;
Now that the two position words are aligned correctly all that’s left to do is combine them in the format
explained in section 1.2. The first 9 bits of the EIUCNT value are shifted to the left so as to occupy the MSB
of the first word. The first 7 bits of the analogue value are added to complete the first position word. The
remainder on the analogue value placed in the second position word, shifted into the MSB position.
end_of_alignment:

{
Now the aligned EIUCNT value is combined with the analogue value to get the overall position.
}

AR=AX0;

© Analog Devices Inc., January 2000 Page 31 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

SR=ASHIFT AR by 7 (lo);
AX0=SR0;
AY1=SR1;
AR=DM(EIUCNT);
SR=ASHIFT AR by 14 (lo);
SR=ASHIFT SR1 by 7 (lo);
AR=SR0+AY1;
RTS;

{Handle Sin = Zero}

SinZero:
AR=DM(cosSinZero);
AR=setbit 3 of AR;
DM(cosSinZero)=AR;
jump CosGet;

{Handle Cos = Zero}

CosZero:
AR=DM(cosSinZero);
AR=setbit 2 of AR;
DM(cosSinZero)=AR;
AR=tstbit 1 of AR;
IF EQ jump minusNinety;
AR=0x3FFF;
jump end_sign;

{Handle the angle = minus ninety}

minusNinety:
AR=0xBFFF;
jump end_sign;
This routine gets the analogue position information. It first gets the result from the ADC1, i.e. the digitised
Sine value and then ADC5, the Cos. In both cases it checks for a zero result.
{***************************************************************************************
* *
* Type: Routine *
* *
* Call: call Stegmann_GetAnaloguePosition_; *
* *
* Get the cycle position. IE the fine position in one of the 512 cycles. *
* *
* Inputs : None *
* *
* Ouputs : AX0: MSB of the cycle position *
* AR: LSB of the cycle position *
* *
* Modified: AX0, AX1, AY0, AY1, AR, AF, SR0, SR1, SE, SI CNTR, MR0, MR1, MF, *
* MX1, MY0, MY1, I5, M5, L5 *
* *
***************************************************************************************}

Stegmann_GetAnaloguePosition_: !get the analogue position

Ax0 =0x03; ! presume both sin and cos are positive


DM(cosSinZero)=AX0; ! and neither are equal to zero

{
Get the sin value
Get the modulus making it an unsigned number => easier for ACRTAN calculation
Store status information
}

SinGet:
ADC_Read(ADC0, Offset_0to3); { Use ADC converter on ADCM401 }
AY0=DM(offSetSin); !Default set to zero
ENA AR_SAT;

© Analog Devices Inc., January 2000 Page 32 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

AR=AR-AY0; !Correct for system offsets


DIS AR_SAT;
MY0=DM(sinAmpComp); !Load sin amplitude compensating factor
MR=AR*MY0 (su); !Do the scale
SR=ASHIFT MR1 by 1 (lo); !Correct for integer mode (see ADSP-2100 family 2-3)
AR=SR0;
AR=ABS AR;
IF AV AR=pass 0x7FFF;
SR0=AR;
IF EQ jump sinZero;
IF POS jump section1;
AR= DM(cosSinZero);
AR=clrbit 1 of AR;
DM(cosSinZero)=AR;

{
To preserve all the information in a divide both the numerator and denominator are
shift to the left removing zero information and then the result is shifted by the relevant amount
}

section1:
SE=EXP SR0(HI);
SR = NORM SR0(lo);
DM(SINVALUE)=SR0;
AR=SE;
AR=-AR;
DM(SINVALUESH)=AR;
AX0= SR0;

{
Get the Cos value
Get the modulus making it an unsigned number => easier for ACRTAN calculation
Store status information
}

CosGet:
ADC_Read(ADC4, Offset_4to7); { Use ADC converter on ADCM401 }
AY0=DM(offSetCos); !Default set to zero
ENA AR_SAT;
AR=AR-AY0; !Correct for system offsets
DIS AR_SAT;
AR=ABS AR;
IF AV AR=pass 0x7FFF;
SR0=AR;
IF EQ jump cosZero;
IF POS jump section2;
AR= DM(cosSinZero);
AR=clrbit 0 of AR;
DM(cosSinZero)=AR;

{Same as section one of Cos}

section2:
SE=EXP SR0(HI);
SR = NORM SR0(lo);
DM(COSVALUE)=SR0;
AR=SE;
AR=-AR;
DM(COSVALUESH)=AR;
AY1=AX0;
AX0=SR0;
AY0=0;
AR=ax0-ay1;
IF GT jump do_divide;
SI=AY1;
SR=ASHIFT SI by -1 (HI);
AY1=SR1;
AR=DM(SINVALUESH);
AR=AR-1;
DM(SINVALUESH)=AR;

© Analog Devices Inc., January 2000 Page 33 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

DM(SINVALUE)=AY1;
{
Do the divide
}

do_divide:
AF=PASS AY1;
ASTAT=0;
DIVQ AX0;DIVQ AX0;DIVQ AX0;DIVQ AX0;DIVQ AX0;DIVQ AX0;
DIVQ AX0;DIVQ AX0;DIVQ AX0;DIVQ AX0;DIVQ AX0;DIVQ AX0;
DIVQ AX0;DIVQ AX0;DIVQ AX0;DIVQ AX0;

{ Correct for the shift earlier }


AX1=DM(SINVALUESH);
AF=pass AX1;
AR=DM(COSVALUESH);
AR=AR-AF;
AR=AR+1;
SE=AR;
AR=AY0;
SR= ASHIFT AR (LO);

{ Do ARCTAN }

Set_DAG_registers_for_trigonometric;
Atan(SR1,SR0);
AX0=DM(cosSinZero);
AF=tstbit 1 of AX0;
IF GT jump pos_sin;
AF=tstbit 0 of AX0;
IF GT jump n_sin_and_p_cos;

{ Since the value is between 0 and 90 it is necessary to correct for modulation earlier }

n_sin_and_n_cos:
AY1=0x1;
AR=AR-0X7FFF;
AR=AR-AY1;
jump end_sign;

n_sin_and_p_cos:
AR=-AR;
jump end_sign;

pos_sin:
AF=tstbit 0 of AX0;
IF GT jump end_sign;
AF=pass AR; !pos sin and neg cos
AX0=0x7FFF;
AR=AX0-AF;
IF AV jump carry_con;
AY0=1;
AR=AR+1;
jump end_sign;

carry_con:
AR=pass 0x7FFF;

end_sign:
nop;
rts;

.ENDMOD;

4 Software Example: Obtaining Position Information


This example combines all the application-modules discussed in this applications note. It uses the
PWMSYNC Interrupt to call the Stegmann_GetPosition macro, which gets the current position. Since the

© Analog Devices Inc., January 2000 Page 34 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

PWMSYNC is periodic a speed calculation can be carried out using the Stegmann_GetSpeed macro. This
is only possible if the Stegmann_Getpositon is calculated at a periodic rate. Another method is to use the
event timer to time consecutive Stegmann_GetPosition requests. The speed information is simply the
subtraction of last position (old_position) and current position (position). As already stated a further
scaling to the appropriate format is required.

4.1 The main program: Main.dsp


The file “main.dsp” contains the initialisation and PWM Sync and Trip interrupt service routines. To
activate, build the executable file using the attached build.bat either within your DOS prompt or clicking
on it from Windows Explorer. This will create the object files and the main.exe example file. This file
may be run on the Motion Control Debugger.
In the following, a brief description of this is given.
Start of code – declaring start location in program memory
.MODULE/RAM/SEG=USER_PM1/ABS=0x60 Main_program;
{***************************************************************************************
* *
* Application: ADMC401 as an interface to the Stegmann SinCos Encoder *
* *
* File: Main.dsp *
* *
* Description: main program file *
* Purpose : Using functions to call initialise and get position information *
* continuously from the Stegmann SCM60 encoder. *
* *
* Author : JB *
* Version : 1.0 *
* Date : January 2000 *
* Modification History: none *
* *
* Embedded Control Systems *
* Analog Devices Inc. *
***************************************************************************************}

Next, the general systems constants and PWM configuration constants (main.h – see the next section) are
included. Also included are the Library functions for the PWM, ADC, Uart0 and of course the application
specific routine - Stegmann.
{***************************************************************************************
* Include General System Parameters and Libraries *
***************************************************************************************}
#include <main.h>;
#include <adc401.h>;
#include <pwm401.h>;
#include <uart0.h>;

#include <stegmann.h>;

{***************************************************************************************
* Constants Defined in the Module *
***************************************************************************************}

{none}

{***************************************************************************************
* Global Routines Defined in this Module ( .Entry ) *
***************************************************************************************}

{ none }

{***************************************************************************************
* Global Variables Defined in this Module ( .Global ) *
***************************************************************************************}

{ None }

© Analog Devices Inc., January 2000 Page 35 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

{***************************************************************************************
* Local Variables Defined in this Module *
***************************************************************************************}

.VAR/DM/RAM Old_position1;
.VAR/DM/RAM Old_position2;
.VAR/DM/RAM position1;
.VAR/DM/RAM position2;
.VAR/DM/RAM speed1;
.VAR/DM/RAM speed2;

The initialisation of PWM block, ADC and the Stegmann Encoder is executed and the interrupts are enabled.
The program then enters a loop, which just waits for interrupts.
{********************************************************************************************}
{ Start of program code }
{********************************************************************************************}

STARTUP:

UART0_Init;
PWM_Init(PWMSYNC_ISR, PWMTRIP_ISR);

IFC = 0x80; { Clear any pending IRQ2 interrupt }


AR=IMASK; { unmask irq2 interrupts. }
AR=SETBIT 9 of AR;
IMASK =AR; { IRQ2 ints fully enabled here }

ADC_Init;

!The motor must not be running when initialising the encoder


Stegmann_Init_Total_Pos(position1,position2);

MAIN: {Wait for interrupt to occur}


NOP;
NOP;
JUMP MAIN;

RTS;
The interrupt service routine simply places the old position information into two data memory words and
gets the new position information. Then it calculates the speed, i.e. the difference between the new position
and the old position.
{********************************************************************************************}
{ PWM Interrupt Service Routine }
{********************************************************************************************}

PWMSYNC_ISR:

Copy_DM(position1,Old_position1);
Copy_DM(position2,Old_position2);
Stegmann_GetPosition(position1,position2);
Stegmann_GetSpeed(position1,position2,Old_position1,Old_position2,AX1,AX0);

RTI;
PWM-Trip service routine and initialisation of PWM block.
{********************************************************************************************}
{ PWM Trip Interrupt Service Routine }
{********************************************************************************************}

PWMTRIP_ISR: {No action taken in this demo}

nop;
nop;
RTI;

.ENDMOD;

© Analog Devices Inc., January 2000 Page 36 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

4.2 The main include file: main.h


This file contains the definitions of ADMC401 constants, general-purpose macros and the configuration
parameters of the system and library routines. It should be included in every application. For more
information refer to the “The Library Documentation File” document.
This file is mostly self-explaining. The relevant sections to this example are shown here. For the Stegmann
Interface, only its address code is required.
{********************************************************************************************}
{ Application specific constants and header files }
{ file : none }
{********************************************************************************************}

{********************************************************************************************}
{ Library: Stegmann Encoder functions }
{ file : stegmann.dsp }
{ Application Note: Interfacing the ADMC401 with a Stegmann Encoder }

.const addressOfEncoder = 0x40; !The serial address of the encoder


{********************************************************************************************}
For a first test, a data memory buffer was set-up and the encoder was run at constant speed. is a plot of the
highest 16 bits of the position information.

Figure 10: Plot of position for an encoder rotated at constant speed.

4.3 Changing to a 1024-line encoder


There are many different encoders within the Stegmann SINCOS® product range. The two main
characteristics are the number of lines and where it has the ability to product multi-turn information.
Since this application note does not deal with multi-turn information but simply ignores the information,
it is relatively easy to switch between the two types of encoders. What follows is a brief explanation of
changes that are necessary to change the code so that it will work with a 1024-line encoder.
The first routine to be modified is the Init-Stegmann routine in the Stegmann.dsp file. The basic
requirements for that routine are to put the correct value into the EIUCNT and EIUMAXCNT registers. In
the case of the EIUMAXCNT register, the new initialisation value is (4*1024 -1) 4095 or 0xFFF.
Line 121 of Stegmann.dsp changes to:

AR=0XFFF; !1024*4-1=4096-1 =>0x1000-1=0XFFF see ADMC401 datasheet pages 36/37

© Analog Devices Inc., January 2000 Page 37 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Since there are now 10 bits of cycle information, plus 5 bits of internal cycle information, the first 15 bits
of digitalPosLSB must be stored and the 16th bit cleared, so line 132 of Stegmann.dsp changes to:

AY0=0x7FFF;

Next, due to the extra bit all shifting by 7 are now replaced by shifting by 6 as follows:
Line 221 of end_of_alignment in Stegmann.dsp

SR=ASHIFT AR by 6 (lo);

Line 226 of end_of_alignment in Stegmann.dsp

SR=ASHIFT SR1 by 6 (lo);

Line 117 of end_of_alignment in Stegmann.h

SR=ASHIFT AR by 6 (lo);

Line 122 of end_of_alignment in Stegmann.h

SR=ASHIFT SI by 6 (lo);

5 Testing the accuracy


Two sets of tests have been carried out using the ADMC401 and the external circuitry. Firstly the
algorithm has been tested to see if the fixed-point processor is capable of producing high enough
resolution and accuracy. The second involves testing the overall system.

5.1 DSP results


The difference between the exact position (from ideal sine and cosine waveforms, quantized a the 12-bit
level) and the estimate computed by the DSP is plotted over 1 electrical cycle in Figure 11. As may be
seen, the maximum error is 0.01 degrees per electrical revolution. This means that the error occurring in
this figure due to the finite quantization levels and calculation inaccuracies of the DSP is at the 15th bit
position of the computed 16-bit fine position value. This implies, that the fundamental limit on such a
calculation method is located at the 24th bit in position (for a 512 line encoder). In other words, the
maximum achievable resolution from such a solution is:
∆θ fine = 2 −24 × 360 × 60 × 60 = 0.077 arc − sec (2)
Naturally, this analysis does not take into account position accuracy errors due to the expected
imperfections in the physical system offset or gain errors in the sine and cosine channels from the encoder
or in the analog signal processing circuits prior to the ADC. Additional errors are also introduced by
phase-imbalance in the encoder such that the sine and cosine waveforms are no longer in perfect
quadrature.

© Analog Devices Inc., January 2000 Page 38 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Figure 11: Quantization Error in Position over Electrical Cycle for 512 Line Sinusoidal Encoder

5.2 Overall System Results


What follows is the results of the work done be Stegmann Inc. in Germany using the circuitry described
above and a 1024-line encoder8. Changes where made to the code as explained in section 4.3 so that it
would work using a 1024-line encoder.
The code was run and the maximum and minimum for both the Sin and Cos waveforms was recorded for
one period. These values were used to calculate values for offsetSin, offsetCos and sinAmpComp as
explained in section 3.4. The lines 80, 81, and 82 of Stegmann.dsp where modified as follows:

.INIT offSetSin :120;


.INIT offSetCos :144;
.INIT sinAmpComp :0x42F0;

(Note that these values are specific to this test and may vary depending on temperature and other factors)

The program was compiled and run again.

Then using an extremely high-resolution incremental encoder the position was calculated over one
complete electrical revolution using both the ADMC401 and the Stegmann SRS50 SINCOS® and the
high-resolution incremental encoder. The difference between the two results is plotted in Figure 12.
As can be seen the largest error is 0.6 electrical degrees. This error occurs at the 10th bit per electrical
revolution, or in the case of the 1024-line encoder position information at the 20th bit of complete cycle
information.

8
The encoder used was the SRS50, a single turn 1024-line SinCos® encoder.

© Analog Devices Inc., January 2000 Page 39 of 40


a Interfacing the ADMC401 to the Stegmann SINCOS® Encoder AN401-20

Figure 12: A graph of the error over one electrical revolution.

6 Improvements and further work


This application note is intended as a starting point for work involving the ADMC401 and the Stegmann
Hiperface Encoders. It was never envisioned that it would deal with all the possible applications, such
as revolution overflow and glitch free speed calculation. However to aid people who may be interested in
adding to this application note, an outline of the requirements needed to make the application multi-turn
compliant follows.
In the routine Stegmann_Init_ it is first necessary to store the multi-turn information in a Data Memory
address for future use. In the alignment algorithm section of this routine, there are four points indicated in
the code where changes are needed. It is necessary to check for cycle over flow and to handle it
accordingly at these points.
Once this is done all subsequent cycle rollover’s could be detected in the Stegmann_GetSpeed calculation
as the shaft passes from 359° to 0° or visa versa, and again handled accordingly.
The Stegmann_GetSpeed routine also needs to be modified to handle the revolution turn over.
.

© Analog Devices Inc., January 2000 Page 40 of 40

You might also like