Skip to content

Conversation

@Moddingear
Copy link

I have a 60deg hall sensor motor, it didn't work. This fixes that.

@runger1101001 runger1101001 changed the base branch from master to dev March 6, 2025 23:57
@runger1101001
Copy link
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.

@runger1101001 runger1101001 added the enhancement New feature or request label Mar 7, 2025
@Moddingear
Copy link
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.

@Moddingear
Copy link
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"])```
@Moddingear
Copy link
Author

Moving to Drivers repo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

3 participants