Issue: while stepper spinning, LCD backlight flickering

Hi! I'm using 28byj-48 5V stepper with ULN2003 and 16x2 LCD. While stepper spinning not full speed, LCD backlight flickering to the step change. If I set stepper speed to full (1ms) I can't see flickering on LCD. Do I need to add something to breadboard? Power supply 5V 2A (YS12-0502000), Arduino powered by USB.

Power the LCD, resistor ladder, and the DHT22 from Arduino's 5volt pin,
and only the motor from that external 5volt supply.
Leo..

Are your connecting wires designed for high current - a lot of breadboard hook-up wire kits are no use
for high current, only for signals.

MarkT:
Are your connecting wires designed for high current - a lot of breadboard hook-up wire kits are no use
for high current, only for signals.

Forgot to mention that I hadn't this problem last week when I was using stepper.h library. Problem began when I changed stepper.h library to switch case (switch case more silent stepper). If I disconnect stepper from uln2003 flickering stops.

And the reason, my fine OP, for what my two colleges are suggesting is this:

A stepper motor, when it steps, is going to need a lot of current to get it going--basically to build the magnetic field that will exert the force that causes the step, AND there is all that inertia business to deal with. Thus, there needs to be VERY low resistance paths from the power source, to the stepper driver, and then from the driver to the stepper coils.

As pointed out, breadboards are notorious for high contact resistance, which can, indeed, produce the result you are seeing. I suggest you prototype the thing, using decent gauge wire from the power source, to the ULN2003, and from the ULN2003 to the stepper motor.

Also, power the LCD from the Arduino +5 output, not from the power source you're suing to drive the stepper motor. These need to be separate current paths. In fact, all Arduino interfaced circuitry should be powered by the Arduino +5 supply, including those pushbuttons. I'm assuming you're using an Analog input to essentially mux those buttons. In which case, because the Arduino ADC is using the Arduino's +5V as the reference for doing it's conversions, its important, for consistent conversion, that the buttons also use that supply.

Stipa:
Forgot to mention that I hadn't this problem last week when I was using stepper.h library. Problem began when I changed stepper.h library to switch case (switch case more silent stepper). If I disconnect stepper from uln2003 flickering stops.

Well, then...almost certainly, we need to see your code!

Code that drives stepper:

if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    
    if (OpenedState == LOW && temperature > SetTemp + 0.10) {
    state = 1;
    steps++;
      if (steps >=8)
        steps=0;
    }

    if (ClosedState == LOW && temperature < SetTemp - 0.10) {
     state = 1;
     steps--;
      if (steps <= 0)
        steps=8; 
    }

    
      switch(steps){ 
       case 0: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, HIGH); 
        break;  
       case 1: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, HIGH); 
        break;  
       case 2: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 3: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 4: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 5: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 6: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 7: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, HIGH); 
        break;  
       default: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;   
    } 
    if (state == 0) {
        steps = 8;
    } 
  }

Whole code if needed:

#include <dht_nonblocking.h>
#define DHT_SENSOR_TYPE DHT_TYPE_22

static const int DHT_SENSOR_PIN = 3;
DHT_nonblocking dht_sensor( DHT_SENSOR_PIN, DHT_SENSOR_TYPE );

#include "LiquidCrystal.h"
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

#include <AnalogMultiButton.h>
const int BUTTONS_PIN = A0;
const int BUTTONS_TOTAL = 5;
const int BUTTONS_VALUES[BUTTONS_TOTAL] = {0, 289, 452, 555, 627};
const int BUTTON_CLOSE = 0;
const int BUTTON_INCREASE = 1;
const int BUTTON_SET = 2;
const int BUTTON_DECREASE = 3;
const int BUTTON_OPEN = 4;

const int Opened = 12;
const int Closed = 13;

int OpenedState = 0 ;
int ClosedState = 0 ;
int Pin1 = 8; 
int Pin2 = 9; 
int Pin3 = 10; 
int Pin4 = 11; 
int steps = 0;
int interval = 25;
unsigned long previousMillis = 0;
float SetTemp = 23.50;
float temperature;
float humidity;

AnalogMultiButton buttons(BUTTONS_PIN, BUTTONS_TOTAL, BUTTONS_VALUES);

void setup()
{
  pinMode(Pin1, OUTPUT);  
  pinMode(Pin2, OUTPUT);  
  pinMode(Pin3, OUTPUT);  
  pinMode(Pin4, OUTPUT);  
  pinMode(Opened, INPUT_PULLUP);
  pinMode(Closed, INPUT_PULLUP);
  lcd.begin(16, 2); 
}
/*
 * Poll for a measurement, keeping the state machine alive.  Returns
 * true if a measurement is available.
 */
static bool measure_environment( float *temperature, float *humidity )
{
  static unsigned long measurement_timestamp = millis( );

  /* Measure once every four seconds. */
  if( millis( ) - measurement_timestamp > 4000ul )
  {
    if( dht_sensor.measure( temperature, humidity ) == true )
    {
      measurement_timestamp = millis( );
      return( true );
    }
  }

  return( false );
}

/*
 * Main program loop.
 */
void loop() {
  
  unsigned long currentMillis = millis();  
  
  OpenedState = digitalRead(Opened) ;
  ClosedState = digitalRead(Closed) ;
  buttons.update();
  int state = 0;

if (buttons.onPress(BUTTON_CLOSE))  {
      SetTemp = 40.00;
      lcd.clear();
      lcd.setCursor(5,0);
      lcd.print("Closing");
      interval = 1;
  }

  if (buttons.onPress(BUTTON_INCREASE)) {
      SetTemp = SetTemp + 0.10;
      lcd.clear();
      lcd.setCursor(6,0);
      lcd.print(SetTemp);
  }
  
  if (buttons.onPress(BUTTON_SET))  {
      SetTemp = 23.50;
      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print("Temp Set");
      lcd.setCursor(6,1);
      lcd.print(SetTemp);
      interval = 25;
  }
  
  if (buttons.onPress(BUTTON_DECREASE)) {
      SetTemp = SetTemp - 0.10;
      lcd.clear();
      lcd.setCursor(6,0);
      lcd.print(SetTemp);
  }
  
  if (buttons.onPress(BUTTON_OPEN)) {
      SetTemp = 10.00;
      lcd.clear();
      lcd.setCursor(5,0);
      lcd.print("Opening");
      interval = 1;
  }

if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    
    if (OpenedState == LOW && temperature > SetTemp + 0.10) {
    state = 1;
    steps++;
      if (steps >=8)
        steps=0;
    }

    if (ClosedState == LOW && temperature < SetTemp - 0.10) {
     state = 1;
     steps--;
      if (steps <= 0)
        steps=8; 
    }

    
      switch(steps){ 
       case 0: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, HIGH); 
        break;  
       case 1: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, HIGH); 
        break;  
       case 2: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 3: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 4: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 5: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 6: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 7: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, HIGH); 
        break;  
       default: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;   
    } 
    if (state == 0) {
        steps = 8;
    } 
  } 
  
  /* Measure temperature and humidity.  If the functions returns
     true, then a measurement is available. */
  if( measure_environment( &temperature, &humidity ) == true )
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T:");
    lcd.print(temperature);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("H:");
    lcd.print(humidity);
    lcd.print("%");
    lcd.setCursor(9, 0);
    lcd.print("S:");
    lcd.print(SetTemp);  

       if (OpenedState == LOW && temperature > SetTemp + 0.10) {
          lcd.setCursor(9,1);
          lcd.print("Opening");
       }
       else if (ClosedState == LOW && temperature < SetTemp - 0.10) {
          lcd.setCursor(9,1);
          lcd.print("Closing");
       }
       else {
       lcd.setCursor(9,1);
       lcd.print("Normal ");
       }
  }
  
  
}

It looks like you're "half stepping" in your code--which means half the time two stepper motor coils are turned on. When you were using the stepper.h library, was the stepper motor being half stepped? If not, then perhaps the flickering is due to the extra current needed to energize two coils at once. Which might mean:

  1. Your power supply can't handle the extra current [a hefty capacitor across the supply -- on the order of a 1000uF or more -- might supply current during these periods of extra demand].
  2. The wires aren't fat enough to handle the current surges [i.e. voltage dropped across the wires are causing the LCD to dim].
  3. if the LCD has a contrast control, or a fixed resistor is setting the contrast, if the voltage, there, is drawn from the same supply as the stepper motor, and especially if the power is being drawn NEAR the stepper motor, then the contrast-set voltage could be shifting.

Otherwise, I'm wondering, if the stepper.h library was working, then why use the case statement?

Actually, you have tricked yourself.

If the stepper is stepping slowly - and possibly using half steps - the flicker is slow enough to discern. At maximum speed, it is still flickering, but so fast you simply do not see it, just as you do not see flicker on multiplexed displays even though they necessarily are strobing.

As has been explained, the flicker is caused by your supply - and wiring together - being unable to maintain the demanded current.

Now the rule is, the 5 V terminal on the Arduino cannot be used to provide a significant current, but it can supply the resistor ladder, the switches using INPUT_PULLUP and the actual LCD (Pin 2) and you should do so to avoid interference.

The backlight probably is not critical, but it does make sense to power it from the external 5 V supply given that you fix the flicker. A 1 mF capacitor directly across the stepper driver may help a lot. The 47 Ohm resistor is not necessary if R8 or R9 on the LCD module is already "101" - 100 Ohms.

I note you have picked up on my correction to the contrast control setting and are using a simple, chosen by trial-and-error, resistor to ground.

ReverseEMF, I tried Full Step with switch case, and same flickering happens. Strange that if I use stepper.h lib it doesn't happen. The reason I went for Half Step is that stepper works with very low noise and I can't even hear it, so it doesn't disturb me while I try to sleep, which is nice. Full Step is a bit irritating from noise perspective.

Paul_B, yes resistors for LCD is chosen pretty much by trial and error :slight_smile: But I had to use them because backlight without resistor is just too bright at night, contrast on the other hand without resistor starts to show full character blocks a bit, so it's getting hard to read text from different angles.

Solved problem by converting project to 12V system. 12V 2.5A power supply, 12V 28byj-48 stepper motor. Powered Arduino and stepper from same power supply, LCD from Arduino 5V.
Now what is left is to get everything on PCB, print case housing and Window Actuator is done!

Thanks for help!

OK, so the problem was that either the 5 V supply - whatever it was - was not adequately regulated or you had poor connections causing voltage drop. If the problem was only the flicker, then you have simply avoided that by powering the LCD backlight separately from the stepper.

The concern is that the on-board regulator is only capable of powering the Arduino itself and a few other things whose requirements are a few milliamps each. The backlight is only drawing about 15 mA or so and the DHT22, trivial, so this will work for the present. If you wanted to power other things, you could be in trouble.

The resistor to dim the backlight is perfectly fine, my comment was in regard to whether you needed a resistor to limit the current as there is usually one already on the module. And the contrast resistor is perfect; there is a long-standing misunderstanding on just how you do that.