Arduino Resetting Itself..??

Hi,
I have a small project on the go ( see attached ), that will be used to interface to a stepper motor driver. It consists of a Sparkfun rotary encoder used to change speed numbers on a 7-segment display, with additional button for motor stop/start and toggle switch for motor direction, all powered by USB.

Everything works great but occasionally I get odd behaviour which occurs on power up. I did a test where I repeatedly disconnected/reconnected power by pulling out the USB cable and re-inserting. Most of the time it fires up fine and I am able to turn the encoder knob and the numbers change as they should. Three problems occur randomly in about 1 in 10 power ups, these are:

  1. The display reads '0' but turning the knob does not change the display ( when I press the start/stop button it starts to work).
  2. The knob changes the display but the numbers are out of step with the rotation of the encoder.
  3. The display reads '0' but almost immediately the Arduino resets itself ( sometimes when in the process of changing the display ).

The setup

  1. The display is driven by Digital pins 4-11. Each LED segment is driven by one of these pins, each having a resistor to give the correct amount of sinking current. These pins are set to OUTPUT and HIGH and current is sunk through these pins on a LOW and is no more than 15mA sunk on each pin).

  2. The stop/start button is attached to pin 3, set up as an INPUT with pullups on.

  3. The encoder is hooked up to Analogue input pins 0 and 1 and these are set as INPUTS with pullups on. The encoder pulls these pins to ground.

  4. The stop/start button has an integral, independent LED that is lit when the button is pressed. The power is provided by Analogue pin 2, set to OUTPUT. Current drawn is through a 200ohm resistor drawing around 10mA.

  5. The toggle switch is attached to Analogue pin 3, set up as an INPUT with pullups on.

  6. Analogue pins 4 and 5 are setup as OUTPUTS and are used to provide the direction and frequency inputs to the stepper driver.

The initialisation code:

...

#define BUTT_STEP 3 // Stepper start/stop switch interrupt pin
#define ESTOP 2 // Emergency stop interrupt.

// Definitions for Analog port pins
#define ENC_A 14 // Encoder input A
#define ENC_B 15 // Encoder input B
#define BUTT_LED 16 // Power for button LED
#define SWCH_DIR 17 // Switch input for direction
#define DIR 18 // Output for direction input to microstepping drive
#define PUL 19 // Output for frequency input to microstepping drive
#define ENC_PORT PINC // Analog port

void setup()
{

// Set display pins for sinking current.
for( byte n=4;n<=11;n++)
{
pinMode(n, OUTPUT);
digitalWrite(n,HIGH);
}

// Setup stepper start/stop button
pinMode(BUTT_STEP, INPUT);
digitalWrite(BUTT_STEP, HIGH);
attachInterrupt(1, StartStopPressed, FALLING);

// Setup emergency stop interrupt
pinMode(ESTOP, INPUT);
digitalWrite(ESTOP, HIGH);
attachInterrupt(0, EmergenyStop, FALLING);

// Setup encoder pins as inputs
pinMode(ENC_A, INPUT);
digitalWrite(ENC_A, HIGH);
pinMode(ENC_B, INPUT);
digitalWrite(ENC_B, HIGH);

//Setup button LED power pin
pinMode(BUTT_LED, OUTPUT);
digitalWrite(BUTT_LED, HIGH);

//Setup direction switch pin
pinMode(SWCH_DIR, INPUT);
digitalWrite(SWCH_DIR, HIGH);

//Setup direction output pin
pinMode(DIR, OUTPUT);
digitalWrite(DIR, LOW);

//Setup frequency output pin
pinMode(PUL, OUTPUT);
digitalWrite(PUL, LOW);

}

Anyone have any ideas as to what the problem is? Is it a power supply issue? The fact that the Arduino occasionally resets itself leads me to think yes. Or, am I doing something fundamentally wrong in using the Analogue pins in this way? Is there a fundamental flaw in the initialisation code, maybe a different sequence...?

Any pointers greatly appreciated... thanks! :slight_smile:

I don't know whether you have anything connected to the motor driver, but if you do I suggest you disconnect it. That would remove any heavy loads or inductive spikes on the power supply which might be upsetting your Arduino. If this fixes the problem, it points to a power supply or noise problem.

Some of the symptoms also make me suspect uninitialised memory or memory corruption or stack overflow. It would be worth posting all your code so that we can check for that. If that involves a lot of code, I suggest you try to reproduce the key symptoms in the simplest possible sketch. That would make it easier to investigate, and also force you to find out which parts of the code are involved.

If the symptoms seem to change with seemingly unrelated changes to the code, this points to a memory corruption or stack overflow problem.

You say the board sometimes resets. If your fuse settings leave the brown-out detection enabled, this could point towards a power supply issue. However, some memory corruptions can also lead to the Arduino resetting so you can't make any definite conclusion at this stage.

When posting code, please enclose it in [ code ] [ /code ] tags. You can go back and fix your original post by editing it, selecting all the code and clicking the # button in the message edit window.

If you're trying to power the stepper motor from the Arudino 5V pin,
that's a bad idea.

Hi,
Thanks for the replies.. :slight_smile: This is the code in it's entirety:

#include <stdio.h>
#include <TimerOne.h>  

// Each segment is defined as a single bit value of '1' in a byte. Bit positions are mapped to pin numbers,
// Bit 7 represents pin 11 running down to bit 0 representing pin 4.
const byte SegG = B10000000; // G = pin 11
const byte SegF = B01000000; // F = pin 10
const byte SegA = B00100000; // A = pin 09
const byte SegB = B00010000; // B = pin 08
const byte SegE = B00001000; // E = pin 07
const byte SegD = B00000100; // D = pin 06
const byte SegC = B00000010; // C = pin 05
const byte SegDP =B00000001; // DP = pin 04

// Individual segment definitions are 'OR'ed to make up the digit definitions. These are then negated so that a '1' means off and
// '0' means on. This is so that when a '0' is written to a pin output, i.e. a particular segment needs to be turned on,
// the pin acts like a sink and draws current to drive the individual LED. This is particular to the display used, which uses a common anode
// where LED current needs to be sunk.
const byte Digit0 = ~( SegA | SegB | SegC | SegD | SegE | SegF);
const byte Digit1 = ~( SegB | SegC);
const byte Digit2 = ~( SegA | SegB | SegD | SegE | SegG );
const byte Digit3 = ~( SegA | SegB | SegC | SegD | SegG );
const byte Digit4 = ~( SegB | SegC | SegF | SegG );
const byte Digit5 = ~( SegA | SegC | SegD | SegF | SegG );
const byte Digit6 = ~( SegA | SegC | SegD | SegE | SegF | SegG );
const byte Digit7 = ~( SegA | SegB | SegC );
const byte Digit8 = ~( SegA | SegB | SegC | SegD | SegE | SegF | SegG );
const byte Digit9 = ~( SegA | SegB | SegC | SegD | SegF | SegG );

byte Digits[]={Digit0,Digit1,Digit2,Digit3,Digit4,Digit5,Digit6,Digit7,Digit8,Digit9};


// Definitions for interrupt pins
#define BUTT_STEP 3 // Stepper start/stop switch interrupt pin
#define ESTOP 2 // Emergency stop interrupt. e.g. safety door opened.

// Definitions for Analog port pins
#define ENC_A 14  // Encoder input A
#define ENC_B 15  // Encoder input B
#define BUTT_LED 16  // Power for button LED 
#define SWCH_DIR 17  // Switch input for direction
#define DIR 18  // Output for direction input to microstepping drive 
#define PUL 19  // Output for frequency input to microstepping drive
#define ENC_PORT PINC // Analog port


void setup()
{
  
  // Set display pins for sinking current.
  for( byte n=4;n<=11;n++)
  {
    pinMode(n, OUTPUT);   
    digitalWrite(n,HIGH);
  }
  
  // Setup stepper start/stop button
  pinMode(BUTT_STEP, INPUT);
  digitalWrite(BUTT_STEP, HIGH);
  attachInterrupt(1, StartStopPressed, FALLING);

  // Setup emergency stop interrupt
  pinMode(ESTOP, INPUT);
  digitalWrite(ESTOP, HIGH);
  attachInterrupt(0, EmergencyStop, FALLING);
  
  // Setup encoder pins as inputs
  pinMode(ENC_A, INPUT);
  digitalWrite(ENC_A, HIGH);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_B, HIGH);

  //Setup button LED power pin
  pinMode(BUTT_LED, OUTPUT);
  digitalWrite(BUTT_LED, LOW);
  
  //Setup direction switch pin
  pinMode(SWCH_DIR, INPUT);
  digitalWrite(SWCH_DIR, HIGH);

  //Setup direction output pin
  pinMode(DIR, OUTPUT);
  digitalWrite(DIR, LOW);

  //Setup frequency output pin
  pinMode(PUL, OUTPUT);
  digitalWrite(PUL, LOW);

  
  //Display initial splash screen on startup
  Splash();
  
  PrintDigit(0);
}
 
 

int Digit = 0;
volatile boolean MotorRun = false;

// The code in the loop() funtion constantly polls a rotary encoder and displays a user selected
// number on a 7 segment display until an interrupt occurs on the motor start/stop pin.
void loop()
{
  
// The following is code to read a rotary encoder ( slighty modified  to suit ) and is borrowed from here:
// http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino
 static int enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
 static int tmpdata;
 static int counter = 0;      //this variable will be changed by encoder input
 static uint8_t old_AB = 0;


  if(!MotorRun) { // Allow user to change speed only when motor is stopped.{
    old_AB <<= 2;                   //remember previous state
    old_AB |= ( ENC_PORT & 0x03 );  //add current state
    tmpdata = enc_states[( old_AB & 0x0f )];

    if( tmpdata )
      counter += tmpdata ;
// End borrowed code....

   if( counter == 4  ) // Counter has rotated one 'notch' clockwise
   {
     counter=0;
     if( Digit <9 ) 
     {
       Digit++;
       PrintDigit(Digit); 
     }
   } 

   if( counter == -4 ) // Counter has rotated one 'notch' anti-clockwise
   {
     counter=0;
     if( Digit >0 )
     {
       Digit--;
       PrintDigit(Digit);
     }
   }    
  }
}
 

// Display a start up animation
void Splash()
{

const byte x = 60;

  for( int n=0;n<=1;n++)
  {
  PrintBits(SegA);
  delay(x);
  PrintBits(SegA | SegB );
  delay(x);
  PrintBits(SegA | SegB | SegC );
  delay(x);
  PrintBits(SegA | SegB | SegC | SegD );
  delay(x);
  PrintBits(SegA | SegB | SegC | SegD | SegE );
  delay(x);  
  PrintBits(SegA | SegB | SegC | SegD | SegE | SegF);
  delay(x);

  PrintBits(SegB | SegC | SegD | SegE | SegF);
  delay(x);
  PrintBits(SegC | SegD | SegE | SegF);
  delay(x);
  PrintBits(SegD | SegE | SegF);
  delay(x);
  PrintBits(SegE | SegF);
  delay(x);
  PrintBits(SegF);
  delay(x);  
  }  
  
  PrintBits(B00000000);
  delay(50);
}


//Display an arbitrary byte
void PrintBits( byte Bits )
{ 
  Bits=~Bits;
  for( int n=7;n>=0;n--)
  {
   digitalWrite(n+4,bitRead(Bits,n));
  }
}


// Display a digit
void PrintDigit( byte digit )
{
  for( int n=7;n>=0;n--)
  {
   digitalWrite(n+4,bitRead(Digits[digit],n));
  }
}


// Interrupt routine called when stop/start button is pressed
void StartStopPressed()
{
  if ( !MotorRun )
  {
    MotorRun = true;
    digitalWrite(BUTT_LED, HIGH);             // Turn on button LED
    digitalWrite(DIR,digitalRead(SWCH_DIR));  // Set motor direction to selected direction
    Timer1.initialize(500000/(Digit+1));      // Set Timer for 1/2 desired frequency. Here it is set for 1Hz on display setting '0'
    Timer1.attachInterrupt(Pulse);            // Start motor
  }
  else
  {
    Timer1.detachInterrupt();     // Stop motor
    digitalWrite(BUTT_LED, LOW);  // Turn off button LED
    digitalWrite(PUL, LOW);   
    MotorRun = false;
  }    
}  


void Pulse()
{
  digitalWrite(PUL,digitalRead(PUL)^1); // Toggle frequency output pin using XOR
}


void EmergencyStop()
{
    Timer1.detachInterrupt();     // Stop motor
    digitalWrite(BUTT_LED, LOW);  // Turn off button LED
    digitalWrite(PUL, LOW);   
    MotorRun = false;
}

I have attached a pic of the whole setup.

The stepper motor has it's own separate power supply and driver. The inputs to the driver are frequency and direction and are internally opto-isolated. I have driven the stepper motor this way before, directly plugged into the Arduino ( actually I'm using a Seeeduino board ) with a short piece of test code and hadn't had any problems at all.

The problems occur with or without the stepper motor system attached. As well as the symptoms already mention in my original post, the board also resets itself sometimes when it is in the start up splash() function which simply displays a little animation. It's been a while since I did any coding maybe I've done something silly and I've just missed it... or could the board be at fault..? The rotary encoder is fine, I've used another one and I get the same results. I've checked my wiring on the protoboard, but I'm going to check again in case I've missed a short somewhere....

Incidentally, I intend to drive the stepper motor using direct port manipulation rather than the slower digitalWrite() functions I am using at the moment, but first I want to get things working properly... :wink:

Thanks again... :slight_smile:

That looks like a great project.

I can't see anything in the code to cause concern. Given that the problem sometimes occurs in setup(), you could disable parts of setup() and see whether any of that logic is required in order to provoke the problem. For example, you attach some interrupt handlers pretty early on and your handlers enable the Timer1 library interrupts, so there could be quite a bit going on outside of your immediate control. Ultimately, if you simplify the sketch down to void setup(){} void loop(){} and it still crashes, you've shown pretty conclusively that it's not a software issue!

Hi,
I think I finally found out what the problem was... well, at least I corrected a problem and things seem to be ok. I scoured the board for any faults, shorts, etc, and eventually found a teensy tiny short between the analogue pins 4 and 5. Originally these were connected on the protoboard and I thought I had removed the connection but it was still there, albeit barely. This time I ensured that the connection was broken and hey presto no more resetting..! Not sure why this would reset the board but it seems to have done the trick..! :smiley:

Thanks for your help!