Code not working

Hi

I have been building a camera slider. There are two modes to the operation of the slider. One is manual using two push switches and the other is automatic using limit switches to change the direction of the stepper motor.

I used the the blink without delay method for timing so that other operations can happen.

The problem is that I have introduced a rotary switch so that I can change the speed of the stepper motor.
The rotary switch, consists of 1k resistors in series, with the different pole positions having different resistor reading, is an analog sensor and I have mapped the incoming variable.

I first adapt the blink with out delay sketch to changing the speed of the flashing led with the rotary switch and it works as I want it to, however when I added it into the sketch for the slider control, the stepper motor freezes.

this is the sketch for the working blink without delay
/* Blink without Delay

Turns on and off a light emitting diode(LED) connected to a digital
pin, without using the delay() function. This means that other code
can run at the same time without being interrupted by the LED code.

The circuit:

  • LED attached from pin 13 to ground.
  • Note: on most Arduinos, there is already an LED on the board
    that's attached to pin 13, so no hardware is needed for this example.

created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen

This example code is in the public domain.

*/

// constants won't change. Used here to
// set pin numbers:
const int ledPin = 13; // the number of the LED pin

// Variables will change:
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long x;

const int sensorMin = 0; // sensor minimum, discovered through experiment
const int sensorMax = 930;// interval at which to blink (milliseconds)

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
Serial.begin (9600);
}

void loop()
{
// read the sensor:
int sensorReading = analogRead(A0);
// map the sensor range to a range of four options:
int range = map(sensorReading, sensorMin, sensorMax, 1, 10);

// do something different depending on the
// range value:
switch (range) {
case 1: // your hand is on the sensor
Serial.println("200");
x = 200;

break;
case 2: // your hand is close to the sensor
Serial.println("600");
x = 600;
break;
case 3: // your hand is a few inches from the sensor
Serial.println("1000");
x = 1000;
break;
case 4: // your hand is nowhere near the sensor
Serial.println("1600");
x = 1600;
break;
case 5: // your hand is on the sensor
Serial.println("2000");
x = 2000;
break;
case 6: // your hand is close to the sensor
Serial.println("1700");
x = 1700;
break;
case 7: // your hand is a few inches from the sensor
Serial.println("1300");
x = 1300;
break;
case 8: // your hand is nowhere near the sensor
Serial.println("900");
x = 900;
break;
case 9: // your hand is on the sensor
Serial.println("500");
x = 500;
break;

case 10: // your hand is a few inches from the sensor
Serial.println("100");
x = 100;
break;
}
// here is where you'd put code that needs to be running all the time.

// check to see if it's time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > x) {
// save the last time you blinked the LED
previousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}

This is the sketch for the slider control

//stepper
#define stepPin 6
#define dirPin 7

// maunal control
#define button1 2
#define button2 3

// automatic control
#define dirChangeL 8
#define dirChangeR 9

//function change
#define functionSwitch 10

// Speed control

const int sensorMin = 0; // refering to the selector switch
const int sensorMax = 930;

int stepState = LOW;
long x;
long previousMillis = 0;

void setup() {

Serial.begin(9600);

//stepper

pinMode(stepPin , OUTPUT);
pinMode(dirPin , OUTPUT);

digitalWrite(stepPin , LOW);
digitalWrite(dirPin , LOW);

//manual contol
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);

//automatic control
pinMode(dirChangeL, INPUT_PULLUP);
pinMode(dirChangeR, INPUT_PULLUP);

//function switch
pinMode(functionSwitch, INPUT_PULLUP);

}
void loop() {

if (digitalRead(functionSwitch)==HIGH) {
automatic();
}
else if (digitalRead(functionSwitch)==LOW){
manual();
}
}

// operation code
//automatic

void automatic(){

digitalWrite(dirPin, HIGH);
while (digitalRead(dirChangeL) == HIGH)
{
motion();
if (digitalRead(functionSwitch) ==LOW){
break;
manual();
}

}
digitalWrite(dirPin, LOW);
while (digitalRead(dirChangeR) == HIGH)
{
motion();
if (digitalRead(functionSwitch) ==LOW){
break;
manual();
}

}
}

//manual

void manual(){
if (digitalRead(button1) == LOW && digitalRead(button2) == HIGH) {
digitalWrite(dirPin, LOW);

}

else if (digitalRead(button1) == HIGH && digitalRead(button2) == LOW) {
digitalWrite(dirPin, HIGH);

}

if (digitalRead(button1) == LOW || digitalRead(button2) == LOW) {
digitalWrite(stepPin , HIGH);
motion();
}
}

void motion() {
//read and map the rotary select switch
int sensorReading = analogRead(A0);
int range = map(sensorReading, sensorMin, sensorMax, 1, 10); // this is based on the readings form the selector switch

//setting up the switch options
//due to the way that the rotary switch was wired with the resistors in series
//to get the different values. The differnt case options will follow the pin positions and the various readings
//from these postions

//differnt speed settings

switch (range) {
case 1:
Serial.println("600 milliseconds");
x = 600;

break;
case 2:
Serial.println("2 seconds");
x = 2000;
break;
case 3:
Serial.println("10 seconds");
x = 10000;
break;
case 4:
Serial.println("1 Minute");
x = 60000;
break;
case 5:
Serial.println("10 Minutes");
x = 600000;
break;
case 6:
Serial.println("5 Minutes");
x = 300000;
break;
case 7:
Serial.println("30 seconds");
x = 30000;
break;
case 8:
Serial.println("5 Seconds");
x = 5000;
break;
case 9:
Serial.println("1 second");
x = 1000;
break;

case 10:
Serial.println("200 milliseconds");
x = 200;
break;
}

unsigned long currentMillis = millis();
if(currentMillis - previousMillis > x) {
previousMillis = currentMillis;
if (stepState == LOW)
stepState = HIGH;
else
stepState = LOW;
digitalWrite(stepPin, stepState);
}
}

What does the debug output look like?
Why so many debug prints? Why not just print the value of x at the end of the switch block?

Please use code tags when posting code.

You need to post your code properly. It took me a while to realize there are two completely separate programs in all that stuff.

I suspect these are not the cause of the problem but ...

previousMillis and x should be unsigned long

the code for a single step should be (to give a nice clean short pulse)

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

and then x should represent the period between steps.

I would be inclined to put the code for reading the rotary switch and updating x in a separate function called from loop(). Then you could easily not use it and try a fixed value for x.

Are you getting the expected values from Serial.println() ?

Trying a fixed value for x would be my first debug step.

I will try to find time to test your code later today.

...R

I tried your code and I don't see any reason why it is not working. I made a few small mods for testing.

I commented out all the Serial.println("600 milliseconds"); statements so they would not clutter up the Serial monitor.

I added the line sensorReading = NNN

int sensorReading = analogRead(A0);
  sensorReading = 1000;

as I was too lazy to rig up a potentiometer; I know that the Arduino analogRead() works properly and it allows me to try different fixed values.

And i added two lines to see if x is causing the steps to happen - and it seems that it is

if(currentMillis - previousMillis > x) {
	  Serial.print("STEP after ");
	  Serial.println(x);

I did not check with a stepper motor (more laziness).

I suggest you check that the input to analogRead() is working correctly.

By the way, the sequence of your X values seems very strange - and a step every 10 minutes would be very slow.

...R

Hi Robin

Thanks for the info.

What I am trying to achieve is a camera slider that can be controlled either manually or automatically. The long time would be for time lapse purposes.

what is happening is that when in manual mode the select switch does not work. In automatic operation the select switch will show up in the console but not change the speed.

here is the code with amendments and hopefully better comments.

//stepper
#define stepPin 6 
#define dirPin 7

   // maunal control
#define button1 2 // control left direction of camera slider
#define button2 3 // control right direction of camera slider

  // automatic control
#define dirChangeL 8 // limit switch change the direction of the slider(automaic)
#define dirChangeR 9// limit switch change the direction of the slider(automaic)

 //function change
#define functionSwitch 10 // change between manul operation and automaic operation

// Speed control

 const int sensorMin = 0;  // refering to the selector switch    
 const int sensorMax = 930;

 int stepState = LOW; 
 long x;
 long previousMillis = 0;       
 
  



void setup() {
 
 Serial.begin(9600);
 
//stepper
 
 pinMode(stepPin , OUTPUT);
 pinMode(dirPin , OUTPUT);
 
 digitalWrite(stepPin , LOW);
 digitalWrite(dirPin , LOW);

   //manual contol
 pinMode(button1, INPUT_PULLUP);
 pinMode(button2, INPUT_PULLUP);
 
   //automatic control
 pinMode(dirChangeL, INPUT_PULLUP);
 pinMode(dirChangeR, INPUT_PULLUP);
 
   //function switch
 pinMode(functionSwitch, INPUT_PULLUP);


}
void loop() {
 
 if (digitalRead(functionSwitch)==HIGH) {
    automatic();
 }
 else if (digitalRead(functionSwitch)==LOW){
   manual();
 }
}
 
 

// operation code
   //automatic

void automatic(){
  
digitalWrite(dirPin, HIGH);  
while (digitalRead(dirChangeL) == HIGH) 
{
 motion(); 
 if (digitalRead(functionSwitch) ==LOW){
   break;
   manual();
}

}
   digitalWrite(dirPin, LOW); 
  while (digitalRead(dirChangeR) == HIGH) 
{
 motion();
if (digitalRead(functionSwitch) ==LOW){
   break;
  manual(); 
}

}
}

   //manual
   
 void manual(){
   if (digitalRead(button1) == LOW && digitalRead(button2) == HIGH) {  
     digitalWrite(dirPin, LOW);
 
 }
 
 else if (digitalRead(button1) == HIGH && digitalRead(button2) == LOW) {
 digitalWrite(dirPin, HIGH);
 
}

if (digitalRead(button1) == LOW || digitalRead(button2) == LOW) {
   digitalWrite(stepPin , HIGH);
   motion();
}
}



void motion() {
 //read and map the rotary select switch
 int sensorReading = analogRead(A0);
 int range = map(sensorReading, sensorMin, sensorMax, 1, 10); // this is based on the readings form the selector switch
 
 //setting up the switch options
 //due to the way that the rotary switch was wired with the resistors in series
 //to get the different values. The differnt case options will follow the pin positions and the various readings
 //from these postions

//different speed settings

switch (range) {
 case 1:    
   x = 600;
   break;
 case 2:    
   x = 2000;
   break;
 case 3:    
  x = 10000;
   break;
 case 4:   
   x = 60000;
   break;
    case 5:    
   x = 600000;
   break;
 case 6:    
   x = 300000;
   break;
 case 7:    
  x = 30000;
   break;
 case 8:   
   x = 5000;
   break;
 case 9:    
   x = 1000;
   break;  
 case 10:    
   x = 200;
   break;
 }


 unsigned long currentMillis = millis();
 if(currentMillis - previousMillis > x) { 
   previousMillis = currentMillis; 
   Serial.print("STEP after ");
   Serial.print(x); 
   if (stepState == LOW)
     stepState = HIGH;
   else
     stepState = LOW;
      digitalWrite(stepPin, stepState);
}
}

TerenceCollings:
here is the code with amendments and hopefully better comments.

I asked you earlier to post your code properly. Please go back to modify your post and put the code in code tags (see image below) so it looks like this. Then I can select it all with one click and copy into my text editor to study it.

...R

2014-11-04_0-01-25.jpg

Hi Robin

Sorry about that I thought I had managed to do it, new to the forum. I revised my earlier post.

Thanks

Thanks - that makes life much easier.

I will try to look at it later tonight, but more likely tomorrow.

...R

I have had another look at your code - as respite from some other code I am trying to figure out.

I'm afraid I can't remember the basis of my earlier comments and I have overwritten the code I had copied and amended then.

Looking at your latest code what strikes me is that you ave digitalRead()s all over the place. For example digitalRead(functionSwitch) appears 4 times when once should be plenty. With this sort of scatter-gun approach it is difficult to isolate problems.

And I'm not sure that the distinction you are making between manual and automatic is appropriate. It seems to me that in manual mode you want the push buttons to change direction rather than the limit switches - but why not allow either to work all the time. If you don't do a manual change the automatic one will kick in.

I also see that you have a WHILE loop in automatic() - that prevents other things happening until it finishes

If this was my project I think I would reorganize it like this

void loop() {
   readButtons();          // changes direction as user wishes
   readLimitSwitches(); // changes direction as necessary 
   readSensor();          // detects the selector setting and calculates the timing
   moveStep();            // makes one step in the current directio after the timing interval
}

This approach is explained further in the Thread planning and implementing a program

Separating the activities like this allows each part to be tested separately.

...R

Edit to add ...

It just occurred to me that maybe in manual mode you want to move the stepper only on a button press - that was not obvious from your code - rather than simply change direction.

That would also be fully compatible with my organization style. You could have a variable which is tested in the moveStep() function and , if it is TRUE the step would happen and then immediately be set to FALSE if manual mode was selected, in which case a push would set it back to TRUE for the next step. In automatic mode it would stay TRUE.

...R

Hi Robin

Thanks a lot to get my head around.

The function of manual operation would be to track a object or reposition the camera for a different angle. Once the desired position is reached or the object stops moving, then the camera needs to stay in that position.

Thanks for the help.

Terence

TerenceCollings:
The function of manual operation would be to track a object or reposition the camera for a different angle.

I was thinking a bit more about this.
You could easily program it so that when manual mode is selected the platform moves left at the selected speed as long as the left button is pressed etc.

...R

Hi Robin

The code that I have is working that when manual mode is selected the platform will move in the direction of which button is pushed. When the button is released then the platform stops.

I am struggling with getting the different speeds.

Thanks for your time

Terence

TerenceCollings:
I am struggling with getting the different speeds.

That's why I am suggesting a clearer organization of your code.

...R