Arduino pro micro + оптический энкодер + 7 сегментный индикатор
- Войдите на сайт для отправки комментариев
Пнд, 08/08/2016 - 11:03
Доброго времени суток!
Подскажите, пожалуйста, в чем затык? Написал скетч для считывания показаний энкодера и отображения на 7-ми сегментном индикаторе на сдвиговых регистрах 74HC595
При медленном вращении вала энкодера идет нормальный счет, как начинаешь вращать быстрее - все сбивается и цифры бегут как им захочется (причем, как в мониторе порта, так и на индикаторе)
Не стправляется Ардуина с потоком данных?
#include <Encoder.h> #define ENCODER_OPTIMIZE_INTERRUPTS Encoder knobLeft(5, 6); int buttonPin = 7; #define SCLK 2 // пины ардуины #define RCLK 3 #define DIO 4 byte digitBuffer[4]; void setup() { Serial.begin(9600); Serial.println("TwoKnobs Encoder Test:"); pinMode(buttonPin, INPUT); pinMode(RCLK, OUTPUT); pinMode(SCLK, OUTPUT); pinMode(DIO, OUTPUT); } long positionLeft = -999; void loop() { long newLeft; int x1; int x2; int x3; int x4; newLeft = knobLeft.read(); if (newLeft != positionLeft) { Serial.print("Left = "); Serial.print(newLeft); Serial.println(); positionLeft = newLeft; } x4 = (newLeft / 1000) % 10; x3 = (newLeft / 100) % 10; x2 = (newLeft / 10) % 10; x1 = newLeft % 10; digitBuffer[0] = x4; digitBuffer[1] = x3; digitBuffer[2] = x2; digitBuffer[3] = x1; showDisplay(); } void showDisplay(){ const byte digit[10] = { // маска для 7 сигментного индикатора 0b11000000, // 0 0b11111001, // 1 0b10100100, // 2 0b10110000, // 3 0b10011001, // 4 0b10010010, // 5 0b10000010, // 6 0b11111000, // 7 0b10000000, // 8 0b10010000, // 9 }; const byte chr[4] = { // маска для разряда 0b00001000, 0b00000100, 0b00000010, 0b00000001 }; // отправляем в цикле по два байта в сдвиговые регистры for(byte i = 0; i <= 3; i++){ digitalWrite(RCLK, LOW); // открываем защелку shiftOut(DIO, SCLK, MSBFIRST, digit[digitBuffer[i]]); // отправляем байт с "числом" shiftOut(DIO, SCLK, MSBFIRST, chr[i]); // включаем разряд digitalWrite(RCLK, HIGH); // защелкиваем регистры delay(1); // ждем немного перед отправкой следующего "числа" } }
Что такое "медленно" и что такое "быстрее" ведомо только Вам.
Записать два байта в сдвиговый регистр - это примерно 360-370 мкс, а вот с какой частотой у Вас идут импульсы с энкодеров, лично мне неизвестно. Поэтому сравнить два числа и сделать на основании этого вывод я не могу.
что бы не терять тики от энкодера вешайте его на внешнее прерывание
или уберите SERIAL из LOOP
он конкретно тормозит
или уберите SERIAL из LOOP
он конкретно тормозит
Поддерживаю, или хотя бы на 115200 скорость поменять. Как то раз тоже долго не мог понять, почему всё тормозит.. :)
убрал SERIAL - вывожу только на индикатор - то же самое.
если закомментить void showDisplay(), и выводить на монитор - то ничего не тормозит при любой скорости вращения энкодера..и тики не теряются...
Уберите последнюю строку в подпрограмме индикации delay(1) и посмотрите, что получится.
Если не поможет, то сделайте вывод на дисплей в условии.
Скорее всего, дело в том, что на консоль Вы бросаете данные только при изменениии положения, а на дисплей выводите постоянно.
убрал delay - не помогло
если вывод на бисплей добавить в условие, то он загорается только тогда, когда крутиш энкодер и гаснет, т.к. получается, что разряды включаются только когда выполняется условие...
весь затык, кажется, в этом куске кода
Как думаете. если поменять 7 сегментник на LCD дисплей - изменится ситуация?
Извините, не обратил внимания, что индикация динамическая. Тогда лучше будет сделать индикацию 1 разряда после очередного считывания энкодера. Что-то вроде
В начале программы прописываете
byte Number =0;
Там, где индикация пишете
i=Number;
// дальше собственно индикация одного разряда с номером i без задержки в конце
if (Number >3 ) Number=0 else Number++;
Ну а если и это не поможет, то надо ускорять работы подпрограмм загрузки значения в сдвиговые регистры, если она сделана на DigitalWrite, то это может быть ОЧЕНЬ долго.
вам помогут прерывания
на внешнее прерывание вешаете одну ногу энкодера
а на таймере 2 организуете динамическую индикацию
имхо
Почитал про библиотеку Encoder.h - повесил ноги энкодера на пины ардуино, поддерживающие прерывания (2, 3) и все нормально заработало.
спасибо всем за помощь!