Hello all, hope you're doing well.
I got a brushless motor with 3 Hall sensors inside it. It is 3-phase motor and I want to write a code to calculate the speed in RPM of the motor. I know that using the hall sensors, the speed can be calculated, but I'm new and I don't know how to read the hole sensors and do the calculations. I appreciate any advice or help!
Thank you @Railroader,
I have tried with one wire and I noticed with spinning the motor with my hand that before reaching a full revolution, the pin outputs 0 and 1 multiple times.
I can relate to this image:
Any advices?
The 3 sensors simplify the implementation, in discrete circuits or in software. An ESC has to operate in 3 states: acceleration, deceleration and controlled run. For acceleration the phases should be switched as soon as possible, for deceleration as late as possible, and else synchronized with the set speed. A PLL algorithm may be sufficient for all that.
I don't know how many pulses.
Actually if I use the Hall B to read from it, will this code measure the correct RPM?
#include <SPI.h>
#include <Wire.h>
int tON=0;
int tOFF=0;
int Tperiod=0;
int freq=0;
int RPM=0;
void setup()
{
Serial.begin(9600);
}
void loop()
{
tON=pulseIn(2,HIGH);
tOFF=pulseIn(2,LOW);
Tperiod=tON + tOFF;
freq= 1000000.0/ Tperiod;
RPM=freq * 30;
if(digitalRead(2)==HIGH)
{
Serial.println(RPM);
}
tON=0;
tOFF=0;
Tperiod=0;
freq=0;
RPM=0;
}
The period Tperiod is the sum of the time when the sensor on and off. Then the frequency is calculated and then the rpm. I know there are mistakes since the numbers I'm getting I think are high. What do you think? I have seen this code on the internet and adjusted it a little bit.
freq will be in revs per second. Multiply by 60 for revs per minute.
Somebody knowing the interior of that motor can tell if there is only one cycle per rev, or if there are more cycles per rev. In that case add a divide by the number of pulse cycles per rev.
#include <SPI.h>
#include <Wire.h>
const int NUM_CYCLES_PER_REV = 1;
const int BAUDRATE = 115200;
const int PRINT_DELAY = 1000;
int tON = 0;
int tOFF = 0;
int Tperiod = 0;
int freq = 0;
int RPM = 0;
unsigned long previousMillis = 0; //inorder to keep track of previous time
void setup()
{
Serial.begin(BAUDRATE);
}
void loop()
{
tON = pulseIn(2, HIGH);
tOFF = pulseIn(2, LOW);
Tperiod = tON + tOFF;
freq = 1000000.0 / Tperiod;
RPM = freq * 60 / NUM_CYCLES_PER_REV;
//only print if the signal is high
if (digitalRead(2) == HIGH)
{
// Check the current time and print only after the specified delay
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= PRINT_DELAY)
{
Serial.println(RPM);
previousMillis = currentMillis;
}
}
tON = 0;
tOFF = 0;
Tperiod = 0;
freq = 0;
RPM = 0;
}
Should it be calculating correctly right now?
N.B. nothing is being printed ..
That will not work. The int variable can't hold such large numbers. Write like this: #define BAUDRATE 115200.
As print delay use some 300 mS giving You an update 3 time per second. That rate is low but nice for the human mind! I've used that and it feels fast enough but not like that hysterical tombola.
Well done! 6 poles confirms Your feeling for "more pulses". 3 phases and 6 poles. I interpret that as there are 2 pulses per rew for each phase.
30 000 000L / rev-time ought to give RPM. Make a test running the motor as slow as possible. That way You eye has a chance to verify it's reasonable correct.