-
Notifications
You must be signed in to change notification settings - Fork 578
Add 60deg setting for hall sensors #455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
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. |
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. |
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"])``` |
I have a 60deg hall sensor motor, it didn't work. This fixes that.