Привет всем! Нужна помощь с подключением нескольких энкодеров miniQ(http://amperka.ru/product/miniq-wheel-encoder). Как их можно подключить через макетную плату, чтобы считывать показания с каждого энкодера(под левое и правое колесо)? И как прописать в программе, чтобы на монитор последовательного порта выводилось показание с правого и левого энкодеры(желательно еще и сделать пометки, чтобы понимать что откуда)? Заранее спасибо откликнувшимся!
Данный энкодер просто выдает цвет противостоящих датчикам энкодера участков колеса. Не знаю, черный (отсутствие отражения) или белый (отражение) приводит к появлению единицы, но это значения не имеет. Суть в том, что колесо, предназначенное для использования с этим энкодером, имеет чередование черных и белых участков. А датчики сдвинуты относительно друг друга таким образом, что по разнице их показаний можно судить о направлении вращения колеса. Датчики подключаются к цифровым пинам и их текущее состояние может быть считано с помощью digitalRead, но лучше воспользоваться механизмом прерываний. Для этого сигнал с одного из датчиков заводится на пин с прерыванием, а другой на какой-нибудь иной пин. Прерывание можно "повесить" на любое событие (падение уровня, увеличение уровня, изменение уровня). Последний вариант позволит более точно определять угол поворота (импульсы будут возникать в два раза чаще, т.е. при повороте на вдвое меньший угол). В самом простом случае в обработчике прерывания можно просто считать факты вызова прерывания, увеличивая значение глобальной переменной на единицу, которую надо не забыть объявить как volatile. Можно также учитывать направление движения. Для этого достаточно в обработчике прерывания получить состояние второго датчика и в зависимости от него увеличивать или уменьшать счетчик на единицу (поскольку направление движения "туда" и "обратно" относительно, придется экспериментально установить, какое именно значение на втором датчике следует использовать для увеличения счетчика, а какое для уменьшения). Если прерывание установлено по смене уровня, также придется дополнительно прочитать состояние и первого датчика и также учитывать его при определении направления вращения. Для второго энкодера, установленного на другом колесе, все будет точно так же. Как использовать счетчик - отдельный вопрос. Простенький пример: Спойлер: Код Код (C): #define BTSERIAL Serial #define DEBUGMODE 1 #define nop() __asm volatile ("nop") #if 1 nop(); #endif #define PIN_MDIR_1 4 #define PIN_MDIR_2 7 #define PIN_MPWR_1 5 #define PIN_MPWR_2 6 #define PIN_MENC_IRQ_1 2 #define PIN_MENC_IRQ_2 3 #define PIN_MENC_ADD_1 10 #define PIN_MENC_ADD_2 11 #define STOPZONE_SPEED 12 #define STOPZONE_DIR 12 #define MINPOWER 100 signed int speedM=0; signed int diff=0; volatile long int Encoder1=0; volatile long int Encoder2=0; void setup() { pinMode(PIN_MDIR_1, OUTPUT); pinMode(PIN_MDIR_2, OUTPUT); pinMode(PIN_MPWR_1, OUTPUT); pinMode(PIN_MPWR_2, OUTPUT); pinMode(PIN_MENC_IRQ_1, INPUT); pinMode(PIN_MENC_IRQ_2, INPUT); pinMode(PIN_MENC_ADD_1, INPUT); pinMode(PIN_MENC_ADD_2, INPUT); #if DEBUGMODE Serial.begin(9600); #endif //BTSERIAL.begin(57600); attachInterrupt(0, Encoder1Interrupt, RISING); attachInterrupt(1, Encoder2Interrupt, RISING); } void loop() { WriteSerialMessage(); ReadSerialMessage(); byte dirL = LOW; byte dirR = HIGH; byte pwrL = 0; byte pwrR = 0; signed int speedL = 0; signed int speedR = 0; speedM=(speedM>-STOPZONE_SPEED)&&(speedM<STOPZONE_SPEED)?0:speedM; diff=(diff>-STOPZONE_DIR)&&(diff<STOPZONE_DIR)?0:diff; int halfdiff=diff/2; if (halfdiff>0) { speedL = (speedM-halfdiff>=-512)?speedM-halfdiff:-512; speedR = (speedM+halfdiff<=511)?speedM+halfdiff:511; } else { speedL = (speedM-halfdiff<=511)?speedM-halfdiff:511; speedR = (speedM+halfdiff>=-512)?speedM+halfdiff:-512; } dirL = (speedL >= 0); dirR = !(speedR >= 0); pwrL = (speedL==0)?0:map(abs(speedL),1,512,MINPOWER,255); pwrR = (speedR==0)?0:map(abs(speedR),1,512,MINPOWER,255); digitalWrite(PIN_MDIR_1, dirL); digitalWrite(PIN_MDIR_2, dirR); analogWrite(PIN_MPWR_1, pwrL); analogWrite(PIN_MPWR_2, pwrR); } void ReadSerialMessage() { char c; if (BTSERIAL.available()) { c=BTSERIAL.read(); Serial.print(c); if (c=='C') { speedM = BTSERIAL.parseInt(); diff = BTSERIAL.parseInt(); #if DEBUGMODE Serial.print("C command: "); Serial.print("Speed = "); Serial.print(speedM); Serial.print(" Diff = "); Serial.println(diff); #endif } } } long int lastEncoder1=0; long int lastEncoder2=0; void WriteSerialMessage() { if ((Encoder1!=lastEncoder1)||(Encoder2!=lastEncoder2)) { BTSERIAL.print("E"); BTSERIAL.print(Encoder1); BTSERIAL.print(","); BTSERIAL.print(Encoder2); BTSERIAL.print("."); BTSERIAL.println("Z"); lastEncoder1=Encoder1; lastEncoder2=Encoder2; } } void Encoder1Interrupt() { if (digitalRead(PIN_MENC_ADD_1) == LOW) { Encoder1--; } else { Encoder1++; } } void Encoder2Interrupt() { if (digitalRead(PIN_MENC_ADD_2) == LOW) { Encoder2++; } else { Encoder2--; } } Данные с энкодеров передаются по последовательному порту (посылка, начинающаяся с "E" и содержащая через запятую текущее значение счетчиков, которые получены при помощи энкодеров): Через тот же порт осуществляется и управление командами вида "С<скорость>,<поворот>Z" Пример рассчитан на применение амперковского моторшилда и вроде бы леонардоподобной ардуины (точно не помню, для перехода на уну, возможно, что-то придется подправить с прерываниями).
Спасибо за объяснения. У меня уже есть код для определения направления вращения и скорости колеса, меня интересует только как различать энкодеры(левое и правое колесо). Если необходимо - я могу приложить код. Пробовал подключать их в разные порты (2-3 и 4-5) - значения выдает с каждого, но не зная заранее какой куда подключен невозможно определить какой куда вращается. Меня интересует именно как в программе присвоить "имя" каждому датчику, чтобы различать их показания при выводе на экран.
Только введением именованных констант для пинов, к которым подключены энкодеры и заданием соответствующих имен для переменных, в которых будут храниться счетчики, а потом в качестве номеров пинов использовать только соответствующие константы. Для полноты картины можно и для номеров прерываний задать константы, чтобы в программе было понятно, что к какому энкодеру относится Примерно как приведенном примере, только в примере до констант для номеров прерываний не дошло. Контролировать же, какой именно энкодер подключен к каким пинам физически, придется исключительно "вручную", поскольку энкодер не имеет никаких отличительных признаков, которые можно запросить в программе.
Хорошо, это для случая, когда каждый энкодер в свой пин, а что делать, если я их включу в макетную плату? Или в таком случае они просто не будут работать?
При использовании макетной платы должна четко прослеживаться цепь от энкодера к пину ардуины (маркировкой или цветом проводов). Тогда будет видно, какой энкодер подключен к какому пину.
Вы меня возможно неправильно поняли. Я хочу подключить оба энкодера в одну пару пинов (2-3, например) с помощью макетной платы. Как мне, опрашивая пины 2-3 понять, какие показания идут с левого, а какие с правого энкодера?