Определить, проходит ли магнитный датчик 360 или 0 и в каком направлении (направление переворачивания / обтекания?) - C - PullRequest
0 голосов
/ 13 июня 2018

Я использую магнитный энкодер, который реагирует на ручные вводы.При повороте рассчитывает угол, и эта часть отлично работает.Это означает, что если я поверну кодировщик на 360 градусов, угол будет сброшен.(поэтому снова 0).Тем не менее, я хотел бы определить, прошел ли энкодер 360 и возвращается ли он к 0 или же он возвращается от 0 до 360. Мне нужно знать, в каком направлении повернут энкодер, с шагом 30 градусов.

Итак: Как мне узнать, повернут ли датчик в направлении по часовой стрелке (происходит от 0 -> 360 -> 0 -> 360) или если он вращается в направлении против часовой стрелки (идетfx. от 360 -> 0 -> 360 -> 0)

Прямо сейчас он видит шаг от 360 до 0 поворотом против часовой стрелки, где он фактически является поворотом по часовой стрелке ...

Есть предложения?

Ответы [ 3 ]

0 голосов
/ 14 июня 2018

Если вы можете гарантировать, что опрос происходит чаще всего при самом быстром повороте на пол-оборота (180 °), то должны быть выполнены следующие соображения:

  1. абсолютная разница между текущим показанием ипоследний не может превышать пол оборота = 180 °
  2. Если абсолютная разница равна >= 180°, мы пересекли .Подсчет степени, которую мы переместили, рассчитывается путем сложения или вычитания полного поворота (360 °) в зависимости от текущего значения поворота (cw add, ccw subtract).
  3. Если абсолютная разница равна < 180° и знак разницыположительно, мы сместились по часовой стрелке (угол приращения)
  4. Если абсолютная разница равна < 180°, а знак разницы отрицательный, мы сместились против часовой стрелки (угол уменьшения)
  5. Если разница == 0тогда никакого движения не произошло.

В коде:

int LastAngle = GetAngle();    // Init angle reading
bool bClockWise = true;
...
// polling or interrupt handler
int CurrAngle = GetAngle();
int diff = CurrAngle - LastAngle;
if (diff==0)
{
    //No move
    ...
}
else if (abs(diff) < 180)   //Angle changed from last read
{
    //if we are here diff is not 0
    //we update rotation accordingly with the sign
    if (diff > 0)
        bClockWise = true;     //we were rotating clockwise
    else
        bClockWise = false;    //we were rotating counterclockwise
}
//If absolute difference was > 180° we are wrapping around the 0
//in this case we simply ignore the diff sign and leave the rotation
//to the last known verse.
...

Если вы хотите считать ходы, вы можете кодировать:

int Turns = 0;
if ((diff != 0) && (abs(diff) > 180))
{
    if (bClockWise)
        Turns++;     //Increase turns count
    else
        Turns--;     //Decrease turns count
}

Следующие макросы могутиспользоваться для проверки движения и чувствительности вращения:

#define IsMoving    (diff)        //Give a value !=0 if there is a movement
#define IsCw        (bClockWise)  //Give true if clockwise rotation
#define IsWrap      (abs(diff) >= 180)  //Give true if knob wrapped

PS Обратите внимание, что переменная diff является функциональной для определения и вращения, а не является абсолютнойразница в градусах между движениями .

Если вы хотите вычислить реальное движение, вы должны принять во внимание переходное значение:

int Angle = 0;    //the real angle tracked from code start
if (diff != 0)
{
    if (abs(diff) >= 180)
    {
        if (bClockWise)
            Angle += diff + 360;     //Adjust for positive rollover
        else
            Angle += diff - 360;     //Adjust for negative rollover
    }
    else
        Angle += diff;
}
0 голосов
/ 14 июня 2018

Вот очень простое решение:

int rotation_angle(int new_reading, int old_reading) {
    /* angle readings are in [0..360] range */
    /* compute the difference modulo 360 and shift it in range [-180..179] */
    return (360 + 180 + new_reading - old_reading) % 360 - 180;
}

rotation_angle() вернуть разность углов со знаком.

Примечания:

  • , начиная с new_reading иПредполагается, что old_reading находится в диапазоне [0 .. 360], диапазон их разности равен [-360 .. 360], добавление 360 гарантирует, что операция по модулю возвращает положительное значение между 0 и 359.
  • добавление 180 перед модулем и вычитание 180 из результата сдвигает диапазон выходных значений до [-180 .. 180].
  • 0 означает отсутствие изменения угла
  • отрицательное значение означает поворот к меньшим значениям угла.
  • положительное значение означает поворот к большим значениям угла
  • , еслиизменение угла может превышать 180 градусов, интерпретация возвращаемого значения, скорее всего, неверна.Выборка угла должна быть выполнена достаточно быстро, чтобы предотвратить такие условия.
0 голосов
/ 13 июня 2018

Поскольку магнитный датчик может быть повернут более чем на 180 градусов за раз (хотя и маловероятно), технически невозможно узнать, в каком направлении он был повернут, например,.поворот на 90 градусов по часовой стрелке также мог быть поворотом на 270 градусов против часовой стрелки.

Если ваш магнитный энкодер не указывает направление вращения, лучшее, что вы можете сделать, это угадать (например, самое короткое расстояние -т.е. 90 градусов по часовой стрелке более вероятно, чем 270 градусов против часовой стрелки), но иногда вы можете ошибиться.

Если это приемлемо, это сделать относительно легко (при условии целочисленных углов в градусах от 0 до 360).):

int rotation_angle(int old_angle, int new_angle) {
  int result = (360 + new_angle - old_angle) % 360;
  return (result > 180) ? result - 360 : result;
}

Тогда:

printf("%d\n", rotation_angle(0, 330)); // prints : -30
printf("%d\n", rotation_angle(330, 0)); // prints : 30
...