Showing posts with label DC Servo. Show all posts
Showing posts with label DC Servo. Show all posts

Saturday, 13 July 2019

Decoding absolute reference marks on Heindenhain LS378C


After a recent ebay find of affordable 0.001 glass scales, for my lathe cross slide, I now need a suitable DRO. Mixing scales with different reference mark standards, is a bad idea, but I like the challenge. Lets build a DRO capable of decoding Heidenhain reference marks.
 Although there are some DIY solutions out there, nothing I found was open source without custom hardware, thus not usable to extend.

Dedicated chips like ls7366r have automatic decoding for index pulses, but do not support encoded reference marks.

The idea is to use three HCTL2000 chips connected to an arduino, then feed the output to an ESP8266 for serving a simple web page.

The document Linear scales by Heidenhain [1] ,gives the formulae to decode the absolute reference marks on their linear glass scales [page 9].

Below a screenshot of the three tracks, the index pulses appear to be randomly spaced.

 After applying the formula to the input data, the result makes no sense.

my $Mrr = 0; # Signal periods between two reference marks





$B = (2*$Mrr)-$N;
$D = +1; #direction
# P1 Position of the first traversed reference mark in signal periods
$P1 = (abs($B) - sgn($B) -1) * $N/2 + ( sgn($B) - sgn($D) ) * abs( $Mrr) /2;
$N = 1000; #Nominal increment between two fixed reference marks in signal periods (see table below)


References
1 http://www.auto-met.com/heidenhain/08PDF/NC%20Linear.pdf

Saturday, 16 March 2019

Arduino based quadrature decoder experiments


While looking for a very efficient method to decode quadrature signals directly on the Arduino Nano, I came up with this solution for 2 encoders. While not suitable for high resolution encoders, it is at least fast enough for 400 CPR running at 3000 rpm. Interesting finding was the lookup table method found else where on the internet, is about twice as slow. The  subroutine is called from a timer interrupt routine.





// GPL, Hannes de Waal 2019 
// Measured 97 KHz, 5.8us duration with lookup table 
// 128.9 kHz with 3.36us using 2 case statements, instead of lookup

void read_encoder() {

 
  static uint8_t enc1_ab = 0;
  static uint8_t enc1_idx = 0;
  static uint8_t enc2_ab = 0;
  static uint8_t enc3_ab = 0;
  
  /**/
  unsigned char port = PINC;
  enc1_ab <<= 2;               //remember previous state
  enc1_ab |=  ( port & 0x03 );  //add current state
  enc1_idx <<= 1;
  enc1_idx |= ( port & 0b00000100 );
  
  enc2_ab <<= 2; 
  enc2_ab |= ( port>>2 & 0x03 );
 // Pos1 +=  enc_states[( enc2_ab & 0x0f )];
 
/* state transitions
  10 -> 11 +
  11 -> 01 +
  01 -> 00 +
  00 -> 10 +
  10 -> 00 -
  00 -> 01 -
  01 -> 11 -
  11 -> 10 -
  10 -> 01 e
  01 -> 10 e
  00 -> 11 e
  11 -> 00 e
  */
  switch( ( enc1_ab & 0x0f ) ) {
    
    case 0b00001011 : Pos += 1; break;
    case 0b00001101 : Pos += 1; break;
    case 0b00000100 : Pos += 1; break;
    case 0b00000010 : Pos += 1; break;
    
    case 0b00001000 : Pos -= 1; break;
    case 0b00000001 : Pos -= 1; break;
    case 0b00000111 : Pos -= 1; break;
    case 0b00001110 : Pos -= 1; break;
    
    case 0b00001001 : Err ++; break;
    case 0b00000110 : Err ++; break;
    case 0b00000011 : Err ++; break;
    case 0b00001100 : Err ++; break;
   // 0000 hold
   // 0101 hold
   // 1010 hold
   // 1111 hold
        
  }
  

 switch( ( enc2_ab & 0x0f ) ) {
    
    case 0b00001011 : Pos1 += 1; break;
    case 0b00001101 : Pos1 += 1; break;
    case 0b00000100 : Pos1 += 1; break;
    case 0b00000010 : Pos1 += 1; break;
    
    case 0b00001000 : Pos1 -= 1; break;
    case 0b00000001 : Pos1 -= 1; break;
    case 0b00000111 : Pos1 -= 1; break;
    case 0b00001110 : Pos1 -= 1; break;
    
    case 0b00001001 : Err1 ++; break;
    case 0b00000110 : Err1 ++; break;
    case 0b00000011 : Err1 ++; break;
    case 0b00001100 : Err1 ++; break;
        
  }
 
}

Saturday, 12 January 2019

Surface Grinder CNC Notes


Controlling the Z axis

Option A - Stepper motor
Using a stepper motor with 1.8 deg steps will give a resolution of 200 steps in full step mode per rotation. This would require a 46:1 reduction to achieve the desired 0.5um resolution on a 5mm lead screw.  Cons: discreet steps, not sure if this will be an issue, holding torque goes down with reducing step size.

Option B - Servo
With a servo motor using dual loop position feedback control will make more sense since steps are no longer discrete. The dunker motor I have had lying around for years, seems like a good fit. 23:1 gear ratio with a 100ppr encoder, without using the linear encoder as additional feedback this will give a resolution of 9200 steps or 0.543 um. Quick estimation with Bresenham algorithm, gave the following approximations for 0,001um increments. But i would like to hit them exactly...well in theory at least.

1 0,000543
2 0,001087 0,001
3 0,00163
4 0,002174 0,002
5 0,002717
6 0,003261 0,003
7 0,003804 0,004
8 0,004348
9 0,004891 0,005
10 0,005435
11 0,005978 0,006
12 0,006522
13 0,007065 0,007
14 0,007609
15 0,008152 0,008
16 0,008696
17 0,009239 0,009
18 0,009783 0,01
19 0,010326
20 0,01087 0,011
21 0,011413
22 0,011957 0,012
23 0,0125

This made me research the possibility of using dual loop feedback, seems common in commercial machines.
LinuxCNC supports it out of the box
http://wiki.linuxcnc.org/cgi-bin/wiki.pl?Combining_Two_Feedback_Devices_On_One_Axis
http://linuxcnc.org/docs/2.7/html/man/man9/offset.9.html
This great explanation https://granitedevices.com/wiki/Dual-loop_feedback_position_control
Gave me another idea, just use Elm Chan SMC3 Velocity control mode with LinuxCNC, feeding position from Heidenhain encoder to LinuxCNC, which controls the SMC3 servo in velocity mode.
http://elm-chan.org/works/smc/report_e.html

Chipmaster Gear Cutting

  Calculate all the possible gear combinations for the gear selector to cut a 15TPI thread: Imperial TPI C 5 24 20 Imperial TPI ...