Sin/Cos encoder?


So I got this DJI motor that has an internal encoder that outputs one sin and one cos signal (phase shift with each other) they cross 7 times per motor spin. DJI has an asic to drive the motor in FOC and reads the encoder from 0-8000ish (they claim to be physical angle), I saw there is a pull on github about SPI encoder, so there might be a chance that if I can have a separate microcontroller to spit out data (angle)?

So right now I have the AMT10x encoder and it works beautifully but I want to use the internal encoder so it’s smaller and mechanically better.


Oh cool, I didn’t know that was a thing. Do you have any more info on this that you can link to?

Are the signals in 0 to 3.3V level? If so you may be able to hook them up directly to the ODrive, and just add the decoding firmware. We have general-purpose ADC sampling implemented in this PR.

should look something like this, they have the encoder inside the motor and it’s hard to remove that to see exactly what they use. But I used scope and getting the waveform that pretty much sine and cosine (phase shift each other), the level might be 0-5v. so voltage divider i guess?


Yeah a divider and maybe a small filter cap close to the ODrive to keep noise out, making sure the RC time constant of the divider resistors and the cap is suitable.
Then just add a case statement here for analog SinCos input. You may need to also have it have some virtual CPR so the other parts of the code work correctly, say 8k or similar.


Did more testing. the encoder spits out sin and cos 90 degrees shift depends on the rotating direction. the voltage varies from 1 to 2v. Made an arduino code and it works pretty well to track the counts. gonna try to integrate with ODrive now.


How often does encoder::update() gets called and where is it being called?
int16_t delta_enc_16 = (int16_t)hw_config_.timer->Instance->CNT - (int16_t)shadow_count_;
so the timer->CNT will get cleared somewhere? or the timer->CNT will keep all the encoder steps, what if it overflows?


And it seems like the fw4 branch doesn’t do the calibration at startup? I am using a mac and the odrivetool detects the odrv0 and disconnect very soon if it’s not being actively used.


All of the following pertains to the branch fw4. The closed loop control runs in a loop which is part of a function in axis.hpp called run_control_loop. This loop runs at about 10kHz right now and executes all control loops. It calls do_updates which is in axis.cpp, which in turn calls Encoder::update().

In the code timer->CNT will overflow and wrap around. This is why we have the shadow count and circular counts. The trick is that we compare to (int16_t)shadow_count_, so the subtraction will “unroll” the overflow and it works still when rolling around the overflow.

Yes fw4 is new and not released yet, sorry there is not much documentation. You must send odrv0.axis0.requested_state = 4, then = 7 then = 8. Have a look at axis.hpp to see the states.


It works! thanks for the help! One thing to know is the ADC reading on stm32 is convert to 0-3.3 float. but reads differently on the odrivetool.


@Steven_Sun Do you have a picture of the unit? Or maybe a link to where you go it?



motor i have is this one:

i don’t know the specific model of the encoder but it outputs sin/cos signal.


@Steven_Sun awesome, thank you!


Did you ever release any code for your sin/cos encoder interfacing?