@@ -340,4 +340,180 @@ I'm just going to get into the 'magnetic angle' pointing system for the DACs now
This makes sense: so when I'm at '0 degs' my A phase is on 100%, B phase is zero. Or, the way I've my LUT written, I'll have A at 0 and B at full-width positive. If I don't like this for some reason (It'll calibrate away) I can change the LUT.
I'm up to pointing, now I just need to deliver some power to the motor.
\ No newline at end of file
I'm up to pointing, now I just need to deliver some power to the motor.
OK, this is making sense and I can point my magnetic vector around:
```cpp
// do _aStep and _bStep integers, op electronics
voidSTEP_A4950::writePhases(void){
// a phase,
if(LUT_8190[_aStep]>4095){
A_UP;
}elseif(LUT_8190[_aStep]<4095){
A_DOWN;
}else{
A_OFF;
}
// a DAC
dacs->writeDac0(dacLUT[_aStep]*_cscale);
// b phase,
if(LUT_8190[_bStep]>4095){
B_UP;
}elseif(LUT_8190[_bStep]<4095){
B_DOWN;
}else{
B_OFF;
}
// b DAC
dacs->writeDac1(dacLUT[_bStep]*_cscale);
}
// magnetic angle 0-1 maps 0-2PI phase
// magnitude 0-1 of <range> board's max amp output
One magnetic period is four full 'steps', so my LUT is 1024 positions long and I am effectively 'microstepping' 256 times (or have this amount of resolution).
Now I need to write the table, so I'll take 200 samples at each full step, maybe averaging encoder readings 10x.
OK, I've those samples, so I guess the next move is just to write my table. I think I want to check that all of the readings are continuous (pointing in the same direction) but this also seems a bit tricky: one will be reversed as well, for sure.
Then I'll get a table that has one jump around the encoder origin. I think I want to start by rewriting the readings table to base zero around the origin, well, obviously since this is a LUT. Finding the actual 'zero' is a bit of a trick though, and requires the interpolation routine to set the first 'mag angle' at that point.
Maybe this is less complicated... for each value 0-16k, I find the interval it's between in 0-199 indices from the scan. One of these is a bit tricky, otherwise it's whatever. I do the linterp and write down a float.
Here's the calib so far,
```cpp
booleanStep_CL::calibrate(void){
// (1) first, build a table for 200 full steps w/ encoder averaged values at each step
floatphase_angle=0.0F;
for(uint8_ti=0;i<200;i++){
// pt to new angle
stepper_hw->point(phase_angle,CALIB_CSCALE);
// wait to settle / go slowly
delay(CALIB_STEP_DELAY);
// do readings
floatreading=0.0F;
for(uint8_ts=0;s<CALIB_SAMPLE_PER_TICK;s++){
enc_as5047->trigger_read();
while(!enc_as5047->is_read_complete());// do this synchronously
reading+=(float)(enc_as5047->get_reading());
// this is odd, I know, but it allows a new measurement to settle
This works inside of 'normal' intervals, but fails around the origin due to that wrap issue. I should detect this case...
OK, new bug: when I average readings that are around the origin, I have samples like i.e.
```
16383
1
16384
2
16382
1
```
etc, so the average of these needs to wrap as well, ya duh, tough to do with the wrap tho yeah. I can just add the total counts to each measurement and then sub that value from the total average... or from the sum.
I have this problem: https://en.wikipedia.org/wiki/Mean_of_circular_quantities
The maths-ey way to do this is to convert to cartesian coordinates, given the theta, average in that space and then return to r coords.
I guess doing this like that isn't too aweful, tho it's expensive. It would be awesome to have a faster method later on, but there probably better filters (like a kalman) make more sense than just a big ol' average.
I can imagine taking the measurement spreads: if any were larger than 20 ticks, I could sweep through that set and add the enc_count to the lo vals, then average. Or I could just do this for any reading < 31 ticks, as these are the small ones in *this particular window* but then I have that crawling window issue for measurements really ~ around 31 ticks. Might just be prettier to take a real circular average.