Digital read out in position measurement's problem

Thread Starter

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
30,621
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.
 

Thread Starter

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:

Thread Starter

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
30,621
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;
 
Top