PDA

View Full Version : Handling limit switches?



Pages : [1] 2

neksmerj
3rd February 2015, 09:36 PM
I'm trying to build a basic camera slider, didn't have much success with an earlier post.

I have all the hardware sorted, and 99% of the code for controlling an Arduino UNO. The sketch for the Arduino was written by Brian Schmalz, basically consisting of a left push button, a stop push button, a right push button and a speed control pot.

The basic hardware consists of an aluminium track, a carriage, a nema17 stepper motor at one end and a return pulley at the other for the toothed belt.

So far so good, where I'm struggling is code for limit switches at each end. The problem is once the limit switch is depressed and kept depressed, no other action can take place.

What I'm trying to achieve is this. Once a limit switch is hit, tell the Arduino to stop the motor with no further movement in that direction, but allow motion in the opposite direction to take place when the appropriate pb is pressed.

Brian's sketch is here, it's the last example using an Adafruit motor shield V2.

http://www.schmalzhaus.com/EasyDriver/Examples/EasyDriverExamples.html

One of my thoughts was that as soon as the limit switch is hit, the motor stops and backs off the switch, allowing the reverse button to be pressed. I don't reckon this is the answer, and in fact I wouldn't know how to code that anyway.

I'm hoping for some assistance, you blokes are supposed to be smart, meow.

Ken

RustyArc
3rd February 2015, 10:18 PM
There's no mention of limit switches in that code, only direction and a stop switch. I'm going to guess you've wired the limit switches in parallel with the stop switch? There's a bunch of ways to skin that cat, but one would be to use two input pins for the limit switch and test their state in the main loop after the other switches. In that test, you'd allow the sign to be the correct value to move off the limit switch, or you'd leave it as zero (stopped).

neksmerj
4th February 2015, 01:24 AM
Hi RustyArc.

You are correct, limit switches were not figured into the sketch I pointed to, hence this inquiry.

If you were able to write a simple bit of code to do as you suggest, I'd be extremely grateful.

Ken

RustyArc
4th February 2015, 09:10 AM
So you'd define 2 more input pins:

// Define our three input button pins and two limit switches
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6

Then in the main loop you'd add two more tests - note this isn't the most efficient or elegant way to do it, but hopefully easier to understand:

// If a switch is pushed down (low), set the sign value appropriately
if (digitalRead(LEFT_PIN) == 0) {
sign = 1;
}
if (digitalRead(RIGHT_PIN) == 0) {
sign = -1;
}
if (digitalRead(STOP_PIN) == 0) {
sign = 0;
}
if (digitalRead(LEFT_LIM_PIN) == 0) { // If we're sitting on the left limit switch...
if (digitalRead(RIGHT_PIN) == 0) { // Allow the right button to move off the limit
sign = -1;
}
else {
sign = 0; // Otherwise stop the motor
}
}
if (digitalRead(RIGHT_LIM_PIN) == 0) { // If we're sitting on the right limit switch...
if (digitalRead(LEFT_PIN) == 0) { // Allow the left button to move off the limit
sign = 1;
}
else {
sign = 0; // Otherwise stop the motor
}
}

foobillious
4th February 2015, 11:36 AM
umm rusty's code is pretty good, but it won't actually stop the motor until analog_read_counter gets down to 0. given your hitting a limit switch, you'd probably want the motor to stop straight away.

I'd add a stepper1.setSpeed(sign); on a new line after every sign=0; in Rusty's code. alternatively add a analog_read_counter=0; line after every sign=0; that'll have the same effect.

let me know if that isn't clear and i'll update rusty's code.

neksmerj
4th February 2015, 01:04 PM
RustyArc

Thank you for taking the time to go through Brian Schmalz's sketch and incorporating into it, your code to handle limit switches.

There are a few delays in his code as it stands, ie, it can take several rotations of the motor shaft before it stops or is reversed. This is something I have to overcome. One other problem is the speed pot. There doesn't appear to be a great variation in speed from full to crawl, and again it takes a second or so to respond. I'm not 100% sure the pot I'm using is linear.

foobillious

I dare not ask how you came up with that user name.

Many thanks for your contribution, anything to pull the motor up sharply makes good sense. If you have time to rewrite the sketch to reflect your ideas, great.

I'm using an Arduino UNO R3, an Adafruit terminal shield and an Adafruit motor shield V2, and having fun.

Gentlemen, thank you both

Ken

foobillious
4th February 2015, 02:31 PM
the pot may be a log (logarithmic) pot, which could be making your life a little bit difficult, but personally I find even the linear ones hard to set accurately repeatedly. You could try investing in a 5 or 10 turn multiturn pot, which would give you a great deal more control, or you could switch to an optical encoder and control the speed more directly from within the Arduino.
*edit* you could also just add another couple of buttons and use those to increase / decrease the speed.
I'd concentrate on getting the rest of it working first, and then add that.

The second or two to respond is because the loop function of the code (where all the work is being done below) has code in it that stops the speed pot being read every time it goes through the loop. this is because the AnalogRead function is fairly slow and would limit the speed your stepper motor can achieve. I'd experiment with changing the number it counts down from (default is 3000) to see if you can find an acceptable response / speed compromise. Try 1000 or 500 first. I've commented the relevant line of the code.

the updated code for the entire sketch is below. As Rusty noted there are more elegant ways of handing the limit switch, but this should be fine until you get everything figured out. I recommend trying it with the limits set a long way off the physical stops, or by manually triggering the limits. Please note I don't have an Arduino with me right now, and I don't have a motor shield at all so I haven't tested this at all.

*edit* thing to check - what pins are your limit switches actually hooked up to? make sure they match the number in the defines.



// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, SINGLE);
}
void backwardstep() {
motor1->onestep(BACKWARD, SINGLE);
}

AccelStepper stepper1(forwardstep, backwardstep); // use functions to step

// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6

// Define our analog pot input pin
#define SPEED_PIN A0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1

void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs, with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
}

void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to turn the motor on/off and control direction
static int analog_value = 0; // Holds raw analog value.

// If a switch is pushed down (low), set the sign value appropriately
if (digitalRead(LEFT_PIN) == 0) {
sign = 1;
}
if (digitalRead(RIGHT_PIN) == 0) {
sign = -1;
}
if (digitalRead(STOP_PIN) == 0) {
sign = 0;
}
// code from Rusty
if (digitalRead(LEFT_LIM_PIN)==0) { // if the left limit pin is hit
if (digitalRead(RIGHT_PIN)==0) { // allow the right button to move us off the limit
sign=-1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}
if (digitalRead(RIGHT_LIM_PIN)==0) { // if the right limit pin is hit
if (digitalRead(LEFT_PIN)==0) { // allow the left button to move us off the limit
sign=1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}

// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 3000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
// Give the stepper a chance to step if it needs to
stepper1.runSpeed();
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
}

// This will run the stepper at a constant speed
stepper1.runSpeed();
}

neksmerj
4th February 2015, 03:19 PM
Foobillious
Many, many thanks, have not wired in the limits yet
Can't wait to get home and try the revised code out
If you'd like to muck around, I can lend you a spare Arduino, Adafruit terminal shield and motor shield

Ken

foobillious
4th February 2015, 04:25 PM
thanks for the offer, but I've frankly got too many projects on as it is.

RustyArc
4th February 2015, 05:13 PM
Poo. I posted without checking how the code would turn out - I didn't realise it'd lose all its indenting.

foobillious clearly knows the right way to do it, and I must say I hadn't noticed the direction only gets set as part of reading the pot and setting the speed. I also noticed you need to initialise the extra pins as inputs. I've moved the speed calc out of the analogue read so it happens on every iteration of the main loop, meaning it should catch stop and direction changes immediately.

My code mods adding to foobillious's version (and note, untested, so there may be a bug or three somewhere):


// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, SINGLE);
}
void backwardstep() {
motor1->onestep(BACKWARD, SINGLE);
}

AccelStepper stepper1(forwardstep, backwardstep); // use functions to step

// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6

// Define our analog pot input pin
#define SPEED_PIN A0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1

void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to turn the motor on/off and control direction
static int analog_value = 0; // Holds raw analog value.

// If a switch is pushed down (low), set the sign value appropriately
if (digitalRead(LEFT_PIN) == 0) {
sign = 1;
}
if (digitalRead(RIGHT_PIN) == 0) {
sign = -1;
}
if (digitalRead(STOP_PIN) == 0) {
sign = 0;
}
// code from Rusty
if (digitalRead(LEFT_LIM_PIN)==0) { // if the left limit pin is hit
if (digitalRead(RIGHT_PIN)==0) { // allow the right button to move us off the limit
sign=-1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}
if (digitalRead(RIGHT_LIM_PIN)==0) { // if the right limit pin is hit
if (digitalRead(LEFT_PIN)==0) { // allow the left button to move us off the limit
sign=1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}

// Give the stepper a chance to step if it needs to
stepper1.runSpeed();
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed
stepper1.runSpeed();

// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 3000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
}


}

neksmerj
4th February 2015, 10:50 PM
Rusty & foob,

You've done a great job with the limit switch code. I haven't had a chance to try it out yet, and will wait for the morning light.
I'd like to send a copy to Brian Schmalz for his comment, if you agree.

Rusty, why do you say the code is not exactly elegant, it makes sense to me? Are you saying there are better ways of doing it?

Where can I learn to write my own code?, I'm well over the pension age and this old dog is eager to learn new tricks.

Ken

RustyArc
5th February 2015, 08:30 AM
Rusty, why do you say the code is not exactly elegant, it makes sense to me? Are you saying there are better ways of doing it?

If you look through the main loop, there's 5 button reads, and as many as 6 if a limit switch is triggered. This makes the code easy to read and understand, but we know only one of the three buttons should be pressed (multiple buttons at one time doesn't make sense). So as soon as you find one button pressed, you'd not bother checking the others.

With the limit switches added, there's potentially more checks, but the code as it stands has redundancies.

So for example, more efficient code would check the stop button first - if it's pressed, there's no point checking anything else (including the limits) as the motor will be stopped as a result.

If, say, the left button is pressed, you'd jump to the limit checks without checking the right button. Then, when you test the limit inputs, you don't really need to check the corresponding button to see if it should be moving off the limit switch - the value of the "sign" variable will actually tell you that, as it's just been set in the previous button tests.

All that said, there's no problem with inefficient code if it's easier to understand and debug.

As for learning to code, there's excellent tutorials for the Arduino online.

foobillious
5th February 2015, 09:18 AM
nice catch Rusty, I forgot about initialising the inputs. my bad.

I've got no objections to you sending the code to the original author for comment, but all we have really done is add a few lines. He'll probably re-write before he posts anything on it. I would if it was me - what we've done detracts a bit from how easy the code is to understand.

The best place to learn to code depends really on what you want to do. If your interested in incorporating smarts into electronics, like your doing with your current project, then the arduino platform is a pretty good starting point. Plus you already have one. Its been a very popular platform for a number of years, so there are lots of tutorials out there. Everything from absolute beginner projects (ye olde blinky LEDs) to much more complex tasks. The arduino code editor comes with a bunch of sample code too, which makes seeing how other people have done stuff pretty easy.

Two starting points for tutorials would be the arduino site: http://www.arduino.cc/en/Tutorial/HomePage
and the tronixstuff site: http://tronixstuff.com/tutorials/
(please note, I haven't read either, so I cant really vouch for quality).

You could start at the beginner ones and work your way through. That way you'll pick up some electronics knowledge along with the how to code stuff.

neksmerj
5th February 2015, 02:18 PM
Rusty and foob,

There is a problem when compiling the amended sketch, and I don't know how to debug it.

Below is a copy of the error report.

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
Arduino: 1.0.6 (Windows 7), Board: "Arduino Uno"

RustyArc_stepper:1: error: function definition does not declare parameters
RustyArc_stepper:22: error: 'AccelStepper' does not name a type
RustyArc_stepper.ino: In function 'void setup()':
RustyArc_stepper:43: error: 'stepper1' was not declared in this scope
RustyArc_stepper.ino: In function 'void loop()':
RustyArc_stepper:76: error: 'stepper1' was not declared in this scope
RustyArc_stepper:85: error: 'stepper1' was not declared in this scope
RustyArc_stepper:90: error: 'stepper1' was not declared in this scope

Ken

foobillious
5th February 2015, 03:03 PM
Rusty and foob,

There is a problem when compiling the amended sketch, and I don't know how to debug it.
<snip>

RustyArc_stepper:1: error: function definition does not declare parameters
RustyArc_stepper:22: error: 'AccelStepper' does not name a type

<snip>
Ken

Hi Ken,

Just guessing at this point (got Arduino software downloading now to check)... Looks like you haven't got the AccelStepper library installed. It is a library most of those examples are based on. Instructions for doing so are in example 3. Or you can get the file here:
http://www.airspayce.com/mikem/arduino/AccelStepper/AccelStepper-1.45.zip

Once you've downloaded that you'll then need to install it by unziping it to your arduino libraries folder. I've got some memory that there was a way to install it through the IDE as well. just can't remember what it is.

I'll post again in a couple of minutes when the download has finished and I've installed it.

RustyArc
5th February 2015, 03:05 PM
Have you installed the AccelStepper library as per Example 3 on Brian Schmalz's page?

neksmerj
5th February 2015, 03:24 PM
Gentlemen,

I have all the necessary libraries installed, and have been running Brian Schmaltz's example 6 sketch without error, apart from the delays.

Am currently trying to printout the amended sketch, and wouldn't you know it, the printer is spewing out blank pages. Can't take a trick.

Ken

foobillious
5th February 2015, 03:28 PM
okay, sorry for the double post and the delay. very slow internuts at the moment.

So it looks like there are two ways to install. The easiest (i accidentally downloaded the beta arduino, which is version 1.5.8) is to download the zip file from http://www.airspayce.com/mikem/arduino/AccelStepper/AccelStepper-1.45.zip

Once you've downloaded the file, go into your arduino ide and go to the sketch menu. Select Import Library and then Add Library...

Next browse to where you downloaded the AccellStepper-1.45.zip file and select that. The Arduino software will import that library and will use it from the downloaded location.

Alternatively, if that option isn't available to you, right click on the AccellStepper-1.45.zip file and select Extract All...

Next browse to the Arduino Library folder (normally My Documents\Arduino\libraries ) and extract into there. If you restart your arduino IDE the library should appear in your Import library list (don't bother clicking on it - it is already in your sketch).

I apparantly need to get the Adafruit motorshield library, so I'll go get that and then do a test compile on the code.

urgghh.. looks like the Adafruit motorshield library has changed a bit since those examples were written. give me a sec and I'll try and work it out.

foobillious
5th February 2015, 03:42 PM
okay, and apologies for the triple post.

I installed the adafruit library following the instructions here: https://learn.adafruit.com/adafruit-motor-shield/library-install

Once I'd done that I modified the code so it is similar to the adafruit examples, while still keeping the original author's intent and our modifications. Make sure you have both the AccelStepper library and the Adafruit library installed and then give this a try. It compiles for me, but I haven't got any hardware to test it with.



// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html

#include <AccelStepper.h>
#include <Wire.h>
#include <AFMotor.h>


// Define the stepper and the pins it will use
AF_Stepper motor1(200,1); // this sets up your stepper motor as 200 stps per revolution and on port 1



// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1.onestep(FORWARD, SINGLE);
}
void backwardstep() {
motor1.onestep(BACKWARD, SINGLE);
}

AccelStepper stepper1(forwardstep, backwardstep); // use functions to step

// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6

// Define our analog pot input pin
#define SPEED_PIN A0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1

void setup() {
// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to turn the motor on/off and control direction
static int analog_value = 0; // Holds raw analog value.

// If a switch is pushed down (low), set the sign value appropriately
if (digitalRead(LEFT_PIN) == 0) {
sign = 1;
}
if (digitalRead(RIGHT_PIN) == 0) {
sign = -1;
}
if (digitalRead(STOP_PIN) == 0) {
sign = 0;
}
// code from Rusty
if (digitalRead(LEFT_LIM_PIN)==0) { // if the left limit pin is hit
if (digitalRead(RIGHT_PIN)==0) { // allow the right button to move us off the limit
sign=-1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}
if (digitalRead(RIGHT_LIM_PIN)==0) { // if the right limit pin is hit
if (digitalRead(LEFT_PIN)==0) { // allow the left button to move us off the limit
sign=1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}

// Give the stepper a chance to step if it needs to
stepper1.runSpeed();
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed
stepper1.runSpeed();

// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 3000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
}


}

foobillious
5th February 2015, 03:50 PM
Gentlemen,

I have all the necessary libraries installed, and have been running Brian Schmaltz's example 6 sketch without error, apart from the delays.

Am currently trying to printout the amended sketch, and wouldn't you know it, the printer is spewing out blank pages. Can't take a trick.

Ken
whups.. missed this. sorry, ignore me.

foobillious
5th February 2015, 03:54 PM
Ken are you able to post back the code that is throwing the error?
if you just copy it, and then past it into a post between code blocks (use the button that looks like a # ) it'll be easier to read and figure out what is going wrong.

*edit* sorry - i mean please post the entire sketch..

*edit2* annnnd as it turns out I'd downloaded the old Adafruit motorshield library, not the one for the current V2 motor shield. so, definately ignore my code.

neksmerj
5th February 2015, 04:03 PM
foobillious,

That's strange, you say your sketch compiles ok, and yet mine does not.

This is the error report

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
Arduino: 1.0.6 (Windows 7), Board: "Arduino Uno"


function definition does not declare parameters


sketch_feb05a:1: error: function definition does not declare parameters
sketch_feb05a:11: error: 'AF_Stepper' does not name a type
sketch_feb05a.ino: In function 'void forwardstep()':
sketch_feb05a:17: error: 'motor1' was not declared in this scope
sketch_feb05a:17: error: 'FORWARD' was not declared in this scope
sketch_feb05a:17: error: 'SINGLE' was not declared in this scope
sketch_feb05a.ino: In function 'void backwardstep()':
sketch_feb05a:20: error: 'motor1' was not declared in this scope
sketch_feb05a:20: error: 'BACKWARD' was not declared in this scope
sketch_feb05a:20: error: 'SINGLE' was not declared in this scope
sketch_feb05a.ino: At global scope:
sketch_feb05a:23: error: 'AccelStepper' does not name a type
sketch_feb05a.ino: In function 'void setup()':
sketch_feb05a:42: error: 'stepper1' was not declared in this scope
sketch_feb05a.ino: In function 'void loop()':
sketch_feb05a:75: error: 'stepper1' was not declared in this scope
sketch_feb05a:84: error: 'stepper1' was not declared in this scope
sketch_feb05a:89: error: 'stepper1' was not declared in this scope

Ken

foobillious
5th February 2015, 04:13 PM
Hi Ken,

yes, i had the wrong library downloaded. It was for an older version of the Adafruit motorshield. I'll try again with the new one. Just have to clear some work first. Should be about 5-10 more minutes and then I'll try again.

foobillious
5th February 2015, 04:20 PM
Hi Ken,
Okay, I've installed the correct Adafruit Motorshield v2 library and I've done a test compile on rusty's code. It seems to compile fine for me. Would you be able to try it again? Code below for ease of use:


// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, SINGLE);
}
void backwardstep() {
motor1->onestep(BACKWARD, SINGLE);
}

AccelStepper stepper1(forwardstep, backwardstep); // use functions to step

// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6

// Define our analog pot input pin
#define SPEED_PIN A0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1

void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to turn the motor on/off and control direction
static int analog_value = 0; // Holds raw analog value.

// If a switch is pushed down (low), set the sign value appropriately
if (digitalRead(LEFT_PIN) == 0) {
sign = 1;
}
if (digitalRead(RIGHT_PIN) == 0) {
sign = -1;
}
if (digitalRead(STOP_PIN) == 0) {
sign = 0;
}
// code from Rusty
if (digitalRead(LEFT_LIM_PIN)==0) { // if the left limit pin is hit
if (digitalRead(RIGHT_PIN)==0) { // allow the right button to move us off the limit
sign=-1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}
if (digitalRead(RIGHT_LIM_PIN)==0) { // if the right limit pin is hit
if (digitalRead(LEFT_PIN)==0) { // allow the left button to move us off the limit
sign=1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}

// Give the stepper a chance to step if it needs to
stepper1.runSpeed();
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed
stepper1.runSpeed();

// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 3000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
}


}

neksmerj
5th February 2015, 04:22 PM
Hi foob,

I too made the same mistake initially, as did Brian Schmalz, some of the Adafruit sketches are old and only apply to the V1 board.

I appreciate the help you are giving me. For me trying to decipher code is trying to untangle Egyptian hieroglyphics.

Ken

foobillious
5th February 2015, 05:43 PM
How did you get on re doing the cut, paste and compile? any change or is it still throwing errors at you?

neksmerj
5th February 2015, 06:12 PM
foob,

I finally got your sketch to compile, think I missed one squiggly bracket right at the bottom of the sketch.

There is one error message though,

avrdude:st500_getsync():not in sync:reap=0x00

Despite that, the motor turns CW, ACW and stops, however, the limit switches have no effect.

Using a 5V digital probe, I don't get a high on pins 5 & 6, (limit switch pins) but do get a low on those pins when I depress the limit switches.

I get a high on pins 2,3 &4 which get pulled low with the appropriate PB

Any thoughts?

edit: changed the pin numbers to 5 & 6, inadvertently called them pins 4 & 5

Ken

RustyArc
5th February 2015, 07:12 PM
Using a 5V digital probe, I don't get a high on pins 5 & 6, (limit switch pins) but do get a low on those pins when I depress the limit switches.

Do you have these two initialisation lines in your code?


pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);

neksmerj
5th February 2015, 08:05 PM
Hi Rusty,

Yes, I'm using your code, cut and pasted from the screen.

What ever you have written, I'm using.

Just wondering whether pins 5 & 6 are reserved for something else, however, I think not.

I wonder whether adding external resistors, say 1K, would help?

Ken

RustyArc
5th February 2015, 08:47 PM
I'm not familiar with the Arduino architecture, but a quick read of the docs suggests there's nothing special about 5 & 6. You could change the code to use pins 7 & 8 just to check.

You shouldn't need to add an external pullup resistor, the two INPUT_PULLUP commands I mentioned above connect the pins to the supply rail via a 20k resistor, which then should be registering as high.

foobillious
5th February 2015, 11:53 PM
sorry about the late reply. A quick google tells me that error is apparantly caused by a comms error as the program is being uploaded. Try saving your sketch, shutting down the arduino software, disconnecting your arduino (unplugging the usb cables). Then plug it all back in again, open the arduino software and try to upload the sketch again.

you can probably eliminate the pins being an issue by disconnecting everything external to the arduino board before uploading....

this may also help:
http://www.instructables.com/id/A-solution-to-avrdude-stk500getsync-not-in-syn/

neksmerj
6th February 2015, 01:25 PM
I tried to run the last sketch by Rusty and foob, and nothing except errors again. This is a mystery as this sketch was compiling, and running ok last night, except for the limit switches.

This is the error report

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
Arduino: 1.0.6 (Windows 7), Board: "Arduino Uno"
RustyArc_stepper:1: error: function definition does not declare parameters
RustyArc_stepper:22: error: 'AccelStepper' does not name a type
RustyArc_stepper.ino: In function 'void setup()':
RustyArc_stepper:43: error: 'stepper1' was not declared in this scope
RustyArc_stepper.ino: In function 'void loop()':
RustyArc_stepper:76: error: 'stepper1' was not declared in this scope
RustyArc_stepper:85: error: 'stepper1' was not declared in this scope
RustyArc_stepper:90: error: 'stepper1' was not declared in this scope

And the sketch


Code:
// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html


#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>


// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1);




// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, SINGLE);
}
void backwardstep() {
motor1->onestep(BACKWARD, SINGLE);
}


AccelStepper stepper1(forwardstep, backwardstep); // use functions to step


// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6


// Define our analog pot input pin
#define SPEED_PIN A0


// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1


void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}


void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to turn the motor on/off and control direction
static int analog_value = 0; // Holds raw analog value.

// If a switch is pushed down (low), set the sign value appropriately
if (digitalRead(LEFT_PIN) == 0) {
sign = 1;
}
if (digitalRead(RIGHT_PIN) == 0) {
sign = -1;
}
if (digitalRead(STOP_PIN) == 0) {
sign = 0;
}
// code from Rusty
if (digitalRead(LEFT_LIM_PIN)==0) { // if the left limit pin is hit
if (digitalRead(RIGHT_PIN)==0) { // allow the right button to move us off the limit
sign=-1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}
if (digitalRead(RIGHT_LIM_PIN)==0) { // if the right limit pin is hit
if (digitalRead(LEFT_PIN)==0) { // allow the left button to move us off the limit
sign=1;
}
else {
sign=0; // but otherwise we should stop the motor
stepper1.setSpeed(sign); // by setting the motor's speed to 0
}
}


// Give the stepper a chance to step if it needs to
stepper1.runSpeed();
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed
stepper1.runSpeed();


// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 3000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
}



}

Ken

foobillious
6th February 2015, 06:13 PM
Okay, I'm a little puzzled by those errors. Essentially what its saying is there is a problem with the first line of your sketch, which then seems to be carrying into the AccelStepper library and breaking stuff there.

hmm.. you don't have that 1st line which says Code: actually in your sketch do you? If so, delete it and then try compiling.

*edit* Yup, that seems to be the problem - I get the same errors as you if I have that first line in. Delete the Code: line and you should be fine.

foobillious
6th February 2015, 06:32 PM
Okay, I've verified this compiles, although I havn't tested anything else.

Give the attached file a try

neksmerj
6th February 2015, 07:33 PM
FINAL TEST

I've just got home, and read your email. Such a simple oversight causing all those errors. Soon fixed that and rewired the limit switches.

The other thing I had to do was down in line 8 that reads in part-

=AFMS.getStepper(200, 1); change 1 to 2 as my motor is connected to terminals M3 & M4, not M1 & M2

LIMIT SWITCHES

They work as follows-depress the limit switch and the motor stops. Keep the limit switch depressed and push fwd or rev pb, motor runs only while the button is held down, ie, let go the button and the motor stops.

This seems to working really well thanks to you and RustyArc

I'll let you blokes have a little rest before I hit you with the next amendment, and that will be drive carriage for say 300mm, stop and take picture, move another 300mm, stop and take picture etc etc

I'm impressed,

Ken

RustyArc
6th February 2015, 08:45 PM
So you sorted out the pullups for the limit switches then?

Good catch picking up the code: thing foobillious - I saw that line 1 error in previous posts, but the penny never dropped. I have to say, the way cutting and pasting works on this forum software can often be a bit offputting.

neksmerj
6th February 2015, 09:24 PM
Rusty and foob.

My stepper gets terribly hot rotating or stopped. I know this is one of the drawbacks of steppers, they draw max power when stationary. Since this project will eventually be battery powered, is there some way of squeezing in the "release" command that takes power off the motor when it is stopped?

I've had several attempts at this and failed. I can't find the right protocol. The command is release()

Ken

foobillious
6th February 2015, 10:43 PM
Before I take a whack at the move x amount then stop code, could you please check if this works?
I'm a bit tired, but I think it should fix the movement off the limit switches issue, and it should also stop the motor from getting hot if its stopped.


// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html


#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 2);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, SINGLE);
}
void backwardstep() {
motor1->onestep(BACKWARD, SINGLE);
}

AccelStepper stepper1(forwardstep, backwardstep); // use functions to step

// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6


// Define our analog pot input pin
#define SPEED_PIN A0


// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1


void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}


void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to control direction
static char enabled=0; // used to keep track of if the motor has been enabled (used to allow the motors to idle)
static int analog_value = 0; // Holds raw analog value.


if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1) { // allow movement LEFT if the LEFT limit switch isn't hit
sign=1;
} else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1) { // allow movement RIGHT if the RIGHT limit switch isn't hit
sign=-1;
} else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0) { // if neither of the above is true, and a limit or stop switch has been hit then stop the motors
sign=0;
stepper1.setSpeed(sign);
}

if (sign!=0) { // motor has a valid direction
if (enabled==0) { // motor was previously disabled, re-enable it (but don't re-enable it every single time we go through the loop)
enabled=1;
stepper1.enableOutputs();
}
} else { // a limit switch or the stop switch has been hit. disable the output to the motor.
enabled=0;
stepper1.disableOutputs();
}

// Give the stepper a chance to step if it needs to
if (enabled==1) {
stepper1.runSpeed();
}
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed, if the motor is currently enabled.
if (enabled==1) {
stepper1.runSpeed();
}

// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 3000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
}
}

neksmerj
7th February 2015, 12:30 PM
Hi foobillious,

I was too tired last night to have a proper look at your code changes. Not sure why you changed the limit switch code, they seem to be working as they should.
Can you briefly describe in English what changes you did and why.

What I really like about your code changes is the fact that the motor stops, in it's tracks, when a button is pressed or limit switch. As mentioned earlier, the motor would run on for a turn or two before stopping.

I sent your code to Brian Schmalz for comment, and he was most impressed with the upgrade.

With respect to the motor getting hot when stopped, I see you have tried to address that problem, however, the motor is still drawing power when stopped. I can feel it vibrating and getting hot.

This is a bit of a worry.

Ken

foobillious
7th February 2015, 12:58 PM
Hi Ken,

Sorry, I must have been more tired than I thought. I was under the impression that it wasn't working the way you wanted it to.

I changed the switch code so that movement in a direction is allowed only if that direction's limit switch isn't hit. What I think will happen now is if the right limit switch is hit then no movement to the right will be allowed, however if the left direction button is hit then the carriage will start moving to the left at the pre set speed, and will continue in that direction until the other limit switch is hit, or the stop button is pushed. Its pretty straightforward to change it back to the old code. just let me know which way around you want it.

I'll take a look at the Adafruit library, and see if I can figure out the release command. I was concentrating on the accelstepper library.

foobillious
7th February 2015, 01:22 PM
okay, release command was fairly straightforward. I've added it in. We can probably change the disableOutputs(); stuff as well, but I'd like to know if this works first:


// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html


#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 2);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, SINGLE);
}
void backwardstep() {
motor1->onestep(BACKWARD, SINGLE);
}

AccelStepper stepper1(forwardstep, backwardstep); // use functions to step

// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6


// Define our analog pot input pin
#define SPEED_PIN A0


// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1


void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}


void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to control direction
static char enabled=0; // used to keep track of if the motor has been enabled (used to allow the motors to idle)
static int analog_value = 0; // Holds raw analog value.

if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1) { // allow movement LEFT if the LEFT limit switch isn't hit
sign=1;
} else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1) { // allow movement RIGHT if the RIGHT limit switch isn't hit
sign=-1;
} else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0) { // if neither of the above is true, and a limit or stop switch has been hit then stop the motors
sign=0;
stepper1.setSpeed(sign);
}

if (sign!=0) { // motor has a valid direction
if (enabled==0) { // motor was previously disabled, re-enable it (but don't re-enable it every single time we go through the loop)
enabled=1;
stepper1.enableOutputs();
}
} else { // a limit switch or the stop switch has been hit. disable the output to the motor.
enabled=0;
motor1->release();
stepper1.disableOutputs();
}

// Give the stepper a chance to step if it needs to
if (enabled==1) {
stepper1.runSpeed();
}
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed, if the motor is currently enabled.
if (enabled==1) {
stepper1.runSpeed();
}

// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 3000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
}
}

neksmerj
7th February 2015, 02:45 PM
Hi foobillious,

You nailed it. (Wish you lived next door, bet you're glad you don't) When the motor is stopped, there's not a hint of any vibration, I don't have a way of verifying it electrically.

I guess now all the superfluous code can be wiped. Where did you look to find out how the "release" command works and is worded?

I'm not sure which version of the limit switch code is best, perhaps you could advise. All my requirement was that when the right limit is hit, no further movement can take place in that direction and vica versa. I think both versions of your code do this.

I really struggled with the release command and got absolutely no help from the Adafruit forum for this project. In the end they gave me the big A and locked the thread, charming!

I think my age hinders me a bit from learning new tricks, but at least I'm trying and picking things up from you blokes.

Many thanks

Ken

foobillious
7th February 2015, 03:57 PM
weird, the adafruit people are normally quite good with newbies. guess they thought you were a troll. Mind you with this sort of thing your only really going to get help if people are in the mood.

anyway, I found the correct usage by looking in the library file itself. If you go into your arduino libraries folder and into the Adafruit_Motor_Shield folder you'll see a Adafruit_MotorShield.h and Adafruit_MotorShield.cpp file. the .h file is a header file (its just a text file, you can open it with notepad), and basically tells the compiler about a lot of definitions the compiler needs to actually link to the Adafruit library. Include in that are the functions definitions.

In the Adafruit_StepperMotor class in the public section there is a function: void release(void); which is your release function. the (void) bit tells us that it doesn't need any parameters passed to it, and the void before the word release tells us it doesn't return anything either. The public section means we can access that code from anywhere in our program, as long as we have a Adafruit_StepperMotor object.

In your code the Adafruit_StepperMotor object is a variable of type Adafruit_StepperMotor called motor1. Its set up on line 10 and 11:


// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); // this creates a variable of type Adafruit_MotorShield called AFMS
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 2); // this asks AFMS to give us a pointer to one of its Adafruit_StepperMotor objects
// a pointer is a reference, or link to the actual object.


once we have that, if we can use that pointer to call the object's release() function:


motor1->release();


It's probably not an age thing. It tends to look like giberrish unless you've taken the time to work through and figure out what everything means. Once you understand how programming languages tend to work it becomes a lot easier.

Moving on though.
I'm not 100% clear on what your trying to do. I've got a vague concept that you want a camera on a carriage to move a specific distance along the track, stop and take a photo, then repeat? Do you know how far your carriage moves either per step of your stepper motor or per revolution? The way the AccelStepper library works is we can tell it we want to move X steps from the current position, and then it move that far along. If we know how far your carriage moves for a given number of steps then we can use an exact distance. If not then we'll just play around till we get something that works

neksmerj
7th February 2015, 04:46 PM
Hi foobillious,

Thanks for the insight into the Adafruit code.

I've never actually seen a camera slider in the flesh, but have seen some units on the web whereby everything is controlled by a small LCD screen. Far, far too complicated for me, coding would be a nightmare. I'm just after something very basic with knobs and switches to do the controlling.

This unit will be used out in the field and I imagine the circuit boards and controls will be in an enclosure. The possibility of changing code on the fly, is not feasible.

DISTANCE CONTROL

That said, I would like to be able to control the distance traveled with a potentiometer, say zero to 300mm max per movement, along a 2m track. I believe the GT2 (2mm) toothed pulley is about 25mm in dia so it's circumference is about 78mm, therefore one turn will give me 78mm.

If you have a better suggestion, I'm all ears.

I'm really pleased with what you have come up with so far, it's appreciated.

Ken

neksmerj
7th February 2015, 05:02 PM
foobillious,

One other small problem, speed control.

I will definitely be using the "microstep" function as it's nice and smooth, however, using a 10K pot the max speed is one rev every 10 seconds.

I'd like to use "microstep" so that some shots can be taken whist the camera is moving. (less jitter)

I've fiddled with some of the parameters and the speed doesn't seem to alter. Is there an easy way of speeding up the motor?

Ken

foobillious
8th February 2015, 01:04 PM
Hi Ken,

Can you please give this a try? You will need to add a second pot (on pin A1), which will be your distance set pot.

What should happen (I think, again, as usual untested) is that when you power it on it'll just sit there doing nothing. Set what speed you want and what distance you want and then press one of the direction buttons (left or right). The motor should accelerate up to speed quickly as it moves to the specified distance, then it should accelerate back down again and stop. Hit the direction button again and it should move the same distance. If you don't want the acceleration feature (probably a waste of time for very small distances, but it may help to eliminate your camera mount shaking as the motor stops) just change line 24 to the same value as the MAX_SPEED value.

I've also changed everything around so the loop() function is less messy. I've tried to make each function a discrete task, which should make the debugging a little eaiser. the checksetIdle function is a little untidy, but should work.

Could you also please check the limit function still works (set a distance and hit the direction button, then hit the limit switch before it reaches that distance)?



// Ken's Arduino Controled Camera Slider
// based on code from Example6 of Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
//
// Designed for Arduino UNO

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <AccelStepper.h>

// Definitions - these make it easier to change what pins we are plugging things into on our arduino, and other control options such as speed
// First Define the 3 digital input pins for direciton control
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// And the 2 digital inputs to test for limits
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6
// and our two analog pot input pin
#define SPEED_PIN A0
#define DISTANCE_PIN A1
// and our MAX SPEED and accelleration
#define MAX_SPEED 1000
#define MAX_ACCEL 400 // set this to the same as MAX_SPEED if you don't want acceleration
#define MIN_SPEED 0.1
// and the minimuum and maximum distance in steps
#define MAX_DISTANCE 800 // this max distance was selected based on 1 revolution being 200 steps causing a 78mm travel. comes out at 312mm travel
#define MIN_DISTANCE 0

// Function forward definitions
void forwardstep();
void backwardstep();
char checkInputs();
char checksetIdle(char *direction);
void checksetDistance(char direction,char olddir);
char checkDTG();
float calcSpeed(int speedpot,int direction);
float calcDistance(int destpot);

// Global Variables:
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1=AFMS.getStepper(200,2);
AccelStepper stepper1(forwardstep,backwardstep);

// initialise any global variables and tell the Arduino what to use the various pins for
void setup()
{
AFMS.begin();

// Tell AccelStepper what the maximum speed should be in steps per second.
stepper1.setMaxSpeed(MAX_SPEED);
stepper1.setAcceleration(MAX_ACCEL);

// set up the 3 input button inputs and the limit inputs with pullps
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

// This is where the main body of the work gets done. The loop function gets called repeatedly
void loop()
{
static float current_speed=0.0; // holds the current motor speed in steps/second
static int analog_read_counter=1000; // counts down to 0 to fire analog read
static char direction=0; // holds -1, 1 or 0 to control direction
char enabled; // used to keep track of if the motor has been enabled
static int speed_value; // holds the raw analog value of the speed
char olddir; // used to see if the direction has changed

// step 1 - check inputs
olddir=direction;
direction=checkInputs(); // get the direction we should be moving in, based on inputs from the dir switches and limits
checksetDistance(direction,olddir); // check and set a new distance from the current point, if necessary
enabled=checksetIdle(&direction); // check if the motor should be idling or not (note this may set the directuib to 0 if we have reached the specified distance)

// step 2 - run the motor
if (enabled==1)
{
stepper1.run(); // let the motor step if it needs to before we change the speed
}
current_speed=calcSpeed(speed_value,direction); // calculate what our speed should be based on last pot setting and direciton
stepper1.setSpeed(current_speed);
if (enabled==1) {
stepper1.run();
}

// step 3 - update analog values, if necessary
if (analog_read_counter>0)
{
analog_read_counter--;
}
else
{
analog_read_counter=3000; // change this to a lower number to increase pot response
speed_value=analogRead(SPEED_PIN); // get the speed value
// distance value read could go here, but as it isn't updated all that often
// its easier just to do it when necessary
}
}

// this function will be called by the AccelStepper every step the motor turns forward
void forwardstep()
{
motor1->onestep(FORWARD, MICROSTEP);
}

// this function will be called by the AccelStepper every step the motor turns backward
void backwardstep()
{
motor1->onestep(BACKWARD, MICROSTEP);
}

// this function checks our inputs and returns a number indicating if the motor will turn LEFT (1), RIGHT (-1)
// or if it should stop (0)
char checkInputs()
{
char direction=0;

if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1)
{
direction=1;
}
else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1)
{
direction=-1;
}
else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0)
{
direction=0;
}
return direction;
}

// this function checks if our motor should idle or not, based on the direction. it also puts the motor into the idle state
// returns 1 if the motor is in the idle state
char checksetIdle(char *direction)
{
if (*direction==0)
{
motor1->release();
return 1;
}
if (checkDTG()==0)
{
motor1->release();
*direction=0;
return 1;
}
return 0;
}

// this function reclculates the speed for the motor, based on the last speed potentiometer value and the direction.
// returns a float indicating what the speed should be
float calcSpeed(int speedpot,int direction)
{
return (direction * ((speedpot/1023.0) * (MAX_SPEED-MIN_SPEED)) + MIN_SPEED);
}

// this function calculates how far we should move before stopping, based on the last destination potentiometer value
long calcDistance(int destpot, int direction)
{
return (direction * ((destpot/1023.0) * (MAX_DISTANCE-MIN_DISTANCE)) + MIN_DISTANCE);
}

// this function determines if a new distance to move is necessary, and provides a new distance relative to the current position to the AccelStepper library.
void checksetDistance(char direction,char olddir)
{
int dist_value; // holds the raw analog value of the distance
long distance; // holds how far we are going to move

if (direction==0 || olddir==direction) // we only update the distance if we are about to move (direction is set), and we are changing direction (olddir doesn't equal the new dir)
return;

dist_value=analogRead(DISTANCE_PIN); // read the distance pot to figure out how far we have to move
distance=calcDistance(dist_value,direction); // calculate the distance
stepper1.move(distance); // set the distance to move from the current position
}

// check the distance to go to determine if we should idle the motor or not.
char checkDTG()
{
if (stepper1.distanceToGo()>0)
{
return 1;
}
return 0;
}

neksmerj
8th February 2015, 04:39 PM
Hi foob,

You have certainly been busy, wow.

Your amended sketch compiled with that stupid "avrdude:" error, but disappeared when I selected com3 port.

Now this is a mystery.

1. Connected up a second pot with one side to GND, the centre to A1 and the other side to 5V. Initially everything was working as it should except that the distance pot had no effect. I checked with a digital probe that it was swinging from 5V to GND, all good
2. Changed the stepping from "microstep" to "single" and recompiled. This time nothing unless the fwd or rev button was kept depressed. The motor just oscillated and sounded like it was going crook .
3. Smoked started coming off the Adafruit motor shield, or the Ardunio UNO, not sure which, so quickly pulled the pin.

I've got spares but am reluctant to try again until I find the cause of the burn out.

Ken

foobillious
8th February 2015, 05:12 PM
wow, guess i screwed something up there. sorry about that...

I'd be betting the smoke was off the motorshield..

neksmerj
8th February 2015, 06:22 PM
Hi foob,

Tried connecting my motor to the other set of terminals on the stepper board, no go, it's stuffed I'd say.

Just assembled a spare Adafruit motor shield I had, reverted back to the last known good sketch where you incorporated the "release" command, and I'm back in business.

At least the Arduino seams to be ok.

I have absolutely no idea why the stepper shield burnt out. All I can think of is with three levels of boards, 1. Arduino, 2. Adafruit terminal shield then 3. the Adafruit stepper shield, that a short occurred somewhere between boards.

Do you have any theories?

Ken

foobillious
8th February 2015, 09:23 PM
sorry, but I've got no idea what went wrong. I'll take a look at the code again tomorrow to see if I can identify what screwed up. Off the top of my head I can take a wild guess that the distance code was telling the stepper to go one way and the speed was telling the stepper to go the other, but I dunno. its a bit hard doing this with out any real idea of the hardware or how the libraries are interacting.

neksmerj
9th February 2015, 04:57 PM
Hi foob, have you come up with any ideas?
Ken

foobillious
10th February 2015, 09:30 AM
Hi Ken, the checksetIdle function wasn't right, but not in a way that should have caused the motor to burn out.

Could you please test out the code below for me?

This should ignore the speed pot completely, but the distance pot should work. I'll put the speed stuff back in once we've got it sorted out.

Your test procedure should be
1. connect your distance pot to pin A1. check there is nothing else connected to pin A1 through your shields.
2. Set your distance pot to 1V output.
3. press one of the direction buttons. You should get movement in that direction for a distance of about 160mm. If you do not get movement power everything off straight away. Abandon the test at this point and let me know
4. press the other direction button and you should get movement in that direction for a distance of about 160mm. again, if it doesn't move, power off and tell me (if 3 worked this should).
5. press the first direction button again, but this time hit the stop button before it gets there. carriage should halt and the motor shouldn't get warm.
6. press the first direction button again (this time it will try and move to 160mm from where you are now). hit the limit button for this direction and hold it down. carriage should halt and the motor shouldn't get warm. keep holding the limit switch down
6. press the first direction button again. the carriage should not do anything. motor should stay in the idle state and not get warm. keep holding the limit switch down
7. press the second direction button, which should allow the carriage to back away from the limit switch 160mm. release the limit switch if it starts the moment.
8. press the second direction button again (another 160mm in that direction), but hit the limit switch (hold down) before it gets there. carriage should halt and the motor shouldn't get warm.
9. release the limit switch. carriage should not do anything, motor should stay idle.

Basically if you get a failure at any point of those tests, power off straight away and let me know. Sorry if I sound paranoid - I want to make sure we don't cook another motor shield.



// Ken's Arduino Controled Camera Slider
// based on code from Example6 of Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
//
// Designed for Arduino UNO

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <AccelStepper.h>

// Definitions - these make it easier to change what pins we are plugging things into on our arduino, and other control options such as speed
// First Define the 3 digital input pins for direciton control
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// And the 2 digital inputs to test for limits
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6
// and our two analog pot input pin
#define SPEED_PIN A0
#define DISTANCE_PIN A1
// and our MAX SPEED and accelleration
#define MAX_SPEED 500
#define MAX_ACCEL 250 // set this to the same as MAX_SPEED if you don't want acceleration
#define MIN_SPEED 0.1
// and the minimuum and maximum distance in steps
#define MAX_DISTANCE 800 // this max distance was selected based on 1 revolution being 200 steps causing a 78mm travel. comes out at 312mm travel
#define MIN_DISTANCE 0

// Function forward definitions
void forwardstep();
void backwardstep();
char checkInputs();
char checksetIdle(char *direction);
void checksetDistance(char direction,char olddir);
char checkDTG();
float calcSpeed(int speedpot,int direction);
float calcDistance(int destpot);

// Global Variables:
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1=AFMS.getStepper(200,2);
AccelStepper stepper1(forwardstep,backwardstep);

// initialise any global variables and tell the Arduino what to use the various pins for
void setup()
{
AFMS.begin();

// Tell AccelStepper what the maximum speed should be in steps per second.
stepper1.setMaxSpeed(MAX_SPEED);
stepper1.setAcceleration(MAX_ACCEL);

// set up the 3 input button inputs and the limit inputs with pullps
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

// This is where the main body of the work gets done. The loop function gets called repeatedly
void loop()
{
static float current_speed=0.0; // holds the current motor speed in steps/second
static int analog_read_counter=1000; // counts down to 0 to fire analog read
static char direction=0; // holds -1, 1 or 0 to control direction
char enabled; // used to keep track of if the motor has been enabled
static int speed_value; // holds the raw analog value of the speed
char olddir; // used to see if the direction has changed

// step 1 - check inputs
olddir=direction;
direction=checkInputs(); // get the direction we should be moving in, based on inputs from the dir switches and limits
checksetDistance(direction,olddir); // check and set a new distance from the current point, if necessary
enabled=checksetIdle(&direction); // check if the motor should be idling or not (note this may set the directuib to 0 if we have reached the specified distance)

// step 2 - run the motor
// if (enabled==1)
// {
// stepper1.run(); // let the motor step if it needs to before we change the speed
// }
// current_speed=calcSpeed(speed_value,direction); // calculate what our speed should be based on last pot setting and direciton
// stepper1.setSpeed(current_speed);
if (enabled==1) {
stepper1.run();
}
/*
// step 3 - update analog values, if necessary
if (analog_read_counter>0)
{
analog_read_counter--;
}
else
{
analog_read_counter=3000; // change this to a lower number to increase pot response
speed_value=analogRead(SPEED_PIN); // get the speed value
// distance value read could go here, but as it isn't updated all that often
// its easier just to do it when necessary
}
*/
}

// this function will be called by the AccelStepper every step the motor turns forward
void forwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(FORWARD, SINGLE);
}

// this function will be called by the AccelStepper every step the motor turns backward
void backwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(BACKWARD, SINGLE);
}

// this function checks our inputs and returns a number indicating if the motor will turn LEFT (1), RIGHT (-1)
// or if it should stop (0)
char checkInputs()
{
char direction=0;

if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1)
{
direction=1;
}
else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1)
{
direction=-1;
}
else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0)
{
direction=0;
}
return direction;
}

// this function checks if our motor should idle or not, based on the direction. it also puts the motor into the idle state
// returns 0 if the motor is in the idle state
char checksetIdle(char *direction)
{
static char lastval=0;

if (*direction==0)
{
motor1->release();
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (checkDTG()==0)
{
motor1->release();
*direction=0;
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (lastval==0)
{
stepper1.enableOutputs();
lastval=1;
}
return 1;
}

// this function reclculates the speed for the motor, based on the last speed potentiometer value and the direction.
// returns a float indicating what the speed should be
float calcSpeed(int speedpot,int direction)
{
return (direction * ((speedpot/1023.0) * (MAX_SPEED-MIN_SPEED)) + MIN_SPEED);
}

// this function calculates how far we should move before stopping, based on the last destination potentiometer value
long calcDistance(int destpot, int direction)
{
return (direction * ((destpot/1023.0) * (MAX_DISTANCE-MIN_DISTANCE)) + MIN_DISTANCE);
}

// this function determines if a new distance to move is necessary, and provides a new distance relative to the current position to the AccelStepper library.
void checksetDistance(char direction,char olddir)
{
int dist_value; // holds the raw analog value of the distance
long distance; // holds how far we are going to move

if (direction==0 || olddir==direction) // we only update the distance if we are about to move (direction is set), and we are changing direction (olddir doesn't equal the new dir)
return;

dist_value=analogRead(DISTANCE_PIN); // read the distance pot to figure out how far we have to move
distance=calcDistance(dist_value,direction); // calculate the distance
stepper1.move(distance); // set the distance to move from the current position
}

// check the distance to go to determine if we should idle the motor or not.
char checkDTG()
{
if (stepper1.distanceToGo()>0)
{
return 1;
}
return 0;
}

neksmerj
10th February 2015, 02:33 PM
Hi foobillious,

Just got your reply. I have all this set up on a mini breadboard, and reckon that's inviting trouble.

I have a spare Arduino mounted on a plastic plate together with a full length breadboard. I'll carefully transfer all the jumpers etc across, and give your revised code a go.

I'll also change power supplies to a low current one. Currently using an Arlec battery charger which is probably not ideal.

Ken

neksmerj
10th February 2015, 06:45 PM
Hi foob,

Sorry for the delay in getting back to you.

Have reassembled all the components on a new breadboard, and hooked up a 12V, 2A wall plug. This power pack is so light it makes me doubt it has enough grunt.

OK, your revised sketch compiled ok and runs as per some of the older iterations, ie, push buttons work, limit switches work and the speed pot sort of works. When I say sort of works, it doesn't slow the motor down until it's nearly backed right off.

1. What's not happening is the distance pot. It is not having any effect on the motor, and I've tried different settings and, waited for half a minute or so.

I've checked with a multi meter and pin A1 can be varied from 5V to GND. It's currently set on 1V as suggested.

2. Changing the stepper setting from "single" through to "microstep" does nothing. Feels like the motor is running on "microstep" all the time, it's quite slow. One rev takes about 10 secs.
This micro stepping also occurs with some older sketches which reinforces my feeling that the plug pack just can't supply the current. Your thoughts?

My next test will be to revert back to the Arlec battery charger with the risk of blowing something up. I don't have another spare motor shield but there's another on order.

Ken

neksmerj
10th February 2015, 08:53 PM
Hi foob,

I've just run the Adafruit stepper test sketch. The stepper cycles through the various step modes which means the stepper is ok, and the power pack is adequate.

This is a bit of a mystery.

Ken

edit. another mystery. When I load your sketch, I get the error message avrdude: blah blah, and it seems the sketch does not really load. Powering up the board and the previous stepper test sketch runs.
Is there a way to delete sketches out of the Arduino memory?

edit2

The various stepper modes have come good.

RustyArc
10th February 2015, 09:20 PM
Just had a chance to look at Foob's code. A couple of things to note (assuming I read the code correctly - not guaranteed!) the distance movement thing will only work if you keep the direction button pressed. It'll also only do a new distance if you change directions - i.e. you can't do two 100mm moves in the same direction.

As for frying driver boards, given the way the Arduino environment is set up, it seems like it should be impossible to smoke an H bridge in a stepper driver - you'd think the board and library would both be designed to make this not happen. That said, I kind of can see how changing step mode without allowing the motor to step to a full-step position might cause problems if the library doesn't ensure that (the use of the stepper1.runSpeed thing in Brian's code makes me think you need to consider this).

It'd help if you posted a link to the Adafruit stepper test sketch.

neksmerj
10th February 2015, 10:20 PM
Hi Rusty,

So you think there maybe some problems? I've got another problem. How can I get the Arduino onto com port 3?

foob's sketch doesn't seem to want to compile on ports 1 and 4.


/* This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
It won't work with v1.x motor shields! Only for the v2's with built in PWM
control


For use with the Adafruit Motor Shield v2
----> http://www.adafruit.com/products/1438
*/




#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"


// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);


// Connect a stepper motor with 200 steps per revolution (1.8 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);




void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("Stepper test!");


AFMS.begin(); // create with the default frequency 1.6KHz
//AFMS.begin(1000); // OR with a different frequency, say 1KHz

myMotor->setSpeed(10); // 10 rpm
}


void loop() {
Serial.println("Single coil steps");
myMotor->step(100, FORWARD, SINGLE);
myMotor->step(100, BACKWARD, SINGLE);


Serial.println("Double coil steps");
myMotor->step(100, FORWARD, DOUBLE);
myMotor->step(100, BACKWARD, DOUBLE);

Serial.println("Interleave coil steps");
myMotor->step(100, FORWARD, INTERLEAVE);
myMotor->step(100, BACKWARD, INTERLEAVE);

Serial.println("Microstep steps");
myMotor->step(50, FORWARD, MICROSTEP);
myMotor->step(50, BACKWARD, MICROSTEP);



This is ridiculous, the sketch is now compiling, but the motor will only run if the fwd button is kept depressed. Finger off the button, motor stops. The other button does nothing

Think I need to have a good look in the morning in full sunlight.

Ken

foobillious
10th February 2015, 11:26 PM
The code shouldn't need the button held down. So something isn't right. What version of the code are you running Ken, the updated one I posted or an older version?

With the revised version of the code the speed pot shouldn't do anything at all. I gave you that new version to establish that the distance stuff was working right before I tried sticking the speed stuff back in.

The distance pot should purely set how many steps the motor is going to take. So basically if you have that pot set at 5V it should do 800 steps. If you have it set at 1V it should do 160steps (probably about 3/4 of a revolution). At the moment it won't do anything unless the motor is stopped and you then press a direciton button
(you can keep going in the same direction I think, but the motor needs to stop first). The speed will be fairly slow at this stage - we'll sort that out if we can figure out where your at now. At the moment I'm kind of lost as to what your doing.

Best give it a fresh start in the morning. stay away from the arlec charger for now, they often don't make good power supplies. I'll be online about 1200AEST tomorrow, everything going to plan (I'm at work, so won't be able to check anything until lunch)

*edit* btw if your getting compile errors, the arduino software doesn't upload the new code. So we need to sort that out first before we do any tests. Can you post what errors you are getting? in some of those posts you say it compiles, but in others you say it doesn't? Did you ever get a compile and upload of the new code without errors?

neksmerj
10th February 2015, 11:40 PM
RustyArc or foob,

Is there an easy way of copying code from the screen?

At present I'm starting at the bottom of a sketch, holding down the mouse button, and scrolling up to highlight the code I want. Press copy, then paste it into an Arduino window.

I'll wait until morn to check my board connections.

Ken

foobillious
11th February 2015, 11:52 AM
click once at the top, scroll down to the bottom, hold down shift and click again... that'll highlight the lot. Its not much faster, but some people find it easier.

RustyArc
11th February 2015, 12:56 PM
click once at the top, scroll down to the bottom, hold down shift and click again... that'll highlight the lot. Its not much faster, but some people find it easier.

Thanks for that - the select and drag thing is pretty tedious. I paste the code into an editor like Notepad++ as it colour-codes everything, making it a bit easier to read.

In the checkInputs() function, direction is always initialised to zero, so if you take your finger off the direction button, it'll get set to zero every time that function is called, stopping the motor.

I agree about being able to do more than one distance hop in the same direction - I didn't appreciate that a change in the direction value included changing from stopped to a direction.

As for only one direction button working, have you checked that both limit inputs are high?

foobillious
11th February 2015, 01:14 PM
ohhh good point. I'd intended to do something else there. Thanks for picking that up rusty.

Updated version (direction pot only testing, speed pot still to come)


// Ken's Arduino Controled Camera Slider
// based on code from Example6 of Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
//
// Designed for Arduino UNO

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <AccelStepper.h>

// Definitions - these make it easier to change what pins we are plugging things into on our arduino, and other control options such as speed
// First Define the 3 digital input pins for direciton control
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// And the 2 digital inputs to test for limits
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6
// and our two analog pot input pin
#define SPEED_PIN A0
#define DISTANCE_PIN A1
// and our MAX SPEED and accelleration
#define MAX_SPEED 500
#define MAX_ACCEL 250 // set this to the same as MAX_SPEED if you don't want acceleration
#define MIN_SPEED 0.1
// and the minimuum and maximum distance in steps
#define MAX_DISTANCE 800 // this max distance was selected based on 1 revolution being 200 steps causing a 78mm travel. comes out at 312mm travel
#define MIN_DISTANCE 0

// Function forward definitions
void forwardstep();
void backwardstep();
char checkInputs(char direction);
char checksetIdle(char *direction);
void checksetDistance(char direction,char olddir);
char checkDTG();
float calcSpeed(int speedpot,int direction);
float calcDistance(int destpot);

// Global Variables:
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1=AFMS.getStepper(200,2);
AccelStepper stepper1(forwardstep,backwardstep);

// initialise any global variables and tell the Arduino what to use the various pins for
void setup()
{
AFMS.begin();

// Tell AccelStepper what the maximum speed should be in steps per second.
stepper1.setMaxSpeed(MAX_SPEED);
stepper1.setAcceleration(MAX_ACCEL);

// set up the 3 input button inputs and the limit inputs with pullps
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

// This is where the main body of the work gets done. The loop function gets called repeatedly
void loop()
{
static float current_speed=0.0; // holds the current motor speed in steps/second
static int analog_read_counter=1000; // counts down to 0 to fire analog read
static char direction=0; // holds -1, 1 or 0 to control direction
char enabled; // used to keep track of if the motor has been enabled
static int speed_value; // holds the raw analog value of the speed
char olddir; // used to see if the direction has changed

// step 1 - check inputs
olddir=direction;
direction=checkInputs(direction); // get the direction we should be moving in, based on inputs from the dir switches and limits
checksetDistance(direction,olddir); // check and set a new distance from the current point, if necessary
enabled=checksetIdle(&direction); // check if the motor should be idling or not (note this may set the directuib to 0 if we have reached the specified distance)

// step 2 - run the motor
// if (enabled==1)
// {
// stepper1.run(); // let the motor step if it needs to before we change the speed
// }
// current_speed=calcSpeed(speed_value,direction); // calculate what our speed should be based on last pot setting and direciton
// stepper1.setSpeed(current_speed);
if (enabled==1) {
stepper1.run();
}
/*
// step 3 - update analog values, if necessary
if (analog_read_counter>0)
{
analog_read_counter--;
}
else
{
analog_read_counter=3000; // change this to a lower number to increase pot response
speed_value=analogRead(SPEED_PIN); // get the speed value
// distance value read could go here, but as it isn't updated all that often
// its easier just to do it when necessary
}
*/
}

// this function will be called by the AccelStepper every step the motor turns forward
void forwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(FORWARD, SINGLE);
}

// this function will be called by the AccelStepper every step the motor turns backward
void backwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(BACKWARD, SINGLE);
}

// this function checks our inputs and returns a number indicating if the motor will turn LEFT (1), RIGHT (-1)
// or if it should stop (0)
char checkInputs(char direction)
{
if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1)
{
direction=1;
}
else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1)
{
direction=-1;
}
else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0)
{
direction=0;
}
return direction;
}

// this function checks if our motor should idle or not, based on the direction. it also puts the motor into the idle state
// returns 0 if the motor is in the idle state
char checksetIdle(char *direction)
{
static char lastval=0;

if (*direction==0)
{
motor1->release();
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (checkDTG()==0)
{
motor1->release();
*direction=0;
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (lastval==0)
{
stepper1.enableOutputs();
lastval=1;
}
return 1;
}

// this function reclculates the speed for the motor, based on the last speed potentiometer value and the direction.
// returns a float indicating what the speed should be
float calcSpeed(int speedpot,int direction)
{
return (direction * ((speedpot/1023.0) * (MAX_SPEED-MIN_SPEED)) + MIN_SPEED);
}

// this function calculates how far we should move before stopping, based on the last destination potentiometer value
long calcDistance(int destpot, int direction)
{
return (direction * ((destpot/1023.0) * (MAX_DISTANCE-MIN_DISTANCE)) + MIN_DISTANCE);
}

// this function determines if a new distance to move is necessary, and provides a new distance relative to the current position to the AccelStepper library.
void checksetDistance(char direction,char olddir)
{
int dist_value; // holds the raw analog value of the distance
long distance; // holds how far we are going to move

if (direction==0 || olddir==direction) // we only update the distance if we are about to move (direction is set), and we are changing direction (olddir doesn't equal the new dir)
return;

dist_value=analogRead(DISTANCE_PIN); // read the distance pot to figure out how far we have to move
distance=calcDistance(dist_value,direction); // calculate the distance
stepper1.move(distance); // set the distance to move from the current position
}

// check the distance to go to determine if we should idle the motor or not.
char checkDTG()
{
if (stepper1.distanceToGo()>0)
{
return 1;
}
return 0;
}

neksmerj
11th February 2015, 08:26 PM
Hi gentlemen,

I swapped out the limit switches for a couple of push buttons, (reckon the limit switch wiring was a bit dickie), and all is well.

The last sketch compiles ok and runs despite the error message "avrdude: st500 blah blah.

I'm just a shade confused, is the distance pot set up but not implemented yet? Was Rusty's concerns justified?

Ken

RustyArc
11th February 2015, 09:28 PM
I'm just a shade confused, is the distance pot set up but not implemented yet? Was Rusty's concerns justified?

I haven't read through the latest code, but I believe the distance pot should work, and you now don't have to hold down the direction button - you should be able to press a direction button briefly and the stepper should run for a fixed distance and stop.

neksmerj
11th February 2015, 09:52 PM
Mmmmm, the distance pot does not seem to function. Twiddling the pot has no effect. The voltage on pin A1 definitely swings from GND to 5V by turning the pot.

I'm beginning to think that the new sketch is not being compiled, and that an old sketch is still in the Arduino memory.

The reason I think this is because the little orange light on the Arduino does not blink during an upload. It usually does but now doesn't.

Again I ask, is it possible to erase the memory of the Arduino?

Ken

foobillious
11th February 2015, 10:06 PM
yeah, i'm pretty sure your still running the old code. that avrdude error means that the upload didn't happen. The arduino wipes itself with the new upload, but you havn't got there yet unfortunately.

If you can sort that avrdude error (avrdude is what is actually doing the upload), you might be able to progress things. try checking what com port your arduino is actually on.

*edit* oh, and to clarify, the distance pot is set up and implemented and we are trying to test if it works. Rusty did identify a bug in one of my functions that would have meant that the button would need to be held down to get movemen. That should no longer be necessary, with the latest version of the code (I think). Your also spot on with that LED. if it doesn't blink the code doesn't update.

neksmerj
11th February 2015, 10:43 PM
Hi foob.

Just about there. Swapping ports solved the compiling issue.

The distance pot works beautifully, however only in the fwd direction. Pressing the rev push button does nothing.

It was fine running under an older sketch, and no wiring changes have occurred since.

A digital probe on the appropriate pin, D4, indicates high until pressed, so the press button is fine.

Ken

foobillious
12th February 2015, 12:27 PM
great ken - I'll take a look and see if I can figure out why it doesn't work going the other way.

foobillious
12th February 2015, 01:13 PM
Having a bit of trouble finding whats wrong with this.

Ken, what happens if you hit the fwd movement button a second time? does it move the same distance again?

RustyArc
12th February 2015, 01:28 PM
A digital probe on the appropriate pin, D4, indicates high until pressed, so the press button is fine.

Have you also checked that the right limit pin (D6) is also high?

When debugging code, it's *really* important to ensure the wiring is correct, and to make sure the power supply is good, otherwise you can end up chasing a problem in code when it's actually on the breadboard.

neksmerj
12th February 2015, 03:37 PM
Gentlemen,

I have thoroughly checked out all the switch functions with a digital probe, and all seems well.

Rusty, to answer your question re pushing the fwd button twice, push once, the motor does a few turns then stops, press again, the motor turns then stops.

I ran an earlier sketch and both direction buttons work including the limit switches

That sketch is here


/ Example6 code for Brian Schmalz's Easy Driver Example page// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html




#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>


// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 2);




// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, DOUBLE);
}
void backwardstep() {
motor1->onestep(BACKWARD, DOUBLE);
}


AccelStepper stepper1(forwardstep, backwardstep); // use functions to step


// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6




// Define our analog pot input pin
#define SPEED_PIN A0




// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1




void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(1000.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}




void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to control direction
static char enabled=0; // used to keep track of if the motor has been enabled (used to allow the motors to idle)
static int analog_value = 0; // Holds raw analog value.


if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1) { // allow movement LEFT if the LEFT limit switch isn't hit
sign=1;
} else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1) { // allow movement RIGHT if the RIGHT limit switch isn't hit
sign=-1;
} else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0) { // if neither of the above is true, and a limit or stop switch has been hit then stop the motors
sign=0;
stepper1.setSpeed(sign);
}

if (sign!=0) { // motor has a valid direction
if (enabled==0) { // motor was previously disabled, re-enable it (but don't re-enable it every single time we go through the loop)
enabled=1;
stepper1.enableOutputs();
}
} else { // a limit switch or the stop switch has been hit. disable the output to the motor.
enabled=0;
stepper1.disableOutputs();
}


// Give the stepper a chance to step if it needs to
if (enabled==1) {
stepper1.runSpeed();
}
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed, if the motor is currently enabled.
if (enabled==1) {
stepper1.runSpeed();
}


// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 1000; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
}
}

With respect to the distance control, I did not get my thoughts across properly. What I would like happen is this-

Press the fwd button and the motor does a few turns according to the pot setting, then stops for a second while a shot is being taken. After one second the motor does a few more turns then stops etc etc automatically.

I feel so inadequate that I can't help in writing the code, and greatly appreciate the amount of time you gentlemen have given me.

Ken

foobillious
12th February 2015, 04:03 PM
okay, thanks Ken. I've clearly made a logic error somewhere, so I'll work through and try and identify where.

I did understand what you want to get to with the distance pot, but before getting it working with a delay in the middle we need to get it working at all, otherwise debugging it just becomes harder. Its already fairly hard, as other than checking the code compiles I don't have any way to test this is working.

the code to go to the delay is about 4 lines long (I think). That'll be last, after we've got it travelling the set distances in both directions, and at different speeds. Speeds should be fairly straightforward too. We can't just use runSpeed() like we did before though, because it (runSpeed()) ignores the distance setting.

neksmerj
12th February 2015, 05:36 PM
Hi foob,

mate, you are a genius, how on earth you can write all this code and see it working in your head without the actual hardware.

I need a kick up the bum, power for the stepper stopped, so assumed the el cheapo 12V plug pack had failed. Went out and bought another one, plugged it in, and the same story, no juice.
Turned out to be the bloody power point had gone belly up.

Thanks for the refresher re the distance code.

Incidently, when I press the fwd push button, the stepper rotates slightly in the reverse direction before rotating in the correct direction. Is this a clue?

Ken

foobillious
12th February 2015, 06:10 PM
Its a lots of practice thing, not a genius thing... rusty can probably tell you, but that code is a bit of a mess... I changed my mind how it was going to work about 3 times while putting it together, and it kinda shows. poor programming practice really. In theory somebody who can program could read the source code to a program and tell you exactly what its going to do. You shouldn't actually have to be able to run it to see whats going to happen.

Unfortunately I'm having a bit of a mental block where I've got a picture of how the code works in my head and your reporting that it is doing things that it shouldn't (or not, as in this case). I then look at it and can't get past the "but it has to work!" to figure out why not. Frustrating. Fortunately she who must be obeyed has demanded some housework, so hopefully that'll shake the cobwebs loose enough. I'll take a look at it again in a couple of hours when I'm done.

Yep, the reverse thing is definately a clue, because it shouldn't do that either. actually that gives me an idea of where to look. gah! housework.

neksmerj
12th February 2015, 10:10 PM
Hi foob,

I'm hoping by now you will have washed and dried the dishes, swept the floor, vacuumed the carpets, done the ironing, put the bins out, cooked the tea, taken the dog for a walk and cleaned up his mess.

Have I missed anything, oh yeh, the washing machine needs to be reloaded after you've cut the grass. I'd much rather be writing code, if I could, what about you?

There's just one last request, and that is, when the stepper stops, and lets assume it stops for one second, half a second after stopping, a 5v pulse is output to one of the spare pins, maybe pin 13.

This signal will be used to fire the camera shutter. Haven't figured this out yet, but I'm sure there will be something on the web.

Ken

foobillious
14th February 2015, 11:39 AM
Hi Ken,

sorry to leave you hanging like this. I havn't tracked down why the reverse button isn't working yet. I'll download an arduino simulator to see if I can figure out whats going on, but I've got some of my own projects to work through today.

In the meantime can you please give this a try? What it should do (fwd only, because i havn't fixed the reverse bug yet but feel free to try it) is when you hit the fwd button the motor should start turning for the number of steps set by the distance pot. When it gets there it should stop, there should be a half second delay, then pin 13 will go high for a quarter second, then low for a quarter second and it should then move forward the same distance again, repeating until the stop button is pushed or the limit switches are hit.

Please make sure you test that the limit switches/stop switches actually work before it moves too far (do you have this hooked up to an actual carriage and track at the moment, or is the motor just spinning the air?).



// Ken's Arduino Controled Camera Slider
// based on code from Example6 of Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
//
// Designed for Arduino UNO

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <AccelStepper.h>

// Definitions - these make it easier to change what pins we are plugging things into on our arduino, and other control options such as speed
// First Define the 3 digital input pins for direciton control
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// And the 2 digital inputs to test for limits
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6
// and our two analog pot input pin
#define SPEED_PIN A0
#define DISTANCE_PIN A1
// and our MAX SPEED and accelleration
#define MAX_SPEED 500
#define MAX_ACCEL 250 // set this to the same as MAX_SPEED if you don't want acceleration
#define MIN_SPEED 0.1
// and the minimuum and maximum distance in steps
#define MAX_DISTANCE 800 // this max distance was selected based on 1 revolution being 200 steps causing a 78mm travel. comes out at 312mm travel
#define MIN_DISTANCE 0
// camera trigger pin
#define CAMERA_PIN 13
#define CAMERA_PULSE 250 // pulse time in uSeconds

// Function forward definitions
void forwardstep();
void backwardstep();
char checkInputs(char dir);
char checksetIdle(char *dir);
void checksetDistance(char dir,char olddir);
char checkDTG();
float calcSpeed(int speedpot,int dir);
float calcDistance(int destpot);
char doCamera(char dir,char olddir);

// Global Variables:
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1=AFMS.getStepper(200,2);
AccelStepper stepper1(forwardstep,backwardstep);

// initialise any global variables and tell the Arduino what to use the various pins for
void setup()
{
AFMS.begin();

// Tell AccelStepper what the maximum speed should be in steps per second.
stepper1.setMaxSpeed(MAX_SPEED);
stepper1.setAcceleration(MAX_ACCEL);

// set up the 3 input button inputs and the limit inputs with pullps
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

// This is where the main body of the work gets done. The loop function gets called repeatedly
void loop()
{
static float current_speed=0.0; // holds the current motor speed in steps/second
static int analog_read_counter=1000; // counts down to 0 to fire analog read
static char dir=0; // holds -1, 1 or 0 to control direction
char enabled; // used to keep track of if the motor has been enabled
static int speed_value; // holds the raw analog value of the speed
char olddir; // used to see if the direction has changed

// step 1 - check inputs
olddir=dir;
dir=checkInputs(dir); // get the direction we should be moving in, based on inputs from the dir switches and limits
checksetDistance(dir,olddir); // check and set a new distance from the current point, if necessary
enabled=checksetIdle(&dir); // check if the motor should be idling or not (note this may set the directuib to 0 if we have reached the specified distance)

// step 2 - run the motor
// if (enabled==1)
// {
// stepper1.run(); // let the motor step if it needs to before we change the speed
// }
// current_speed=calcSpeed(speed_value,direction); // calculate what our speed should be based on last pot setting and direciton
// stepper1.setSpeed(current_speed);
if (enabled==1) {
stepper1.run();
}

// step 3 - take photo with camera if necessary
dir=doCamera(dir,olddir);
/*
// step 4 - update analog values, if necessary
if (analog_read_counter>0)
{
analog_read_counter--;
}
else
{
analog_read_counter=3000; // change this to a lower number to increase pot response
speed_value=analogRead(SPEED_PIN); // get the speed value
// distance value read could go here, but as it isn't updated all that often
// its easier just to do it when necessary
}
*/
}

// this function will be called by the AccelStepper every step the motor turns forward
void forwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(FORWARD, SINGLE);
}

// this function will be called by the AccelStepper every step the motor turns backward
void backwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(BACKWARD, SINGLE);
}

// this function checks our inputs and returns a number indicating if the motor will turn LEFT (1), RIGHT (-1)
// or if it should stop (0)
char checkInputs(char dir)
{
if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1)
{
dir=1;
}
else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1)
{
dir=-1;
}
else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0)
{
dir=0;
}
return dir;
}

// this function checks if our motor should idle or not, based on the direction. it also puts the motor into the idle state
// returns 0 if the motor is in the idle state
char checksetIdle(char *dir)
{
static char lastval=0;

if (*dir==0)
{
motor1->release();
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (checkDTG()==0)
{
motor1->release();
*dir=0;
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (lastval==0)
{
stepper1.enableOutputs();
lastval=1;
}
return 1;
}

// this function reclculates the speed for the motor, based on the last speed potentiometer value and the direction.
// returns a float indicating what the speed should be
float calcSpeed(int speedpot,int dir)
{
return (dir * ((speedpot/1023.0) * (MAX_SPEED-MIN_SPEED)) + MIN_SPEED);
}

// this function calculates how far we should move before stopping, based on the last destination potentiometer value
long calcDistance(int destpot, int dir)
{
return (dir * ((destpot/1023.0) * (MAX_DISTANCE-MIN_DISTANCE)) + MIN_DISTANCE);
}

// this function determines if a new distance to move is necessary, and provides a new distance relative to the current position to the AccelStepper library.
void checksetDistance(char dir,char olddir)
{
int dist_value; // holds the raw analog value of the distance
long distance; // holds how far we are going to move

if (dir==0 || olddir==dir) // we only update the distance if we are about to move (direction is set), and we are changing direction (olddir doesn't equal the new dir)
return;

dist_value=analogRead(DISTANCE_PIN); // read the distance pot to figure out how far we have to move
distance=calcDistance(dist_value,dir); // calculate the distance
stepper1.move(distance); // set the distance to move from the current position
}

// check the distance to go to determine if we should idle the motor or not.
char checkDTG()
{
if (stepper1.distanceToGo()>0)
{
return 1;
}
return 0;
}

char doCamera(char dir,char olddir)
{
// concept here is that when we stop (direction==0), we want to delay for a while, then take a shot, delay some more, then continue moving in the same direction we were before
if (dir==0 && olddir!=0) // we don't want to do this if we are stopped by the stop button or the limit switches
{
return 0;
}

delay(500); // delay half a second after stopping
digitalWrite(CAMERA_PIN,HIGH); // drive the camera pin high
delay(CAMERA_PULSE); // leave it high for the pulse time
digitalWrite(CAMERA_PIN,LOW); // drive the camera pin low
delay(500-CAMERA_PULSE); // snooze for the rest of the second
return checkInputs(olddir); // and return the old direction value, so the motor starts moving again, but not if the limit or stop button is hit
}

neksmerj
14th February 2015, 03:07 PM
Hi foob,

You haven't left me hanging, I have supreme patience. This project started months ago, and has progressed at my pace.

I only have this project bread boarded attached to a stepper in mid air. I'm putting off buying all the "OpenBuilds" hardware until I have a working sketch.

This is the sort of thing I have in mind http://www.openbuilds.com/builds/v-slot-belt-driven-linear-actuator-build.80/

Your latest sketch does not want to play ball. It compiles ok but something screwy is going on. Pressing the FWD button causes the stepper to rotated one pulse at a time at approx one sec intervals like the second hand on a clock. No other input, pot or switch, has any effect.

If this is a clue, output pin 13 pulses high every second, my probe does not indicate that it goes low. Should there be a pulldown resistor on this output?

Ken

RustyArc
14th February 2015, 04:42 PM
Just had a quick read through that latest code. I can't quite see the point of the lastval variable in the checksetIdle function.

As for the one step per second, it'd be doing that if the distance was set to zero - check to see if you're getting varying voltage on A1 when you turn the distance pot.

Props to foobillious for writing and debugging this code without any hardware to test it on (hopefully the emulator will help? I've never seen it).

neksmerj
14th February 2015, 05:16 PM
Hi Rusty,

I too can't imagine how someone can write code without having the hardware in front of them, as mentioned earlier, foob is a genius.

With respect to pin A1, according to my digital probe, the voltage varies between GND and 5V by turning the pot.

I'm not sure what you meant by your first comment, in fact, I don't understand how most of the code works anyway. I got lost when the distance pot was added. Up till then it was pretty straight forward for this dummy.

Ken

RustyArc
14th February 2015, 06:48 PM
Sorry, I should refer to whom I'm speaking. My comment about the lastval variable was more or less directed at foobillious - and the variable may well have a role, I just didn't get it at first glance.

Looking again, the bug is in the doCamera() function - if direction is not zero, on each call it pauses for half a second, fires the shutter, pauses for another half second and returns to the main loop, which steps the motor, then goes into the doCamera() function again and so on.

neksmerj
14th February 2015, 08:38 PM
Thanks Rusty, I'm sure foob will look into that after "bringing in the bins" and "cleaning the gutter" after "repainting the front door". I think he's a busy man!

I have a little side issue that's got me stumped, I can't upload any sketches. The lights on the Arduino have stopped blinking when a sketch is uploaded.

I've tried unplugging the USB connection and motor power. In desperation, I went to Device manager and deleted the Arduino driver file, then reinstalled it.

Still not uploading, any clues?

Ken

neksmerj
14th February 2015, 10:04 PM
Hi Rusty and foob,

solved the problem of not being able to upload a sketch just by fiddling with the advanced port settings.

foob, going back to your last sketch, more is going on than I realized. Pressing the FWD button starts the stepper ticking over one step at a time, pressing the REV button does exactly the same and in the same direction.

This is really weird.

Ken

foobillious
15th February 2015, 09:57 PM
good news on the port settings things.

The concept with the lastval variable was to ensure the ports for the motor only get re-enabled once, the rest of the time they just snooze. Its not really necessary, but I was doing it a) because i think it takes longer to make the ports active again than to do that test and b) because I don't know what killed the motorshield.... so I was being more paranoid than usual.

latest version of the code. I think the one step at a time thing is because I plain f***** up. Its interesting the reverse button does the same thing. I don't know what the hell is up with that. hasn't been tested beyond compile yet.


// Ken's Arduino Controled Camera Slider
// based on code from Example6 of Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
//
// Designed for Arduino UNO

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <AccelStepper.h>

// Definitions - these make it easier to change what pins we are plugging things into on our arduino, and other control options such as speed
// First Define the 3 digital input pins for direciton control
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// And the 2 digital inputs to test for limits
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6
// and our two analog pot input pin
#define SPEED_PIN A0
#define DISTANCE_PIN A1
// and our MAX SPEED and accelleration
#define MAX_SPEED 500
#define MAX_ACCEL 250 // set this to the same as MAX_SPEED if you don't want acceleration
#define MIN_SPEED 0.1
// and the minimuum and maximum distance in steps
#define MAX_DISTANCE 800 // this max distance was selected based on 1 revolution being 200 steps causing a 78mm travel. comes out at 312mm travel
#define MIN_DISTANCE 0
// camera trigger pin
#define CAMERA_PIN 13
#define CAMERA_PULSE 250 // pulse time in uSeconds

// Function forward definitions
void forwardstep();
void backwardstep();
char checkInputs(char dir);
char checksetIdle(char *dir);
void checksetDistance(char dir,char olddir);
char checkDTG();
float calcSpeed(int speedpot,int dir);
float calcDistance(int destpot);
char doCamera(char dir,char olddir);

// Global Variables:
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1=AFMS.getStepper(200,2);
AccelStepper stepper1(forwardstep,backwardstep);

// initialise any global variables and tell the Arduino what to use the various pins for
void setup()
{
AFMS.begin();

// Tell AccelStepper what the maximum speed should be in steps per second.
stepper1.setMaxSpeed(MAX_SPEED);
stepper1.setAcceleration(MAX_ACCEL);

// set up the 3 input button inputs and the limit inputs with pullps
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
}

// This is where the main body of the work gets done. The loop function gets called repeatedly
void loop()
{
static float current_speed=0.0; // holds the current motor speed in steps/second
static int analog_read_counter=1000; // counts down to 0 to fire analog read
static char dir=0; // holds -1, 1 or 0 to control direction
char enabled; // used to keep track of if the motor has been enabled
static int speed_value; // holds the raw analog value of the speed
char olddir; // used to see if the direction has changed

// step 1 - check inputs
olddir=dir;
dir=checkInputs(dir); // get the direction we should be moving in, based on inputs from the dir switches and limits
checksetDistance(dir,olddir); // check and set a new distance from the current point, if necessary
enabled=checksetIdle(&dir); // check if the motor should be idling or not (note this may set the directuib to 0 if we have reached the specified distance)

// step 2 - run the motor
// if (enabled==1)
// {
// stepper1.run(); // let the motor step if it needs to before we change the speed
// }
// current_speed=calcSpeed(speed_value,direction); // calculate what our speed should be based on last pot setting and direciton
// stepper1.setSpeed(current_speed);
if (enabled==1) {
stepper1.run();
}

// step 3 - take photo with camera if necessary
dir=doCamera(dir,olddir);
/*
// step 4 - update analog values, if necessary
if (analog_read_counter>0)
{
analog_read_counter--;
}
else
{
analog_read_counter=3000; // change this to a lower number to increase pot response
speed_value=analogRead(SPEED_PIN); // get the speed value
// distance value read could go here, but as it isn't updated all that often
// its easier just to do it when necessary
}
*/
}

// this function will be called by the AccelStepper every step the motor turns forward
void forwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(FORWARD, SINGLE);
}

// this function will be called by the AccelStepper every step the motor turns backward
void backwardstep()
{
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
motor1->onestep(BACKWARD, SINGLE);
}

// this function checks our inputs and returns a number indicating if the motor will turn LEFT (1), RIGHT (-1)
// or if it should stop (0)
char checkInputs(char dir)
{
if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1)
{
dir=1;
}
else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1)
{
dir=-1;
}
else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0)
{
dir=0;
}
return dir;
}

// this function checks if our motor should idle or not, based on the direction. it also puts the motor into the idle state
// returns 0 if the motor is in the idle state
char checksetIdle(char *dir)
{
static char lastval=0;

if (*dir==0)
{
motor1->release();
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (checkDTG()==0)
{
motor1->release();
*dir=0;
lastval=0;
stepper1.disableOutputs();
return 0;
}
if (lastval==0)
{
stepper1.enableOutputs();
lastval=1;
}
return 1;
}

// this function reclculates the speed for the motor, based on the last speed potentiometer value and the direction.
// returns a float indicating what the speed should be
float calcSpeed(int speedpot,int dir)
{
return (dir * ((speedpot/1023.0) * (MAX_SPEED-MIN_SPEED)) + MIN_SPEED);
}

// this function calculates how far we should move before stopping, based on the last destination potentiometer value
long calcDistance(int destpot, int dir)
{
return (dir * ((destpot/1023.0) * (MAX_DISTANCE-MIN_DISTANCE)) + MIN_DISTANCE);
}

// this function determines if a new distance to move is necessary, and provides a new distance relative to the current position to the AccelStepper library.
void checksetDistance(char dir,char olddir)
{
int dist_value; // holds the raw analog value of the distance
long distance; // holds how far we are going to move

if (dir==0 || olddir==dir) // we only update the distance if we are about to move (direction is set), and we are changing direction (olddir doesn't equal the new dir)
return;

dist_value=analogRead(DISTANCE_PIN); // read the distance pot to figure out how far we have to move
distance=calcDistance(dist_value,dir); // calculate the distance
stepper1.move(distance); // set the distance to move from the current position
}

// check the distance to go to determine if we should idle the motor or not.
char checkDTG()
{
if (stepper1.distanceToGo()>0)
{
return 1;
}
return 0;
}

char doCamera(char dir,char olddir)
{
// concept here is that when we stop (direction==0), we want to delay for a while, then take a shot, delay some more, then continue moving in the same direction we were before
if (dir==0 && olddir!=0) // we don't want to do this if we are stopped by the stop button or the limit switches
{
delay(500); // delay half a second after stopping
digitalWrite(CAMERA_PIN,HIGH); // drive the camera pin high
delay(CAMERA_PULSE); // leave it high for the pulse time
digitalWrite(CAMERA_PIN,LOW); // drive the camera pin low
delay(500-CAMERA_PULSE); // snooze for the rest of the second
return checkInputs(olddir); // and return the old direction value, so the motor starts moving again, but not if the limit or stop button is hit
}
return dir;
}

neksmerj
15th February 2015, 10:51 PM
Hi foobillious,

nice to have you back.

Your latest sketch compiled ok, with a few problems relating to ports. For some stupid reason, the com port changes. When the sketch is up, there is usually the option under tools, serial port, to select a port. Sometimes there's no option and sometimes serial port is greyed out.

Back to the sketch. When the FWD button is pressed, the motor will turn according to the pot, then stop, and remain stopped. Pressing the FWD button again does nothing. If the stop button is pressed after the motor has stopped, and the FWD button is pressed, it will rotate again a few turns then stop. Pressing the REV button has no effect.

This must be driving you crazy, especially without the hardware.

I'm happy to lend you a spare Arduino UNO and Adafruit stepper shield plus breadboard etc. I don't have a spare nema17 stepper motor.

Ken

foobillious
15th February 2015, 11:24 PM
I've got a UNO, but no stepper motor shield.

yeah, its pretty frustrating. I just tried it with the emulator, which is interesting, but probably too buggy with the library interactions. What was interesting is that the rev motor (the right button yeah?) seems to work.

I should have ordered a motor shield the other day when I was ordering something else from those guys. I normally don't like to order from them, as the shipping to AUS is just brutal. They occassionally have nice gear though.

I might start from scratch get something working properly without any libraries. That way I can check all the switch interactions are working as expected with either the emulator or my own UNO. Have to think about it. I'll let you know if I want to borrow the shield.

neksmerj
15th February 2015, 11:44 PM
Hi foob,

I've been buying all my electronic boards and parts from Core Electronics in NSW. Their service is second to none, unless a part has to be shipped in, with really keen prices.

I have a spare Adafruit stepper motor shield that just needs to be assembled, would you like it to keep? I was going to put the stacking type headers on it so a terminal shield is not required.

Just plonk it on top of the Arduino, and plug in your jumper leeds.

If yes, please PM me your address details.

http://core-electronics.com.au/

Ken

neksmerj
19th February 2015, 02:01 PM
Hi foobillious and RustyArc.

Whilst mucking around with this project, ie, uploading different sketches, unplugging and reconnecting the USB cable, I occasionally run into compiling problems.

As mentioned before, I get this error message avrdude:st500_getsync():not in sync:resp=0x00

I'm pretty sure this is related to the com port. If I muck around with the port settings, I finally get a sketch that will compile without errors.

Are my port problems caused by different sketches looking for different ports, or is my problem simply from disconnecting and reconnecting the Arduino UNO?

Ken

RustyArc
19th February 2015, 07:06 PM
I haven't played with an Uno, but if you're unplugging and reconnecting the USB cable, it may be that there's a delay or conflict while the driver enumerates the device and allocates a serial port to it. Does it end up with the same com port no. each time?

neksmerj
19th February 2015, 07:16 PM
Hi Rusty,
You may be right. When I get it sorted, it's always com port 1
What I can't understand is device manager indicates com 1, and when compiling, the sketch indicates com 1, so the sketch should compile error free. I'm embarised to be so dumb
Can't even spell!
Ken

RustyArc
19th February 2015, 09:20 PM
It's a bit odd that it's mapping as Com1 - those USB-serial things usually start at a higher number. Is this on a laptop?

neksmerj
19th February 2015, 10:02 PM
Hi Rusty
I'm using a PC and running windows 7
Looks like I've scared off foobillious, guess he's really busy.
Ken

neksmerj
21st February 2015, 06:53 PM
Hi foobillious,

I have sent you a PM.

Ken

foobillious
23rd February 2015, 07:35 AM
Hi guys,

I'm around, but I've been out of town and away form my workshop, decent computer and electronics gear.

I've had a few thoughts about how to do this and get it to work properly, so I'll post in a day or two when I've actually tried it out.

neksmerj
28th February 2015, 05:06 PM
Hi foob,

I have sent you another PM

Ken

neksmerj
3rd March 2015, 05:33 PM
Hi foob and Rusty,

This is pretty crude, but seems to work, almost.

To reiterate, I'm driving a carriage along a linear track using an Arduino, Adafruit motor shield and a stepper motor. At each end of the track is a limit switch.

There are three push buttons, fwd, stop and rev. I have to thank foob for writing the limit switch code, it had me baffled.

The other requirements are that the motor turn for say half a turn, stop, and turn pin 13 on briefly to fire a camera shutter.

I have the motor stopping and starting by simply adding delay(1000); to the end of the sketch, and I can get pin 13 to go high, then low, when the motor is stopped.

The only problem I have is pin13 turns on and off all the time. Sorry if I have confused everyone.

Attached is the sketch so far

Ken




// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html




#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>


// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 2);




// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, MICROSTEP);
}
void backwardstep() {
motor1->onestep(BACKWARD, MICROSTEP);
}


AccelStepper stepper1(forwardstep, backwardstep); // use functions to step


// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6




// Define our analog pot input pin
#define SPEED_PIN A0




// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1




void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
pinMode(13,OUTPUT);


}




void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to control direction
static char enabled=0; // used to keep track of if the motor has been enabled (used to allow the motors to idle)
static int analog_value = 0; // Holds raw analog value.

if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1) { // allow movement LEFT if the LEFT limit switch isn't hit
sign=1;
} else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1) { // allow movement RIGHT if the RIGHT limit switch isn't hit
sign=-1;
} else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0) { // if neither of the above is true, and a limit or stop switch has been hit then stop the motors
sign=0;
stepper1.setSpeed(sign);
}

if (sign!=0) { // motor has a valid direction
if (enabled==0) { // motor was previously disabled, re-enable it (but don't re-enable it every single time we go through the loop)
enabled=1;
stepper1.enableOutputs();
}
} else { // a limit switch or the stop switch has been hit. disable the output to the motor.
enabled=0;
motor1->release();
stepper1.disableOutputs();
}


// Give the stepper a chance to step if it needs to
if (enabled==1) {
stepper1.runSpeed();
}
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed, if the motor is currently enabled.
if (enabled==1) {
stepper1.runSpeed();
}


// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 500; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
delay(1000);

digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(500); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW

}
}

foobillious
6th March 2015, 08:49 AM
Hi Guys, sorry I haven't been responding. I've been busy with my own project, out of town or stuck at work for the last couple of weeks. I'm also out of town this weekend and all next week... *sigh*

Ken you might want to check out the recent ben heck show episodes on youtube:
https://www.youtube.com/watch?v=NxlqawCnX3s

he is doing an auto-tracking camera thing which uses a lot of the same ideas.

neksmerj
6th March 2015, 08:42 PM
Hi foob,

I may have over complicated this project with my wishlist requirements.

Instead of determining how many turns of the motor between stops, by setting a pot, would it be much simpler if the motor is programmed to step say 100 turns between stops?

Something like motor1->step(100)? Then command it to stop for say 1 second, then continue etc etc?

Ken

neksmerj
11th March 2015, 09:52 PM
Gentlemen, I really hope I have not bored everyone to tears with my project.

I now have something that really works, and hope that RustyArc and foobillious read this thread, because I need some advice.

Briefly the motor rotates approx 1/2 a turn, and stops briefly to pulse pin13, the camera pin. The motor stops when it reaches the delay command down near the bottom of the sketch.

This is not ideal, can someone show me how to program the stepper to rotate so many steps, say 200 in either direction depending on which push button is pressed.

I've been fiddling in this area, and can't get anything to work.

Ken




// Example6 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html




#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>


// Define the stepper and the pins it will use
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 2);




// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep() {
motor1->onestep(FORWARD, MICROSTEP);
}
void backwardstep() {
motor1->onestep(BACKWARD, MICROSTEP);
}


AccelStepper stepper1(forwardstep, backwardstep); // use functions to step


// Define our three input button pins
#define LEFT_PIN 2
#define STOP_PIN 3
#define RIGHT_PIN 4
// and define our two Limit inputs
#define LEFT_LIM_PIN 5
#define RIGHT_LIM_PIN 6
#define CAMERA_PIN 13




// Define our analog pot input pin
#define SPEED_PIN A0




// Define our maximum and minimum speed in steps per second (scale pot to these)
#define MAX_SPEED 500
#define MIN_SPEED 0.1




void setup() {
AFMS.begin();

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
stepper1.setMaxSpeed(500.0);

// Set up the three button inputs & limit inputs with pullups
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
pinMode(13,OUTPUT); //camera shutter pin


}




void loop() {
static float current_speed = 0.0; // Holds current motor speed in steps/second
static int analog_read_counter = 1000; // Counts down to 0 to fire analog read
static char sign = 0; // Holds -1, 1 or 0 to control direction
static char enabled=0; // used to keep track of if the motor has been enabled (used to allow the motors to idle)
static int analog_value = 0; // Holds raw analog value.

if (digitalRead(LEFT_PIN)==0 && digitalRead(LEFT_LIM_PIN)==1) { // allow movement LEFT if the LEFT limit switch isn't hit
sign=1;
} else if (digitalRead(RIGHT_PIN)==0 && digitalRead(RIGHT_LIM_PIN)==1) { // allow movement RIGHT if the RIGHT limit switch isn't hit
sign=-1;
} else if (digitalRead(LEFT_LIM_PIN)==0 || digitalRead(RIGHT_LIM_PIN)==0 || digitalRead(STOP_PIN)==0) { // if neither of the above is true, and a limit or stop switch has been hit then stop the motors
sign=0;
stepper1.setSpeed(sign);
}

if (sign!=0) { // motor has a valid direction
if (enabled==0) { // motor was previously disabled, re-enable it (but don't re-enable it every single time we go through the loop)
enabled=1;
stepper1.enableOutputs();
}
} else { // a limit switch or the stop switch has been hit. disable the output to the motor.
enabled=0;
motor1->release();
stepper1.disableOutputs();
}


// Give the stepper a chance to step if it needs to
if (enabled==1) {
stepper1.runSpeed();
}
// And scale the pot's value from min to max speeds
current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
// Update the stepper to run at this new speed
stepper1.setSpeed(current_speed);
// This will run the stepper at a constant speed, if the motor is currently enabled.
if (enabled==1) {
stepper1.runSpeed();
}


// We only want to read the pot every so often (because it takes a long time we don't
// want to do it every time through the main loop).
if (analog_read_counter > 0) {
analog_read_counter--;
}
else {
analog_read_counter = 500; // <-- change this to a lower number (i.e 500 or 1000) to increase pot response
// Now read the pot (from 0 to 1023)
analog_value = analogRead(SPEED_PIN);
delay (1000); //Stop the motor

if (sign==0) { // If motor is stopped by stop button or limit switch
digitalWrite (13,LOW); // disable camera pin.
}else digitalWrite (13,HIGH); // Activate camera pin
delay (250); // Short delay
digitalWrite (13,LOW); // Deactivate camera pin

}
}

RustyArc
12th March 2015, 09:28 PM
This is not ideal, can someone show me how to program the stepper to rotate so many steps, say 200 in either direction depending on which push button is pressed.

I've had a very quick look at this - you've used an earlier, and what is probably simpler, version of the code. The catch here is that you can't count steps with this approach, you'd need to use the code Foob wrote.

What you could probably do with this code is control distance moved based on time, which while not as accurate, is probably easier to code and understand. In short, pressing a direction button would set a time value that would be decremented on each iteration of the loop until it reaches zero, at which point the motor would stop and trigger the shutter pin. It'd also need to stop if it hit a limit or the stop switch was hit.

foobillious
17th March 2015, 06:08 PM
Hi guys, i'm back in town and I've got a bunch of electronics stuff i'm planning on playing with this weekend, including another crack at this. I've got some gear that I think will work well enough for testing purposes, so I'll give it a go anyway. I've got to do my stuff first, but hopefully sunday afternoon I'll be able to have a go.