Pausing a For loop with an If statement

I am trying to get 1 stepper motor to sweep back and forth.

Once my camera sees a barcode, the stepper motor will pause for 3 seconds. The stepper motor will continue the sweep from exactly where is stopped. (This is what I want)

I put the IF statement before the For. The sweep does stop when seeing a barcode but only after a full sweep. Not mid sweep. This is the code for that. Closest I got to it working. (code edited)

 // Stepper Motor X
  const int stepPin = 2; //X.STEP
  const int dirPin = 5; // X.DIR

#include <Pixy2.h>
Pixy2 pixy;
 
 void setup() {
 // Sets the two pins as Outputs
 pinMode(stepPin,OUTPUT); 
 pinMode(dirPin,OUTPUT);

  Serial.begin(115200);
  Serial.print("Starting...\n");

  pixy.init();
  // change to the line_tracking program.  Note, changeProg can use partial strings, so for example,
  // you can change to the line_tracking program by calling changeProg("line") instead of the whole
  // string changeProg("line_tracking")
  Serial.println(pixy.changeProg("line"));



 
 }
 void loop() {


int8_t i;
  char buf[128];
 
  pixy.line.getMainFeatures();

 digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction
 // Makes 600 pulses for making one full cycle rotation
 
 
 if (pixy.line.barcodes->m_code==0){    // camera sees a barcode
  Serial.println("zero");      // print zero
  delay(3000);  // wait 3 seconds
 return;

 
 }
 
 for(int x = 0; x < 600; x++) {
 digitalWrite(stepPin,HIGH); 
 delayMicroseconds(150); 
 digitalWrite(stepPin,LOW); 
 delayMicroseconds(150); 

 }

 
 digitalWrite(dirPin,LOW); //Changes the rotations direction
 // Makes 600 pulses for making two full cycle rotation
 for(int x = 0; x < 600; x++) 

if (pixy.line.barcodes->m_code==0){ // camera sees a barcode
 Serial.println("zero"); // print zero
 delay(3000); // wait 3 seconds
 return;

 }
 
 for(int x = 0; x < 600; x++) {
 digitalWrite(stepPin,HIGH); 
 delayMicroseconds(150); 
 digitalWrite(stepPin,LOW); 
 delayMicroseconds(150); 

 }
 }
 
 

I don't see any code that would pause the stepper for 3 seconds and what do you think that the break; commands are doing ?

1 Like

Oops. I changed it back to 3 seconds. Was (500) before to save time.

Stepper motor got stuck after seeing the barcode. I did the break to reset it.

The break is wrong because the stepper won't reset from the position it stopped at.

It Is always worrying when an instruction and a comment say different things.
Do you want to pause for one second, like the comment.
Or do you want to pause for 0.2 of a second like the instruction will?

That is not what the break instruction does. There is no single instruction to do what you want to do.

1 Like

I don't think you want to use break because that ends the for loop, which means the value x is lost, so the loop cannot continue from where it was paused. This may result in it moving too far in either direction and hitting any "gimbal" limits you may have (physical limits of where the motor can move to). That might be causing the shaking you described.

1 Like

pause for 0.2sec. I deleted the comment

Yes I am lost.

You are correct.

I think this is close to what you want. After every step, check the camera to see if it is seeing any barcode features.

// Stepper Motor X
const int stepPin = 2; //X.STEP
const int dirPin = 5; // X.DIR

#include <Pixy2.h>
Pixy2 pixy;

void setup()
{
  // Sets the two pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  Serial.begin(115200);
  Serial.print("Starting...\n");

  pixy.init();
  // change to the line_tracking program.  Note, changeProg can use partial strings, so for example,
  // you can change to the line_tracking program by calling changeProg("line") instead of the whole
  // string changeProg("line_tracking")
  Serial.println(pixy.changeProg("line"));
}

void sweep()
{
  // Makes 600 pulses for making one full cycle rotation
  for (int x = 0; x < 600; x++)
  {
    // Take one step.
    digitalWrite(stepPin, HIGH);
    digitalWrite(stepPin, LOW);

    // Check for a barcode.
    pixy.line.getMainFeatures();
    if (pixy.line.barcodes)   // camera sees a barcode
    {
      pixy.line.barcodes->print();      // print barcodes
      delay(3000);  // wait 3 seconds
    }
  }
}

void loop()
{
  digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction
  sweep();

  digitalWrite(dirPin, LOW); //Changes the rotations direction
  sweep();
}
1 Like

wow thank you so much!

The concepts works but the stepper motor sweep is slow. The delaymicroseconds adjusts the speed. 150 is fast, 400 is medium.

I added the delaymicroseconds to your void sweep() but the speed is the same.

The concept works though. Stepper stops (at any sweeping position) after detecting barcode, pause and continues.

 digitalWrite(stepPin,HIGH); 
 delayMicroseconds(150); 
 digitalWrite(stepPin,LOW); 
 delayMicroseconds(150); 

It takes time to analyze a picture, looking for barcodes. You may want to check the image only every 6, 10, 20, 30, or 60 steps. That will give less position resolution but will speed up the sweep quite a bit.

Adding delays is not going to make the sweep faster.

const int STEPS_PER_FRAME = 10;  // 600/10 (60) frames per sweep

void sweep()
{
  // Makes 600 pulses for making one full cycle rotation
  for (int x = 0; x < 600; x++)
  {
    // Take one step.
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(150);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(150);

    if (x % STEPS_PER_FRAME == 0)
    {
      // Check for a barcode.
      pixy.line.getMainFeatures();
      if (pixy.line.barcodes)   // camera sees a barcode
      {
        pixy.line.barcodes->print();      // print barcodes
        delay(3000);  // wait 3 seconds
      }
    }
  }
}
1 Like

I got it working!

I added the delayMicroseconds.

I also put the If (camera) command first, then the for (stepper motor) second in the void sweep ().
Thanks a lot! You did 99% of it.

edit: false alarm: stepper only stops at end of sweep.

[code]
// Stepper Motor X
const int stepPin = 2; //X.STEP
const int dirPin = 5; // X.DIR

#include <Pixy2.h>
Pixy2 pixy;

void setup()
{
  // Sets the two pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  Serial.begin(115200);
  Serial.print("Starting...\n");

  pixy.init();
  // change to the line_tracking program.  Note, changeProg can use partial strings, so for example,
  // you can change to the line_tracking program by calling changeProg("line") instead of the whole
  // string changeProg("line_tracking")
  Serial.println(pixy.changeProg("line"));
}

void sweep()
{

  // Check for a barcode.
    pixy.line.getMainFeatures();
    if (pixy.line.barcodes)   // camera sees a barcode
    {
      pixy.line.barcodes->print();      // print barcodes
      delay(3000);  // wait 3 seconds
    }
  
  
  // Makes 600 pulses for making one full cycle rotation
  for (int x = 0; x < 600; x++)
  {
    // Take one step.
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(150); 
    digitalWrite(stepPin, LOW);
    delayMicroseconds(150); 

    
    
  }
}

void loop()
{
  digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction
  sweep();

  digitalWrite(dirPin, LOW); //Changes the rotations direction
  sweep();
}
[/code]

That a really good suggestion. There is a second delay between camera and stepper.

It looks to me as though you check for a barcode once then make 600 steps so the camera only ever looks for a barcode at the ends of the sweep range. Is that really what you want to do ? I thought that the idea was to look all around for a barcode

Hmm your right. Its only stopped at end of a sweep.

Still tweaking it. Stepper motor runs for 100 steps before checking the camera. This repeats 6 times (total 600 steps) before changing direction.

If I check camera every step, the stepper motor gets jittery so I am compromising by checking camera every 100 steps.

[code]
// Stepper Motor X
const int stepPin = 2; //X.STEP
const int dirPin = 5; // X.DIR

#include <Pixy2.h>
Pixy2 pixy;

void setup()
{
  // Sets the two pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  Serial.begin(115200);
  Serial.print("Starting...\n");

  pixy.init();
  // change to the line_tracking program.  Note, changeProg can use partial strings, so for example,
  // you can change to the line_tracking program by calling changeProg("line") instead of the whole
  // string changeProg("line_tracking")
  Serial.println(pixy.changeProg("line"));
}

void sweep()
{
  
  for (int y = 0; y < 6; y++) // number of times to run x before changing direction
{
  for (int x = 0; x < 100; x++) //check the camera every 100 steps.
  {
    // Take one step.
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(200); // stepper doesn't run without these delays.
    digitalWrite(stepPin, LOW);
    delayMicroseconds(200); // stepper doesn't run without these delays.

  }

    
    // Check for a barcode.
    pixy.line.getMainFeatures();
   
    
    if (pixy.line.barcodes)   // camera sees a barcode
    {
      pixy.line.barcodes->print();      // print barcodes
      delay(3000);  // wait 3 seconds
    }

    
  
}
}

void loop()
{
  digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction
  sweep();

  digitalWrite(dirPin, LOW); //Changes the rotations direction
  sweep();
}
[/code]

You could get the same effect by changing one line in my last version of sweep():
const int STEPS_PER_FRAME = 100; // 600/100 (6) frames per sweep

1 Like

Thanks I'll try that!

I got it down to checking camera every 20 steps.

Thanks man tips coming your way.

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