Beginner help with Hobbysky BLDC 6374 With Hall Sensor

Just a quick note to add in here, just because a motor contains its own hall sensors doesn’t mean you can’t add other angular measurement systems of your own. I’m not sure to what extent a “record cutting” lathe should have precise position control vs having simply speed control, but if the internal hall sensors only get you 6 discrete locations per electrical revolution of the motor, you could always add a diametrically polarised magnet on the backshaft and put as AS5600 behind it, or 3d print a disc to attach to the motor with a bunch of tiny magnets embedded into it, and have these external tiny ones sweep past analogue, rather than latching, hall sensors.

1 Like

State 7 / sector -1(all hall high) and State 0 / sector -1(all hall low) shouldn’t happen with 120 degree hall placement.

I think you have 60 degree hall placement. You might have to invert the digital state of one hall.
For example inverting here:
B_active = ! digitalRead(pinB);

(Sorry I edited the message several times)

Or is it noise ? :thinking:

You are correct about the sensors being placed at 60 degrees. I opened up the motor and took a peek at it. There is a pcb in there that has the hall sensors attached. I then drew a little mock up of the motor just to check.

So I guess my question(s) now is, why does inverting the output of one of the sensors correct the issue? Could you do any of them? Additionally uh…where do I edit that file at? :sweat_smile:

Sorry about the double post. Here is an image of the inside of the motor and pcb

Nice catch, @Candas1!

You have to invert the middle sensor. For most pole/slot combos, spacing the sensors equally around the motor (120 degrees) will get you a valid placement. This placement is equivalent to that except the middle sensor has been moved to the other side of the motor. Since the rotor magnets are always a multiple of 2, this puts it in the same relative position but opposite polarity.

Unfortunately the SimpleFOC HallSensor class doesn’t provide any way to do it. But it’s easy to add. All you have to do is add a new variable invert_hall_state, set it to 2, and modify one line in HallSensor::updateState()
int8_t new_electric_sector = ELECTRIC_SECTORS[hall_state^invert_hall_state];

1 Like

I actually never owned one of those, but people use to share this page that explains it nicely.
I could only find it in the webarchive now, so I will copy the content here just in case:

120deg Hall Effect Sensors
The following diagram shows 120-degree hall-effect sensors. Notice that there is electrically 120 degrees between hall transitions.

60deg Hall Effect Sensors
The following diagram shows 60-degree hall-effect sensors. Notice the Hall 3 signal is inverted (compared to 120-degree hall3) This changes the number of electrical degrees between the rising edge of the hall states.


All of the hall motors Compumotor uses are 120degrees. If we use an inverter on Hall 3 we can change a 60degrees hall state to 120degrees and vise versa.

Now that I see it again, the diagram with the inverted hall signal is correct, but the explanation about the electrical degrees between hall transitions seems weird lol

1 Like

Sounds like an option we should add to the HallSensor class?

Either a simple option to flip one of the halls.
Or building the ELECTRIC_SECTORS array during the sensor alignment, but then you have to set it manually in the code or save it to eeprom. That’s much more complicated.

Yes, I think it’s worth supporting. This sensor placement is useful because it puts them exactly half way between 3 consecutive pairs of stator teeth, which can be done precisely by hand for motors that don’t come with sensors. And has them all close together for cleaner wire routing than 120 degree placement.

Hello again. More questions

With regard to the code (which I don’t understand all that much and will demonstrate lol) stuff for @Candas1 solution do I invert the state at line 32, 106 and 165 or just on one line? For @dekutree64 solution do I declare the variable in the HallSensor::updateState function ie:

void HallSensor::updateState() {
  int8_t new_hall_state = C_active + (B_active << 1) + (A_active << 2);

  int8_t invert_hall_state = 2;

  // glitch avoidance #1 - sometimes we get an interrupt but pins haven't changed
  if (new_hall_state == hall_state) return;

  long new_pulse_timestamp = _micros();
  hall_state = new_hall_state;

  int8_t new_electric_sector = ELECTRIC_SECTORS[hall_state ^ invert_hall_state];
  int8_t electric_sector_dif = new_electric_sector - electric_sector;

Or do I put that variable somewhere else? Additionally does either solution change the math done in Hallsensor::getSensorAngle()?

There are a few more things I have questions about in Step 2. Testing the driver + motor combination

@dekutree64 you were correct about the phase resistance. I measured 0.2 ohm across all combinations of pins

driver.voltage_power_supply: I would assume that this value at a minimum would need to be 18v per the motor parameters on the amazon page. The max for the motor is 42v but I would assume that the actual cap on voltage is dictated by the driver board (35v). Should I go higher on this value, maybe the middle of the range?

driver.voltage_limit: In the example code this value is set to half that of driver.voltage_power_supply is this what it should be in all cases? With my motor should it be the case that i use a driver.voltage_power_supply of 35v and set the limit to half of that to get close to the minimum voltage of the motor?

motor.voltage_limit. I understand that it must be different from the driver.voltage_limit but not exactly how it differs from the driver.voltage_limit in practice. Reading the commented code and the getting started page says the same thing that @dekutree64 said and if I pop in my values of 0.2 ohm and the suggested 2*phase_resistance, that is 0.4. Intuitively it seems low and runs counter to the code comment “start very low for high resistance motors” since the mentioned 10 ohm resistance is much higher than 0.2

Finally, when do I need to consider the Kv of the motor. Should it be a part of the decision making process for the above variables?

It feels like I am missing some assumptions or something. I apologize if any of this is unclear or scattered.

Anywho, thanks for your help

Looks like I share this in the wrong thread lol

From the diagrams I shared, it looks like inverting the wrong hall would still give you 111 or 000 states.
In the diagrams, hall 3 is inverted, but on the picture I shared, the middle one is inverted.
From your picture it’s unclear which one is inverted. I am not sure if they only solder the hall upside down, or if there are halls inverted internally.

if you are using enableinterrupts():
I would try to invert 26/31/37 one by one here until all the positions are valid.

if you are not using enableinterrupts():
I would invert 101/102/103 one by one here until all the positions are valid.

I think I would still check also if with the same wiring you get:

  • 000 and 111 invalid states which would point to 60 degrees hall placement
  • only 000 which could mean one hall is not wired well or defective (always OFF)
  • only 111 which could mean one hall is shorted (always ON)

It will work if you declare invert_hall_state in updateState() like that, but for a proper implementation it should be a member variable so you can configure it from user code without modifying the library. Default 0, and set to 1, 2, or 4 (binary 001, 010, 100) to invert each of the sensors. You should never have to invert two sensors.

driver.voltage_power_supply must be set to the actual DC voltage you’re feeding it, nothing to do with motor ratings. The PWM duty values are calculated relative to this.

You generally don’t need to set driver.voltage_limit. It will automatically be set equal to voltage_power_supply.

motor.voltage_limit is what’s normally used to keep from drawing excessive current until you get it running well with the voltage-based current limiting. Then you can rely on motor.current_limit and increase voltage_limit so you can reach higher speeds.

motor.voltage_limit should usually be at most half of voltage_power_supply, because motor voltage gets multiplied by sine/cosine which range -1 to +1, so the actual voltage difference between motor wires can be twice the limit. It’s confusing.

That code comment “start very low for high resistance motors” in the getting started page is wrong. It should be “start very low for low resistance motors”.

1 Like

I did another test where I pulled rotor(? The part with the magnets and not the coils) and then did the sensor test and got this:
Sensor ready
Angle -0.15, state 7, sector -1, rotations 0, interrupts 1

I can latch the individual sensors with a magnet. Does this mean that all/none of them are inverted?

Further when I use notepad to change this line in HallSensor.cpp and then verify and upload the hall_sensor_software_interrupts_example

void HallSensor::handleA() {
  A_active = digitalRead(pinA);
  updateState();
}

to

void HallSensor::handleA() {
  A_active = !digitalRead(pinA);
  updateState();
}

I would expect a starting state of 3/6(011/110) but I still get 7. Is there a step that I am missing?

The initial state comes from the digitalRead calls in HallSensor::init(), so you’d have to invert the first one of those to match. But it should work itself out after a bit of movement.

Testing the sensors with a magnet is a good way to find out if any are inverted. You’ve verified that they’re all functioning, but you need to find out if they all report the same value for the same pole of the magnet. It might be easier if you print sensor.A_active, B_active and C_active individually so you don’t have to sort out the individual bit values from hall_state. You’ll have to change those variables to public in HallSensor.h.

Play with it until you figure out which sensor is which, and then hold the magnet near each of them one by one and check what value they report.

The long term implementation could be like that lol

1 Like

Okay so I moved

volatile int A_active; //!< current active states of A channel
volatile int B_active; //!< current active states of B channel
volatile int C_active; //!< current active states of C channel

from private to public in HallSensor.h then added the following lines to hall_sensor_software_example.ino in the loop and in the setup right before sensor.init()

Serial.print(" Sensor A State "); Serial.print(sensor.A_active);
Serial.print(" Sensor B State "); Serial.print(sensor.B_active);
Serial.print(" Sensor C State "); Serial.print(sensor.C_active);

I then removed the rotor again and used a magnet that verified the polarity on. I found that the A,B and C sensors start with a state of 0 and after being initialized go to 1. Then the sensors could only be changed to 0 with the north pole of a magnet and would stay at 0 until a south pole was sensed. Here is the serial output from me doing that:

 Sensor A State 0
 Sensor B State 0
 Sensor C State 0
Sensor ready
 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 7, sector -1, rotations 0, interrupts 1
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle -0.15, state 3, sector 5, rotations -1, interrupts 2
 Sensor A State 0 Sensor B State 1 Sensor C State 1 Angle 0.00, state 1, sector 0, rotations 0, interrupts 3
 Sensor A State 0 Sensor B State 0 Sensor C State 1 Angle 0.00, state 1, sector 0, rotations 0, interrupts 3
 Sensor A State 0 Sensor B State 0 Sensor C State 1 Angle 0.00, state 1, sector 0, rotations 0, interrupts 3
 Sensor A State 0 Sensor B State 0 Sensor C State 1 Angle -0.15, state 0, sector -1, rotations 0, interrupts 4
 Sensor A State 0 Sensor B State 0 Sensor C State 0 Angle -0.15, state 0, sector -1, rotations 0, interrupts 4
 Sensor A State 0 Sensor B State 0 Sensor C State 0 Angle -0.15, state 0, sector -1, rotations 0, interrupts 4
 Sensor A State 0 Sensor B State 0 Sensor C State 0 Angle -0.15, state 0, sector -1, rotations 0, interrupts 4
 Sensor A State 0 Sensor B State 0 Sensor C State 0 Angle -0.15, state 0, sector -1, rotations 0, interrupts 4
 Sensor A State 0 Sensor B State 0 Sensor C State 0 Angle -0.15, state 0, sector -1, rotations 0, interrupts 4
 Sensor A State 0 Sensor B State 0 Sensor C State 0 Angle 0.30, state 4, sector 2, rotations 0, interrupts 5
 Sensor A State 1 Sensor B State 0 Sensor C State 0 Angle 0.30, state 4, sector 2, rotations 0, interrupts 5
 Sensor A State 1 Sensor B State 0 Sensor C State 0 Angle 0.30, state 4, sector 2, rotations 0, interrupts 5
 Sensor A State 1 Sensor B State 0 Sensor C State 0 Angle 0.30, state 4, sector 2, rotations 0, interrupts 5
 Sensor A State 1 Sensor B State 0 Sensor C State 0 Angle 0.30, state 4, sector 2, rotations 0, interrupts 5
 Sensor A State 1 Sensor B State 0 Sensor C State 0 Angle 0.30, state 4, sector 2, rotations 0, interrupts 5
 Sensor A State 1 Sensor B State 0 Sensor C State 0 Angle 0.30, state 4, sector 2, rotations 0, interrupts 5
 Sensor A State 1 Sensor B State 0 Sensor C State 0 Angle 0.45, state 6, sector 3, rotations 0, interrupts 6
 Sensor A State 1 Sensor B State 1 Sensor C State 0 Angle 0.45, state 6, sector 3, rotations 0, interrupts 6
 Sensor A State 1 Sensor B State 1 Sensor C State 0 Angle 0.45, state 6, sector 3, rotations 0, interrupts 6
 Sensor A State 1 Sensor B State 1 Sensor C State 0 Angle 0.75, state 7, sector -1, rotations 1, interrupts 7
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle 0.75, state 7, sector -1, rotations 1, interrupts 7
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle 0.75, state 7, sector -1, rotations 1, interrupts 7
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle 0.75, state 7, sector -1, rotations 1, interrupts 7
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle 0.75, state 7, sector -1, rotations 1, interrupts 7
 Sensor A State 1 Sensor B State 1 Sensor C State 1 Angle 0.75, state 7, sector -1, rotations 1, interrupts 7
 Sensor A State 1 Sensor B State 1 Sensor C State 1
1 Like

I put my bet on B being inverted

We should make those variables public by default, I was also doing the same change in the past.

So they respond to magnets like they should, and none are inverted, yet they still don’t switch in proper order… I doubt spacing would be wrong with them on a PCB, so I am officially stumped.

I suppose you could test for your initial question of whether the sensors are digital or analog. Connect one of them to an analog pin on the arduino, call analogRead on that pin, and print the value to see if it switches all at once or changes gradually as you move the magnet around it. But given the placement very close to the rotor magnets, analog sensors would saturate and give an essentially digital signal anyway.

Maybe time to give up and use a different kind of sensor.