Rotation counter and ejector

Hello Everyone, Thank you for your time reading this!

I am trying to build a device that starts an ejector at every 9th rotation of a wheel this ejector is stopped when a signal comes in from pin 6. This is my code:


const int rotationPin = 2;  
const int ejectorStartPin = 5;
const int ejectorStopPin =6;


int rotationCounter = 0;  
int sensorState = 0;      
int lastSensorState = 0;  
bool ejectorStarted = false;

void setup() {

  pinMode(rotationPin, INPUT);
  pinMode (ejectorStartPin, OUTPUT);
  pinMode (ejectorStopPin, INPUT);
  Serial.begin(9600);
}


void loop() {
  
  sensorState = digitalRead(rotationPin);

    if (sensorState != lastSensorState) {
    if (sensorState == HIGH) {
      rotationCounter++;
      Serial.println("on");
      Serial.print("number of rotation: ");
      Serial.println(rotationCounter);
    } else {
      Serial.println("off");
    }
    delay(50);
  }
  lastSensorState = sensorState;

  if (rotationCounter % 9 == 0 && !ejectorStarted) {
    digitalWrite(ejectorStartPin, HIGH);
    ejectorStarted = true;
  }

  if (digitalRead(ejectorStopPin) == HIGH) {
    delay(500);
    digitalWrite(ejectorStartPin, LOW);
    ejectorStarted = false;
  }
}

I would like to stop the ejector whenever ejectorStopPin goes HIGH. Now in the event if the rotationCounter is at value 9 (or multiple), the ejector is started, and I can not switch it to LOW from a signal HIGH of the ejectorStopPin only if rotationCounter is at other value than 9 (or multiple).
In other words if rotationCounter is at 9 (or multiple) I can not switch ejectorStartPin to LOW by a HIGH signal from ejectorStopPin.

I think there might be a loop in the code I can not recognize.

Any ideas? Thanks for the help!!!

not sure what this means

is the stopPin is feedback to confirm the startPin has reached some position. does it work?

what prevents from the ejector sequence repeating before the rotationCount has incremented past a multiple of 9? should some flag only be cleared when the rotationCount is no longer a multiple of 9?

if the rotationPin switch is mechanical, doesn't it need to be debounced ,,, sorry, see that is is debounced

What is is you're actually trying to accomplish?

Got a picture/graphic you can share?

More info = better answers.

You can, but its immediately switched to high again as long as ratationCounter is 9 or a multiple, because this if:

 if (rotationCounter % 9 == 0 && !ejectorStarted) {
 

will get true again in the next loop. It's only low for a couple of microseconds.

the following may be a bit over complicated, but makes the sequence of things clearer by

  • putting everything into the state machine,
  • avoids the use of delay() which blocks and
  • guarantees a single ejection cycle each multiple of 9 rotations,

not sure this addresses your concern but may more clearly express a set of requirements

void loop()
{
    unsigned long msec = millis ();

    sensorState = digitalRead(rotationPin);
    if (sensorState != lastSensorState) {
        lastSensorState = sensorState;
        delay(50);

        if (sensorState == HIGH) {
            rotationCounter++;
            Serial.println(rotationCounter);
        }
    }

    switch (state) {
    case Idle:
        if (rotationCounter % 9 == 0) {
            digitalWrite(ejectorStartPin, HIGH);
            state  = Start;
        }
        break;

    case Start:
        if (digitalRead(ejectorStopPin) == HIGH) {
            msec0 = msec;
            state = Wait;
        }
        break;

    case Wait:
        if (msec - msec0 >= 500)  {
            digitalWrite(ejectorStartPin, LOW);
            state = Done;
        }
        break;

    case Done:
        if (rotationCounter % 9 != 0)
            state = Idle;
        break;
    }
}

Agree. And .....

What exactly do you mean by "ejector" in this context. There's a lot of people here that know about programming and also projects for different applications. But, don't assume there's wide-spread knowledge about some specific niche area. You should provide a description of your project (of reasonable length). Pictures help, as does avoiding specialized jargon.

Hi All, and thank you for helping/adding thoughts!

A little bit more about the project:

On a vehicle (ATV) I would like to install a hall sensor and and magnets on the wheel of the vehicle so I can measure the length the vehicle made. I would like to attach an ejector (similar to a cylinder of a revolver gun) that holds small tubes and fill automaticly by gravity from the top and releases the tubes at the bottom also by gravity. This is what I call the ejector.
The ejector is rotated by a motor, and the cylinder holds magnets so with a hall sensor I can read the rotation of the ejector so I can regulate how many tubes are released at a certain distance. The project is so far basic and I can only share a picture of the test version - obviously, I will get industrial-grade sensors and motors (windshield wiper motor) and I might include a relay for controlling the motor but in principle it does not change much in the wiring.

Based on the comments so far (and thanks again for them) I realized that I need to change the program, especially in light what MicroBahner suggested.
My code is now the following:


const int rotationPin = 2;  
const int ejectorStartPin = 5;
const int ejectorStopPin =6;

// Variables will change:
int rotationCounter = 0;
int lastrotationCounter = 0;  // counter for the number of button presses
int sensorState = 0;        // current state of the button
int lastSensorState = 0;    // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(rotationPin, INPUT);
  // initialize the LED as an output:
  pinMode (ejectorStartPin, OUTPUT);
  pinMode (ejectorStopPin, INPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  sensorState = digitalRead(rotationPin);
  // compare the buttonState to its previous state
  if (sensorState != lastSensorState) {
    // if the state has changed, increment the counter
    if (sensorState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      rotationCounter++;
      Serial.println("on");
      Serial.print("number of rotation: ");
      Serial.println(rotationCounter);
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  lastSensorState = sensorState;


  if (rotationCounter % 9 == 0 && lastrotationCounter != rotationCounter ) {
      digitalWrite(ejectorStartPin, HIGH);
      lastrotationCounter = rotationCounter;
  } 
 
  if (digitalRead(ejectorStopPin) == HIGH) {
    delay (500);
    digitalWrite(ejectorStartPin, LOW);
  }
}


Seems to work fine, the ejector starts on every 9th magnetic impulse on the hall sensor (rotation) and the ejector stops on every magnetic impulse on the hall sensor attached to the ejector - no matter what the value of the rotation counter is.
I am a rookie in Arduino (and have no programming background at all) so any modification/suggestion is more than welcome and thank you for reading this!

Hi,
So it sounds like you are making a control system for a road white line marking machine?
image

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Tom... :grinning: :+1: :coffee: :australia:

1 Like

Hi Everyone,

I adjusted the program a bit and made a technical drawing.

drawing.pdf (207.7 KB)

This is the code:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int rotationPin =13;  
const int ejectorStartPin =10;
const int ejectorStopPin =6;
const int manualejectorStartPin = 8;
// Variables will change:
int rotationCounter = 0;
int ejectorCounter = 0;
int lastrotationCounter = 0;  // counter for the number of button presses
int sensorState = 0;
int manualEjectorsensorState = 0;
int lastmanualEjectorsensorState = 0;        // current state of the button
int lastSensorState = 0;    // previous state of the button

void setup() {
  lcd.begin (16, 2);
  // initialize the button pin as a input:
  pinMode(rotationPin, INPUT);
  // initialize the LED as an output:
  pinMode (ejectorStartPin, OUTPUT);
  pinMode (manualejectorStartPin, INPUT);
  pinMode (ejectorStopPin, INPUT);
}


void loop() {
  // read the pushbutton input pin:
  sensorState = digitalRead(rotationPin);
  // compare the buttonState to its previous state
  if (sensorState != lastSensorState) {
    // if the state has changed, increment the counter
    if (sensorState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      rotationCounter++;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("distance:");
      lcd.setCursor(10, 0);
      lcd.print(rotationCounter*1);
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  lastSensorState = sensorState;


  if (rotationCounter % 9 == 0 && lastrotationCounter != rotationCounter ) {
      digitalWrite(ejectorStartPin, HIGH);
      ejectorCounter++;
      lastrotationCounter = rotationCounter;
  } 

  
manualEjectorsensorState = digitalRead(manualejectorStartPin);
  // compare the buttonState to its previous state
  if (manualEjectorsensorState != lastmanualEjectorsensorState) {
    // if the state has changed, increment the counter
    if (sensorState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      digitalWrite(ejectorStartPin, HIGH);
      ejectorCounter++;
      
    delay(50);
  }
  manualEjectorsensorState = lastmanualEjectorsensorState;
  
  }
 
      lcd.setCursor(0, 1);
      lcd.print("eject:");
      lcd.setCursor(7, 1);
      lcd.print(ejectorCounter);

  if (digitalRead(ejectorStopPin) == HIGH) {
    delay (500);
    digitalWrite(ejectorStartPin, LOW);
  }
}


The problem I am facing now, is that when I push the pushbutton, the ejector starts as it should and stops as it should, but on the LCD screen the ejection counter is increased noz by the number of pushes but the number is running up depending how long I keep the button pushed. I am stuck here, can you suggest me what I should change?

Thanks!!!!

Hi, @aster33

Is this the same project?

Tom.. :grinning: :+1: :coffee: :australia:

Yes, same project, two different problems.

Solve one problem at a time.
You cannot keep both threads up to date if you change different parts of your code in either thread.
The left hand does not know what the right hand is doing.

Tom... :grinning: :+1: :coffee: :australia:

1 Like

Sorry, I thought the other thread was closed because I found a solution for the problem I raised initially and I marked it with "solution".

Then other issues came and saw that the thread was still open. Sorry for the rookie mistake. I am new to this whole forum thing I am trying to catch up!

Nice! It looks like you are directly driving the relay from an output pin. That may work, and may only work for awhile. That really draws a fair amount of current and you could damage the output pin.

Also, FYI, in the 21st century you can lose the little croquet wickets on your signal lines.

On a schematic, if two lines cross each other and are meant to be connected, a dot is placed at the intersection. No dot, no connection. So you can cross your wires right over each other all you want.

It would make for less visual noise, which may be why the fashion has largely been abandoned.

a7

Alto777, I see what you mean!

Regarding the schematic, I will keep that in mind, thanks.

HI,
This is where the problem occurs.
I have explained in the other thread that a relay module or a driver transistor will need to be used.
With some diagrams.

Tom... :grinning: :+1: :coffee: :australia:

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