SinCos encoder ERROR_CPR_POLEPAIRS_MISMATCH, hoverboard motor

Good day! I have trouble calibrating my motor. Motor type - hoverboard, encoder - sincos. When using a standard hoverboard motor with an Hall encoder, the calibration is straightforward. When using the same motor, but with the sincos encoder, rotation occurs only in one direction, the calibration ends with the error ERROR_CPR_POLEPAIRS_MISMATCH. This engine works without problems with a driver from another manufacturer. Board - ODrive v3.6 24V, firmware 0.5.1. Sincos pins - gpio 3,4. Hall cpr - 90, sincos cpr - 6283. I can publish calibration script if need.

Searching for Odrive...
Odrive found
Voltage = 22.81157112121582 V
Reset current board settings? [Y/n]: y
Connection lost due to device erasing and restart...
Connection lost due to device restart...
Searching for Odrive... 
Odrive found
Calibrate the engine? [Y/n]: y
Connection lost due to device restart...
Searching for Odrive... 
Odrive found
Make sure the motor spins freely and press Enter...
Waiting for engine calibration to complete...
Waiting for encoder calibration to complete...

Error: Odrive reported an error of 2 while in the state 
AXIS_STATE_ENCODER_OFFSET_CALIBRATION. Printing out Odrive encoder data for debug:
error = 0x0002 (int)
is_ready = False (bool)
index_found = False (bool)
shadow_count = 3835 (int)
count_in_cpr = 3829 (int)
interpolation = 0.0 (float)
phase = 0.9330251216888428 (float)
pos_estimate = 0.6100223064422607 (float)
pos_estimate_counts = 3832.859375 (float)
pos_cpr = 0.6100136041641235 (float)
pos_cpr_counts = 3832.724365234375 (float)
pos_circular = 0.6100334525108337 (float)
hall_state = 7 (int)
vel_estimate = -0.004177940543740988 (float)
vel_estimate_counts = -26.25 (float)
calib_scan_response = 208.0 (float)
pos_abs = 0 (int)
spi_error_rate = 0.0 (float)
config:
  mode = 2 (int)
  use_index = False (bool)
  find_idx_on_lockin_only = False (bool)
  abs_spi_cs_gpio_pin = 1 (int)
  zero_count_on_find_idx = True (bool)
  cpr = 6283 (int)
  offset = 0 (int)
  pre_calibrated = False (bool)
  offset_float = 0.0 (float)
  enable_phase_interpolation = True (bool)
  bandwidth = 100.0 (float)
  calib_range = 0.019999999552965164 (float)
  calib_scan_distance = 150.0 (float)
  calib_scan_omega = 12.566370964050293 (float)
  idx_search_unidirectional = False (bool)
  ignore_illegal_hall_state = False (bool)
  sincos_gpio_pin_sin = 3 (int)
  sincos_gpio_pin_cos = 4 (int)
set_linear_count(count: int)

I’ve no experience with sincos encoders but are you sure that the cpr is correct? 6283 does not sound like a logical amount as cpr tends to be values resulting from 2^X resulting from the resolution in bits. Though it might be different for a sincos, is it an analogue signal?

On another note, this error is also often thrown if the encoder is misaligned or not connected properly. Though it’s likely you’ve already checked that thoroughly.

sincos is an analog signal, taken from the source code encoder.cpp

In that case I’ve got no clue what’s wrong

I recommend just having your motor do more revolutions. Set encoder.config.calib_scan_distance to a larger multiple of 2*Pi

I used multiple values encoder.config.calib_scan_distance = 50; 100; 150; 62.83; 628.3; 6283, but to no avail. Is the signal incorrect? The image shows the output from the sincos encoder.

Ah, you may have to boost those voltages. Vpp is expected to be 3V.

I partially modified the software in the part of the ADC sampling in order to fit the signal to the required range and not add additional hardware blocks between the ODrive and the encoder. sincos_sample_s_ and sincos_sample_c_ now convert the input signal to the range - 0.5f: + 0.5f Also increased encoder.config.calib_scan_distance to 628. But the problem remains. Motor connected to channel 1, plot for axis1.encoder.pos_estimate

err, how many poles does the wheel have? Is the sincos enocder poles a multiple of the wheel poles? If not, you may have a problem.

Oh, of course. That makes sense.

Can you also multiply pole_pairs by 15? Or would it be divide? :thinking:

Hey guys, have you solved your problem? I have encountered the same problem. My configuration environment is basically the same as yours;

Hi,I have the same situation and the same error prompt. The motor is 7 pairs of poles. How to match the cycle of this encoder? The encoder is linear Hall and the output waveform is sincos waveform;

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.

from encoder.cpp

    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;

HI! Where did you define these two variables?(sincos_subphase_counter 、sincos_subphase_counter)

encoder.hpp

class Encoder : public ODriveIntf::EncoderIntf {
public:
    static constexpr uint32_t MODE_FLAG_ABS = 0x100;

    uint8_t sincos_subphase_counter = 0;
    float sincos_subphase_previous = 0.0;

    struct Config_t {

Hi, Is CPR set to 6283?

Hi! Yes, CPR = 6283.