Storing information of photoelectric barrier while motor is moving

Hello Everybody,

I am as new as they come regarding C++ and Arduino and I have the following problem to solve:

While a stepper motor is turning, it will power a camshaft, that is moving a stamp to get a pill out of its packaging. I will use a photoelectric barrier (short: PEB) to detect, wether a pill was actually dispensed out of its packaging, or if it wasn't. The PEB will be triggered while the stepper is still completing the movement, so I need to store the information, that one pill activated the PEB. Based on that information, I will move (with a second stepper motor) a sorting system (future problems possibly...).

My question is the following:

How can I store the information, so I can later use it in an if- statement? Is there a function for that sort of thing? Do I even need to store the information, or can I say for example: while "x is happening", do "y if z happened during x".

I hope I could express myself good enough for you guys to understand and maybe help me :slight_smile:

Have a nice rest of the day!

Hi @julen_se and welcome to the forum.

In general, a variable is created and is used to store the information you will want to act on. For example:

int photoElectric_status = 0; // PEB photo electric barrier

It will then be changed by the detection of the pill to say 1. Note I used a long and meaningful name. While a short name like p will work, I know I would not remember that 3 months from now :grin:

Could you give us some more info?
Which Arduino are you using?
Have you created a program as yet? Please post that in code-tags.
Do you have the data sheet for the PEB?

1 Like

For someone who is just starting to learn the programming language, you have chosen a challenging project. It would make your task MUCH easier to first work through a bunch of the examples in the Arduino IDE, to learn the special features of Arduino and more about the language.

Doing so will also have great impact on how you think about the overall project design.

2 Likes

Hello, thanks for the replies. I think I haven't described my problem good enough, here is my code:
(Notes are in German, with english version below)
I am using an Arduino Nano

#include* <Stepper.h>

#include <LiquidCrystal.h>

// Sortiersystem je 9 Schritte pro Fach (200 Schritte = 360°, 120° = 66 Schritte, 66/7 = 9,
// also 9*1,8°= 16,2° -- so weit dreht sich der Motor für jedes Fach
// Die Nockenwelle besteht aus 7 Nocken, verteilt auf 180°: 180/5 = 30°, 30° entspricht 20 Schritten
// mit je 1,8° --> Das Ausrdrücken einer Tablette dreht den Motor um 20 Schritte
// ACHTUNG: In der Realität sollte der Motor nicht von Peak to Peak laufen, sondern genau dazwischen.
// Das bedeutet, dass der Motor zuerst 30 Schritte macht, um im Zwischenraum der beiden Nocken zu landen,
// und ab dann jeweils 20 Schritte macht um wieder in die Zwischenräume zu gelangen

English Version:
// Sorting system 9 steps per compartment (200 steps = 360°, 120° = 66 steps, 66/7 = 9,
// i.e. 9*1.8°= 16.2° -- that's how far the motor turns for each compartment
// The camshaft consists of 5 cams spread over 180°: 180/5 = 36°, 36° corresponds to 20 steps
// with 1.8° each --> Squeezing out a tablet rotates the motor by 20 steps
// ATTENTION: In reality, the engine should not run from peak to peak, but right in between.
// This means that the motor first takes 30 steps to land in the gap between the two cams,
// and from then on takes 20 steps to get back into the gaps

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

const int spu = 200; // Steps per revolution Motor
const int start = 2; // Start des ganzen Ausdrückvorgangs
const int M1_stepPin = 3;
const int M1_dirPin = 4;
const int M2_stepPin = 5;
const int M2_dirPin = 6;
const int lsPin = 7; // Lichschranke
const int steps_nw = 14; // Laufvariable der einzelnen Schritte Nockenwelle
const int steps_ss = 9; // Laufvariable der einzelnen Schritte Sortiersystem

int nos_nw = 0; // Laufvariable der Schrittpakete Nockenwelle (number of steps)
int nos_ss = 0; // Laufvariable der Schirrpaketen Sortiersystem
int reverse_nw = -1 * nos_nw * steps_nw; // Laufvariable Rückbewegung Nockenwelle
int reverse_ss = -1 * nos_ss * steps_ss; // Laufvariable Rückbewegung Sortiersystem

void setup() {

  // Initialisierung der Arduino I/O Pins

pinMode(2, INPUT_PULLUP);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, INPUT_PULLUP);
lcd.begin(16,2);

// Bewegung des Motors in die Startposition: halber Schritt, um mit einem ganzen Schritt

// in die Zwischenräume der einzelnen Nocken zu kommen

for (int x=0; x < 10; x++) {
  digitalWrite(M1_stepPin, HIGH);
  delay(50);
  digitalWrite(M1_stepPin, LOW);
  delay(50);

}

// UI: gibt auf Display aktuellen Stand aus

lcd.print("Motor ist in");
lcd.setCursor(0,1);
lcd.print("Startposition");

}

void loop() {

  if (digitalRead(start) == LOW) {
       for (int x=0; x<5; x++) {
          while (digitalRead(lsPin) == LOW) {
             for(int x=0; x<9; x++) {
                digitalWrite(M2_stepPin, HIGH);
                delay(10);
                digitalWrite(M2_stepPin, LOW);
                delay(10);
        }

            for (int x=0; x<20; x++) {
               digitalWrite(M1_stepPin, HIGH);
               delay(10);
               digitalWrite(M1_stepPin, LOW);
               delay(10);

        }
      }
    }
  }
}

My problem is, that when the PEB is activated, the program wont "jump" into the while loop, and I don't really know how to fix it.

I basically want the program to turn the camshaft repeatedly for 20 steps, and if during those 20 steps the PEB gets activated, I want the second stepper to turn 9 steps, before the first stepper initiates the next 14-step action. All that should happen for 5 times.

Then the program is finished and should wait for the press of the start button again. I haven't really put any thought into that part yet as I am stuck with the first part, that I just described.

Also, how do I format the Code part for it to be readable?

The middle part of your code is in the appropriate format.
Could you select all your code from below the comments in English and wrap it all in the code in the marks?

And to clarify, how much of the code have you tested so far?
Is most of it working?
Have you tested the stepper motors to see if they do indeed take the steps ordered by the program?
Is lsPin the PEB pin?

A side note (for future use):
You assigned names to the pins at the top of the program, but didn't use those names to set INPUT status, etc.

Two more questions:
Is the PEB pin active LOW when a pill is detected?
Do you want motor 1 to stop when PEB pin is active?

Sorry, but this is not a modern way to use C. A boolean type is provided for logical variables, 'bool'.
example:

bool photoElectric_detected = false; // PEB photo electric barrier

It will then be changed by the detection of the pill to 'true'.

It was aimed at the level of the OP's expertise and I deliberately did not want to add another data type to the mix.
Without going into a lot of complexity with using bool in Arduino, you would just be saving one byte over int. And I think giving variables meaningful names is far more important.

Hello,

thank you for your constructive answer.

The stepper motor does the intended steps when the code is not written inside the while loop (when I activate it manually). In this configuration right now, it doesn't turn when the PEB gets activated by an object passing through it. Which is precisly my problem...

The lsPin is indeed meant to be the PEB Pin. Thank you for pointing out my mistake not using the variables I asigned while declaring the pins, as I said, I am new to Arduino and C++, just trying to apply some of the previous experience I had with coding.

I didn't see your second answer, so sorry for the double texting :smiley:

The PEB should switch from HIGH to LOW when activated, I thought that is how INPUT PULLUP pins work?

Motor 1 should complete its 20 Steps, regardless of the PEB getting activated or not. IF the PEB gets activated, I want Stepper 1 to wait for Stepper 2 (sorting system) to complete its steps, so that the next object is sorted into the right compartment, and then initiate the movement of Stepper 1 again. If during that movement the PEB is activated again, I want Stepper 2 to move again after the 20 Steps, until Stepper 1 did 20 Steps 5 times. Then I want the program to repeat everything it just did with the hit of the start button.

I hope I could acuratly describe what my program is intended to do :slight_smile:

There isn't really anything I can do about that, I am the only one with some level of coding experience in our uni project, so I have to work the software, while the other people are doing the hardware stuff

About your lack of knowledge and experience with the programming language?

Please reread post #3, where I offer suggestions to correct that deficiency.

Thanks for the info; that is what I thought, but its always best not to assume :grinning:
And putting the whole code in proper format really helps.

I'm going to suggest the following as a troubleshooting step:
Add a few print statements here and here:

  if (digitalRead(start) == LOW) {
	Serial.print("Start Pin status: ");
	Serial.println(start);

       for (int x=0; x<5; x++) {
          while (digitalRead(lsPin) == LOW) {
	Serial.print("lsPin status: ");
	Serial.println(lsPin);
             for(int x=0; x<9; x++) {

Let us see what the Arduino is actually seeing as to the values of start and lsPin.

Thanks, I’ve read your suggestions and done some
similar things with the components I’ll be using.

Thanks again for the help and good suggestion, I’ll try it as soon as I’m home :grin:

Just realised something else, once I copied the code:
You are declaring x in the first if loop, and then re-declaring and initialising it in the while loop, which is nested in the if loop.
Perhaps change the names of the second and third x to y and z respectively, since they refer to different counts.

Also, I noticed that you have imported the stepper library but not really used it. It may be worthwhile creating individual stepper objects, e.g motor1 and motor2. The use the library function step(), setSpeed() etc. It would avoid these problems
There is an error in the header:

#include* <Stepper.h>

I have implemented your recommended changes, however I have another Problem. After Motor1 has completed 5 20 Step cycles, I want it to return to its original starting position, making 100 steps in the opposite direction. But the Motor doesn't stop after 100 steps and I don't know how to fix it.

Another thing I have noticed:

When the PEB is activated while Motor1 is doing its 20 Steps, Motor2 doesn't move its 9 steps after Motor1 is finished with its 20. Can I store the information of the PEB getting activated and read it at a later time?

#include <Stepper.h>
#include <LiquidCrystal.h>

// Sortiersystem je 9 Schritte pro Fach (200 Schritte = 360°, 120° = 66 Schritte, 66/7 = 9,
// also 9*1,8°= 16,2° -- so weit dreht sich der Motor für jedes Fach

// Die Nockenwelle besteht aus 7 Nocken, verteilt auf 180°: 180/7 = 25,7°, 25,2° entspricht 14 Schritten
// mit je 1,8° --> Das Ausrdrücken einer Tablette dreht den Motor um 14 Schritte
// OBACHT: In der Realität sollte der Motor nicht von Peak to Peak laufen, sondern genau dazwischen.
// Das bedeutet, dass der Motor zuerst 21 Schritte macht, um im Zwischenraum der beiden Nocken zu landen,
// und ab dann jeweils 14 Schritte macht um wieder in die Zwischenräume zu gelangen

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

const int spu = 200; // Steps per revolution Motor
const int start = 2; // Start des ganzen Ausdrückvorgangs
const int M1_stepPin = 3;
const int M1_dirPin = 4;
const int M2_stepPin = 5;
const int M2_dirPin = 6;
const int lsPin = 7; // Lichschranke

const int steps_nw = 14; // Laufvariable der einzelnen Schritte Nockenwelle
const int steps_ss = 9; // Laufvariable der einzelnen Schritte Sortiersystem 
int nos_nw = 0; // Laufvariable der Schrittpakete Nockenwelle (number of steps)
int nos_ss = 0; // Laufvariable der Schirrpaketen Sortiersystem
int reverse_nw = -1 * nos_nw * steps_nw; // Laufvariable Rückbewegung Nockenwelle
int reverse_ss = -1 * nos_ss * steps_ss; // Laufvariable Rückbewegung Sortiersystem

void setup() {

  // Initialisierung der Arduino I/O Pins

pinMode(start, INPUT_PULLUP);
pinMode(M1_stepPin, OUTPUT);
pinMode(M1_dirPin, OUTPUT);
pinMode(M2_stepPin, OUTPUT);
pinMode(M2_dirPin, OUTPUT);
pinMode(lsPin, INPUT_PULLUP);
lcd.begin(16,2);

// Bewegung des Motors in die Startposition: halber Schritt, um mit einem ganzen Schritt
// in die Zwischenräume der einzelnen Nocken zu kommen
for (int x=0; x < 10; x++) {
  digitalWrite(M1_stepPin, HIGH);
  delay(50);
  digitalWrite(M1_stepPin, LOW);
  delay(50);
}

// UI: gibt auf Display aktuellen Stand aus

lcd.print("Motor ist in");
lcd.setCursor(0,1);
lcd.print("Startposition");
}

void loop() {
  if (digitalRead(start) == LOW) {
    	Serial.print("Start Pin status: ");
    	Serial.println(start);

      for (int x1=0; x1<20; x1++){
        digitalWrite(M1_stepPin, HIGH);
        delay(10);
        digitalWrite(M1_stepPin, LOW);
        delay(10);

      }
  }
    
  while (digitalRead(lsPin) == LOW) {
    //	Serial.print("lsPin status: ");
    //  Serial.println(lsPin);
    for(int x3=0; x3<9; x3++) {
      digitalWrite(M2_stepPin, HIGH);
      delay(10);
      digitalWrite(M2_stepPin, LOW);
      delay(10);
    }
    for (int x4=0; x4<20; x4++) {
      digitalWrite(M1_stepPin, HIGH);
      delay(10);
      digitalWrite(M1_stepPin, LOW);
      delay(10);

      }
    nos_nw++;
    }

  if (nos_nw == 4) {
    for (int x5=0; x5<100; x5++) {
      digitalWrite(M1_dirPin, HIGH); 
      digitalWrite(M1_stepPin, HIGH);
      delay(10);
      digitalWrite(M1_stepPin, LOW);
      delay(10);
    }
    nos_nw == 0;
   //Motor dreht zwar zurück, aber hört nicht auf zu drehen, macht mehr als 80 Schritte
  }
}

My next problem will be the following: I also need Motor1 to do 20 steps if the PEB is not activated as a result of there not being a pill to deispense out of its packaging. I need the programm to realise, that no pill was ejected, so the camshaft needs to do another 20 steps to eject the next pill (if its there). If that package is empty again, do another 20 Steps until the total number of 100 steps were made, than turn back again.

I'm sorry that I have so many questions and problems and so few answers... But you are very kindly saving me a little bit @cncnotes

I am very happy to help :grinning:

If I may suggest a detour before we go much further?
You had started by using the stepper library. I am going to recommend using the Accelstepper library.
It is widely used, and is much better in many ways. It allows you to use the stepPin and dirPin values. It allows you to set the acceleration and max speed, but more importantly, it allows you to return to a particular step (return to zero, so to speak).

It will simplify coding and troubleshooting tremendously, and remove the need for the for loop/delay statements.

So, questions for you:

  1. What board are you using to control the stepper motors?
  2. How fast do you want the motors to turn? That is, how long should it take for each of the cycles . Does not have to be exact, just some rough idea, like 0.5 sec or 2 sec, which will help us set the motor speed.