Using Hall Effect Sensor as Home point for Stepper Motor

Hi everyone! this is my first time posting here and I'm pretty new to coding so bear with me here. But I have been working on making my own split-flap display using a 28byj-48 stepper motor and a ULN2003 Driver. its all being controlled by an ELEGOO UNO R3. all it is, is a wheel with 40 positions, each position being a different character. so I am able to tell the stepper to go to a position based on the ASCII values. There is also a KY-003 hall effect sensor mounted to the wheel. each time a letter is displayed, the stepper first goes through a homing procedure, waits to see the sensor and then goes to the typed character. my current issue is that every time it goes to a character that is next to the magnet for the hall sensor, it homes itself in the middle of the magnet, where normally it would home at the beginning of magnet. this usually throws it off by 1 or 2 characters. I'm pretty sure what i need is a falling interrupt. since the sensor is in a normal high then goes low when it sees the magnet, but I'm unsure how to integrate this into my code. Could anyone help point me in the right direction? thanks! P.S. Sorry if my code is sloppy, like i said I'm pretty new.

#include <Stepper.h>
 
//Include the Arduino Stepper Library;#include <Stepper.h>
 
// Define Constants
#define HALL_SENSOR 3
 
// Number of steps per internal motor revolution 
const float STEPS_PER_REV = 32; 
 
//  Amount of Gear Reduction
const float GEAR_RED = 64;
 
// Number of steps per geared output rotation
const float STEPS_PER_OUT_REV = STEPS_PER_REV * GEAR_RED;

// Equates to 1 flap change on display

const int STRT = STEPS_PER_OUT_REV /40;



// Number of Steps Required
int StepsRequired;

// for incoming serial data
int incomingByte = 0; 

//Stepper speed global setting
 int Spd = 1000;


// Create Instance of Stepper Class
// Specify Pins used for motor coils
// The pins used are 8,9,10,11 
// Connected to ULN2003 Motor Driver In1, In2, In3, In4 
// Pins entered in sequence 1-3-2-4 for proper step sequencing
 
Stepper steppermotor(STEPS_PER_REV, 8, 10, 9, 11);




//Setup for the home function of stepper

 void HomeFunction(){
    Serial.println("Finding Home...");
    
  
    steppermotor.setSpeed(Spd);
    steppermotor.step(STRT *3);
    
    
  while(digitalRead(HALL_SENSOR)==1)
  {
    steppermotor.setSpeed(Spd);   
    steppermotor.step(STRT);
 
    }
    steppermotor.step(STRT *3); //SET TO 20 FOR A TO BE HOME
     Serial.println("Home Found!");
  }
void setup()
{

//serial monitor startup message waiting

  Serial.begin(9600);
    while (!Serial);
 
// Hall effect sensor
  pinMode(HALL_SENSOR,INPUT);

  Serial.println("Please wait for startup sequence to complete...");
  delay(200);

 //Home motor
    HomeFunction();

   Serial.println("Input a character to be displayed on split flap module!");
   Serial.println("--------------------------------------------------------");
 
}
 
void loop(){


//Tells stepper motor where to rotate based on inputed character

 // send data only when you receive data:
  if (Serial.available() >0) {
    // read the incoming byte:
    
    incomingByte = Serial.read();


// Rotate to character based on ascii chart conversion

 if (incomingByte != 10) {
Serial.println((char) incomingByte);
   HomeFunction(); 
   
  if (incomingByte < 58){
 steppermotor.step(STRT * (incomingByte % 48));
  }
  
  else{
    steppermotor.step(STRT * (incomingByte % 48)-2);
  }
 
    
  

  
 delay(200);
 Serial.println("DONE!");
 delay(200);
 Serial.println("Input a character to be displayed on split flap module!");
 Serial.println("--------------------------------------------------------");
  }

delay(1600);
  }}

Basically you don't have reliable homing. You may want to have a while (digitalRead(HALL_SENSOR) == LOW) in order to ensure that when you do start trying to home that the hall effect sensor is not already HIGH.

Also, should you be moving the sensor by STRT (51) steps while homing? If you single step then you are ensured you are within a single step accuracy every time you home. Alternatively, determine what accuracy you do need and adjust your homing step calls accordingly.

Maybe something like this:

void HomeFunction() {
  Serial.println("Finding Home...");
  steppermotor.setSpeed(Spd);
  steppermotor.step(STRT * 3);
  while (digitalRead(HALL_SENSOR) == LOW)
  {
    steppermotor.step(1);
  }
  while (digitalRead(HALL_SENSOR) == HIGH)
  {
    steppermotor.step(1);
  }
  steppermotor.step(STRT * 3); //SET TO 20 FOR A TO BE HOME
  Serial.println("Home Found!");
}

BTW, you should use HIGH and LOW instead of 1 and 0 and you don't have to call setSpeed every time you call step.

Unless you are re-homing each time for visual effect, it would be faster to record the last known position and re-home only when the desired character has already been passed.

johnwasser:
Unless you are re-homing each time for visual effect, it would be faster to record the last known position and re-home only when the desired character has already been passed.

Agree. Can't you just home at power-up and track your number of steps to move to the new position? You could also re-home using a special input.

Thanks Todd! i will give that a shot soon, and its doing 51.2 steps at the moment because there is 40 points on the wheel, and a gear reduction of 64:1 with a full step revolution of 32. so i believe that's how it should be right? And that's a good point John, are you saying have it check its home position when it passes by it under normal rotation? (instead of doing a home search for every character).

russter500:
And that's a good point John, are you saying have it check its home position when it passes by it under normal rotation? (instead of doing a home search for every character).

Yes. Remember the current position in steps from 'home'. If the desired position is less than the current position, step until you reach 'home' and then move to the position.
Note: Your mapping from incomingByte to index can produce numbers outside the range 0 to 39. That could cause problems if any characters that aren't on the wheel are received. Maybe check for ranges of characters that ARE on the wheel: (incomingByte >= '0' && incomingByte <= '9') and ignore anything else.
Note: Your 'STRT' is an integer so it can't contain 51.2 steps. Better to calculate steps from character.
Something like this:

#include <Stepper.h>  //Include the Arduino Stepper Library


// Define Constants
const byte HALL_SENSOR_PIN = 3;


// Number of steps per geared output rotation
const float STEPS_PER_OUT_REV = 32  * 64;


//Stepper speed global setting
const int SPEED = 10;


// Create Instance of Stepper Class
// Specify Pins used for motor coils
// The pins used are 8,9,10,11
// Connected to ULN2003 Motor Driver In1, In2, In3, In4
// Pins entered in sequence 1-3-2-4 for proper step sequencing


Stepper steppermotor(STEPS_PER_OUT_REV, 8, 10, 9, 11);


unsigned LastPosition = 0;
//Setup for the home function of stepper


void HomeFunction()
{
  Serial.println("Finding Home...");


  while (digitalRead(HALL_SENSOR_PIN) == LOW)  // Move past the magnet
    steppermotor.step(1);


  while  (digitalRead(HALL_SENSOR_PIN) == HIGH) // Move to reach the magnet
    steppermotor.step(1);


  LastPosition = 0;


  Serial.println("Home Found!");
}


void setup()
{
  //serial monitor startup message waiting
  Serial.begin(9600);
  while (!Serial);


  // Hall effect sensor
  pinMode(HALL_SENSOR_PIN, INPUT);


  steppermotor.setSpeed(SPEED);


  Serial.println("Please wait for startup sequence to complete...");
  delay(200);


  //Home motor
  HomeFunction();


  Serial.println("Input a character to be displayed on split flap module!");
  Serial.println("--------------------------------------------------------");
}


void loop()
{
  //Tells stepper motor where to rotate based on inputed character


  // send data only when you receive data:
  if (Serial.available() > 0)
  {
    // read the incoming byte:
    int incomingByte = Serial.read();
    Serial.println((char) incomingByte);


    // Keep track of the desire
    unsigned int position = LastPosition;  // Use the last known position as the default


    // Rotate to character based on ascii chart conversion
    if  (incomingByte >= '0' && incomingByte <= '9')
    {
      // Digits start at flap 0
      position = ((incomingByte - '0') * STEPS_PER_OUT_REV) / 40;
    }
    else if  (incomingByte >= 'A' && incomingByte <= 'Z')
    {
      // Alphabet starts at flap 10
      position = ((incomingByte - 'A' + 10) * STEPS_PER_OUT_REV) / 40;
    }
    else if  (incomingByte >= 'a' && incomingByte <= 'z')
    {
      // Alphabet starts at flap 10
      position = ((incomingByte - 'a' + 10) * STEPS_PER_OUT_REV) / 40;
    }
    else if  (incomingByte >= ' ')
    {
      // What is the position for a space?
    }


    // If we are already past that character, home to 0
    if (position < LastPosition)
      HomeFunction();


    // Move to new position
    steppermotor.step(position - LastPosition);
    LastPosition = position;


    Serial.println("DONE!");
    delay(200);
    Serial.println("Input a character to be displayed on split flap module!");
    Serial.println("--------------------------------------------------------");
  } // end if (Serial.available())
}
pinMode(HALL_SENSOR,INPUT_PULLUP);

Sensor output is normally HIGH, goes LOW when activated.

const int STRT = STEPS_PER_OUT_REV /40;

This will return 51, not 51.2, you can't move a fraction of a step anyway. You will be 1 step short every 5 moves, so every 5 moves you need to add 1 step to stay in sync.

JCA34F:

pinMode(HALL_SENSOR,INPUT_PULLUP);

Sensor output is normally HIGH, goes LOW when activated.

Yes. I just looked up the KY-OO3 module and it uses an Alegra 3144 hall effect sensor which has an Open Collector output. That means it requires a pull-up resistor on the output. There is an LED and a resistor between the output and +5V and that will sort of work as a pull-up but only to the LED forward voltage, which may not be a solid HIGH. Best to use INPUT_PULLUP with this device.

Oh my gosh, you guys are awesome! this works so much better john! it actually goes to the letter I tell it to every time. Thanks a bunch! and i did go ahead and switch it to a pullup input as well. the only other issue i have now is, my code i sent had a small error in it. so the letters and numbers were in the wrong positions because my math wasn't perfect. So i adjusted the 0-9 and a-z to where they need to be, but now i need to make it home one more position forward. because instead of homing on 0 it homes to z, and i cant for the life of me figure it out. would i just add an additional statement to the home function telling it to move one more step forward? Thanks again to everyone helping this has been so helpful and I'm glad to learn from it!

You were having it 'home' at 153 steps past sensing the magnet, and you were moving toward the magnet 51 steps at a time so that could have been randomly up to 50 steps late. Stepping one at a time should give you a more reliable home (0).

You have digits 0-9 and letters A-Z on 36 of your 40 flaps. What's on the other four? What is the order of all of the characters on the wheel? You should leave position 0 at the step where the magnet is sensed and adjust the position of the characters to be relative to that.

Oh okay, i see now, i thought that it made sense but i see doing single steps makes a lot more sense. and the other four will be a blank space(spacebar input), which preferably would be home, then a question mark, dollar sign, and a colon. and that's true, I suppose I could just move the flaps to the required positions on the index wheel.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.