Motor not behaving as expected

Hi Guys,

I have set up a small system to count how many times I could activate a push button on a panel before it collapsed.
The button is guaranteed to 500K activations, but we experienced some collapsing long before that.
Thus I made a test

I used the following:
Arduino Uno
Adafruit Motor Shield
12DC motor with a short (3cm) metal arm
The pushbutton to be tested ( connected to pin 4)
12V 5A external power supply for the motor

The idea is to Start the Uno and loop through the following:

Set the motor running forward and forcing the mounted arm to hit the button on the table
When the button is activated, the motor stops and reverses
After 250 milliseconds , the motor stops and goes forward again
The loop is wrapped round a "watchdog" that stops the UNO when the button eventually breaks and saves to count to EEProm
Progress is showed on a LCD

The test has worked fine and we even counted more than 2 million activations before the button broke.

Success - and all is fine from that point of view.

But I am pussled by the behavior of the motor because the cycle is as follows:

Turn clockwise( forward) and hit the button
Turn counterclockwise approx 45 degrees
Turn clockwise( forward) and hit the button
Turn counterclockwise approx 45 degrees
Turn clockwise( forward) and hit the button
Turn counterclockwise approx 120 degrees

This cycle continues until the button breaks, i.e. 2 short burst and a long burst.

Why is the cycle uneven?

Is my code "uneven" or is it perhaps a hardware issue?
It has made no difference if I have had the Uno powered by USB, separate 12V, or 12V from the Motor shield

And here is the code

#include <Wire.h>
#include <EEPROM.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"


Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 


Adafruit_DCMotor *myMotor = AFMS.getMotor(2);



#include <SoftwareSerial.h>
// Create a software serial port!
SoftwareSerial lcd = SoftwareSerial(0,2);

long Watchdog =millis();
long cycletime=millis();
long counter=0;
int fspeed=55;
int rspeed=55;
int run=4; // name of button to be tested on touchpad
boolean reversing=false;


const int MaxTimeWatchDog =700;
const int MaxCycletime=250;


void setup() 
{

  counter= EEPROMReadlong(0);
  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  myMotor->setSpeed(fspeed);
  pinMode(run,INPUT_PULLUP);
  lcd.begin(9600);  
 
 
  // Set up LCD
  lcd.write(0xFE);
  lcd.write(0xD1);
  lcd.write(16);  // 16 columns
  lcd.write(2);   // 2 rows
  delay(10);       

  // set the contrast, 
  lcd.write(0xFE);
  lcd.write(0x50);
  lcd.write(200);
  delay(10);       

  // set the brightness -
  lcd.write(0xFE);
  lcd.write(0x99);
  lcd.write(255);
  delay(10);       

  // turn off cursors
  lcd.write(0xFE);
  lcd.write(0x4B);
  lcd.write(0xFE);
  lcd.write(0x54);

  // Clear screen
  lcd.write(0xFE);
  lcd.write(0x01);
  delay(10);   

  // lcd.print(" ButtonBounce"); 
  // delay(1000);

  //  lcd.print("     Idle    ");
  delay(30);



}

void loop() 
{

  while ((millis()-Watchdog) < (MaxTimeWatchDog))
  {

    if( millis()-cycletime>MaxCycletime)
    {
      // lcd.println ("now in loop");
      // lcd.println(cycletime);
     
      myMotor->run(RELEASE);
      delay(50);
      myMotor->run(FORWARD);
      cycletime=millis();



    }

    if(digitalRead(run)==LOW & !reversing)
    {

      myMotor->run(RELEASE);
      delay(50);
      myMotor->run(BACKWARD);


      reversing=true;
      counter++;
      Watchdog=millis();

      // Clear screen
      lcd.write(0xFE);
      lcd.write(0x01);
      delay(10);
      lcd.write(1);
      delay(10);
      lcd.print("Cnt: ");
      lcd.print(counter);
      // updatelcd;



    }
    if(digitalRead(run)==HIGH)
    {
      reversing=false;
    }
  }
  // Clear screen
  
  // If we get to here we are out of the while loop and have timed out
  EEPROMWritelong(0,counter);
  lcd.write(0xFE);
  lcd.write(0x01);
  delay(10);
  lcd.write(1);
  delay(10);
  lcd.print(" Cnt: ");
  lcd.print(counter);
  lcd.print("     Stopped");
  myMotor->run(RELEASE);
  // updatelcd;


}

// Functions to read & write values to EEprom

void EEPROMWritelong(int address, long value)
{
  //Decomposition from a long to 4 bytes by using bitshift.
  //One = Most significant -> Four = Least significant byte
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);

  //Write the 4 bytes into the eeprom memory.
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}

//This function will return a 4 byte (32bit) long from the eeprom
//at the specified address to address + 3.
long EEPROMReadlong(long address)
{
  //Read the 4 bytes from the eeprom memory.
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);

  //Return the recomposed long by using bitshift.
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
    if (digitalRead(run) == LOW & !reversing)

A single & is a binary AND, a double & is a logical AND.

Not sure though if it explains the behaviour

Thanks sterretje,

I don't know much about compilers, but I doubt that it could be the problem since I am comparing boolean values, but I will give it a try.

Also not the cause of your problem, but you would be wise to make your timing variable unsigned longs

Thanks UKHeliBob,

It seems that my basic logic is correct, so I will look at the motor and try mounting some capacitors over it to soften up possible spikes.

But it is not too important - the setup did the job of testing the push button :slight_smile: