Problems with 74HC595 and 28byj-48

Hello, I have problem using stepper motor(28BYJ-48) thru 74hc595 (yes i use ULN2003AN in between). I tried writitng my own code, but i dont know whats wrong with it. Everytime i write command thru BT terminal to HC05 i receive confirming message (,,čekám" or ,,pootáčím") but it seems it has problems with halfRotation and fullRotation, which are meant to rotate the motor 180° and 360°, instead it does nothing and then after 20+ secs writes second confirming message (,,Hotovo, dočkal jsem" / ,,pootočeno").The pins used are Q1 to Q4, bc i dont want to have problems designing pcb later. I dont know what to do, i wrote code where it doesnt use 74HC595 and it works, the n i modified it to this and i dont know how to fix this.
The problem is it doesnt react

The code:

#include <SoftwareSerial.h>

#define dataPin 2 //ds na PB0
#define clockPin 4 // shcp na PB1
#define latchPin 3 //stcp na PB2

SoftwareSerial BTSerial(5, 6); // RX (2) | TX (3) pro HC-05

char command[16];  // Buffr pro příjem příkazu (zkráceno)

void latch() {
  digitalWrite(latchPin, LOW);  // Začneme s LATCH_PIN na LOW
  digitalWrite(latchPin, HIGH); // Poté přepneme LATCH_PIN na HIGH, čímž přeneseme hodnotu na výstupy
  digitalWrite(latchPin, LOW);  // Resetujeme LATCH_PIN zpět na LOW
}

int motPoz;

void stepMotor() {
  static int motSeq = 0;  // Uchovává aktuální sekvenci motoru
  motSeq++;
  if (motSeq > 7) {  // Zajistíme, že motSeq bude mezi 0 a 7
    motSeq = 0;
  }
  
  // Vytvoříme sekvenci podle motSeq
  switch (motSeq) {
    case 0:
      motPoz = 2;   // 0001
      break;
    case 1:
      motPoz = 6;   // 0011
      break;
    case 2:
      motPoz = 4;   // 0010
      break;
    case 3:
      motPoz = 12;  // 0110
      break;
    case 4:
      motPoz = 8;   // 0100
      break;
    case 5:
      motPoz = 24;  // 1100
      break;
    case 6:
      motPoz = 16;  // 1000
      break;
    case 7:
      motPoz = 18;  // 1001
      break;
    default:
      motPoz = 0;
      break;
  }

  // Posíláme hodnotu do shift registru
  shiftOut(dataPin, clockPin, MSBFIRST, motPoz); 
  latch();  // Zavoláme latch, abychom posunuli hodnoty na výstupy
  delay(10);  // Zpoždění mezi sekvencemi pro lepší pozorování
}

void fullRotation() {
  const int steps_per_rev = 4096;  // Počet kroků pro úplnou rotaci

  for (int i = 0; i < steps_per_rev; i++) {
    stepMotor();  // Voláme funkci pro posun motoru o krok
    delayMicroseconds(1500);  // Zpoždění pro kontrolu rychlosti otáčení
  }
}

void halfRotation() {
  const int steps_per_half = 2048;  // Počet kroků pro půl rotace

  for (int i = 0; i < steps_per_half; i++) {
    stepMotor();  // Voláme funkci pro posun motoru o krok
    delayMicroseconds(1500);  // Zpoždění pro kontrolu rychlosti otáčení
  }
}


void setup() {
  BTSerial.begin(9600);
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  shiftOut(dataPin, clockPin, MSBFIRST, B00000000);
  latch();
}

void loop() {
    if (BTSerial.available()) {
        BTSerial.readBytesUntil('\n', command, sizeof(command)); // Čtení příkazu z Bluetooth
        if (command[0] == 'c' && command[1] == 'k' && command[2] == 'j') {
            int delayTime = atoi(&command[4]); // Přečte číslo po prefixu "ckj_"
            BTSerial.println("čekám");
            if (delayTime > 0) {
                delay(delayTime);
                fullRotation();
                BTSerial.println("Hotovo, dočkal jsem");
            }
        } else if (command[0] == 'b' && command[1] == 'u' && command[2] == 'l' && command[3] == 'b') {
            BTSerial.println("pootáčím");
            delay(2000);
            halfRotation();  // nebo halfRotation, podle potřeby
            BTSerial.println("pootočeno");
    }
  }
}


Thanks

Neither do we, you forgot to explain what the problem is.

None of these decimal numbers match the binary numbers in the comments. Which are correct?

1 Like

decimal numbers represent the sum of the pins i. e. 2 = Q1 (0001) which has value 2 / 6 = Q1 and Q2 (2 + 4).

I'd bet its a wiring issue and that the bits aren't getting to the proper wires.

Schematic?

Pics?

Sorry, none of that made any sense to me.

2 in decimal is 0010 in binary
6 in decimal is 0110 in binary

1 Like

i use Q1 to Q4 bits, so i skp Q0, but yeah i forgot to write zeros at the end of each bit


You could use the 0b binary prefix and avoid the addition/ translation/potential source of typos:

 motPoz = 0b00110;   // 0011

Is this part correct?

Do you have a meter or something to test the voltage on the lines?

yep, the shift register doesnt output anything.

@kamenozrout

Try connecting pin 13 OE to GND. That should Output Enable

Thank you!, now it outputs but it does not want to spin, it just vibrates

@kamenozrout

This code is just wrong!

void latch() {
  digitalWrite(latchPin, LOW);  // Začneme s LATCH_PIN na LOW
  digitalWrite(latchPin, HIGH); // Poté přepneme LATCH_PIN na HIGH, čímž přeneseme hodnotu na výstupy
  digitalWrite(latchPin, LOW);  // Resetujeme LATCH_PIN zpět na LOW
}

Use a function like this to write to the register

void updateShiftRegister()
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, your variable);
  digitalWrite(latchPin, HIGH);
}

how do I implement it in the code? Do I replace latch(); with it? what do i write in ,,your variable" part?

Where you have this...

// Posíláme hodnotu do shift registru
  shiftOut(dataPin, clockPin, MSBFIRST, motPoz); 
  latch();  // Zavoláme latch, abychom posunuli hodnoty na výstupy
  delay(10);  // Zpoždění mezi sekvencemi pro lepší pozorování
}

Replace with...

updateShiftRegister();

The function would be

void updateShiftRegister()
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, motPoz);
  digitalWrite(latchPin, HIGH);
}

If the code needs to output pulses, then add some more lines to updateShiftRegister()

Like so

void updateShiftRegister()
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, motPoz);
  digitalWrite(latchPin, HIGH);
  //delay(10); //if required
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, 0);
  digitalWrite(latchPin, HIGH);

}

Hi, a new problem surfaced, the shift register doesnt output the right things, it seems to ouput random parts of the sequence, also it makes "stops" (zeros on all outputs) between every part.

#include <SoftwareSerial.h>

#define dataPin 2 //ds na PB0
#define clockPin 4 // shcp na PB1
#define latchPin 3 //stcp na PB2

SoftwareSerial BTSerial(5, 6); // RX (2) | TX (3) pro HC-05

char command[16];  // Buffr pro příjem příkazu (zkráceno)


int motPoz;

void updateShiftRegister()
{
  delay(10);
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, motPoz);
  digitalWrite(latchPin, HIGH);

}

void stepMotor() {
  static int motSeq = 0;  // Uchovává aktuální sekvenci motoru
  motSeq++;
  if (motSeq > 7) {  // Zajistíme, že motSeq bude mezi 0 a 7
    motSeq = 0;
  }
  
  // Vytvoříme sekvenci podle motSeq
    switch (motSeq) {
    case 0:
      motPoz = 2;   // 0001
      updateShiftRegister();
      break;
    case 1:
      motPoz = 6;   // 0011
      updateShiftRegister();
      break;
    case 2:
      motPoz = 4;   // 0010
      updateShiftRegister();
      break;
    case 3:
      motPoz = 12;  // 0110
      updateShiftRegister();
      break;
    case 4:
      motPoz = 8;   // 0100
      updateShiftRegister();
      break;
    case 5:
      motPoz = 24;  // 1100
      updateShiftRegister();
      break;
    case 6:
      motPoz = 16;  // 1000
      updateShiftRegister();
      break;
    case 7:
      motPoz = 18;  // 1001
      updateShiftRegister();
      break;
    default:
      break;
  }
updateShiftRegister();
}

void fullRotation() {
  const int steps_per_rev = 4096;  // Počet kroků pro úplnou rotaci

  for (int i = 0; i < steps_per_rev; i++) {
    stepMotor();  // Voláme funkci pro posun motoru o krok
    delayMicroseconds(2500);  // Zpoždění pro kontrolu rychlosti otáčení
  }
}

void halfRotation() {
  const int steps_per_half = 2048;  // Počet kroků pro půl rotace

  for (int i = 0; i < steps_per_half; i++) {
    stepMotor();  // Voláme funkci pro posun motoru o krok
    //delayMicroseconds(2500);  // Zpoždění pro kontrolu rychlosti otáčení
    delay(1000);
  }
}


void setup() {
  
  BTSerial.begin(9600);
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  shiftOut(dataPin, clockPin, MSBFIRST, 0);
  updateShiftRegister();
}

void loop() {
    if (BTSerial.available()) {
        BTSerial.readBytesUntil('\n', command, sizeof(command)); // Čtení příkazu z Bluetooth
        if (command[0] == 'c' && command[1] == 'k' && command[2] == 'j') {
            int delayTime = atoi(&command[4]); // Přečte číslo po prefixu "ckj_"
            BTSerial.println("čekám");
            if (delayTime > 0) {
                delay(delayTime);
                fullRotation();
                BTSerial.println("Hotovo, dočkal jsem");
            }
        } else if (command[0] == 'b' && command[1] == 'u' && command[2] == 'l' && command[3] == 'b') {
            BTSerial.println("pootáčím");
            delay(2000);
            halfRotation();  // nebo halfRotation, podle potřeby
            BTSerial.println("pootočeno");
    }
  }
}

Thanks for looking at it

Check your motPoz output is as expected (in Serial Monitor)

You are clocking out your data twice. You vairable motPoz is also of type int but should ready be a byte since that is what you are clocking out. It also doesn't need to be global.

#include <SoftwareSerial.h>

#define dataPin 2 //ds na PB0
#define clockPin 4 // shcp na PB1
#define latchPin 3 //stcp na PB2

SoftwareSerial BTSerial(5, 6); // RX (2) | TX (3) pro HC-05

char command[16];  // Buffr pro příjem příkazu (zkráceno)


//int motPoz;

void updateShiftRegister(byte motPoz)
{
  delay(10);
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, motPoz);
  digitalWrite(latchPin, HIGH);
}

void stepMotor() {
  static int motSeq = -1;  // Uchovává aktuální sekvenci motoru

  byte motPoz = 0;
  
  if (++motSeq > 7) motSeq = 0;

  // Vytvoříme sekvenci podle motSeq
  switch (motSeq) {
    case 0:
      motPoz = 2;   // 0001
      break;
    case 1:
      motPoz = 6;   // 0011
      break;
    case 2:
      motPoz = 4;   // 0010
      break;
    case 3:
      motPoz = 12;  // 0110
      break;
    case 4:
      motPoz = 8;   // 0100
      break;
    case 5:
      motPoz = 24;  // 1100
      break;
    case 6:
      motPoz = 16;  // 1000
      break;
    case 7:
      motPoz = 18;  // 1001
      break;
  }
  updateShiftRegister(motPoz);
}

void fullRotation() {
  const int steps_per_rev = 4096;  // Počet kroků pro úplnou rotaci

  for (int i = 0; i < steps_per_rev; i++) {
    stepMotor();  // Voláme funkci pro posun motoru o krok
    delayMicroseconds(2500);  // Zpoždění pro kontrolu rychlosti otáčení
  }
}

void halfRotation() {
  const int steps_per_half = 2048;  // Počet kroků pro půl rotace

  for (int i = 0; i < steps_per_half; i++) {
    stepMotor();  // Voláme funkci pro posun motoru o krok
    //delayMicroseconds(2500);  // Zpoždění pro kontrolu rychlosti otáčení
    delay(1000);
  }
}


void setup() {

  BTSerial.begin(9600);
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  //shiftOut(dataPin, clockPin, MSBFIRST, 0);
  updateShiftRegister(0);
}

void loop() {
  if (BTSerial.available()) {
    BTSerial.readBytesUntil('\n', command, sizeof(command)); // Čtení příkazu z Bluetooth
    if (command[0] == 'c' && command[1] == 'k' && command[2] == 'j') {
      int delayTime = atoi(&command[4]); // Přečte číslo po prefixu "ckj_"
      BTSerial.println("čekám");
      if (delayTime > 0) {
        delay(delayTime);
        fullRotation();
        BTSerial.println("Hotovo, dočkal jsem");
      }
    } else if (command[0] == 'b' && command[1] == 'u' && command[2] == 'l' && command[3] == 'b') {
      BTSerial.println("pootáčím");
      delay(2000);
      halfRotation();  // nebo halfRotation, podle potřeby
      BTSerial.println("pootočeno");
    }
  }
}

Thank you, its outputing the right sequence, but theres rather long break between last position and the first, also the motor has trouble rotating even when i adjusted timing between wswitching parts of the sequence

In void halfRotation()
you have...
delay(1000);
So once through stepMotor() you pause for a second each time round the for loop

Sorry @blh64 i copied from your post, oops