Seeed Motordriver commands don't work within if loops

Hi,

This has stumped me for weeks, though admittedly I’m still pretty new to programming the Arduino.
The two if loops work perfectly, that is displaying the direction EAST or WEST, and the recieved value via the serial monitor UNTIL I uncomment the lines calling for motor movement.

I’ve run the motors using the demo example with no problems. I’ve tried enclosing the demo example commands within a simple if loop with no problems. Thinking this might have been some sort of hardware (pin) conflict, I switched from a Uno to a Mega 2560, and made sure none of the digital pins were connected through the motor shield.

I am completely lost. Ideas?

Thanks!

/* Infrared communication with arduino w/motordriver motor shield.
To send short pulses to both A and B motors at once, forward if IR receiver 
receives value 63435, backward if IR receiver recieves 63307, the 
right and left arrows of the remote.*/

//Headers
#include <MotorDriver.h>
#include <IRremote.h>
//Constants
const unsigned int IR_RECEIVER_PIN = 26;
const unsigned int BAUD_RATE = 9600;
const unsigned int EAST = 63435;
const unsigned int WEST = 63307;
//Variables
int value = 0;

IRrecv ir_receiver(IR_RECEIVER_PIN);
decode_results results; 

void setup() {
	motordriver.init();
	motordriver.setSpeed(2000,MOTORB);
	motordriver.setSpeed(2000,MOTORA);
  pinMode(30, OUTPUT);
  Serial.begin(BAUD_RATE);
  ir_receiver.enableIRIn();
}
 
void loop() {
if (ir_receiver.decode(&results)) {
  
if (results.decode_type == JVC) {
  Serial.println();
  delay(250);
  digitalWrite(30, HIGH);
  delay(500);
  digitalWrite(30, LOW);
  Serial.println(results.value);

if (results.value == 63435){
     Serial.println("EAST");	
	//motordriver.goForward();
	delay(250);
	//motordriver.stop();  
      }
      
    if (results.value == 63307){
     Serial.println("WEST");	
	//motordriver.goBackward();
	delay(250);
	//motordriver.stop(); 
      }

}
ir_receiver.resume();
}
}

Oh, "Won't work" means that when the motordriver commands are uncommented, the motor works for one pulse, then hangs at that command until either a new serial monitor window is open, or the program is reloaded. Thanks

Each time through loop() you read a new IR value so if two iterations of loop() get different values the motor will only activate once.

I don't know what the first IF is intended for - presumably you know it is a JVC code ?

All those delay()s just get in the way. Get rid of them all.

You need a variable that holds the state of the motor - eg motorState = 'F' (or 'R') and this should change when you get the appropriate IR code

The motor should decide what to do based on the value of motorState.

Something like this pseudo code

if (irCode == xxx) {
   motorState = 'F';
}
if (irCode == yyy) {
   motorState = 'R';
}
if (motorState == 'R') {
   // motor backwards
}
else {
   // motor forwards
}

You may find some useful stuff in planning and implementing a program

...R

Thanks, Robin2! I get what has to happen.

BTW, Your “Planning and Implementing an Arduino Program” is now bookmarked!
Another big thanks!

I believe I have followed your instructions correctly, but I still get the same result. Program hangs. Here’s the last attempt:

/* Infrared communication with arduino w/motordriver motor shield.
To send short pulses to both A and B motors at once, forward if IR receiver 
receives value 63435, backward if IR receiver recieves 63307, the 
right and left arrows of the remote.*/

//Headers
#include <MotorDriver.h>
#include <IRremote.h>
//Constants
const unsigned int IR_RECEIVER_PIN = 26;
const unsigned int BAUD_RATE = 9600;
const unsigned int EAST = 63435;
const unsigned int WEST = 63307;
//Variables
int value = 0;

IRrecv ir_receiver(IR_RECEIVER_PIN);
decode_results results; 

void setup() {
	motordriver.init();
	motordriver.setSpeed(2000,MOTORB);
	motordriver.setSpeed(2000,MOTORA);
  pinMode(30, OUTPUT);
  Serial.begin(BAUD_RATE);
  ir_receiver.enableIRIn();
}
 
void loop() {
int motorState = 0;
//Initialize IR receiver to JVC remote
if (ir_receiver.decode(&results)) { 
if (results.decode_type == JVC) {
  Serial.println();
  // Confirm IR receipt 
  digitalWrite(30, HIGH);
  delay(500); //keep LED on for 1/2 second
  digitalWrite(30, LOW);
  Serial.println(results.value);
// set motorState from IR input
if (results.value == 63435){
     Serial.println("EAST");	
	motorState = 1;} 
    if (results.value == 63307){
     Serial.println("WEST");	
        motorState = 0;}  
  Serial.println(motorState);      
//Run motor based on state of motorState
if (motorState == 1) {
	motordriver.goForward();
	delay(250); //power to motor for 1/4 second
	motordriver.stop(); }
else {
	motordriver.goBackward();
	delay(250); //power to motor for 1/4 second
	motordriver.stop(); }  

}
ir_receiver.resume();
}
}

Perhaps this is a power issue - make sure the motor example sketch still works reliably - you should not ever be powering a motor from the Arduino 5V rail, BTW.

I have indented your code more clearly so I could see what belongs with what ( have not tested it and I may have introduced errors)

/* Infrared communication with arduino w/motordriver motor shield.
To send short pulses to both A and B motors at once, forward if IR receiver
receives value 63435, backward if IR receiver recieves 63307, the
right and left arrows of the remote.*/

//Headers
#include <MotorDriver.h>
#include <IRremote.h>
//Constants
const unsigned int IR_RECEIVER_PIN = 26;
const unsigned int BAUD_RATE = 9600;
const unsigned int EAST = 63435;
const unsigned int WEST = 63307;
//Variables
int value = 0;

IRrecv ir_receiver(IR_RECEIVER_PIN);
decode_results results;

void setup() {
    motordriver.init();
    motordriver.setSpeed(2000,MOTORB);
    motordriver.setSpeed(2000,MOTORA);
    pinMode(30, OUTPUT);
    Serial.begin(BAUD_RATE);
    ir_receiver.enableIRIn();
}
 
void loop() {
int motorState = 0;
//Initialize IR receiver to JVC remote
if (ir_receiver.decode(&results)) {
    if (results.decode_type == JVC) {
        Serial.println();
        // Confirm IR receipt
        digitalWrite(30, HIGH);
        delay(500); //keep LED on for 1/2 second
        digitalWrite(30, LOW);
        Serial.println(results.value);
        // set motorState from IR input
        if (results.value == 63435){
            Serial.println("EAST"); 
            motorState = 1;
        }
        if (results.value == 63307){
            Serial.println("WEST"); 
            motorState = 0;
        } 
            Serial.println(motorState);     
        //Run motor based on state of motorState
        if (motorState == 1) {
            motordriver.goForward();
            delay(250); //power to motor for 1/4 second
            motordriver.stop(); 
        }
        else {
            motordriver.goBackward();
            delay(250); //power to motor for 1/4 second
            motordriver.stop(); 
        } 

    }
    ir_receiver.resume();
    }
}

You have created motorState as a local variable so it will be reset everytime loop is called. Either make it a global variable or make it static with static int motorState = 0; so that it retains its value between calls to loop().

Why have you got motorDriver.stop() ? I thought you wanted it to keep going ?

…R

Robin2,

I moved the motorState variable to the top, to make it global. No luck. I am powering the shield from a separate power source, Yep, the motordriver demo works fine. I'm actually using the output from the motor shield to briefly power an electro magnet that activates a model railroad rail swith (or turnout), depending on the polarity, thus forward/EAST and backward/WEST. If the electro magnet gets current for too long it heats up, 1/4 second is all that's needed.

So, am I right that as far as you can tell this program should do what I want it to do? That there are no glaring errors?

I have an Adafruit motorshield as well, I think I'll try that tonight. That, of course will require programming with a new library.

Thanks!

mdlafond: I'm actually using the output from the motor shield to briefly power an electro magnet that activates a model railroad rail swith (or turnout), depending on the polarity

I thought you were powering a motor. That has completely thrown me into a spin. I have had a glass of wine so I need to think about this overnight.

Why didn't you say at the top that you were driving a solenoid.

...R

Robin2,
Success!!!
I switched over to the Adafruit Motor Shield, dinked around a bit, and it works! I power motor 1 to switch the turnout to EAST, and then motor 2 to switch the turnout to WEST.
The code is basically the same as I was using with the Seeed Motor Shield (I’ll work on getting rid of those delays next) A huge thanks for your help!!! Now enjoy that glass of wine.

/* Infrared communication with arduino w/motordriver motor shield.
To send short pulses to both A and B motors at once, forward if IR receiver 
receives value 63435, backward if IR receiver recieves 63307, the 
right and left arrows of the remote.*/

//Headers
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <IRremote.h>
//Constants
const unsigned int IR_RECEIVER_PIN = 26;
const unsigned int BAUD_RATE = 9600;
const unsigned int EAST = 63435;
const unsigned int WEST = 63307;
const int motor = 1000;

//Variables
//int value = 0;
int motorState = 0;

IRrecv ir_receiver(IR_RECEIVER_PIN);
decode_results results; 
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
Adafruit_DCMotor *myMotor1 = AFMS.getMotor(1);
Adafruit_DCMotor *myMotor2 = AFMS.getMotor(2);

void setup() {
   AFMS.begin();
  pinMode(30, OUTPUT);
  Serial.begin(BAUD_RATE);
  ir_receiver.enableIRIn();
}

void loop() {

//Initialize IR receiver to JVC remote
if (ir_receiver.decode(&results)) { 
if (results.decode_type == JVC) {
  Serial.println();
  // Confirm IR receipt 
  digitalWrite(30, HIGH);
  delay(500); //keep LED on for 1/2 second
  digitalWrite(30, LOW);
  Serial.println(results.value); //confirm value
// set motorState from IR input
if (results.value == EAST){
     Serial.println("EAST");
     motorState = 1;}
if (results.value == WEST){
     Serial.println("WEST");
     motorState = 0;}
//Run motor based on state of motorState
if (motorState == 1){
	myMotor1->run(FORWARD);
        myMotor1->setSpeed(motor);  
        delay(250);
        myMotor1->setSpeed(0);
        Serial.println(motorState);} 

if (motorState == 0){
        myMotor2->run(FORWARD);
        myMotor2->setSpeed(motor);  
        delay(250);
        myMotor2->setSpeed(0);
        Serial.println(motorState);}  

}
ir_receiver.resume();
}
}

Glad to hear you have it working. I like model trains.

You might consider using servos to move switches (turnouts ?). They work really easily with an Arduino.

...R