Arduino Nano DC Motor Randomly Stopping

Hello!

I have a project where I need to run three motors - a continuous servo, a unipolar stepper and a dc motor- at the same time. The goal of the project is to sort plastic bottles, and I do this through the use of two colour sensors.

The Arduino that I am using is acting as a slave device to a PIC18, which I use to command the Arduino to proceed with a “sort”. The “sort” consists of continuously rotating a DC motor, incrementally rotating a stepper motor, reading values from the colour sensors and then moving the servo motor into a new position. I will show you the code that I have:

//Interface Arduino with PIC over I2C Connection
//Remember to enable the Arduino-PIC switches on RC3 and RC4!

#include <Wire.h>
#include "Adafruit_TCS34725.h"
extern "C" {
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}
#include <Stepper.h>

#define STEPS 200
#define TCAADDR 0x70

Adafruit_TCS34725 tcs1 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
Adafruit_TCS34725 tcs2 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

int state = 1;
char incomingByte;
char sort_bottle = 2;   // 1=eksa cap, 2=eksa no cap, 3=yop cap, 4=yop no cap

int switchPin = 2;
int bump = 0;

int servoPin = 4;
int pulse = 1500;
int pos1 = 1300;
int pos2 = 1600;
int pos3 = 1800;
int pos4 = 2150;
int position = pos1;
int servoState = LOW;
long previousMillis = 0;
int colour_sum1, colour_sum2;

// digital pins for the stepper motor
Stepper stepper(STEPS, 5, 6, 7, 8);
int enable = 9;
int proceed_detection = 0;

// hall effect sensor
int hallPin = 0;

// dc motor
int dcOn = 0;
int dcDirection = 1;
int dcPinFor = 11;
int dcPinBack = 12;
int stepCount = 0;
int stepDiff;

void tcaselect(uint8_t i) {
  if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();
}

void setup() {
  while (!Serial);
  delay(1000);

  pinMode(switchPin, INPUT);
  pinMode(servoPin, OUTPUT);
  pinMode(dcPinFor, OUTPUT);
  pinMode(dcPinBack, OUTPUT);
  pinMode(enable, OUTPUT);
    
  digitalWrite(enable, HIGH);
  stepper.setSpeed(8);

  Wire.begin(8);                // join i2c bus with address 8
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);

  Serial.begin(9600);

  for (uint8_t t = 0; t < 8; t++) {
    tcaselect(t);
    Serial.print("TCA Port #"); Serial.println(t);

    for (uint8_t addr = 0; addr <= 127; addr++) {
      if (addr == TCAADDR) continue;

      uint8_t data;
      if (! twi_writeTo(addr, &data, 0, 1, 1)) {
        Serial.print("Found I2C 0x");  Serial.println(addr, HEX);
      }
    }
  }

  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);
}

// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  if (millis() - previousMillis > 20) {
    servoControl(position);
    previousMillis = millis();
  }
}

void loop() {
  detections();

  Serial.println("======= DC MOTOR =======");
  Serial.println((int) dcOn);

  Serial.println("======= STEPPER MOTOR =======");
  Serial.println((int) proceed_detection);

  digitalWrite(dcPinFor, LOW);
  digitalWrite(dcPinBack, LOW);

  if (proceed_detection == 1) {
    if(dcDirection == 1) {
      dcDirection = 0;
      digitalWrite(dcPinFor, HIGH);
      digitalWrite(dcPinBack, LOW);
    } else {
      dcDirection = 1;
      digitalWrite(dcPinFor, LOW);
      digitalWrite(dcPinBack, HIGH);
    }
    proceed_detection = 0;
    stepper.step(5);
  }

}

void servoControl(int position) {
  digitalWrite(servoPin, HIGH);
  delayMicroseconds(position);
  digitalWrite(servoPin, LOW);
  delay(20);
}

char buf[3];
int counter = 0;

void detections() {
  uint16_t r1, g1, b1, c1, colorTemp1, lux1, r2, g2, b2, c2, colorTemp2, lux2;

  // read from bump switch
  bump = digitalRead(switchPin);
  // select colour sensor number 1
  tcaselect(2);

  // read from the colour sensor 1
  tcs1.getRawData(&r1, &g1, &b1, &c1);
  colorTemp1 = tcs1.calculateColorTemperature(r1, g1, b1);
  lux1 = tcs1.calculateLux(r1, g1, b1);

  // select colour sensor number 2
  tcaselect(6);

  // read from the colour sensor 2
  tcs2.getRawData(&r2, &g2, &b2, &c2);
  colorTemp2 = tcs2.calculateColorTemperature(r2, g2, b2);
  lux2 = tcs2.calculateLux(r2, g2, b2);

  colour_sum1 = r1 + g1 + b1;
  colour_sum2 = r2 + g2 + b2;

  if (bump == HIGH) {

    if (colour_sum1 + colour_sum2 > 3000) {
      // yop bottle
      if ((float)r1 / (float)b1 > 1.6 || (float)r2 / (float)b2 > 1.6) {
        // with a cap
        sort_bottle = 3;
        position = pos3;
      } else {
        // without a cap
        sort_bottle = 4;
        position = pos4;
      }
    } else {
      // eska bottle
      if ( ((float)b1 / (float)r1) > 1 || ((float)b2 / (float)r2) > 1) {
        // with a cap
        sort_bottle = 1;
        position = pos1;
      } else {
        // without a cap
        sort_bottle = 2;
        position = pos2;
      }
    }
  }
  else {
    sort_bottle = 5;
  }
//
//  Serial.println("======= COLOUR SENSOR 1 =======");
//  Serial.print("RED "); Serial.println(r1);
//  Serial.print("GREEN "); Serial.println(g1);
//  Serial.print("BLUE "); Serial.println(b1);
//  Serial.print("TEMP "); Serial.println(colorTemp1);
//  Serial.print("LUX "); Serial.println(lux1);
//
//  Serial.println("======= COLOUR SENSOR 2 =======");
//  Serial.print("RED "); Serial.println(r2);
//  Serial.print("GREEN "); Serial.println(g2);
//  Serial.print("BLUE "); Serial.println(b2);
//  Serial.print("TEMP "); Serial.println(colorTemp2);
//  Serial.print("LUX "); Serial.println(lux2);
//
//  Serial.println("======= TEST CRITERIA =======");
//  Serial.print(" r1 + g1 + b1 = "); Serial.println(r1 + g1 + b1);
//  Serial.print(" r2 + g2 + b2 = "); Serial.println(r2 + g2 + b2);
//  Serial.print(" r1/b1 = "); Serial.println((float)r1 / (float)b1);
//  Serial.print(" r2/b2 = "); Serial.println((float)r2 / (float)b2);
//  Serial.print(" b1/r1 = "); Serial.println((float)b1 / (float)r1);
//  Serial.print(" b2/r2 = "); Serial.println((float)b2 / (float)r2);

  Serial.println("======= DETERMINATION =======");
  Serial.println((int) sort_bottle);
}

void receiveEvent(int howMany) {
  char x = Wire.read();      // receive byte as char

  if ((int) x == 1) {
    dcOn = (int) 1;
  } else {
    dcOn = (int) 0;
  }
}

void requestEvent() {
  proceed_detection = 1;
  Wire.write(sort_bottle); // respond with message of 1 byte, in this case, the detected bottle
}

So the issue that I am having is with my motors - they work inconsistency! By this I mean, sometimes I am able to get a run in where I have everything working, but often times my dc motor cuts out after a second or two of operations. I also notice that sometimes my stepper motor stops spinning too.

I have managed to observe that whenever my DC motor cuts out, the “L” light on my Arduino (I believe this is connected to digital pin 13) flashes. Could this be related?

I also know that working with I2C has given be quite a bit of trouble - is it possible that I am not providing enough delays between when I am making a command to my Arduino over I2C? I’ll attach my PIC code for completeness:

DETECTIONS 
 Delay50N delayR, 0x0a    ; this gives me a 50ms x 0x10 = 500ms delay. 
 call READ_ARDUINO
 movwf DETECTION_VAL
 
 ; first check if there was a bottle detected, if so go to COLLECTIONS_STEP
 movlw d'5'
 subwf DETECTION_VAL, 0
 bz DETECTIONS
 
 ; okay we have a bottle, first increment total count then see what it is
 incf TOTAL_BOTTLES
 
 ; yop no cap
 movlw d'4'
 subwf DETECTION_VAL, 0
 bz INC_YOPNOCAP
 
 ; yop with cap
 movlw d'3'
 subwf DETECTION_VAL, 0
 bz INC_YOPCAP
 
 ; eska no cap
 movlw d'2'
 subwf DETECTION_VAL, 0
 bz INC_ESKANOCAP
 
 ; eksa with cap
 movlw d'1'
 subwf DETECTION_VAL, 0
 bz INC_ESKACAP
 
 ; edge case, cant determine bottle so check if done sorting
 bra DETECTIONS

Now the delays that I have for my I2C calls, I got those simply by trial and error. If I do not afford enough time in between I2C calls, then the data that I get back from my Arduino is always “/” instead of the desired number “0” for example.

Any and all help would greatly be appreciated. I look forward to seeing what you guys have to say, and I am confident that we can work this out!

Matthew

EDIT: The power is fine - all are running off of a 36W power supply giving 1A 3A of current.

1 Amp is probably on the low side for 3 motors, what are the voltage and current requirements for each motor, can you post a datasheet link for each?

Sorry, it is actually 3A. Not sure where I got the 1A from, but 3A is sufficient from my calculations.

I’ve managed to isolate the issue to being one with my I2C protocol: I occasionally get my I2C line freezing up on my - either the clock or data lines get stuck low. Not sure how to remedy this, but I’ve tried implementing a grossly long delay between when I invoke a read/write command and when I actually process the data. As far as I am concerned though, this has not addressed the issue.

Thanks for getting back to me, really do appreciate it! The support on these forums always impresses me, and really does help a newcomer.

Hi,
Can you post a picture of your project so we can see your layout?
How long are the wires for your I2C system?

Thanks.. Tom.. :slight_smile:

Here is an image on my circuitry. Beware: it is a complete mess.

You mention wire length for the I2C line - the I2C connections are done on the integrated circuit, so I do not believe that the length of the line is too long. My primary issue is with the inconsistency.

In my PIC code, I've isolated the issue to be with me initiating the I2C read - if I subvert this and run, there are no issues. Problem is, I need to the I2C read to begin my sort!

Right now I am playing around with delays, which seems to (artificially?) help.

To make things more confusing, I notice that sometimes the I2C lines appear to be fine, but the motor still does not run (this means that my variable "proceed_direction" does not get set to 1). I've made an update to my Arduino code, and I've since updated that in my initial post.

Thanks a bunch.

Hi,
OPs layout.

Have you got the pull up resistors on the I2C?

Tom... :o