Дисковый номеронабиратель (доводка до ума)

Тема в разделе "Arduino & Shields", создана пользователем ZFred, 30 янв 2018.

  1. ZFred

    ZFred Нерд

    Снова подниму эту тему. Сразу прошу прощения кому надоел. Сут в том, что значения все таки стали адекватно считываться, но пришлось поменять резисторы 10КОм на 200 ом и 2 и 3 пины поменять местами, относительно схемы, иначе значения ни в какую не считывались. Проблема в другом: считывание происходит с запозданием на 1 значение. Если 2 и 3 пины оставить как на схеме, то запоздания нет, но считывание не корректно. Подскажите, какую строку в скетче изменять, что бы считывание происходило сразу? схема номеронабиратель.jpg
     
  2. ZFred

    ZFred Нерд

    Снял как смог. Прошу прощения за качество!

     
  3. Tomasina

    Tomasina Сушитель лампочек Модератор

    Скетч-то где?
     
  4. ostrov

    ostrov Гуру

    Там принцип как у энкодера? Два прерывателя по очереди контачат с плюсом или что? Антидребезг то добавили?
     
  5. Tomasina

    Tomasina Сушитель лампочек Модератор

    Нет, один контакт разомкнут при любом положении диска, кроме исходного, другой даёт количество импульсов равное номеру.
     
  6. ZFred

    ZFred Нерд


    Я уж думал никто не отзовётся)

    #include <Bounce.h>

    #define PIN_SW_COUNTER 3 // Выход DC3 - на этом выходе считаем прервывания счетчика
    #define PIN_SW_REVERSE 2 // Выход DC2 - на этом выходе отмечаем конец набора цифры
    #define PIN_SW_HANGUP 4 // Выход DC4 - сюда подключаем рычаг сброса

    #define PIN_LED_PASS 8 // Выход DC8 - сюда сигналим в случае Успешного ввода кода
    #define PIN_LED_FAIL 12 // Выход DC12 = сюда сигналим в случае ошибочного кода

    #define LEN_PASSCODE 4 // Определяем длину кода


    const uint8_t pass[LEN_PASSCODE] = {1,1,1,1}; // Код для проверки
    uint8_t code[LEN_PASSCODE]; // в этом массиве будем запоминать введенные цифры
    uint8_t n_digits = 0; // счетчик кол-ва введенных цифр

    int valH = 0;
    int valC = 0;
    int valR = 0;

    int C_DEBOUNCE = 1000; // Задержка в млСек для обработки дребезга контактов прервывания Счетчика
    int R_DEBOUNCE = 40; // Задержка в млСек для обработки дребезга контактов прервывания Реверса
    volatile unsigned long last_miC; // таймстемп для обработки задержки внутри прерывания
    volatile unsigned long last_miR; // таймстемп для обработки задержки внутри прерывания


    volatile bool vSuccess = false; // Победа или Играем дальше
    volatile bool vSignal = false; // Сигнал давать? или нет?

    volatile int vPinState = HIGH; // Состояние выхода

    int vCount = 0;

    void setup()
    {
    Serial.begin(9600); // Определяем скорость соединения с монитором

    attachInterrupt(digitalPinToInterrupt(PIN_SW_REVERSE),iRevers,RISING); // Определяем процедуру обработки прерывания Реверса
    attachInterrupt(digitalPinToInterrupt(PIN_SW_COUNTER),iCounter,RISING); // Определяем процедуру обработки прерывания Счетчика

    pinMode(PIN_SW_COUNTER, INPUT_PULLUP); // Задаем режим работы выходов
    pinMode(PIN_SW_REVERSE, INPUT_PULLUP);
    pinMode(PIN_SW_HANGUP, INPUT_PULLUP);
    pinMode(PIN_LED_PASS, OUTPUT);
    pinMode(PIN_LED_FAIL, OUTPUT);
    }

    void loop()
    {
    digitalWrite(PIN_LED_PASS, vPinState); // Состояние по умолчанию HIGH - Работает нормально ЗАмкнутый контакт Реле DS2
    digitalWrite(PIN_LED_FAIL, HIGH); // Состояние по умолчанию HIGH - Работает нормально РАЗомкнутый контакт Реле DS1


    if (!digitalRead(PIN_SW_HANGUP)) // Если на этом выходе земля
    {

    for (uint8_t i = 0; i < n_digits; i++) code = 0; // чистим массив введенного кода
    valH = digitalRead(PIN_SW_HANGUP); // пишем в монитор
    Serial.print("HANGUP :");
    Serial.println(valH);
    n_digits = 0; // начинаем считать сначала
    }

    if (vSignal) // если в результате обработки Прерывания Реверс нужно дать сигнал
    {
    if (vSuccess) // и если вдруг Победа, то
    {
    vPinState = LOW; // меняем сигнал на выходе победа
    digitalWrite(PIN_LED_PASS, vPinState); // реле клацает в DS2 начинает работать нормально РАЗомкнутый контакт - светодиод тушится
    Serial.print(vPinState);
    delay(3000); // ждем три секунды (можно либоо вообще не включать назад либо изменить и ждать больше - по желанию)

    vPinState = HIGH;
    digitalWrite(PIN_LED_PASS, vPinState); // зажигаем Победный светодиод снова (реле клацает в нормально DS2 ЗАмкнутое положение)
    }
    else
    { // если Играем дальше, то

    digitalWrite(PIN_LED_FAIL, LOW); // клацаем Реле DS1 в нормально РАЗомкнутое положение = Светодиод Ошибки горит первый раз
    delay(300); // ждем
    digitalWrite(PIN_LED_FAIL, HIGH); // тушим светодиод Ошибки
    delay(300); // ждем
    digitalWrite(PIN_LED_FAIL, LOW); // зажигаем светодиод Ошибки второй раз
    delay(300); // ждем
    digitalWrite(PIN_LED_FAIL, HIGH); // тушим второй Раз


    }
    vSignal = false; // возвращаем индикотор сигнала в исходное положение
    }
    }

    void iRevers(){
    if ((long)(millis()-last_miR) >= R_DEBOUNCE){ // Задержка = обработка дребезга контактов

    valR = digitalRead(PIN_SW_REVERSE);

    if (valR == 1 && vCount > 0) { // Если реально закончили набирать цифру (физически сюда попадаем в начале и в конце набора цифры ... поэтому проверяем чтобы счетчик небыл пустым)

    if (vCount == 10) vCount = 0; // Обработка набора Ноля - в этом случае счетчик возвращает значение 10

    code[n_digits]=vCount; // записываем очередную цифру в массив кода
    Serial.print("CODE:"); // выводим на монитор
    for (uint8_t i = 0; i < LEN_PASSCODE; i++) {
    Serial.print(code);
    }
    Serial.println("");
    n_digits++; // считаем сколько цифр уже введено

    if (n_digits>=LEN_PASSCODE) // если код введен полностью
    {
    bool match = true;
    for (uint8_t i = 0; i < LEN_PASSCODE; i++) if (pass!=code) match = false; // по циклу проверяем каждую цифру

    if (match) // если Победа
    { //digitalWrite(PIN_LED_PASS, LOW);
    //digitalWrite(PIN_LED_FAIL, HIGH);
    Serial.println("SUCCESS!!!!");
    vSuccess = true; // отмечаем Победу в переменной для следующей обработки

    }
    else // играем дальше
    {//digitalWrite(PIN_LED_PASS, HIGH);
    //digitalWrite(PIN_LED_FAIL, LOW);
    Serial.println("FAILED! TRY AGAIN");

    vSuccess = false; // отмечаем Ошибку в переменной для следующей обработки
    }
    vSignal = true; // Взводим индикатор для того, чтобы подать сигнал либо Победа либо Ошибка
    Serial.print("CLEANED CODE:");
    for (uint8_t i = 0; i < n_digits; i++) // Чистим Код
    { code = 0;
    Serial.print(code);
    }
    Serial.println("");
    n_digits = 0; // Сбрасываем счетчик ввденных цифр кода
    }


    vCount=0; // Сбрасываем Счетчик
    last_miR = millis();
    }
    }
    }

    void iCounter(){
    if ((long)(millis()-last_miC) >= C_DEBOUNCE){ // Задержка для обработки дребезга контактов
    vCount++; // Если реально щелчек - то увеличиваем значение текущей цифры
    valC = digitalRead(PIN_SW_COUNTER);
    //Serial.print("COUNT :");
    //Serial.println(vCount);

    last_miC = millis();
    }
    }
     
  7. ZFred

    ZFred Нерд


    http://forum.amperka.ru/threads/Дисковый-номеронабиратель.14257/