Недокументированный промышленный сервопривод с 8-проводным энкодером: как прочитать этот энкодер?

Я извлек промышленный сервопривод с прикрепленным к нему линейным приводом с шариковым винтом из старого широкоформатного сканера и пытаюсь понять, как сделать "сервопривод", он же "сервопривод", он же "сервоконтроллер".

Я полный новичок в arduino и в основном занимаюсь копированием/вставкой кода - так что, конечно, это усложняет мою цель.

Я могу найти много информации о том, как считывать простой кодер смещения AB, для работы которого требуется четыре провода, но кодер, который у меня есть, имеет восемь проводов:

A+, A-, B+, B-, Z+, Z-, +5 В, 0 В(он же GND)

При подаче +5 В на его провод и подключении GND к 0 В, вращая вал двигателя вручную, мой счетчик показывает:

  • A+: +3,97 В как "высокий" и +0,036 В как "низкий"
  • А-: то же самое
  • B+: то же самое
  • Б-: то же самое
  • Z+: то же самое - но только поднимается высоко в одном месте на 360 градусов
    вращение
  • Z-: то же самое - но только поднимается высоко в одном месте при вращении на 360 градусов - в том же месте, что и Z+

ПРИМЕЧАНИЕ: Оба импульса Z совпадают с импульсами на A+, B+ и B- ... но они НЕ совпадают на A-. Так, может быть, у A - есть триггер Z+/- на своем месте? Я не знаю. Было ОЧЕНЬ сложно остановить вращение вала В импульсе из-за крошечного размера делений.

Все напряжения, которые видел мой цифровой мультиметр, были положительными.

Я не понимаю, как правильно использовать кодер с таким количеством проводов. Я могу отчасти понять, что положительное и отрицательное, вероятно, являются противоположными сигналами друг от друга, своего рода защитой от ошибок или чем-то в этом роде? Я знаю, что Z= и Z - это счетчики перемещений либо под углом 90, 180, либо под каким-либо другим углом смещения, позволяющим отмечать полные вращения. Но я не уверен во всем этом и читаю много материала, который мне не по силам. Я в тупике.

Я могу установить следующий код на UNO, и UNO считывает кодер просто отлично с линий A+ и B+, с увеличением количества для одного направления вращения и уменьшением количества для другого направления. Так что это отражает движение так, как оно должно быть...

НО - я получаю 8000 импульсов на оборот вала, а не 2000 импульсов на оборот в документации. Значит, здесь что-то не так. Я должен видеть 2000 импульсов на оборот... это из-за отсутствия использования других проводов? Или что-то еще?

Код, который я использую только для A+ и B+:

    /*
*Quadrature Decoder 
*/
#include "Arduino.h"
#include <digitalWriteFast.h> 

// Quadrature encoders
// Left encoder
#define c_LeftEncoderInterruptA 0
#define c_LeftEncoderInterruptB 1
#define c_LeftEncoderPinA 2
#define c_LeftEncoderPinB 3
#define LeftEncoderIsReversed

volatile bool _LeftEncoderASet;
volatile bool _LeftEncoderBSet;
volatile bool _LeftEncoderAPrev;
volatile bool _LeftEncoderBPrev;
volatile long _LeftEncoderTicks = 0;

void setup()
{
  Serial.begin(9600);

  // Quadrature encoders
  // Left encoder
  pinMode(c_LeftEncoderPinA, INPUT);      // sets pin A as input
  digitalWrite(c_LeftEncoderPinA, LOW);  // turn on pullup resistors
  pinMode(c_LeftEncoderPinB, INPUT);      // sets pin B as input
  digitalWrite(c_LeftEncoderPinB, LOW);  // turn on pullup resistors
  attachInterrupt(c_LeftEncoderInterruptA, HandleLeftMotorInterruptA, CHANGE);
  attachInterrupt(c_LeftEncoderInterruptB, HandleLeftMotorInterruptB, CHANGE);
}

void loop()
{ 
  Serial.print("Encoder Ticks: ");
  Serial.print(_LeftEncoderTicks);
  Serial.print("  Revolutions: ");
  Serial.print(_LeftEncoderTicks/2000.0); //2000 Counts Per Revolution, per the engineering manual
  Serial.print("\n");
}


// Interrupt service routines for the left motor's quadrature encoder
void HandleLeftMotorInterruptA(){
  _LeftEncoderBSet = digitalReadFast(c_LeftEncoderPinB);
  _LeftEncoderASet = digitalReadFast(c_LeftEncoderPinA);

  _LeftEncoderTicks+=ParseEncoder();

  _LeftEncoderAPrev = _LeftEncoderASet;
  _LeftEncoderBPrev = _LeftEncoderBSet;
}

// Interrupt service routines for the right motor's quadrature encoder
void HandleLeftMotorInterruptB(){
  // Test transition;
  _LeftEncoderBSet = digitalReadFast(c_LeftEncoderPinB);
  _LeftEncoderASet = digitalReadFast(c_LeftEncoderPinA);

  _LeftEncoderTicks+=ParseEncoder();

  _LeftEncoderAPrev = _LeftEncoderASet;
  _LeftEncoderBPrev = _LeftEncoderBSet;
}

int ParseEncoder(){
  if(_LeftEncoderAPrev && _LeftEncoderBPrev){
    if(!_LeftEncoderASet && _LeftEncoderBSet) return 1;
    if(_LeftEncoderASet && !_LeftEncoderBSet) return -1;
  }else if(!_LeftEncoderAPrev && _LeftEncoderBPrev){
    if(!_LeftEncoderASet && !_LeftEncoderBSet) return 1;
    if(_LeftEncoderASet && _LeftEncoderBSet) return -1;
  }else if(!_LeftEncoderAPrev && !_LeftEncoderBPrev){
    if(_LeftEncoderASet && !_LeftEncoderBSet) return 1;
    if(!_LeftEncoderASet && _LeftEncoderBSet) return -1;
  }else if(_LeftEncoderAPrev && !_LeftEncoderBPrev){
    if(_LeftEncoderASet && _LeftEncoderBSet) return 1;
    if(!_LeftEncoderASet && !_LeftEncoderBSet) return -1;
  }
}

. . . Может ли кто-нибудь объяснить функцию и как использовать все восемь проводов? Объясните, почему я получаю в 4 раза больше, чем должен, с помощью этого кода выше? ПОЖАЛУЙСТА? . . .

Я публикую изображения страниц из руководства по технике машины, на которых есть информация о сервоприводе и кодере. Информация там показывает, что он более или менее управлялся как RC - сервопривод с точки зрения материнской платы-просто ШИМ. Но у него были детали привода/драйвера/контроллера прямо на материнской плате машины.

Если это будет полезно, я могу опубликовать фотографии самой платы кодировщика, но на данный момент я не считал это необходимым.

Piniout of connector Servo encoder resolution Specs part 1 Specs part 2

, 👍0

Обсуждение

подключите +5 В и GND к кодеру ... используйте вольтметр для контроля одного выходного вывода ... медленно поворачивайте сервопривод вручную, @jsotola

Личность проводника уже установлена. Смотрите опубликованную фотографию таблицы распиновки., @111936

если это правда, то почему в вашем посте есть следующее утверждение? ... `положительное и отрицательное, вероятно, являются противоположными сигналами друг от друга, своего рода защита от ошибок или что-то в этом роде"., @jsotola

Я поместил это в свой пост, потому что прочитал несколько веб-страниц, на которых говорится, что именно так работают некоторые кодеры. И вы не процитировали вопросительный знак сразу после слова "что-то". Я добавил показания напряжения для всех проводов к вопросу., @111936


2 ответа


0

Вы уже выяснили, как работает кодер (в основном, как и любой другой вращающийся кодер, только с большим количеством выходов для разных значений угла). Это отличная работа.

Вы получаете значение в 4 раза больше из-за 2 небольших ошибок:

  1. Когда вы используете attachInterrupt(), вы настраиваете его на срабатывание при ИЗМЕНЕНИИ строки. Один импульс состоит из 2 изменений (например, от НИЗКОГО до ВЫСОКОГО, а затем от ВЫСОКОГО до НИЗКОГО). Таким образом, прерывание срабатывает дважды за импульс кодера. Это коэффициент 2 для результирующего значения.

  2. Вы подключаете прерывание к обеим линиям, но обе линии выводят по одному импульсу на один такт кодера. Таким образом, значение увеличивается дважды за тик, что означает еще один коэффициент 2. Вам нужно только прерывание на одной из линий. Другая линия предназначена только для указания направления вращения. Когда срабатывает прерывание для первой строки, вы должны проверить значение второй строки. Если он ВЫСОКИЙ, то кодер вращается в одном направлении. Если он НИЗКИЙ, он вращается в противоположном направлении. Линии внутренне соединены с маленькими кнопками/переключателями, которые прикреплены к корпусу с небольшим смещением между ними. Они активируются маленькими шишками, которые соединены с осью. В зависимости от того, с какой стороны во время вращения появляется заглушка, первой активируется первая или вторая кнопка/переключатель. Немного позже также активируется второй переключатель. Таким образом, вы можете отслеживать одну линию, и если на ней начинается импульс, вы проверяете, есть ли уже импульс на другой линии. Если да, то первой была активирована другая линия.

Таким образом, в целом это приводит к коэффициенту 4 в результатах кодера.


Обратите внимание, что ваша функция ParseEncoder() немного избыточна и чрезмерно сложна. Во внутренних операторах if вы проверяете наличие некоторых значений, этого не может произойти из-за внешнего оператора if. Но эта функция сведется к одному оператору if (или меньше, если вы используете значение напрямую без if), так как в случае с вышесказанным вам нужно проверить значение только в 1 строке.

,

ХОРОШО - узнать, что квадратурное кодирование может быть прочитано как 1x, 2x или 4x на метку ротора, - это не то же самое, что узнать, как работает этот конкретный кодер. Используя A+ и B+, я считаю все четыре возможных тика, когда проходит отметка ротора. Z+ теоретически позволил бы мне подсчитать полные обороты и проверить пропущенные триггеры прерыванием A+ - если бы я мог понять, как прерывать прерывания, потому что Z+ повышается одновременно с повышением A+. Понял. Но A - и B - и Z - остаются необъясненными/не понятыми. Не то чтобы я ДОЛЖЕН был их использовать, но я действительно хочу понять, для чего они существуют, если смогу., @111936

К сожалению, я не могу помочь вам с недокументированным оборудованием, так как не могу проверить его сам. Вы сами должны проанализировать, как ведут себя результаты. Если вы составите диаграмму, как именно ведут себя выходы, я могу попытаться угадать функцию, но не более того., @chrisl

Справедливо. Мое предположение (и причина для публикации) состояло в том, что кто-то здесь, в стеке, прочитает "кодер 8 проводов", а затем прочитает мои сообщенные напряжения .. и будет знаком с подобными кодерами достаточно, чтобы осветить мне, для чего предназначены другие провода и, возможно, даже как их использовать. У меня все еще есть смутное подозрение, что они являются избыточностью для проверки на ошибки, но я не могу быть уверен в этом с моими почти несуществующими знаниями об этих вещах., @111936

Все еще надеюсь, что кто-нибудь объяснит три других провода: A-, B-и Z -. Нельзя пометить этот ответ как *ответ* без рассмотрения первой части вопроса., @111936


2

У меня тоже были некоторые проблемы с пониманием этого. Я еще немного погуглил и нашел этот сайт ниже через сообщение на форуме Arduino: 8-проводное соединение для квадратурного энкодера, дифференциальная проводка

Вот что они говорят:

"Эти термины относятся не к форме сигналов, а к способу передачи сигналов.

В одноконтурной проводке используется один сигнальный провод на канал, и все сигналы привязаны к общей земле.

TTL и открытый коллектор-это типы односторонней проводки.

Дифференциальная проводка использует два провода на канал, которые связаны друг с другом. Сигналы на этих проводах всегда отклоняются от фазы на 180 электрических градусов или полностью противоположны. Эта проводка полезна для повышения помехозащищенности за счет большего количества электрических соединений. Дифференциальная проводка часто используется при более длинных проводах, так как любой шум, улавливаемый проводкой, отклоняется в обычном режиме".

Таким образом, в основном у нас есть провод питания и заземление, а также 2 провода на сигнал (A+/A -, B+/B -, Z+/Z-).

2 + 6 проводов = 8 проводов

Теперь все, что мне нужно выяснить, - это как подключить эти 6 проводов к Arduino. Я понял, как подключить сигналы A+, B+, Z+ на 3 выводах прерывания, теперь мне просто интересно, должны ли другие 3 (A -, B -, Z-) быть подключены еще к 3 выводам прерывания.

,

Дифференциальные сигналы должны быть подключены к [дифференциальному усилителю](https://en.wikipedia.org/wiki/Differential_amplifier) или [измерительный усилитель](https://en.wikipedia.org/wiki/Instrumentation_amplifier). Усилитель даст один выход, который может быть подключен к Arduino через [гальваническую развязку](https://en.wikipedia.org/wiki/Galvanic_isolation)., @tim