Add 60deg setting for hall sensors#455
Closed
Moddingear wants to merge 5 commits intosimplefoc:devfrom
Closed
Conversation
Member
|
Thank you for contributing this! I'm about to do a release, so I will merge this to the dev branch immediately afterwards so people can test it out. Then it would be part of the following release. |
Contributor
Author
|
Don't merge this just yet, i've got an idea for an algorithm that can find the correct electrical sectors regardless of the connections and the electrical setup. |
Contributor
Author
|
Ok now it's mergeable. By default it will act like a 120deg sensor until it sees that it's not, in which case it will switch the polarity of one line. After two rotations, if it's a 120 deg config, it will stop detecting. Here's a python file simulating the algorithm as well: import random
import matplotlib.pyplot as plt
sine_six_step = [0,0,0,1,1,1]
def rotate(l, n):
return l[n:] + l[:n]
def gen_hall():
hall_120 = not bool(random.randint(0,3)) and False
print(f"{hall_120=}")
sectors = []
#create hall sensor readings, either 120 deg out of phase, or 60 deg
for i in range(3):
sectors.append(rotate(sine_six_step, i*2 if hall_120 else i))
#shuffle hall connections
random.shuffle(sectors)
states = []
truth = []
#random starting point, move randomly
read_pos = random.randint(0,5)
for i in range(30):
shift = random.randint(-1,1)
read_pos = read_pos + shift
#print(f"{i=} {shift=} {read_pos=}")
state = 0
for j in range(3):
state += sectors[j][read_pos%6] << j
states.append(state)
truth.append(read_pos*60)
return (states, truth)
def plot_stacked_arrays(array_of_arrays, labels=None):
num_arrays = len(array_of_arrays)
pos = [i*60 for i in range(len(array_of_arrays[0]))]
# Create subplots
fig, axs = plt.subplots(num_arrays, 1, figsize=(8, 2 * num_arrays), sharex=True)
for i, data in enumerate(array_of_arrays):
axs[i].step(pos, data, where='post', label=labels[i])
axs[i].set_ylabel(labels[i])
axs[i].grid(True)
axs[i].legend()
axs[-1].set_xlabel('Angle') # Label x-axis only for the last subplot
plt.tight_layout()
plt.show()
def get_num_discovered_sectors(ELECTRIC_SECTORS):
discovered_sectors = 0
for sector in ELECTRIC_SECTORS:
if sector != -1:
discovered_sectors +=1
return discovered_sectors
def recompose_sectors(ELECTRIC_SECTORS):
print(f"{ELECTRIC_SECTORS=}")
names = ["120deg hall", "60deg hall A", "60deg hall B", "60deg hall C"]
for i in range(4):
if ELECTRIC_SECTORS[i] == -1 and ELECTRIC_SECTORS[7-i] == -1:
print(names[i])
phases = [0]*3
if i == 0:
roll = 1
phases[0] = 0+roll
phases[1] = 2+roll
phases[2] = 4+roll
else:
#When i==1, hall A is in the middle, phase[0] = 1
roll = 3
phases[(i+2)%3] = 1+roll #middle hall
phases[i%3] = 2+roll #
phases[(i+1)%3] = 0+roll #
print(f"{phases=}")
for j in range(6):
state = 0
for k in range(3):
state += 1<<k if (phases[k]+j)%6 < 3 else 0
print(f"{j=} {state=}")
ELECTRIC_SECTORS[state] = j
break
else:
print("Wtf is that hall?!")
print(f"Recomposed {ELECTRIC_SECTORS=}")
def extract_angle(states, ELECTRIC_SECTORS):
sector_prev = -1
direction = 1
rotations = 0
discovered_sectors = get_num_discovered_sectors(ELECTRIC_SECTORS)
angles = []
for state in states:
new_electric_sector = ELECTRIC_SECTORS[state]
#calibration phase, build the sector map
if new_electric_sector == -1 and discovered_sectors <6:
ELECTRIC_SECTORS[state] = (sector_prev + direction) % 6
new_electric_sector = ELECTRIC_SECTORS[state]
discovered_sectors +=1
print(f"Set sector {state} to {new_electric_sector} ({discovered_sectors}/6)")
if discovered_sectors == 6:
recompose_sectors(ELECTRIC_SECTORS)
print(f"Before {new_electric_sector}, after {ELECTRIC_SECTORS[state]}")
#repeat of previous, regular sector to angle code
if new_electric_sector == sector_prev:
angles.append(angles[-1])
continue
electric_sector_diff = new_electric_sector-sector_prev
if electric_sector_diff > 3:
direction = -1
rotations += direction
elif electric_sector_diff < -3:
direction = 1
rotations += direction
else:
direction = 1 if (new_electric_sector > sector_prev) else -1
sector_prev = new_electric_sector
angles.append((rotations*6+new_electric_sector)*60)
return angles
def extract_angle2(states):
ELECTRIC_SECTORS = [-1, 0, 4, 5, 2, 1, 3 , -1]
state1, state2 = (-1,-1)
sector_prev = -1
direction = 1
rotations = 0
flipbit = 0
angles = []
for state in states:
state = state ^ flipbit
if state == state1:
angles.append(angles[-1] if len(angles) > 0 else 0)
continue
if (state1 == 0 or state1 == 7) and state2 != -1:
if state != state2:
flipbit = (7 - state ^ state2) % 8
print(f"{state=} {state1=} {state2=} {bin(flipbit)=}")
state = state ^ flipbit
state2, state1 = (state1, state)
new_electric_sector = ELECTRIC_SECTORS[state]
electric_sector_diff = new_electric_sector-sector_prev
if electric_sector_diff > 3:
direction = -1
rotations += direction
elif electric_sector_diff < -3:
direction = 1
rotations += direction
else:
direction = 1 if (new_electric_sector > sector_prev) else -1
sector_prev = new_electric_sector
angles.append((rotations*6+new_electric_sector)*60)
return angles
states, truth = gen_hall()
ELECTRIC_SECTORS = [-1]*8
angles = extract_angle2(states)
plot_stacked_arrays([truth, states, angles], ["Truth", "States", "Angle"])``` |
Dev to master v2.3.5
Contributor
Author
|
Moving to Drivers repo |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I have a 60deg hall sensor motor, it didn't work. This fixes that.