Go Down

Topic: Pseudo Bresenham algorithm stepper control via encoder (Read 190 times) previous topic - next topic

TobyOne

Hi all,

here's a slightly less complicated (I think) way of controlling a stepper via an encoder, many thanks to Robin2 and Luni64 without who's help and guidance I would have struggled and certainly wouldn't have got this far in less than a week. What this code does is enable you to run  a stepper motor via an encoder with a predefined ratio for example: The encoder rotates 1 turn whilst the stepper rotates 1/3 turn


Here's the code
Code: [Select]

# define EN  24
# define DIR 26
# define STP 22
# define encoderPin1 20
# define encoderPin2 21

long count=1;
long stepcount=0;
float rem=0; 
float thread=3; //3=1/3
long Step=0;
long pcount=0;

volatile int encoded;
volatile long encoderValue = 0;
volatile int lastEncoded;

void setup()
{
  digitalWrite(EN,HIGH);
  pinMode(STP,OUTPUT);
  pinMode(DIR,OUTPUT);
  pinMode(EN,OUTPUT);
  digitalWrite(EN,LOW);

  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);
  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  attachInterrupt(digitalPinToInterrupt(encoderPin1), GetEncoderPulse, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPin2), GetEncoderPulse, CHANGE);
}

void loop()
{


}

void GetStep()
{
  float ts=thread-rem;
  int tsr=rndd(ts)+0.5;

  if ( ts > tsr ) {Step=rndu(ts);rem=Step-ts;} else {Step=rndd(ts);rem=0;}

  digitalWrite(STP,HIGH);
  digitalWrite(STP,LOW);
 
}

int rndd(float i)
{
  return i = (int) i;
}


int rndu(float i)
{
  i = (int) i;
  return i++;
}

void GetEncoderPulse()
{

  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
 
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {encoderValue ++;digitalWrite(DIR, HIGH);}
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {encoderValue --;digitalWrite(DIR, LOW);}

  lastEncoded = encoded; //store this value for next time

  count++;
   
  if (pcount==Step){GetStep();pcount=0;}
   
  pcount++;
 
}



 it all centres around
 
Code: [Select]
void GetStep()
{
  float ts=thread-rem;
  int tsr=rndd(ts)+0.5;

  if ( ts > tsr ) {Step=rndu(ts);rem=Step-ts;} else {Step=rndd(ts);rem=0;}

  digitalWrite(STP,HIGH);
  digitalWrite(STP,LOW);
 
}


Basically the Getstep() function works out how to "fudge" the stepper pulses by working out the closest approximation, bearing in mind steppers only deal in whole numbers, pretty much the same way as the Bresenham algorithm. I'm sure that there might be better ways of doing things and I still have a lot of tidying up to do, try to sort out the TSR, naming conventions variable type casts etc, but I'm right pleased with it so far.

Robin2

many thanks to Robin2 and Luni64 without who's help and guidance
Link to other Thread

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

luni64

Would love to see a video showing the lathe cutting some threads :-) 
Fast Stepper library? -> https://luni64.github.io/TeensyStep/

TobyOne

I'll see what I can do, but won't be for a while yet!

MarkT

Basically the Getstep() function works out how to "fudge" the stepper pulses by working out the closest approximation, bearing in mind steppers only deal in whole numbers, pretty much the same way as the Bresenham algorithm. I'm sure that there might be better ways of doing things and I still have a lot of tidying up to do, try to sort out the TSR, naming conventions variable type casts etc, but I'm right pleased with it so far.
You don't need floating point for Bressenham's - its an integer algorithm.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

TobyOne

It's not really Bressenham's though , as I understand it Bressenham's equation always deals with integer numbers ,as in find the closest pixels to create the illusion of a straight line between two points on screen and those two points are always integer numbers. With trying to find the closest steps to create a certain ration between two shafts you are going to be dealing with floating point numbers initially and then you can calculate the steps needed to keep the right ratio using integer numbers, that's what the GetStep function does, I can't see how you can do it without using floating point numbers.

Go Up