2

I have a problem with the Arduino Motor Shield R3 on an Arduino Uno. I Have a DC Motor on the A Channel and the Shield is connected to an external power source. When I reset the Arduino card the motor starts running by default until the pins are initialized.

This is really problematic for me because the motor is on a rail delimited by 2 switches, when a switch is reached the motor stops. When the motor moves during reset the value of the switches are not read yet, which causes the motor to go beyond the switch and be blocked afterwards.

When I reset the card I read the value of the 3 digital pins used to drive the motor :

  • pin 12 : Direction (DirA), HIGH motor foward, LOW motor running backward
  • pin 3 : Power (PwmA), HIGH motor running, LOW motor not running
  • pin 9 : Brake (BrakeA), HIGH brake is on, motor can't run, LOW brake is off, motor can run

Before reseting I put the 3 pins at HIGH, At reset, pin 12 == HIGH, pin 9 == LOW, pin 3 == HIGH which means that the brake is disengaged but the Power is still here, so the motor starts running again until the pinMode function is reached. During that reset time of approximately 2 seconds, the motor has the time to go beyond the switches which causes the system to break.

Is this normal ? Is there a way to force the pin 3 to be at LOW when the Arduino resets ? I put my code at the bottom.

Naïve solution : is to put PwmA at LOW when a switch is reached, so I'm sure it will stay that way until the next reset. But if the arduino is reseted while the motor is running I still have the problem.

int closeSwitch = A3;
int openSwitch = A2;
int DirA = 12;
int PwmA = 3;
int BrakeA = 9;

int OpeningDirection = LOW;
int ClosingDirection = HIGH;

bool motorRunning = false;
bool motorOpening = false;
bool openSwitchReached = false;
bool closeSwitchReached = false;

void setup() {

  Serial.begin(9600);

  sendToPC("Init\n"); //This is just to read the init state of the pins
  Serial.print(digitalRead(DirA));
  Serial.print(digitalRead(BrakeA));
  Serial.print(digitalRead(PwmA));

  pinMode(openSwitch, INPUT);//is High when Hublot opened
  pinMode(closeSwitch, INPUT); //is HIGH when hublot closed
  pinMode(DirA, OUTPUT); //Initiates Motor Channel A pin
  pinMode(BrakeA, OUTPUT); //Initiates Brake Channel A pin
  pinMode(PwmA, OUTPUT); //Initiates Brake Channel A pin

  sendToPC("\nAfter\nA:"); //After init all is LOW
  Serial.print(digitalRead(DirA)); 
  Serial.print(digitalRead(BrakeA));
  Serial.print(digitalRead(PwmA));


  //Stopping the motor
  setMotorSpeed(0);
  if (digitalRead(BrakeA) == LOW) {
    brakeMotor();
  }

  //Is the first switch on
  openSwitchReached = (digitalRead(openSwitch) == HIGH);
  //Second switch state
  closeSwitchReached = (digitalRead(closeSwitch) == HIGH);

  handleSerialInput(-3); //Send ping return
  handleSerialInput(-2); //Send status
}


void sendToPC(const char * str) {
  Serial.write(str);
  delay(215); //Delay to avoid answers being read as one
}

void setMotorSpeed(int speed) {
  if (speed > 0)
    digitalWrite(BrakeA, LOW);   //Disengage the Brake for Channel A
  digitalWrite(PwmA, HIGH);   //Spins the motor on Channel A at full speed
}

void setMotorDirection(int direction) {
  digitalWrite(DirA, direction); //Establishes direction of Channel A
}

void brakeMotor() {
  digitalWrite(BrakeA, HIGH);
  //digitalWrite(PwmA, LOW); -> this is my naïve solution
}

void handleSerialInput(int input) {
  Serial.print(input);
  if (input == 1 && !openSwitchReached) { //open
    brakeMotor(); // stop motor
    delay(100);
    setMotorDirection(OpeningDirection);
    setMotorSpeed(255); // set motor max speed
    motorRunning = true;
    motorOpening = true;
    sendToPC("HublotOpening");
  }
  else if (input == 2 && !closeSwitchReached) { //close
    brakeMotor(); // stop motor
    delay(100);
    setMotorDirection(ClosingDirection);
    setMotorSpeed(255); // set motor max speed
    motorRunning = true;
    motorOpening = false;
    sendToPC("HublotClosing");
  }
  else if (input == -2) { //get status
    if (openSwitchReached)
      sendToPC("HublotOpened");
    else if (closeSwitchReached)
      sendToPC("HublotClosed");
    else if (motorRunning && motorOpening)
      sendToPC("HublotOpening");
    else if (motorRunning && !motorOpening)
      sendToPC("HublotClosing");
    else if (!motorRunning)
      sendToPC("HublotNotMoving");
  }
  else if (input == -3) //Ping
    sendToPC("ArduinoHublot");
  else if (input == 0) { //Stop
    brakeMotor(); // set motor max speed
    motorRunning = false;
  }
  else {
    sendToPC("WTF");
    Serial.print(input);
  }
}

void loop() {

  openSwitchReached = (digitalRead(openSwitch) == HIGH);
  closeSwitchReached = (digitalRead(closeSwitch) == HIGH);



  if (openSwitchReached && motorRunning && motorOpening) {
    sendToPC("HublotOpened");
    brakeMotor();
    motorRunning = false;
    delay(200);
  }
  else if (closeSwitchReached && motorRunning && !motorOpening) {
    sendToPC("HublotClosed");
    brakeMotor();
    motorRunning = false;
  }

  if (Serial.available()) {
    int read = (Serial.readStringUntil(':')).toInt();
    handleSerialInput(read);
  }

}

1 Answer 1

1

Add pulldown resistors (10KΩ) to any pins you want to force to be low at reset.

(Quite frankly I'm amazed they don't exist on all inputs to the board by default - it seems a bit of a fatal omission).

1
  • According to this that's what they done for BrakeA, I will try it. Thanks for the answer.
    – ElevenJune
    Commented Mar 3, 2017 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.