I think we might be bumping into the same issue as @cyclone from 2013.
They said, “Hey! As far as I remember, ODrive assumes one sincos period per motor revolution, but we had one sincos period per pole pair, or 15 encoder periods per full wheel revolution. Having corrected the source codes, the wheel was launched. But later I designed my own driver based on MC SDK and modbus.”
And they provided a code snippet that modified encoder.cpp to accomodate more periods in an SINCOS encoder (Which we also have).
case MODE_SINCOS: {
float sincos_subphase = fast_atan2(sincos_sample_s_, sincos_sample_c_);
if ((sincos_subphase - sincos_subphase_previous) < (-3 * M_PI / 2))
{
if (sincos_subphase_counter < 14)
sincos_subphase_counter++;
else
sincos_subphase_counter = 0;
}
if ((sincos_subphase - sincos_subphase_previous) > (3 * M_PI / 2))
{
if (sincos_subphase_counter > 0)
sincos_subphase_counter--;
else
sincos_subphase_counter = 14;
}
sincos_subphase_previous = sincos_subphase;
float phase = (6.283f * sincos_subphase_counter + sincos_subphase) / 15;
int fake_count = (int)(1000.0f * phase);
//CPR = 6283 = 2pi * 1k
delta_enc = fake_count - count_in_cpr_;
delta_enc = mod(delta_enc, 6283);
if (delta_enc > 6283 / 2)
delta_enc -= 6283;
} break;
When I dig through the main branch on Github, it looks like these areas of code have gotten some attention since then, but don’t appear to include these updates.
Current implementation at encoder.cpp:719
case MODE_SINCOS: {
float phase = fast_atan2(sincos_sample_s_, sincos_sample_c_);
int fake_count = (int)(1000.0f * phase);
//CPR = 6283 = 2pi * 1k
delta_enc = fake_count - count_in_cpr_;
delta_enc = mod(delta_enc, 6283);
if (delta_enc > 6283/2)
delta_enc -= 6283;
} break;
But I’ve seen other threads that indicate SINCOS is now supported.
From what I can tell, it looks like our coil design includes multiple poles (7x per rotation), and this is causing the encoder to emit multiple sin waves (7x) per rotation.
Is this causing a problem with the hard-coded CPR during OFFSET calibration?