Renesass IPS2200 SINCOS Error: CPR_POLEPAIRS_MISMATCH

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?

We have managed to mitigate this error and get through a calibration phase by doing the following:

  • Building the firmware with these changes integrated (Thanks @cyclone!)
  • Moving the IPS2200 to 3.3V and spending some time to get the signals calibrated into a good range

Unfortunately, our signal lines have a bit of noise on them and we are not yet getting a clean response from the motor.

As we attempt to tune for position control using these instructions, the motor continuously vibrates, even with very low vel_gain and pos_gain values.

We suspect it’s our line noise.

FWIW, we have twisted our motor wires and used the ODrive ferrite ring next to the ODrive PCB.

We also tried a really simple signal averaging scheme in software, but that mainly just introduced a delay to the motor control algorithm which caused the driver to dump excess power into the motor while trying to catch up.

We are now going to try using shielded & twisted wires for the signal lines.

I’ll fire up a separate thread for the new issue and report on progress there.

1 Like