I am using an BLDC Motor driver for a project, I have managed to give the motor driver an input by potentiometer and I have somewhat managed to implement an switch to turn the motor on and of but I want to get an output in RPM. I think I have to connect the speed pin from the driver to an interuptpin on the arduino but I only get a return of RPM 0 so far. this is the datasheet with information about the motor driver ( China Brushless DC motor Driver BLDC-8015A Manufacturer and Supplier | ACT )
The code I have so far is: tab 1
extern double Amps;
void setup() {
Serial.begin(9600); // Debuggen via seriële monitor
setupMotor(); // Initialiseer motorbesturing
setupMotorSpeed(); // Initialiseer snelheidsmeting
setupCurrentSense(); // Initialiseer stroommeting
}
void loop() {
// Motorbesturing (met knoppen en potentiometer)
controlMotor();
// Bereken de werkelijke snelheid (RPM)
calculateRPM(6); // 6 pulsen per omwenteling (pas dit aan volgens je setup)
float currentRPM = getActualRPM();
// Voer stroommetingen uit
CurrentSense();
// Debug-output naar seriële monitor
Serial.print("RPM: ");
Serial.print(currentRPM);
Serial.print("\tAmps: ");
Serial.println(Amps, 3); // Stroom in Ampère met 3 decimalen
delay(200); // Update-interval
}
tab 2:
// CurrentSense.ino
// CurrentSense.ino
double Amps = 0;
// Pinnen
const int analogIn = A1; // ACS712 analoge pin
// Variabelen
const int mVperAmp = 100; // 100 voor 20A Module, 66 voor 30A Module
const int ACSoffset = 2500; // Offset in mV (kan variëren per module)
int RawValue = 0;
double Voltage = 0;
// Initialisatie van stroommeting
void setupCurrentSense() {
// Geen seriële initialisatie nodig, want deze gebeurt in de main
}
// Functie voor stroommeting
void CurrentSense() {
RawValue = analogRead(analogIn); // Lees de analoge waarde van ACS712
Voltage = (RawValue / 1024.0) * 5000; // Bereken spanning in mV
Amps = ((Voltage - ACSoffset) / mVperAmp); // Bereken stroom in Ampère
// Debuggen gebeurt in de hoofdcode (main)
}
tab 3
// Pindefinities
const int aviPin = 9; // PWM-uitgang voor snelheid
const int brakeSwitchPin = 6; // Rem-schakelaar
const int motorDirPin = 3; // Richting pin voor motor driver
const int motorBrakePin = 4; // Rem pin voor motor driver
const int potPin = A0; // Potentiometer-pin
// Variabelen voor motorstatus
bool motorBrake = false; // Remstatus van de motor
int motorSpeed = 0; // Snelheid van de motor (0-255)
// Debouncing timer voor de schakelaar
unsigned long lastDebounceTimeBrake = 0;
unsigned long debounceDelay = 500; // Debounce vertraging (ms)
bool lastSwitchStateBrake = HIGH; // Vorige toestand van de rem-schakelaar
void setupMotor() {
pinMode(aviPin, OUTPUT); // PWM pin voor snelheid
pinMode(brakeSwitchPin, INPUT_PULLUP); // Rem-schakelaar met interne pull-up
pinMode(motorDirPin, OUTPUT); // Richting pin voor motor driver
pinMode(motorBrakePin, OUTPUT); // Rem pin voor motor driver
pinMode(potPin, INPUT); // Potentiometer pin voor snelheid
// Zet de richting van de motor initieel op false (tegen de klok in)
digitalWrite(motorDirPin, LOW);
Serial.begin(9600); // Seriële communicatie voor debugging
}
void controlMotor() {
// Rem-schakelaar logica
bool currentSwitchStateBrake = digitalRead(brakeSwitchPin); // Lees de huidige schakelaarstatus
if (currentSwitchStateBrake == LOW && lastSwitchStateBrake == HIGH && (millis() - lastDebounceTimeBrake) > debounceDelay) {
motorBrake = !motorBrake; // Toggle de remstatus
lastDebounceTimeBrake = millis(); // Reset debouncing timer
Serial.print("Motor Brake: ");
Serial.println(motorBrake ? "Engaged" : "Released");
}
lastSwitchStateBrake = currentSwitchStateBrake; // Sla de vorige toestand op
// Lees de potmeterwaarde voor snelheid (0-1023)
int potValue = analogRead(potPin); // Leest de waarde van de potmeter (0-1023)
motorSpeed = map(potValue, 0, 1023, 0, 255); // Zet de waarde om naar een bereik van 0-255 voor PWM
// Motorbesturing: pas rem en snelheid aan
applyBrake(motorBrake); // Zet de remstatus
analogWrite(aviPin, motorSpeed); // Zet de snelheid van de motor via PWM
// Debugging informatie
Serial.print("Motor Speed: ");
Serial.println(motorSpeed);
}
// Functie om de remstatus van de motor in te stellen
void applyBrake(bool brake) {
if (brake) {
digitalWrite(motorBrakePin, HIGH); // Zet de rem aan
} else {
digitalWrite(motorBrakePin, LOW); // Zet de rem uit
}
}
And tab 4 as the important tab
// Pinnen
const int speedPin = 2; // SPEED-pin van motor driver
volatile unsigned long pulseCount = 0; // Pulsteller
unsigned long lastTime = 0;
float actualRPM = 0.0;
// Initialisatie
void setupMotorSpeed() {
pinMode(speedPin, INPUT); // Zet de SPEED-pin als invoer
attachInterrupt(digitalPinToInterrupt(speedPin), countPulse, RISING); // Koppel een interrupt aan de pin
Serial.println("Motor speed monitoring initialized."); // Debug bevestiging
}
// Pulsenteller: wordt aangeroepen via interrupt
void countPulse() {
pulseCount++; // Tel elke puls
Serial.println("Pulse detected!"); // Debug: bevestiging dat er een puls is ontvangen
}
// RPM berekenen
void calculateRPM(int pulsesPerRevolution) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - lastTime;
if (elapsedTime >= 1000) { // Berekening elke seconde
actualRPM = (pulseCount * 60.0) / pulsesPerRevolution; // Omrekening naar RPM
pulseCount = 0; // Reset de pulsteller voor de volgende berekening
lastTime = currentTime; // Reset de timer
Serial.print("Calculated RPM: "); // Debug: print de berekende RPM
Serial.println(actualRPM);
}
}
// Haal de werkelijke RPM-waarde op
float getActualRPM() {
return actualRPM;
}
You need to set the pin to input-Pullup() so a positive voltage is applied to the internal opt-isolator. The control will pull the pin down for the RPM signal. Be sure to do the correct math for the motor RPM.
volatile unsigned int pulseCount = 0;
unsigned long lastTime = 0;
void setup() {
pinMode(2, INPUT_PULLUP); // Verbind de SPEED-uitgang met pin 2 van de Arduino.
attachInterrupt(digitalPinToInterrupt(2), countPulse, RISING); // Tel pulsen.
Serial.begin(9600);
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - lastTime >= 1000) { // Bereken elke seconde
noInterrupts();
unsigned int count = pulseCount;
pulseCount = 0;
interrupts();
// Pas de waarden hieronder aan op basis van je motorconfiguratie
int polePairs = 3; // Aantal poolparen van de motor
int frequencyMultiplier = 6; // Interne frequentieverhoging
float rpm = (count * 60.0) / (polePairs * frequencyMultiplier);
Serial.print("RPM: ");
Serial.println(rpm);
lastTime = currentTime;
}
}
void countPulse() {
pulseCount++;
}
The problem now is that te signal seems to be very unstable, I get outputs from 0 RPM to 60 RPM whil I let the BLDC motor go at a constant speed, could this be a problem from using jump wires to connect the driver with the arduino? or something else?
I think that may be the problem because I also get unstable returns from the ampère meter (from the seccond code part in the first message)
I am not getting any pulses returned, using the following code:
volatile unsigned int pulseCount = 0;
unsigned long lastTime = 0;
void setup() {
pinMode(2, INPUT_PULLUP); // Verbind de SPEED-uitgang met pin 2 van de Arduino. Gebruik een externe pull-up weerstand.
attachInterrupt(digitalPinToInterrupt(2), countPulse, RISING); // Tel pulsen bij een stijgende flank.
Serial.begin(9600);
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - lastTime >= 1000) { // Bereken elke seconde
noInterrupts();
unsigned int count = pulseCount;
pulseCount = 0;
interrupts();
// Pas de waarden hieronder aan op basis van je motorconfiguratie
int polePairs = 4; // Aantal poolparen van de motor
int frequencyMultiplier = 6; // Interne frequentieverhoging
float rpm = (count * 60.0) / (polePairs * frequencyMultiplier);
Serial.print("RPM: ");
Serial.println(rpm);
Serial.print("pulseCount: ");
Serial.println(pulseCount);
lastTime = currentTime;
}
}
void countPulse() {
pulseCount++; // Verhoog de puls-teller bij elke puls
Serial.println("Pulse detected");
}
because i don't get Pulse detected returned I fell like i did something wrong with the interupt function
Yes, looks like and interrupt on a rising signal on a digital line that is held high most of the time is wrong. What happens if you change the interrupt trigger to change or to falling?
with both change and falling it returns Pulse detected but it still delivers pulse count 0 :edit when i change pulsecount to count in Serial.println it does return the pulse count and I notice that at higher speeds it can't count any pulses, ( mabey they are to close to eachother for the arduino to count those)
Yes, do not do any serial.print() inside interrupt code! It will just fill the output buffer and cause your program to stop until there is more space in the buffer.
Thank you all for answering, I will remove the pulse detected, I just added it to check if the interrupt was working. But the system only found 2 to 5 pulses in a second while the motor went a lot faster then 12.5 RPM. The arduino has trouble picking up the rest of the pulses to find the correct RPM, the rated speed of the motor is 3000 RPM, the arduino was unable to pick up any pulses at the higher frequenties. I will apply the changes in morning when I am at my internship. (Small company, no one knows how this works and this is my 2th time doing something a bit complex with the arduino)
Bad idea! Don't do this in the future. Your pulse count will give you the identical information and is not inhibited by slow output or limited buffer size or required interrupts being enabled.
A test of pulse count being greater than 0 will give the same information.
with the pulse detected print removed I pick up some more pulses, but the pulsecount still is unreliable and way to low. In the picture is visible how i conected everything (eventhough I am currently only using Digital pin 2) is there some hardware I need to obtain all incomming pulses, or is it still a software issue?
Yes, you need to find an oscilloscope of almost any type to monitor the lead you are using for interrupts. Beg, borrow or steal one, even for a day or so.
Your rats nest of wires concern me, but since you have too FEW interrupts, noise pickup does not seem to be causing this problem.
Please tell us how many interrupts per second should be happening?
at 24V 0,1 A I counted 116 rotations in a minute, 116/2,5= 46,4 pulses per second. At this speed the arduino mesures between 0 and 5 rpm so 2 pulses max, with the external resistor as pullup like ZX80 suggested I observed more movement between different speeds, so at 0,3A it generely mesured between 30 and 50 RPM (somethimes with a 25 or 55 but those were more rare). In the futere the current power supply will be swaped out for a permenent connection so I can't relay on that to get the needed information. Also the rats nest of wires will be fixed when i make the thing I have designed. I unfortionetly do not have acces to an oscilloscope for the forseable future
This somehow does it with the external resistor, I obtained all the pulses, still somewhat inconsistent but it does give about the right RPM, I need to change the math a little bit so when I add load to the motor it takes more Amps to reach the same RPM but because the higher Amps it sends more pulses
but thank you all so much for helping me get this far
volatile unsigned int pulseCount = 0;
unsigned long lastTime = 0;
void setup() {
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), countPulse, FALLING);
Serial.begin(9600);
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - lastTime >= 1000) { // Bereken elke seconde
noInterrupts();
unsigned int count = pulseCount;
pulseCount = 0;
interrupts();
// Pas de waarden hieronder aan op basis van je motorconfiguratie
int polePairs = 4; // Aantal poolparen van de motor
int frequencyMultiplier = 6; // Interne frequentieverhoging
float rpm = (count * 60.0) / (polePairs * frequencyMultiplier);
Serial.print("RPM: ");
Serial.println(rpm);
Serial.print("pulseCount: ");
Serial.println(count);
lastTime = currentTime;
}
}
void countPulse() {
pulseCount++; // Verhoog de puls-teller bij elke puls
}
I added the following piece of code at the end instead of the current void countPulse(){
unsigned long lastInterruptTime = 0;
void countPulse() {
unsigned long currentTime = millis();
if (currentTime - lastInterruptTime > 10) {
pulseCount++;
lastInterruptTime = currentTime;
}
}
this seems to work for getting a more stable signal for lower frequenties of speeds, but for higher speeds it didn't pick up anything anymore, would somting like if lower the x pulses do this code, else do the other piece of code in the interupt work?
This was for two motors or two polePairs, The motor I use has 8poles or 4 PolePairs, I think that is the difference between the example in the link and what I, also I never shared the link from the motor itself, link for motor I use the 57BLF03 version