[SOLVED] help with stepper and timer

Hello everyone

I am trying to get a pice of code to work but i am unable to and i ask for your help if you can... :wink:

The Project

I have a pice of code the runs as:

  • it's a countdown timer that when started, turns a relay on and when it get's to "0" e stops and turns off the relay.

-what i wanted is to is to add a stepper to the mix, so when the countdown gets to "0" all stops.

the realety ... when i add the stepper, the cowntdowd stats to fail in so cases, the stepper keeps starting and stoping, the relay does not turn off and ... nothing works...

I am using a board from DeeksRobot based on the L293D chip to control the stepper

Can anyone inlight me in what i am doing wrong...

Thank you

#include <Wire.h>
#include <Adafruit_SH1106.h>
#include <Adafruit_GFX.h>
#include <Stepper.h>

#define OLED_ADDR       0x3C
// 10000ul =   10 sec
// 30250ul =   30 sec
// 60500ul =   1 min
// 302500ul =  5 min
// 605000ul = 10 min
// 907500ul = 15 min
#define COUNTDOWN_TIME  10000ul // Set timer

#define pinRele 7        //Set relay Pin  
#define nivelRele HIGH   //Relay logic
// Define number of steps per rotation:
const int stepsPerRevolution = 2048;
// Create stepper object called 'myStepper', note the pin order:
Stepper myStepper = Stepper(stepsPerRevolution, 8, 9, 10, 11);


char
    szString[20];
byte
    mins, secs;
       
unsigned long
    timeTemp,
    timeNow,
    timeStart,
    timeElapsed,
    timeLeft;   

#define OLED_RESET -1
Adafruit_SH1106 display(OLED_RESET);
// difine buzzer
const int buzzer = 4; //buzzer to arduino pin 9

void setup()
{
    // Set the speed to 1 or 2 for very slow speed:
  // Set the speed to 15 for very high speed:
  myStepper.setSpeed(2);
    // RELAY SETTINGS 
     pinMode(pinRele, OUTPUT);
     digitalWrite(pinRele, !nivelRele);
    // initialize and clear display
    display.begin(SH1106_SWITCHCAPVCC, OLED_ADDR);
    display.clearDisplay();
    display.setTextSize(3);
    display.setTextColor(WHITE);

    Serial.begin(9600);
    timeStart = millis();
    mins = 1;
    secs = 1;
    pinMode(buzzer, OUTPUT); // Set buzzer - pin 4 as an output
}//setup

void DoCountdown()
{
    static unsigned long
        lastTimeNow = 0;
    static byte
        lastsecs = 1;
       
    timeNow = millis();
    timeElapsed = timeNow - timeStart;
   
    if( mins == 0 && secs == 0 )
        return;
       
    timeLeft = COUNTDOWN_TIME - timeElapsed;

    mins = (byte)(timeLeft / 60000ul);
    timeTemp = timeLeft - (mins * 60000);
    secs = (byte)(timeTemp / 1000ul);
    timeTemp = timeTemp - (secs * 1000ul);

    if( mins == 0 && secs == 0 )
    {
        display.clearDisplay();
        sprintf( szString, "DONE" );
        Serial.println( szString );
        display.setCursor( 25, 20 );
        display.print( szString );
        display.display();
        time_ended();
        return;
         
    }//if
    else if( secs != lastsecs )
    {
        lastsecs = secs;
        sprintf( szString, "%02d:%02d", mins, secs );
        Serial.println( szString );
        
        display.setCursor( 20, 20 );
        display.clearDisplay();
        display.print( szString );
        display.display();
   
    }//if
   
}
void relay_action(){
  
  if ( mins == 0 && secs == 0 ) { 
    
      digitalWrite(pinRele, nivelRele);
      
   } else {
      digitalWrite(pinRele, !nivelRele);
   }
  
  }
void stepper_motor() {
  // Step one revolution in one direction:
   myStepper.step(stepsPerRevolution);

  
  
}
void time_ended() {
tone(buzzer,5000); // Send 1KHz sound signal...
  delay(1000);        // ...for 1 sec
  noTone(buzzer);     // Stop sound...
  delay(1000);        // ...for 1sec                      // wait for a second
  tone(buzzer, 5000);     // Stop sound...
  delay(1000);        // ...for 1sec                      // wait for a second
  noTone(buzzer);
  delay(1000);        // ...for 1sec                      // wait for a second
  tone(buzzer, 5000);     // Stop sound...
  delay(1000);        // ...for 1sec                      // wait for a second
  noTone(buzzer);
}
void loop()//DoCountdown
{
    DoCountdown();
    relay_action();
    stepper_motor();
    return;
           
}//loop

If you want other things to happen while the stepper motor is moving then you must use the AccelStepper library and its non-blocking run() or runSpeed() functions. The standard Stepper library blocks the Arduino until it completes its move.

Conversely, if you want the stepper motor to run while other things are happening you will ALSO need to take all the delay()s out of your program. The functions delay() and delayMicroseconds() block the Arduino until they complete.
Have a look at how millis() is used to manage timing without blocking in Several Things at a Time.

And see Using millis() for timing. A beginners guide if you need more explanation.

...R

thank you for the hint. i will take a look.

regards

M8 i have tryed the exemple ConstantSpeed.pde in the lib and it works fine.

I have added it to my sketch and it works strangely.

Code starts and for each sec the stepper stop's and starts (explme: between end of 3 sec and start of 4 sec ).

The code ends, the relay turns off but the stepper keeps going.

what am i doing wrong :frowning:

#include <Wire.h>
#include <Adafruit_SH1106.h>
#include <Adafruit_GFX.h>
#include <AccelStepper.h>

#define OLED_ADDR       0x3C
// 10000ul =   10 sec
// 30250ul =   30 sec
// 60500ul =   1 min
// 302500ul =  5 min
// 605000ul = 10 min
// 907500ul = 15 min
#define COUNTDOWN_TIME  10000ul // Set timer

#define pinRele 7        //Set relay Pin  
#define nivelRele HIGH   //Relay logic



AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5



char
    szString[20];
byte
    mins, secs;
       
unsigned long
    timeTemp,
    timeNow,
    timeStart,
    timeElapsed,
    timeLeft;   

#define OLED_RESET -1
Adafruit_SH1106 display(OLED_RESET);
// difine buzzer
const int buzzer = 8; //buzzer to arduino pin 9

void setup()
{
    stepper.setMaxSpeed(1000);
    stepper.setSpeed(100);  
  
    // RELAY SETTINGS 
     pinMode(pinRele, OUTPUT);
     digitalWrite(pinRele, !nivelRele);
    // initialize and clear display
    display.begin(SH1106_SWITCHCAPVCC, OLED_ADDR);
    display.clearDisplay();
    display.setTextSize(3);
    display.setTextColor(WHITE);

    Serial.begin(9600);
    timeStart = millis();
    mins = 1;
    secs = 1;
}//setup

void DoCountdown()
{
    static unsigned long
        lastTimeNow = 0;
    static byte
        lastsecs = 1;
       
    timeNow = millis();
    timeElapsed = timeNow - timeStart;
   
    if( mins == 0 && secs == 0 )
        return;
       
    timeLeft = COUNTDOWN_TIME - timeElapsed;

    mins = (byte)(timeLeft / 60000ul);
    timeTemp = timeLeft - (mins * 60000);
    secs = (byte)(timeTemp / 1000ul);
    timeTemp = timeTemp - (secs * 1000ul);

    if( mins == 0 && secs == 0 )
    {
        display.clearDisplay();
        sprintf( szString, "DONE" );
        Serial.println( szString );
        display.setCursor( 25, 20 );
        display.print( szString );
        display.display();
        //time_ended();
        
         
    }//if
    else if( secs != lastsecs )
    {
        lastsecs = secs;
        sprintf( szString, "%02d:%02d", mins, secs );
        Serial.println( szString );
        
        display.setCursor( 20, 20 );
        display.clearDisplay();
        display.print( szString );
        display.display();
   
    }//if
   
}
void relay_action(){
  
  if ( mins == 0 && secs == 0 ) { 
    
      digitalWrite(pinRele, nivelRele);
      
   } else {
      digitalWrite(pinRele, !nivelRele);
   }
  
  }
void stepper_motor() {

            stepper.runSpeed();
 
}
void time_ended() {

}
void loop()//DoCountdown
{
    DoCountdown();
    relay_action();
    stepper_motor();
    
           
}//loop

Original ConstantSpeed.pde

// ConstantSpeed.pde
// -*- mode: C++ -*-
//
// Shows how to run AccelStepper in the simplest,
// fixed speed mode with no accelerations
/// \author  Mike McCauley (mikem@airspayce.com)
// Copyright (C) 2009 Mike McCauley
// $Id: ConstantSpeed.pde,v 1.1 2011/01/05 01:51:01 mikem Exp mikem $

#include <AccelStepper.h>

AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5

void setup()
{  
   stepper.setMaxSpeed(1000);
   stepper.setSpeed(50);	
}

void loop()
{  
   stepper.runSpeed();
}

Managed to solve the part of the Stoping when countdown finished by editing the code:

void stepper_motor() {

if ( mins == 0 && secs == 0 ) { 
    
       stepper.stop();
      
   } else {
       stepper.runSpeed();
   }

           
}

now the only problem is the starting/stoping every sec during countdown

xmodpt:
now the only problem is the starting/stoping every sec during countdown

You need to post the latest version of your program.

...R

here it is my friend

#include <Wire.h>
#include <Adafruit_SH1106.h>
#include <Adafruit_GFX.h>
#include <AccelStepper.h>

#define OLED_ADDR       0x3C
// 10000ul =   10 sec
// 30250ul =   30 sec
// 60500ul =   1 min
// 302500ul =  5 min
// 605000ul = 10 min
// 907500ul = 15 min
#define COUNTDOWN_TIME  30250ul // Set timer

#define pinRele 7        //Set relay Pin  
#define nivelRele HIGH   //Relay logic



AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5



char
    szString[20];
byte
    mins, secs;
       
unsigned long
    timeTemp,
    timeNow,
    timeStart,
    timeElapsed,
    timeLeft;   

#define OLED_RESET -1
Adafruit_SH1106 display(OLED_RESET);
// difine buzzer
const int buzzer = 8; //buzzer to arduino pin 9

void setup()
{
    stepper.setMaxSpeed(1000);
    stepper.setSpeed(500);  
  
    // RELAY SETTINGS 
     pinMode(pinRele, OUTPUT);
     digitalWrite(pinRele, !nivelRele);
    // initialize and clear display
    display.begin(SH1106_SWITCHCAPVCC, OLED_ADDR);
    display.clearDisplay();
    display.setTextSize(3);
    display.setTextColor(WHITE);

    Serial.begin(9600);
    timeStart = millis();
    mins = 1;
    secs = 1;
    pinMode(buzzer, OUTPUT); // Set buzzer - pin 4 as an output
}//setup

void DoCountdown()
{
    static unsigned long
        lastTimeNow = 0;
    static byte
        lastsecs = 1;
       
    timeNow = millis();
    timeElapsed = timeNow - timeStart;
   
    if( mins == 0 && secs == 0 )
        return;
       
    timeLeft = COUNTDOWN_TIME - timeElapsed;

    mins = (byte)(timeLeft / 60000ul);
    timeTemp = timeLeft - (mins * 60000);
    secs = (byte)(timeTemp / 1000ul);
    timeTemp = timeTemp - (secs * 1000ul);

    if( mins == 0 && secs == 0 )
    {
        display.clearDisplay();
        sprintf( szString, "DONE" );
        Serial.println( szString );
        display.setCursor( 25, 20 );
        display.print( szString );
        display.display();
        //time_ended();
        
         
    }//if
    else if( secs != lastsecs )
    {
        lastsecs = secs;
        sprintf( szString, "%02d:%02d", mins, secs );
        Serial.println( szString );
        
        display.setCursor( 20, 20 );
        display.clearDisplay();
        display.print( szString );
        display.display();
   
    }//if
   
}
void relay_action(){
  
  if ( mins == 0 && secs == 0 ) { 
    
      digitalWrite(pinRele, nivelRele);
      
   } else {
      digitalWrite(pinRele, !nivelRele);
   }
  
  }
void stepper_motor() {

if ( mins == 0 && secs == 0 ) { 
    
       stepper.stop();
      
   } else {
       stepper.runSpeed();
   }

           
}
void time_ended() {

}
void loop()//DoCountdown
{
    DoCountdown();
    relay_action();
    stepper_motor();
    
           
}//loop

any idea of what i am doing wrong ?

thankyou

I think all that display code is slow and is causing the problem. You don't need to update the display in every iteration of loop() - humans can't read that fast - once per second may be enough. And you probably do not need to update the complete display all in one go.

...R

thank you for your help but i can seem to find in the loop what you ment.

if i comment the "display.clearDisplay();" on my countdown void the text on screen overleps.

:frowning:

xmodpt:
if i comment the "display.clearDisplay();" on my countdown void the text on screen overleps.

A few thoughts ...

Don't worry about the info on the screen to start with - does limiting the calls to displayXXX improve the stepper performance?

How much (or how little) can you display without causing a problem for the motor?

You may need to interleave the display code with the steps - for example between step X and step X+1 call clearDisplay() only. Between step X+1 and step X+2 call one more display function until the full display is updated.

You may not need to clear the whole display - you might get the effect you need by printing some spaces on a line

I suggest you get the motor working properly and then gradually add code to get the display to function.

...R

I'l give it a try and get back to you.

thankyou

Hello m8

Got it !!! :slight_smile: :slight_smile: :slight_smile:

i had to many display.display(); functions and the only one i needed was out of place.

now one last question if you could help.

this code runs as soon as i turn on the arduno.

is the a simple way that i can add a menu with an encoder so select the motor speed ? for exmple 10rpm and 50 rpm.

I have some examples but they are for the u8g2 lib and i am using the adafruit SH1106 lib

Can you help or point in to the right derection ????

Kind regards

#define COUNTDOWN_TIME 30250ul

Dont know if this is the issue but ul should be capitals UL

up so far it isn't.... it work great :slight_smile:

xmodpt:
is the a simple way that i can add a menu with an encoder so select the motor speed ? for exmple 10rpm and 50 rpm.

I have some examples but they are for the u8g2 lib and i am using the adafruit SH1106 lib

I have no experience with those display devices

...R

:confused:
Thank you anyway. I also have an i2c 0.94" that works also with my code and uses the regular oled driver from adafruit SSD1306

Does it help?

xmodpt:
:confused:
Thank you anyway. I also have an i2c 0.94" that works also with my code and uses the regular oled driver from adafruit SSD1306

Does it help?

I should have said I have never used any display device with an Arduino.

...R

:slight_smile: :slight_smile: :slight_smile:

Ok m8 thank you anyway. Your help was appreciated.

Regards
Nuno