MENWIZ slowing down stepper motor & accelstepper library?

I’ve hit a new hurdle in my most recent project. For several days now, I’ve been playing with MENWIZ to create a menu on a 20x4 LCD. This is being used to change settings (intervals between motion, # of revolutions per interval, etc…) for a stepper motor. I am using the accelstepper library for controlling the stepper motor because I want to use acceleration, and I don’t want the system to be blocked while the stepper is moving, which the accelstepper library provides for.

The issue I’ve happened upon is that the draw() function, which is part of MENWIZ, and is called in ever iteration of loop(), seems to be interrupting the stepper motor’s motion. When I comment out the “menu.draw()” line in my sketch (shown below), the motor moves exactly as I expect using the accelstepper library, completing it’s 4000 steps in about 20 seconds.

If I uncomment this line, meaning that it runs menu.draw() in loop, the motion of the stepper stutters, and takes several minutes to complete the 4000 steps. It seems like it moves a couple of steps, then stop while (I’m guessing here…) the menu gets re-drawn, then a few more steps, and repeat. I’ve even created tests where draw() is called every 20th iteration through loop() and the staggering changes to suit this new condition.

So, is there something I could be doing better using the tools I’m currently trying to use? Accelstepper is a must for me, but I’m really hoping I won’t have to rebuild my menus using some other character LCD library…

I’m using IDE 1.0.6, in case it matters. Below is an abstract from my sketch. It’s been edited down quite a lot to remove unrelated lines. I have verified that it demonstrates the problem. Thank you in advance for taking a peak!

#include <Wire.h>
//INSERT ALL THE FOLLOWING 5 INCLUDES AFTER INCLUDING WIRE LIB 
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <buttons.h>
#include <MENWIZ.h>
#include <EEPROM.h>    //to be included only if defined EEPROM_SUPPORT
#include <AccelStepper.h>
#include <TimeAlarms.h>
#include <Time.h>

//////////////////////////////////////////////////////////
//                      CONSTANTS                       //
//////////////////////////////////////////////////////////
const int  ESCAPE_BUTTON_PIN  =    8;
const int  CONFIRM_BUTTON_PIN =    9;
const int  UP_BUTTON_PIN      =   10;
const int  DOWN_BUTTON_PIN    =   11;
const long REV                = 1600;  //amount of steps in 1 revolution of motor
const long RPM                =    8;  //Speed at which the motor will spin

//////////////////////////////////////////////////////////
//                  GLOBAL VARIABLES                    //
//////////////////////////////////////////////////////////
//WATCH01
boolean w1ACTIVE = 1; //Is this slot turned on or off?
int i = 1;            //for test

//////////////////////////////////////////////////////////
//                    OTHER STUFF                       //
//////////////////////////////////////////////////////////
menwiz menu;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity
AccelStepper w1STEPPER(1, 22, 23);  //1 pin=driver, 22=step pin, 23=direction pin

void setup()
{
  //SET UP ACCELSTEPPERS
  w1STEPPER.setMaxSpeed(((REV*RPM)/60.0));
  w1STEPPER.setAcceleration(200.0);
  
  //START MENU STUFF HERE
  _menu *r,*s1,*s2,*s3;
  _var *v; 
  int  mem;
  
  //INIZIALIZE THE MENU OBJECT (20 COLUMS X 4 ROWS)
  menu.begin(&lcd,20,4);
  
  //CREATE THE MENU TREE
  r=menu.addMenu(MW_ROOT,NULL,F("MAIN MENU"));       //create a root menu at first (required)
    s1=menu.addMenu(MW_SUBMENU,r,F("SUBMENU1"));     //add a child (submenu) node to the root menu
      s2=menu.addMenu(MW_VAR,s1,F("TEST BOOLEAN"));  //add a terminal node (that is "variable"); 
        s2->addVar(MW_BOOLEAN,&w1ACTIVE);            //create a variable of type "boolean" 

  //DECLARE NAVIGATION BUTTONS (REQUIRED)
  menu.navButtons(UP_BUTTON_PIN,DOWN_BUTTON_PIN,ESCAPE_BUTTON_PIN,CONFIRM_BUTTON_PIN);
}

void loop()
{
  menu.draw();  //THIS IS SLOWING DOWN THE STEPPER!!! WHY???
  
  if (i == 1)
  {
    MOVE_MOTOR();
    i = 0;
  }
  
  w1STEPPER.run();
}

void MOVE_MOTOR()
{
  w1STEPPER.move(4000);
}

Is suspect that the menu.draw() might be working or disabling the interrupt. causing the slow down. You would have to look into the library code to find out if that is causing it.

@edit: Just took a quick look at the library of MENWIZ. It does not seem to use any interrupts. However the time needed to process the library could be to long so the stepper would be missing pulses to process. As this is nog more than a menu, you could slow down the response to the menu by using a timer to execute the menu program once every 500mS for example:

global vars etc

#define SAMPLE_MENU_TIME 500       // check once every 500 msec
unsigned long menutTimer;          // timer for sampling the menu

in the setup

menuTimer = millis();

in the loop

//
// check if we have to sample the menu
//
unsigned long currentTime = millis();
if ((currentTime - menuTimer) > SAMPLE_MENU_TIME){
  //
  // yes so call the menu 
  // 
  menu.draw();
  //
  // and set the timer for the next time
  //
  menuTimer = currentTime;
}

Nico, thanks for taking a look. I've tried your suggestions, but unfortunately it doesn't seem to alleviate the issue very effectively.

First, the motor does move in a better(?) way, but not the way it should. Now it pauses every 500ms instead of every loop(). This results in a bit of a jerky motion, which I'd like to avoid. The motor does complete its 4000 steps in a more respectable time, which I suppose is better.

Second, and this is the bigger problem, is that MENWIZ is handling the detection and processing for the navigation buttons tied to the menu. Due to the pauses now being introduced between calls of draw(), the system misses navigational button pushes.

I think it's looking more and more like I'll need to utilize a different menu library. I'm still very open to opinions on getting this to work with the tools I'm currently using. I'm also open to suggestions for different menu libraries that can achieve a similar look to MENWIZ, but with a less processing overhead so that the motor movement will remain smooth. Thanks again Nico, and to anyone else who takes a look.

The menu drawing is slow and reducing the maxium frequency that run() is called on the stepper library.

An interrupt-driven stepper library would be a way to improve matters - offhand can't recall if there's a good one. (I should know that really, sorry).

Just in case anyone else is curious about how this proceeds...

I've ordered an Arduino Due to see if its (much) faster speed will mitigate the issue I'm dealing with. It's a bit of a shot in the dark, but I won't be upset about having another controller around, even if it doesn't fix the issue.

If that doesn't work well enough for me, I'll start investigating how I can work with interrupts as a means to satisfy my needs. I have no experience with this, so i'll have to do some reading up.

I'll update this thread if/when I get anywhere.

Of course you could try not using MENWIZ

...R

Oh sure, I could do that... I'm trying to avoid it because I already spent a bunch of time figuring out how to set up and intergrate MENWIZ into my project. I have everything working nicely, except for the issue I brought up in this thread. I really don't want to do that all over again with a different menu library. I'm not a programmer, so every new thing I have to figure out and learn takes me quite a while.

It may turn out that replacing MENWIZ is the way this gets fixed, but I'm willing to try a few other things first. :)

RyanW:
It may turn out that replacing MENWIZ is the way this gets fixed, but I’m willing to try a few other things first. :slight_smile:

I understand where you are coming from.

This is the main reason why I try to do things without libraries if I can. I have found (and not just on Arduinos) that it is easy to spend time trying to figure out problems in or caused by a library that would be more usefully spent on my own project,

The Arduino system is especially problematic because it is so easy for conflicts to arise with the very limited Arduino resources.

…R

I seem to have figured something out. :slight_smile:

First, the Due was a failure for me. Not the board itself, which is likely fine, and a great tool for someone who knows what they are doing, but not for me.

The Due required me to upgrade to a newer version of the Arduino IDE, and when I did that I started getting all kinds of errors with the MENWIZ library during compile. I was careful to make sure I had all of the proper libraries, from the previous installation, so I can only assume there is some incompatibility.

However, i started looking into the use of interrupts and came across the TimerOne library, which provides an easy way to introduce internal timer based interrupts. I added this to my sketch, and use it to run the stepper.run() call, which moves the stepper despite what’s doing on in the rest of the code. This means that the LCD/MENWIZ parts don’t slow down the stepper.

As I’ve said all along, there is surely a better way to do all of this, but this is working pretty well for me so far. I played around with the timing of the interrupt and settled on 1000 microseconds, which is fast enough for the speed at which I’m running my stepper, and does not seem to interfere with button pushes which control the menu.

Below is the example code for anyone interested.

#include <TimerOne.h>
#include <Wire.h>
//INSERT ALL THE FOLLOWING 5 INCLUDES AFTER INCLUDING WIRE LIB 
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <buttons.h>
#include <MENWIZ.h>
#include <EEPROM.h>    //to be included only if defined EEPROM_SUPPORT
#include <AccelStepper.h>
#include <TimeAlarms.h>
#include <Time.h>

//////////////////////////////////////////////////////////
//                      CONSTANTS                       //
//////////////////////////////////////////////////////////
const int  ESCAPE_BUTTON_PIN  =    8;
const int  CONFIRM_BUTTON_PIN =    9;
const int  UP_BUTTON_PIN      =   10;
const int  DOWN_BUTTON_PIN    =   11;
const long REV                = 1600;  //amount of steps in 1 revolution of motor
const long RPM                =    8;  //Speed at which the motor will spin

//////////////////////////////////////////////////////////
//                  GLOBAL VARIABLES                    //
//////////////////////////////////////////////////////////
//WATCH01
boolean w1ACTIVE = 1; //Is this slot turned on or off?
int i = 1;            //for test

//////////////////////////////////////////////////////////
//                    OTHER STUFF                       //
//////////////////////////////////////////////////////////
menwiz menu;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity
AccelStepper w1STEPPER(1, 22, 23);  //1 pin=driver, 22=step pin, 23=direction pin

void setup()
{
  //SET UP ACCELSTEPPERS
  w1STEPPER.setMaxSpeed(((REV*RPM)/60.0));
  w1STEPPER.setAcceleration(200.0);
  
  //START MENU STUFF HERE
  _menu *r,*s1,*s2,*s3;
  _var *v; 
  int  mem;
  
  //INIZIALIZE THE MENU OBJECT (20 COLUMS X 4 ROWS)
  menu.begin(&lcd,20,4);
  
  //CREATE THE MENU TREE
  r=menu.addMenu(MW_ROOT,NULL,F("MAIN MENU"));       //create a root menu at first (required)
    s1=menu.addMenu(MW_SUBMENU,r,F("SUBMENU"));     //add a child (submenu) node to the root menu
      s2=menu.addMenu(MW_VAR,s1,F("TEST BOOLEAN"));  //add a terminal node (that is "variable"); 
        s2->addVar(MW_BOOLEAN,&w1ACTIVE);            //create a variable of type "boolean" 

  //DECLARE NAVIGATION BUTTONS (REQUIRED)
  menu.navButtons(UP_BUTTON_PIN,DOWN_BUTTON_PIN,ESCAPE_BUTTON_PIN,CONFIRM_BUTTON_PIN);
  
  Timer1.initialize(1000);
  Timer1.attachInterrupt(RUNSTEPPER);
}

void loop()
{
  menu.draw();  //THIS IS SLOWING DOWN THE STEPPER!!! WHY???
  
  if (i == 1)
  {
    MOVE_MOTOR();
    i = 0;
  }
}

void MOVE_MOTOR()
{
  w1STEPPER.move(4000);
}

void RUNSTEPPER()
{
  if (w1STEPPER.distanceToGo() != 0)
  {
    w1STEPPER.run();
  }
}

Ryan,
Thank you very much, I have the same problem … I will try your solution tomorrow

Hi Ryan,

It has been quite a while since you were here but hopefully you still attend the forum and/or get notified of posts in your old threads :) I recently came across your fascinating YouTube video of the winder project (yes, woodwork is so cool!) and am currently building up my Arduino competence trying to replicate your achievements. Have not come too far yet, I am afraid )

If you see this and have 5 minutes, could you briefly cover your winder's power connetion arrangement please? I'm especially interested in the following: - What wall adapter do you use (in terms of voltage/ max. current) and where is it connected to? - What voltage and where from do you supply to the stepper motor driver board?- - Does the motor in the moment draw its maximum specced current (would be 800mA at 10V) with both coils? - What is the total max current the project consumes? - Is the power for display+driver (LCD backpack) supplied from AtMega board 5v pin? - Do you use any other electronic components (like transistors) besides pull-up or pull-down resistors for power management anywhere in the project?

Apologies for off-topic and huge thanks for all the comments and layout that you have provided on GitHub.

Many thanks!