Arduino with BLDC Motor (for brewing)

Hello,
I am currently working on a small stirrer with a BLDC motor for brewing beer. I mostly had the components in the basement, and it basically works quite well. Connected to the Arduino Uno is a DS18b20 sensor, which displays the temperature on the TM1637 display. However, I have two problems where you might be able to help me. Firstly, it doesn't work with a 9V power supply. It only works with the USB cable connected to the laptop. I'm using a 9V guitar pedal power supply with 120mA. Additionally, I want to analyze some data later in a Python program (temperature, speed, etc.). For this reason, I've also connected the SPEED output to the Arduino (and the GND). However, in the serial monitor, it doesn't show correct values for the speed. When the motor runs (at any speed), it sometimes alternates between displaying 0 RPM and 30 RPM. What could be the reason for this? Program codes and motor driver datasheet are attached.


#include <TM1637Display.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2 // Pin für den DS18B20-Sensor
#define CLK 3          // Pin CLK des TM1637-Displays
#define DIO 4          // Pin DIO des TM1637-Displays
#define SPEED_PIN 5    // Pin, an dem der SPEED-Ausgang des Treibers angeschlossen ist
#define MOTOR_POLE_PAIRS 2 // Anzahl der Motorpolpaare

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
TM1637Display display(CLK, DIO);

void setup() {
  Serial.begin(9600);
  sensors.begin();
  display.setBrightness(0x0a); // Helligkeit einstellen (0-0x0f)
  pinMode(SPEED_PIN, INPUT);    // Den Pin für die Drehzahl als Eingang konfigurieren
}

void loop() {
  // Temperatur aktualisieren
  sensors.requestTemperatures();
  float tempC = sensors.getTempCByIndex(0);

  // Drehzahl auslesen
  int pulseFrequency = digitalRead(SPEED_PIN);
  int motorSpeed = (pulseFrequency * 60) / MOTOR_POLE_PAIRS; // Drehzahl berechnen unter Berücksichtigung der Polpaare

  // Temperatur und Drehzahl im Terminal anzeigen
  if (tempC != DEVICE_DISCONNECTED_C) {
    Serial.print("Temperatur: ");
    Serial.print(tempC);
    Serial.println(" °C");

    Serial.print("Drehzahl: ");
    Serial.print(motorSpeed);
    Serial.println(" U/min");

    int temp = int(tempC);
    display.showNumberDec(temp);
  } else {
    Serial.println("Fehler beim Lesen der Temperatur");
    display.showNumberDec(8888);
  }

  delay(1000);
}



More Pictures…



Please post schematics showing the powering.
Using 9 volt You might need a 5 volt power supply for the other devices.

How much current (amps) does the motor require at full load?

You mean the power supply is rated to handle a maximum current of 120mA? If so, I'm going to say that's likely an issue. The Arduino needs 50mA alone, how much does the seven segment display require? Grove states theirs is typical 27/max 80mA and the temp sensor active current I could find is 1mA. Seems close for my liking, if I'm understanding the 9V supply correctly.

Thanks for the answers!
So maybe I should try an ordinary 9V 1A?

The motor is a 24v motor, but I can't remember what power it needs.
But why does it not deliver the correct speed via the speed output?

I can't say I know that. I can make a somewhat educated guess based of things I have done and had to correct, that's all I can offer.

This tells me it works, or at least worked, as you want and you indicate a pretty good place to start looking.
I have often found that when things stopped working for me, it was that the devices were being power starved, happens all the time with just battery powered stuff when the batteries die.
You say it alternates between 0 and 30RPM. I don't know what condition creates the 30 RPM but a resetting Arduino sure could create a 0. If you have a 9V 1A DC power adapter, I'd use that and see. Seems like the easiest thing to try first anyway. Can't hurt to try.

How should this work? The result will be 0 or 30, depending on the state of SPEED_IN

Okay can you help me correct that? I am unfortunately still very inexperienced

Would that be right?


#include <TM1637Display.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2 // Pin für den DS18B20-Sensor
#define CLK 3 // Pin CLK des TM1637-Displays
#define DIO 4 // Pin DIO des TM1637-Displays
#define SPEED_PIN 5 // Pin für den SPEED-Ausgang vom Treiber
#define ALARM_PIN 6 // Pin für den ALM-Ausgang vom Treiber
#define MOTOR_POLE_PAIRS 4 // Anzahl der Motorpolpaare
#define TIME_WINDOW 1000 // Zeitfenster in Millisekunden

volatile int pulseCount = 0; // Variable für die Anzahl der Pulsen

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
TM1637Display display(CLK, DIO);

void setup() {
  Serial.begin(9600);
  sensors.begin();
  display.setBrightness(0x0a); // Helligkeit einstellen (0-0x0f)
  pinMode(SPEED_PIN, INPUT_PULLUP);
  pinMode(ALARM_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(SPEED_PIN), countPulses, RISING);
}

void loop() {
  sensors.requestTemperatures(); // Temperatur aktualisieren
  float tempC = sensors.getTempCByIndex(0); // Temperatur in Celsius lesen
  if (tempC != DEVICE_DISCONNECTED_C) { // Überprüfen, ob ein gültiger Wert gelesen wurde
    // Temperatur im Terminal anzeigen
    Serial.print("Temperatur: ");
    Serial.print(tempC);
    Serial.println(" °C");

    // Temperatur auf dem TM1637-Display anzeigen
    int temp = int(tempC); // Temperatur auf ganze Zahl konvertieren
    display.showNumberDec(temp); // Temperatur ohne Dezimalstelle auf dem Display anzeigen
  } else {
    // Fehlerbehandlung, wenn kein gültiger Wert gelesen werden kann
    Serial.println("Fehler beim Lesen der Temperatur");
    display.showNumberDec(8888); // Anzeige auf "8888" setzen, wenn ein Fehler auftritt
  }

  // Warten bis das Zeitfenster abgelaufen ist
  delay(TIME_WINDOW);
  
  // Anzahl der Impulse im Zeitfenster auslesen
  int pulseCountSnapshot = pulseCount;
  pulseCount = 0; // Reset pulse count for the next window

  // Motordrehzahl basierend auf der Anzahl der Impulse und der Dauer des Zeitfensters berechnen
  float motorSpeed = (pulseCountSnapshot * 60.0) / MOTOR_POLE_PAIRS / (TIME_WINDOW / 1000.0); // Drehzahl in U/min

  // Anzeige der Motordrehzahl
  Serial.print("Drehzahl: ");
  Serial.print(motorSpeed);
  Serial.println(" U/min");
}

void countPulses() {
  pulseCount++; // Increment pulse count when a rising edge is detected
}

Should work, but delay(TIME_WINDOW); is blocking an will cause you problem sooner than later.

Can I solve this differently?

static long last=0;
long now=millis();
if (now-last>TIME_WINDOW) {
    last=now;
    // INSER_CODE_HERE
}

Thank you, I think I understand.
What do you think of this version?

#include <TM1637Display.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2 // Pin für den DS18B20-Sensor
#define CLK 3 // Pin CLK des TM1637-Displays
#define DIO 4 // Pin DIO des TM1637-Displays
#define SPEED_PIN 5 // Pin für den SPEED-Ausgang vom Treiber
#define ALARM_PIN 6 // Pin für den ALM-Ausgang vom Treiber
#define MOTOR_POLE_PAIRS 4 // Anzahl der Motorpolpaare
#define TIME_WINDOW 1000 // Zeitfenster in Millisekunden

volatile int pulseCount = 0; // Variable für die Anzahl der Pulsen

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
TM1637Display display(CLK, DIO);

void setup() {
  Serial.begin(9600);
  sensors.begin();
  display.setBrightness(0x0a); // Helligkeit einstellen (0-0x0f)
  pinMode(SPEED_PIN, INPUT_PULLUP);
  pinMode(ALARM_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(SPEED_PIN), countPulses, RISING);
}

void loop() {
  unsigned long startTime = millis(); // Zeitstempel vor dem Auslesen der Temperatur

  sensors.requestTemperatures(); // Temperatur aktualisieren
  float tempC = sensors.getTempCByIndex(0); // Temperatur in Celsius lesen
  if (tempC != DEVICE_DISCONNECTED_C) { // Überprüfen, ob ein gültiger Wert gelesen wurde
    // Temperatur im Terminal anzeigen
    Serial.print("Temperatur: ");
    Serial.print(tempC);
    Serial.println(" °C");

    // Temperatur auf dem TM1637-Display anzeigen
    int temp = int(tempC); // Temperatur auf ganze Zahl konvertieren
    display.showNumberDec(temp); // Temperatur ohne Dezimalstelle auf dem Display anzeigen
  } else {
    // Fehlerbehandlung, wenn kein gültiger Wert gelesen werden kann
    Serial.println("Fehler beim Lesen der Temperatur");
    display.showNumberDec(8888); // Anzeige auf "8888" setzen, wenn ein Fehler auftritt
  }

  unsigned long endTime = millis(); // Zeitstempel nach dem Auslesen der Temperatur
  unsigned long elapsedTime = endTime - startTime; // Zeit für das Auslesen der Temperatur in Millisekunden

  // Warten bis das Zeitfenster abgelaufen ist
  long remainingTime = max(TIME_WINDOW - elapsedTime, 0); // Sicherstellen, dass die verbleibende Zeit nicht negativ wird
  delay(remainingTime);
  
  // Anzahl der Impulse im Zeitfenster auslesen
  int pulseCountSnapshot = pulseCount;
  pulseCount = 0; // Reset pulse count for the next window

  // Motordrehzahl basierend auf der Anzahl der Impulse und der Dauer des Zeitfensters berechnen
  float motorSpeed = (pulseCountSnapshot * 60.0) / MOTOR_POLE_PAIRS / (TIME_WINDOW / 1000.0); // Drehzahl in U/min

  // Anzeige der Motordrehzahl
  Serial.print("Drehzahl: ");
  Serial.print(motorSpeed);
  Serial.println(" U/min");
}

void countPulses() {
  pulseCount++; // Increment pulse count when a rising edge is detected
}

Aehm .. no.

I don't see a wire for the motor driver's 5V logic supply.
Is it provided internally?

No, the motor driver is not connected to the 5V. Unfortunately, I don't read anything about this in the manual. Where should it be connected?

No need to. The inputs are optocouplers, as your excerpt from the manual shows in post #1

What is the purpose of the 2k resistor from 24V+ to speed input and Arduino pin 5?