# Digital read out in position measurement's problem

#### raychar

Joined Nov 8, 2011
82
Hello,
I am doing a project of building a digital readout (DRO). I use PIC18F452
controller. There are positive and negative sign readout digits when the moving head moves above or below a set zero respectively. Every thing
goes fine when the head move generally. However, when the head or stepper motor was driven up and down rapidly which likes an oscillation, wrong readings appear.

The construction of circuit includes feeding the positive and negative inputing pulses to the stepper driver to the microcontroller's first interrupt pin(INT0) and second interrupt pin(INT1). The program includes two interrupt subrountines to record number of positive and negative steps at every moment. Another subroutine does the multiplication of the number of steps with the length of step, it is a 16bits and 16bits multiplication.

The weird data include a sudden big increment or sudden opposite
sign in the data. I admit that the environment condition is not good because there is high frequency and large current sparkings which were emitted by the motor and relay when the head or motor reverses in directions.

So, there may be one of following cause or some others that I haven't figure out:
1) Sparkings. However, I may rule it out?? because, in the same program,
I write a timer to have readout of each second elapsing and there is no
erratic time readings occur. As well as, I have another IC 18F458 to
have PWM output to control PWM frequency and duty cylce. I haven't
observed any erratic waveform of it from scope, may be the enhance
pwm module have more interferenc immunity??
2) The controller and the program can't cope with the very short interval
time between consercutive pulses inputing to it, because time needed in
doing the multiplication subroutine takes much longer time than this
interval. The controller already run at 40MHz at maximum, is it
sufficient??

Does anyone have the knowledge and experience of this and share the advice and ammendments.
Thanks, and thanks for reading the long descriptions.

#### MrChips

Joined Oct 2, 2009
22,886
A number of suggestions are appropriate here. Post your circuit and the code. Is the code written in asm or C? Are you doing floating point math? Are you using interrupts? Are you doing calculations in the interrupt routines? If we knew clearly what you are doing we may be able to help you.

#### raychar

Joined Nov 8, 2011
82
It is in C, it should be 8x8bits multiplier, and I do 16bit multiplication by softwares as listed in below, because program is long, I listed the multiplication and the interrupts only, it a bit mesh but runs okay and hoping you can understand:

Rich (BB code):
/* *****************Multiplication************************************************/
unsigned long Position(unsigned char G,unsigned char G1,unsigned char G2)
{
/*----------------------------K=(V+8*V1+8*48*V2)-------------------------*/
/*----------------------------K=(V+8*V1+8*16*3*V2)-------------------------*/
unsigned long S1,S2,S3,S4,S5,S6,Z1,Z2,Z3,Z4;
unsigned long P,Q,R,S,T,U,X,W;
K=(G+(G1<<3)+(3*(G2<<7)));
A=(K&0xFF00)>>8;   //upper bits of 16-bits
B=(K&0x00FF);    //lower bits of 16-bits
/*-----------------------------e.g 79.997917mm--------------------------*/
/*------------------------------A10=(V+8*V1+384*V2) * (0.8/(48*8)------------------------*/
/*----magnified by 10^7---------A10=(V+8*V1+384*V2) * (0.8/(48*8) *10^7/10^7------------------------*/
/*------------------------------A10=decimal 799966367 or 0x2FAE849F -----------------------------*/
/*----divided by 10^4-----------A10=(V+8*V1+384*V2) * 20833 /10^7 -------------------------*/
/*------------------------------A10=(V+8*V1+384*V2) * (0x5161)/10^7 ----still magnified by 10^3-----------*/
/*------------------------------Displaying 079.997 (6 digits)--------------------------*/

Z1=B*0x61;   //  was B*97
P=((Z1&0xFF00)>>8); //0x96
Q=(Z1&0x00FF);  //0x69
Z2=A*0x61;   //  was A*97
R=((Z2&0xFF00)>>8); //0x57
S=(Z2&0x00FF);  //0xE3
Z3=B*0x51;   //  was B*98
T=((Z3&0xFF00)>>8); //0x97
U=(Z3&0x00FF);  //0x68
Z4=A*0x51;   //  was A*98
W=((Z4&0xFF00)>>8); //0x58
X=(Z4&0x00FF);  //0x78

S1=Q;  //0x69 was D2
S5=P+S;  //0x179 was 0x1E
S6=R+T;  //0xEE was 0x132
S4=W;  //0x58 was B2 wss 59
if(S5==0x100)
{
S6=S6+0x01;
S5=0x00;
goto loop_p;
}
if(S5>0x100)  //0x179
{
S6=S6+0x01;  //0xEE+1=0xEF
S5=S5&0x0FF; //0x79
}
loop_p:
S2=S5+U; //0x79+0x968=0xE1 was 0x1E+0xFF=0x11D, 3C
if(S2==0x100) //0xE1=P+S+U
{
S6=S6+0x01;  //  was 0x132+0x01=0x133
S2=0;
goto loop_q;
}
if(S2>0x100)  //=P+S+U
{
S6=S6+0x01;  //  was 0x132+0x01=0x133
S2=S2&0x0FF; //  was 0x1D
}
loop_q:
S3=S6+X; //0xEF+0x78=0x167 was 0x133+0x22=0x155, =77=R+T+X
if(S3==0x100)
{
S4=S4+1;
S3=0;
goto loop_r;
}
if(S3>0x100)  //0x167
{
S4=S4+1;  //0x58+1=0x59 was S4=B2+1=B3
S3=S3&0x0FF; //was 0x67
}
loop_r:

A10=((S4&0x000000FF)<<24)+((S3&0x000000FF)<<16)+((S2&0x000000FF)<<8)+(S1&0x000000FF); //decimal

return(A10);
}
/* *******************Interrupts*********************************** */

/*--------------------------------------------------*/
void interrupt HI_ISR()
{
if(INT0IF==1)  //Downward
{
INT0IF=0;
V=V+0x01;
if(V>=0x08)
{
V=0x00;
V1=V1+0x01; //V1*(+8) half-steps done
if(V1>=0x30) //=48
{
V1=0x00;
V2=V2+0x01;  //V2*(+1) revolutions done
if(V2>=0x64)  //=100
{
V2=0x00;
}
}
}
}
if(INT1IF==1)  //Upward
{
INT1IF=0;
Y=Y+0x01;
if(Y>=0x08)
{
Y=0;
Y1=Y1+0x01; //Y1*(+8) half-steps done
if(Y1>=0x30) //was 72 was 12
{
Y1=0x00;
Y2=Y2+0x01;  //Y2*(+1) revolutions or Y2*(+96) half-steps done
if(Y2>=0x64)
{
Y2=0x00;
}
}
}
}
}
/*--------------------------------------------------*/

Last edited by a moderator:

#### MrChips

Joined Oct 2, 2009
22,886
Why do you use hexadecimal notation in your code?

#### raychar

Joined Nov 8, 2011
82
I don't know my thinking is correct or not. Because those variables are later used in 8bits and 8 bits multiplication, so they are valued as hex. at first.

Thanks

#### MrChips

Joined Oct 2, 2009
22,886
This is a common misunderstanding from people who have not fully grasped the basics. The compiler and the MCU do not care whether you use binary, hexadecimal or decimal. They are all the same. The MCU sees BINARY only.

What matters is what humans see in the code!
The rule of thumb is: use whatever representation makes the most sense to the programmer and reader.

If I am going to do a mathematical calculation or a loop counter, I use decimal, e.g. F = C*9/5 + 32;
(just an example. In integer arithmetic, I would do it differently.)

If I am creating a word mask, I use hex, e.g. low_nibble_mask = 0x0F;

If I am creating a bit mask, I use binary, e.g. EOC = 0b0001000;