Hot Wheels track project, stepper motors giving me fits

Hello all

I have what I thought was a basic project that has ballooned beyond my very basic coding skills. I could use a second set of eyes and some pointers.

I have the code working for all but one task, the stepper motor. Here’s the complete timeline of what I would like to happen.

  1. Arduino Uno lies in wait until a button is pushed
  2. Arduino triggers relays to supply 12v to various things
  3. LED light countdown with MP3 Beeps. This works even though I used Delay, cant’ get Millis to work.
  4. After the LED function ends I need the Arduino to fire up the 12v motor on an L289n controller. This works.
  5. Now it monitors an input to count the laps (reed switch under track) and shuts off after 4 laps. this works.

Here’s the kicker. The 12v motor needs 1 second to spin up and gain momentum before a car can go through. So, I have a stepper motor on an arm that can push the car forward into the rollers. I can make the stepper move but not how I want. I also have a limiting switch on the stepper, but can’t make that work either.

Ideally, the 12v motor would spin up for a second, then the stepper would do one full 360 and end back where it started. This may or may not need that limiting switch as I only added it in case, but if it’s just doing a full 350 every time maybe not. I figured since I’m counting the laps already I could just say “if # of laps = zero then rotate the stepper, if more than 0 don’t” but it still constantly spins.

After I trigger 4 laps the code does a little cleanup and resets everything for the next time the button is pressed. I just cant figure out how to control the stepper and time it correctly with the firing off of the 12v motor. Any tips? Here’s my horrid code:






//=======

// -----LIBRARIES

#include <SoftwareSerial.h>
#include <Stepper.h>
// ----CONSTANTS (won't change)



const int RLED = 8;   //map pins
const int YLED1 = 10;
const int YLED2 = 7;
const int GLED = 9;
const int BUTTON = 4;
const int STEPSW = 13;
const int LANE1PWM = 5; //motors
const int LANE11 = A3;
const int LANE12 = A2;
const int LANE1SW = A4;
const int RELAY1 = 2;
const int RELAY2 = 3;
const int Lapinterval = 300; // number of millisecs between button readings 

// Number of steps per internal motor revolution 
const float STEPS_PER_REV = 32; 
//  Amount of Gear Reduction
const float GEAR_RED = 64;
// Number of steps per geared output rotation
const float STEPS_PER_OUT_REV = STEPS_PER_REV * GEAR_RED;
 // Number of Steps Require
unsigned long previousMillis = 0;

// Create Instance of Stepper Class
// Specify Pins used for motor coils
 
// Connected to ULN2003 Motor Driver In1, In2, In3, In4 
// Pins entered in sequence 1-3-2-4 for proper step sequencing

Stepper steppermotor(STEPS_PER_REV, 6, A0, A1, A5);

//------- VARIABLES (will change)

boolean LEDOFF = false;
boolean LANE1OFF = false;

int StepperSwitch = HIGH;
int MainButtonState = HIGH;
int LastMainButtonState = HIGH;

int buttonPushCounter1 = 0;   // counter for the number of reed 1 presses
int buttonState1 = HIGH;         // current state of reed 1
int lastButtonState1 = LOW;     // previous state of reed 1

int CurrentStep = 0; 
int PrevStep = 0;    
int Car1Running = 0;


int SPEED = 100;  // ADJUST SPEED HERE




//MP3 Stuff ======================================================================================

#define ARDUINO_RX 12  //should connect to TX of the Serial MP3 Player module 
#define ARDUINO_TX 11  //connect to RX of the module 
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);//init the serial protocol, tell to myserial which pins are TX and RX 
/////////////////////////////////////////////////////////////////////////////////// 
//all the commands needed in the datasheet(http://geekmatic.in.ua/pdf/Catalex_MP3_board.pdf) 
static int8_t Send_buf[8] = {0} ;//The MP3 player undestands orders in a 8 int string 
                                //0X7E FF 06 command 00 00 00 EF;(if command =01 next song order)  
#define NEXT_SONG 0X01  
#define PREV_SONG 0X02  
#define CMD_PLAY_W_INDEX 0X03 //DATA IS REQUIRED (number of song) 
#define VOLUME_UP_ONE 0X04 
#define VOLUME_DOWN_ONE 0X05 
#define CMD_SET_VOLUME 0X06//DATA IS REQUIRED (number of volume from 0 up to 30(0x1E)) 
#define SET_DAC 0X17 
#define CMD_PLAY_WITH_VOL 0X22 //data is needed  0x7E 06 22 00 xx yy EF;(xx volume)(yy number of song) 
#define CMD_SEL_DEV 0X09 //SELECT STORAGE DEVICE, DATA IS REQUIRED 
#define DEV_TF 0X02 //HELLO,IM THE DATA REQUIRED 
#define SLEEP_MODE_START 0X0A 
#define SLEEP_MODE_WAKEUP 0X0B 
#define CMD_RESET 0X0C//CHIP RESET 
#define CMD_PLAY 0X0D //RESUME PLAYBACK 
#define CMD_PAUSE 0X0E //PLAYBACK IS PAUSED 
#define CMD_PLAY_WITHFOLDER 0X0F//DATA IS NEEDED, 0x7E 06 0F 00 01 02 EF;(play the song with the directory \01\002xxxxxx.mp3 
#define STOP_PLAY 0X16 
#define PLAY_FOLDER 0X17// data is needed 0x7E 06 17 00 01 XX EF;(play the 01 folder)(value xx we dont care) 
#define SET_CYCLEPLAY 0X19//data is needed 00 start; 01 close 
#define SET_DAC 0X17//data is needed 00 start DAC OUTPUT;01 DAC no output 
//////////////////////////////////////////////////////////////////////////////////// 

void setup() { //==========================================================================================

 Serial.begin(9600);
 mySerial.begin(9600);//Start our Serial coms for our serial monitor! 
 Serial.println("Starting Routine");  // so we know what sketch is running

 pinMode(BUTTON, INPUT_PULLUP);   // set the button pin as input with a pullup resistor to ensure it defaults to HIGH 
     // set the Led pins as output:
 pinMode(STEPSW, INPUT_PULLUP);
 pinMode(GLED, OUTPUT);
 pinMode(RLED, OUTPUT);
 pinMode(YLED1, OUTPUT);
 pinMode(YLED2, OUTPUT);
     //set motors as outputs
 pinMode(LANE11, OUTPUT);
 pinMode(LANE12, OUTPUT);
 pinMode(LANE1PWM, OUTPUT);
 pinMode(LANE1SW, INPUT_PULLUP);
 
 pinMode (RELAY1, OUTPUT);
 pinMode (RELAY2, OUTPUT);
  
   //set motor controller pins
 digitalWrite(LANE11, HIGH);
 digitalWrite(LANE12, LOW);
 
 sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card
 
 delay(200);
}

//=============================================================================================
// MP3
void sendCommand(int8_t command, int16_t dat) 
{ 
delay(20); 
Send_buf[0] = 0x7e; //starting byte 
Send_buf[1] = 0xff; //version 
Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte 
Send_buf[3] = command; // 
Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback 
Send_buf[5] = (int8_t)(dat >> 8);//datah 
Send_buf[6] = (int8_t)(dat); //datal 
Send_buf[7] = 0xef; //ending byte 
for(uint8_t i=0; i<8; i++)// 
{ 
  mySerial.write(Send_buf[i]) ; 
} 
} 

//LEDS==============================================================================================

void updateLED_State() {
  
  int LEDDELAY = 1000;
  //(beep)
  digitalWrite(RLED, HIGH);
  sendCommand(CMD_PLAY_WITH_VOL, 0X1E03);  
  delay(LEDDELAY);                       // wait for a second 
  //(beep)
  
  digitalWrite(YLED1, HIGH);
   sendCommand(CMD_PLAY_WITH_VOL, 0X1E03);
  delay(LEDDELAY);                       // wait for a second
  //(beep)

  digitalWrite(YLED2, HIGH); 
  sendCommand(CMD_PLAY_WITH_VOL, 0X1E03);
  delay(LEDDELAY);                       // wait for a second
  //(beep)
  
  digitalWrite(GLED, HIGH);
  sendCommand(CMD_PLAY_WITH_VOL, 0X1E01);
  delay(500);                       // wait for a second
  //(beep)
  sendCommand(CMD_PLAY_WITH_VOL, 0X3202);
  digitalWrite(RLED, LOW);   // turn the LED off
  digitalWrite(YLED1, LOW);   // turn the LED off
  digitalWrite(YLED2, LOW);   // turn the LED off
  Serial.println("Initial LED done");
  LEDOFF = true;

}

//Ending MP3 Sounds ================================================================================

void ShutDown() {

       
       
       sendCommand(STOP_PLAY, 02);    //ending celebration
                 delay (200);
       sendCommand(CMD_PLAY_WITH_VOL, 0X1E04); 
                 delay (3000);
       sendCommand(STOP_PLAY, 04);
                 delay (200);
      
      
}

// Stepper Motor ==================================================================================


 void StepSwing() {    
   

   if (CurrentStep <= STEPS_PER_OUT_REV) {
   
   Serial.println("Stepping");
   steppermotor.setSpeed(800);
   steppermotor.step(-CurrentStep);
   CurrentStep = (CurrentStep + 1);
   
   }
      
   
}

                 



//LANE 1 =======================================================================================

void LANE1CONT() {  


  if (buttonPushCounter1 = 0) StepSwing(); 
  
  while(buttonPushCounter1 < 4) {
      buttonState1 = digitalRead(LANE1SW);  //counting laps
      // Delay a little bit to avoid bouncing
      delay(30);
      
      if (buttonState1 != lastButtonState1) {
      if (buttonState1 == LOW)  
      
      
       buttonPushCounter1++; }
        
      lastButtonState1 = buttonState1;  // save the current state as the last state, for next time through the loop
    
      //if (buttonPushCounter1 < 3) {
      analogWrite(LANE1PWM, SPEED);
      Serial.print("number of laps lane 1: ");
      Serial.println(buttonPushCounter1); 

        
                                }
    
       if (buttonPushCounter1 >= 4) {           //number of laps
        analogWrite(LANE1PWM, 0); 
        LANE1OFF = true;      // main loop needs this to trigger shutdown
     
       }

}
  



//=======
// MAIN LOOP

void loop() {
                
                Serial.println("Ready");
               
                MainButtonState = digitalRead(BUTTON);
                // Delay a little bit to avoid bouncing
                delay(30);
               // compare the buttonState to its previous state 
                    
               if (MainButtonState != LastMainButtonState) {   // if the state has changed, increment the counter    
               
                     if (MainButtonState == LOW) {
          
                     Serial.println("Button Pressed"); 
                     digitalWrite (RELAY1, LOW);
                     digitalWrite (RELAY2, LOW);
                     updateLED_State();
                  
                             
                   do {
                    //call functions that do work 
                      
                     Serial.println("inner loop");  
                                
                      LANE1CONT();
                      
                      
                    
                     }

                    while(LANE1OFF = false); 

                    if (LANE1OFF = true) ShutDown();
                                                  
                 
                 
                               }
                               
                               LastMainButtonState = MainButtonState;
               }

               Serial.println("Outter Main Loop"); 
               buttonPushCounter1 = 0;
               CurrentStep = 0;
               LEDOFF = false;   
               LANE1OFF = false;
               digitalWrite (RELAY1, HIGH);
               digitalWrite (RELAY2, HIGH);
               digitalWrite(GLED, LOW);

               
}    
      
               
    
               

//=====END

Oops! ‘=’ is for assignment, ‘==’ is for comparison.

Its even worse, even if you fix the = to ==, the loop cannot escape since
LANE1OFF is a boolean variable and nothing in the (empty) loop body
can change its value.

BTW uppercase is conventionally used for constants, not variables, so its
hard to read your code.

In general using a while loop will cause problems - the programming model in
microcontrollers is event-handling - loop() is the event loop and you simply need
to test for when to do various things in loop(). Thus you code up the logic
of a state-machine, and avoid using while or delay() - checkout the BlinkWithoutDelay
example as a starting point if this is new to you.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.