# Stepper Moves, IR Flashes, Repeat... How?

Hi

I am new to programming and have been through a lot of the basic beginner arduino tutorials. I’m working on my first ‘real’ project. What I need to do is set a stepper to turn X amount of steps, then fire and IR LED. Then wait for X secs (while a camera takes a pic) and repeat for X number of moves (a full rotation). I would also like a ‘manual mode’ where I press a button and it does one move and one IR flash.

Now I have a sketch working for the stepper and I have a sketch working for the IR flash (to camera). My problem is combining the 2 sketches to make one synchronised routine. As a beginner, I don’t even know what to Google for. I think in basic terms I need this to happen:

1. ‘Start Button’ is Pressed
2. IR Flashes/Camera Shoots
3. Wait for 2 secs for camera to process
4. Motor Turns 10 degrees
5. Wait 5 secs for motor to turn
6. IR Flashes/Camera Shoots
7. Then Loop 3, 4, 5 & 6 35 times.
8. Stop (maybe make a sound at stop).

I do want to learn this, but I’m stumped as to where to start. The two sketches I have working are:

``````int IRledPin =  13;    // LED connected to digital pin 13

void setup()   {
pinMode(IRledPin, OUTPUT);
}

void loop()
{
SendNikonCode();
}

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait

cli();  // this turns off any background interrupts

while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working

// so 26 microseconds altogether
microsecs -= 26;
}

sei();  // this turns them back on
}

void SendNikonCode() {
pulseIR(2080);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(65); // wait 65 milliseconds before sending it again

pulseIR(2000);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);
}
``````

``````#include <AFMotor.h>

AF_Stepper motor(200, 1);

void setup() {
motor.setSpeed(5);  // 10 rpm
}

void loop() {
Serial.println("Double coil steps");
motor.step(6, FORWARD, DOUBLE);
}
``````

If someone could just give me a clue as to which commands I need to be using or if my predicted routine is correct?

You have two functioning sketches. You have no attempt to combine them. How do you know that you will not be successful?

In general, with two sketches that separately work, the thing that you need to do is to define what the requirements of the resulting code are to be. Then, you create a new sketch and borrow pieces from the two working sketches, and add some additional code, to meet the requirements for the combined sketch.

Remember that loop is called over and over in an infinite loop. If you want stuff to happen only now and then, such as when a switch is pressed, you need to add code to make that happen. If you want stuff to happen only a certain number of times, you must add code to make that happen.

ok, sorry. That makes sense and I have been hacking code together with little success. I’ve just gone back over it line by line to see if I can understand what’s going on. Now I don’t have the motor and motor shield here with me today, so I am relying on the serial monitor to give me a clue that stuff if happening.

This is what I currently have

``````#include <AFMotor.h>
int IRledPin =  13;    // LED connected to digital pin 13
AF_Stepper motor(200, 1);

void setup()   {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Start!");
pinMode(IRledPin, OUTPUT);
motor.setSpeed(5);
RotateTT();
}

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait

cli();  // this turns off any background interrupts

while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working

// so 26 microseconds altogether
microsecs -= 26;
}

sei();  // this turns them back on
}

void SendNikonCode() {
Serial.println("Fire Camera!");
pulseIR(2080);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(65); // wait 65 milliseconds before sending it again

pulseIR(2000);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(55);
}

void RotateTT() {
Serial.println("6 Double coil steps");
motor.step(6, FORWARD, DOUBLE);
}

void loop()
{
}
``````

The output that I get in the serial monitor is:

``````Start!
6 Double coil steps
``````

The camera does not fire.

Any suggestions?

Does the motor rotate? If so, look at what causes that to happen, and where that code is called.

There is no call to the function to fire the camera. If you do fire the camera, what will take the pictures in the future? You’ll need to hire a replacement.

Hi IntelliTom.

Looks like you are almost there. I don’t have the kit to fully test but this might help a bit.

So you can see in the Arduino sketch there are three main parts,

there’s the part at the top where you can include other ‘libraries’ and you can initialize variables.

Then there is the void setup() part and this part is usually used to set everything up, change the pinModes, etc.

Then there is the void loop() part and usually what happens in a sketch is that the code will be looping around in here waiting for things to happen and then reacting to those things.

So normally everything would be going on in the void loop() part where for example you might have a button set up and then when the user presses that button the program would turn the stepper motor to the required position and then when it was at the correct position it would fire the camera, then wait again for the motor to turn etc. then fire the camera again etc.

Here is an idea how to do it although you may need to adjust some things, have a play and see if you can get it to work, you can’t break anything

``````#include <AFMotor.h>
int IRledPin =  13;    // LED connected to digital pin 13
AF_Stepper motor(200, 1);
int NumberOfPictures = 10;  // How many pictures should we take?
int CountVariable = 0;  // I'll use this to keep a tab on how many pictures we've taken so far.

void setup()   {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Start!");
pinMode(IRledPin, OUTPUT);
motor.setSpeed(5);
}

void loop() {
if (CountVariable == NumberOfPictures) return; // Stop now as CountVariable indicates that we have taken the correct NumberOfPictures

RotateTT();
delay(500); // wait half a second for good measure
SendNikonCode();
delay(500); // wait half a second for good measure
CountVariable ++; // increment the count variable so it is actually counting :)
}  // at this point it will go to the top of the loop at the void loop() line and start again.

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait

cli();  // this turns off any background interrupts

while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working

// so 26 microseconds altogether
microsecs -= 26;
}

sei();  // this turns them back on
}

void SendNikonCode() {
Serial.println("Fire Camera!");
pulseIR(2080);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(65); // wait 65 milliseconds before sending it again

pulseIR(2000);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(55);
}

void RotateTT() {
Serial.println("6 Double coil steps");
motor.step(6, FORWARD, DOUBLE);
}
``````

Hi Ian

Thanks for taking the time to help. I have been playing with this all day

A friend helped me and I got this working in a different way:

``````#include <AFMotor.h>
int IRledPin =  12;    // LED connected to digital pin 12
const int ButtonPin = 2;
AF_Stepper motor(200, 1);
int ButtonState = 0;

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait

cli();  // this turns off any background interrupts

while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working

// so 26 microseconds altogether
microsecs -= 26;
}

sei();  // this turns them back on
}

void SendNikonCode() {
Serial.println("Fire Camera!");
pulseIR(2080);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(65); // wait 65 milliseconds before sending it again

pulseIR(2000);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(55);
}

void RotateTT() {
Serial.println("6 Double coil steps");
motor.step(6, FORWARD, DOUBLE);
}

// setup() is called first, then loop() is repeatedly called until power is switched off.
// We're doing everything in setup(), so loop() can be empty.

void setup()   {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Start!");
pinMode(ButtonPin, INPUT);
pinMode(IRledPin, OUTPUT);
motor.setSpeed(5);
for (int i = 0; i < 5; i++) {
if (ButtonState == LOW) {
SendNikonCode();
delay(1000);
RotateTT();
delay(1000);
}
else {
digitalWrite(IRledPin, LOW);
}
}
}
void loop()
{
// All done. Loop here, doing nothing.
}
``````

Though your method works too and seems cleaner. However, the next step is as you suggested, a button to start the process. I can’t seem to work out the right code. You can see in the example above what I have tried and it just acts like the button is not there. i.e it cycles through the 2 functions for the amount specified, then stops. I tried to add a button start to your code also and the same happens

``````#include <AFMotor.h>
int IRledPin =  12;    // LED connected to digital pin 12
AF_Stepper motor(200, 1);
int NumberOfPictures = 5;  // How many pictures should we take?
int CountVariable = 0;  // I'll use this to keep a tab on how many pictures we've taken so far.
const int ButtonPin = 2;
int ButtonState = 0;

void setup()   {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Start!");
pinMode(IRledPin, OUTPUT);
motor.setSpeed(5);
}

void loop() {
if (ButtonState == LOW) {
if (CountVariable == NumberOfPictures) return; // Stop now as CountVariable indicates that we have taken the correct NumberOfPictures

RotateTT();
delay(1000); // wait half a second for good measure
SendNikonCode();
delay(1000); // wait half a second for good measure
CountVariable ++; // increment the count variable so it is actually counting :)
}  // at this point it will go to the top of the loop at the void loop() line and start again.
}

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait

cli();  // this turns off any background interrupts

while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working

// so 26 microseconds altogether
microsecs -= 26;
}

sei();  // this turns them back on
}

void SendNikonCode() {
Serial.println("Fire Camera!");
pulseIR(2080);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(65); // wait 65 milliseconds before sending it again

pulseIR(2000);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(55);
}

void RotateTT() {
Serial.println("6 Double coil steps");
motor.step(6, FORWARD, DOUBLE);
}
``````

I would love to know what I’m doing wrong

ok I am a step closer.

``````#include <AFMotor.h>
int IRledPin =  12;    // LED connected to digital pin 12
AF_Stepper motor(200, 1);
int NumberOfPictures = 5;  // How many pictures should we take?
int CountVariable = 0;  // I'll use this to keep a tab on how many pictures we've taken so far.
const int ButtonPin = 2;
int ButtonState = HIGH;

void setup()   {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Start!");
pinMode(IRledPin, OUTPUT);
motor.setSpeed(5);
}

void loop() {
if (ButtonState == LOW) {
Serial.println("Button Pressed");
if (CountVariable == NumberOfPictures) return; // Stop now as CountVariable indicates that we have taken the correct NumberOfPictures

RotateTT();
delay(1000); // wait half a second for good measure
SendNikonCode();
delay(1000); // wait half a second for good measure
CountVariable ++; // increment the count variable so it is actually counting :)
}  // at this point it will go to the top of the loop at the void loop() line and start again.
}

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait

cli();  // this turns off any background interrupts

while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working

// so 26 microseconds altogether
microsecs -= 26;
}

sei();  // this turns them back on
}

void SendNikonCode() {
Serial.println("Fire Camera!");
pulseIR(2080);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(65); // wait 65 milliseconds before sending it again

pulseIR(2000);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(55);
}

void RotateTT() {
Serial.println("6 Double coil steps");
motor.step(6, FORWARD, DOUBLE);
}
``````

I changed the ‘int ButtonState = 0;’ to ‘int ButtonState = HIGH;’ and now I have it where in the serial monitor it prints ‘Start!’ and pauses. But pressing the button does not do anything. I’ve double checked the wiring and tested the button with a separate sketch. My pin numbers are correct.

Hi Tom,

You need to set the pinMode to INPUT_PULLUP because otherwise you will get problems when using things like a stepper motor or a servo.

See if this works, all I’m doing here is first setting the counter to the max so nothing happens in the loop and then when the user presses the button it resets the counter to 0 so that the loop begins the processing.
Gets rid of enclosing everything in an if statement:

``````#include <AFMotor.h>
int IRledPin =  12;    // LED connected to digital pin 12
AF_Stepper motor(200, 1);
int NumberOfPictures = 5;  // How many pictures should we take?
int CountVariable = 5;  // I'll use this to keep a tab on how many pictures we've taken so far. I've set this to 5 already so nothings going to happen until its reset to 0
int ButtonPin = 2; // needn't be a const
// int ButtonState = 0; // don't need this line

void setup()   {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Start!");
pinMode(IRledPin, OUTPUT);
pinMode(ButtonPin, INPUT_PULLUP); // you hadn't set the pin mode in your example, you need to wire the button between pin 2 and Gnd
motor.setSpeed(5);
}

// you also need to use digitalRead(ButtonPin) to get the value of the pin.

void loop() {
if (digitalRead(ButtonPin) == LOW) CountVariable = 0; // the magic line, if the button is pressed then the count is set to 0 so it all begins.
if (CountVariable == NumberOfPictures) return; // Stop now as CountVariable indicates that we have taken the correct NumberOfPictures

RotateTT();
delay(1000); // 1000 milliseconds = 1 second
SendNikonCode();
delay(1000); // 1000 milliseconds = 1 second
CountVariable ++; // increment the count variable so it is actually counting :)
}  // at this point it will go to the top of the loop at the void loop() line and start again.

// everything below this is nicely hidden away :)

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait

cli();  // this turns off any background interrupts

while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working

// so 26 microseconds altogether
microsecs -= 26;
}

sei();  // this turns them back on
}

void SendNikonCode() {
Serial.println("Fire Camera!");
pulseIR(2080);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(65); // wait 65 milliseconds before sending it again

pulseIR(2000);
delay(27);
pulseIR(440);
delayMicroseconds(1500);
pulseIR(460);
delayMicroseconds(3440);
pulseIR(480);

delay(55);
}

void RotateTT() {
Serial.println("6 Double coil steps");
motor.step(6, FORWARD, DOUBLE);
}
``````

Thanks Ian, but no joy. This just cycles through the whole thing endlessly. Doesn't stop at 5, doesn't wait for a button press.

Ah, okay, I was doing it from memory. It's late here. I'll have a go tomorrow and do some testing on my system. Sorry it doesn't work yet but I think we're close!

One thing though. Try using pin 3 for the button instead of pin 2 as pin 2 is the main serial port.

One thing though. Try using pin 3 for the button instead of pin 2 as pin 2 is the main serial port.

No, it isn't. Pins 0 and 1 are.

OP: You have Serial.begin() and Serial.println() in setup(), but no Serial.print() or Serial.println() statements in loop. Why not? Add a Serial.println() statement to tell you when the switch is pressed. (Also tell us how the switch is wired). Add Serial.print() and Serial.println() statements to output what CountVariable and NumberOfPictures are. (Work on that name, too. Of course CountVariable is a variable. That part of the name tells you nothing. Of course, CountVariable is being used to count something. But, there is no clue as to what is being counted. A name like NumberOfPhotosTaken would be better, in my opinion. It's quite clear what that is counting.)

Oh yeah :blush:

Absolutely right PaulS.

Lets get the basics up and running first, here's a sketch that I did actually try out on my Arduino :)

``````int ledPin =  13;    // LED connected to digital pin 13 You will need to change this.
int NumberOfPictures = 5;  // How many pictures should we take?
int NumberOfPicturesTaken = 5;  // I'll use this to keep a tab on how many pictures we've taken so far. I've set this to 5 already so nothings going to happen until its reset to 0
int ButtonPin = 3; // you'll need to change this.

void setup()   {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Start!");
pinMode(ledPin, OUTPUT);
pinMode(ButtonPin, INPUT_PULLUP);
}

void loop() {
if (digitalRead(ButtonPin) == LOW) NumberOfPicturesTaken = 0; // the magic line, if the button is pressed then the count is set to 0 so it all begins.
if (NumberOfPicturesTaken >= NumberOfPictures) return; // Stop now as NumberOfPicturesTaken indicates that we have taken the correct NumberOfPictures

NumberOfPicturesTaken ++;
Serial.print("NOPT = ");
Serial.println(NumberOfPicturesTaken);

digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
}  // at this point it will go to the top of the loop at the void loop() line and start again.

// everything below this is nicely hidden away :)
``````

HI Ian

Sorry for the delay in replying, life has a habit of getting in the way.

I have loaded your code onto the arduino. The serial monitor prints ‘Start!’ then cycles ‘NOPT = 1’ endlessly. If I press the button and hold it, the Serial monitor prints ‘NOPT = 1’ then 2, 3, 4 & 5 and then stops. When I release the button it continues to cycle NOPT = 1 endlessly

It’s late here and I’m not firing on all cylinders, what was the goal of this code? Just to show the button press? It seems to be working in reverse of what I need. The code need to wait for a single press of the button and then cycle through the specified number of pictures/routines.

I’ll spend some more time on this tomorrow. Thanks for taking the time to help

Hi Tom, that's weird.

(worked on mine).

IntelliTom: I have loaded your code onto the arduino. The serial monitor prints 'Start!' then cycles 'NOPT = 1' endlessly. If I press the button and hold it, the Serial monitor prints 'NOPT = 1' then 2, 3, 4 & 5 and then stops. When I release the button it continues to cycle NOPT = 1 endlessly

This code is intended to reset the count when the button input state is LOW.

``````if (digitalRead(ButtonPin) == LOW) NumberOfPicturesTaken = 0; // the magic line, if the button is pressed then the count is set to 0 so it all begins.
``````

It seems that your input is wired differently, so that the input is normally LOW and goes HIGH when you press the button. Given that the software enables the internal pullup resistor, you must have overridden this with another external pull-down resistor. You can either rewire your switch so it reads HIGH in the normal position and LOW when it is pressed, or change the LOW to HIGH in the code above.

(Changing the code would be easier, but IMO it would be better to lose the external pull-down resistor and change the switch wiring so that the switch connects the pin to ground when it is closed.)

Yes Tom, you just need the push switch wired to the input pin (in my code this is set to pin 3 and I call it ButtonPin) and to Gnd (ground or zero volts).

The INPUT_PULLUP causes the pin (pin 3) to normally be set to high via an internal pullup resistor and the reason for this is that it makes it more stable because if you don't do this and you use electric motors then it can spontaneously change with the electronic noise from the motors.

Here's the tutorial about INPUT_PULLUP http://arduino.cc/en/Tutorial/InputPullupSerial

Cheers

ian

Hi Ian

Sorry for the long delay in replying. I went abroad for a bit on business and have just been too busy to look at this. Until today.

I went over it all again and still could not get it to work. I stripped everything off the breadboard and started again. Still nothing. I then tried using a different pin for the button and using the resistor to pull it down to ground. This, I'm glad to say, worked. The whole thing is now working exactly how I wanted. Thanks for all your help on this

Quick question for fun. I would like to add something that stops you from pressing the button while it's running. i.e at the moment if you press it and then press it again, it will reset while running the loop. Also it might be good to have a cancel button to break out of the loop and reset.

Can I get some clues how to do this?

Hi again, if you come over to our forum (see my signature for the link) and post your code I'm sure we can help, we have some good Arduino coders.

Please note also that the newest version of BTInterface works slightly differently.

Regards

ian