[SOLVED] Motor Control and Endstops

I've got a program that pretty much works perfectly. The problem is it rotates the motor one way until the endstop is hit then it rotates it the other way until the endstop is no longer pressed. This is in the loop function. What would you advise? Thanks for the help!

/***************  INTERACTIVE WINDOW DISPLAY  ***************/
/*                       UNO CODE                           */
/*  This is one half of the code necessary to run the
    window display.

    The Uno is connected to the Nano on pin 13.
    
    The circuit is placed within a mirror in a shop window  
    It uses an Arduino Uno, L293D motor controller,         
    2 microswitches, low V DC bidirectional motor and an    
    IR distance sensor with digital output                  
                                                            
    This program will check the IR sensor and if it         
    receives a LOW return it checks both the end switches   
    (NO attached to gnd, C out) before deciding how to move.
    When moving it sends a command to the Nano which then 
    plays the Benny Hill theme tune. This was deemed easier
    than using a time-flag system and is in effect dual
    processing.  
       
    Controller pins: Enable, L1, L2                         
    Enable is power override, L1&2 choose direction
    
    L293D was wired with reference to:
    https://learn.adafruit.com/downloads/pdf/adafruit-arduino-lesson-15-dc-motor-reversing.pdf
    Thanks to johnwasser on the Arduino forums for help with
    endstop debugging                                       
    Thanks to Andy Maybury for help with further debugging  */
/************************************************************/

/******************** GLOBAL CONTROLS ***********************/
//  Pin declarations
int leftTrigger = 7;  
int rightTrigger = 5; 
int IR = 6;
int enable = 11;
int leftSpin = 10;
int rightSpin = 9;
int songActivate = 13;

//  Control declarations
int IRval;                  //Value from IR sensor
int lVal;                   //Value from Left trigger
int rVal;                   //Value from Right trigger
boolean drctn;              //Left or right (chip control)
int velocity = 255;         //Motor speed control
int off = 0;                //Easy-read off 
boolean left = true;        //(chip control)
boolean right = false;      //(chip control)
int rnd;                    //Holds random value

/********************* CIRCUIT SETUP ************************/
void setup() {
pinMode(leftTrigger,INPUT_PULLUP);
pinMode(rightTrigger, INPUT_PULLUP);
pinMode(IR, INPUT_PULLUP);
pinMode(leftSpin, OUTPUT);
pinMode(rightSpin, OUTPUT);
pinMode(enable, OUTPUT);
pinMode(songActivate, OUTPUT);

//DEBUG
Serial.begin(9600);
}

void loop(){
/*********************** RANDOMISER  ************************/
//  Uses a larger range for better randomisation. 
  rnd = random(0, 1000);  
  drctn = right;                    //default case
  if (rnd > 500){drctn = left;}   //option 2

/**********************  MAIN CODE **************************/
//  First we read the IR state
 while (digitalRead(IR) == LOW){
    if (digitalRead(leftTrigger) == LOW){drctn = right;}
    if (digitalRead(rightTrigger) == LOW){drctn = left;}
    setMotor(velocity, drctn);
    digitalWrite(songActivate, HIGH);

    //DEBUG
    Serial.print(rnd);
    Serial.print("  ");
    Serial.print(drctn);
    Serial.print("    ");
  }
setMotor(off,drctn);
digitalWrite(songActivate, LOW);
}

/**************** motor control function  ******************/
void setMotor(int power, boolean direct){
  analogWrite(enable, power);
  digitalWrite(leftSpin, direct);
  digitalWrite(rightSpin, !direct); 
}

What would you advise?

What do you want it to do?

Is it travel to the other end stop? If so then you do need a flag system whit a boolean variable determining the direction of travel and the end stops just toggling this variable.

I want it to move in the new direction for as long as the IR sensor still senses motion or until it hits the other endstop.

The code looks right to me. Have you got the end stops the right way round?

Yeah, it moves till it hits the endstop, reverses and keeps doing so till the endstop isn't triggered.

everses and keeps doing so till the endstop isn't triggered.

Then what happens? does it stop?

It starts going back in the original direction. It basically keeps hugging one end of the track.

I can't understand that action from that code. Have you tried replacing the motors with LEDs to check you are not suffering from interference.

If neither trigger is LOW then the direction will be random. Get rid of the random stuff in loop() and see what happens. You should choose the random direction only when the IR changes state to LOW, not on every trip through loop().

I've attached debug LEDs ad i've tried both removing the randomisation code and moving it into the while loop. Both have no impact on the results. Here is what happens:

IR triggered LEFT LED flashes momentarily RIGHT LED then runs constantly until RIGHT endstop is triggered When RIGHT endstop triggered, LEFT LED runs constantly until RIGHT endstop not triggered, whereby it returns to running RIGHT

is the end stop a on/off switch or a momentary ?

SPDT momentary lever microswitch

SJMaybury:
I’ve attached debug LEDs ad i’ve tried both removing the randomisation code and moving it into the while loop. Both have no impact on the results. Here is what happens:

IR triggered
LEFT LED flashes momentarily
RIGHT LED then runs constantly until RIGHT endstop is triggered
When RIGHT endstop triggered, LEFT LED runs constantly until RIGHT endstop not triggered, whereby it returns to running RIGHT

That is not what your code does. As I have said before this suggests you have wired up you switches incorrectly. Can you post a schematic please.

Here's an extended fritz schematic.

Window Display Wiring.png|539x462

SJMaybury: Here's an extended fritz schematic.

Gulp. Fritzing is not exactly welcomed here. I notice that the symbol for the IR sensor you use is a sensor with an analogue output, not a digital one so why are you feeding it into a digital input?

I have run your code on my system, with just LEDs and change the input output pins to match my switch / LED box, and I do not get the action you report.

Basically while the IR pin is low the motor runs. The direction depends on the end stop last triggered. The end stop only has to be switched briefly for the motor to change. The motor then runs in the new direction when the end stop switch is released and it continues to run in this direction until the other end stop is briefly brought low, which I believe is the situation you want and is what the code would suggest is happening.

Replace your IR sensor input with a switch and see if you can get it to work like you expect.

Hence the png. The IR I used is digital output however that just happened to be the IR symbol I found.

That's odd and very annoying. Thanks for the feedback

Nope, no luck. This doesn't make any sense... :(

The IR I used is digital output however that just happened to be the IR symbol I found.

Yep, that happens and that is one of the reasons why Fritzing is hated. In effect you are not telling the truth.

Try putting a bit more useful debug output.

For example

Serial.println("   out of while loop ");  
setMotor(off,drctn);
digitalWrite(songActivate, LOW);

Will show you if the IR is working like you think. And :-

while (digitalRead(IR) == LOW){
 Serial.print(digitalRead(leftTrigger));
 Serial.print("  ");
 Serial.println(digitalRead(rightTrigger));
 if (digitalRead(leftTrigger) == LOW){drctn = right;}

Will show you the state of the input switches.

Hi, What are you using for end stop switches? Do you have pullup or pull down resistors with them? When the switches are open, you need to have 10K resistors on the arduino inputs to pull them to gnd or 5V. Leaving the input open does not mean it is at gnd potential. The software does allow for internal pullup resistors to be used, if you are switching input to gnd.

Tom... :)

Yes Tom, the code in the first post shows the internal pull ups being used.