Arduino + a4001sr + 74ch4049h

Тема в разделе "Arduino & Shields", создана пользователем dreadfull, 4 апр 2021.

  1. dreadfull

    dreadfull Гик

    доброго времени суток.
    дано: плата с семисигментными индикаторами A4001SR, с операционными усилителями ULN2003 и сдвиговыми регистрами 74CH4049h и с полным комплектом обвязки для их гармоничного фунциклирования.
    имеется разъём питания и разъём для сигнала (5 пинов)

    нужно: собрать часы на ардуинке

    суть проблемы:
    если загуглить "ардуино+индикатор+регистр" то нам предложит тьму тьмущую готовых проектов на базе сдвигового регистра мод. 74hc595 и в вопросе подключения появляются непонятки.....
    как бы логика подсказывает что сдвиговые регистры однотипные, найти похожие пины, подключить, залить скетч и радоваться жизни, но на первом этапе есть проблемы. пины как бы отличаются, нужна подсказка.

    тут даташит на 74CH4049h https://www.infinite-electronic.ru/datasheet/ef-74HC4094N,652.pdf
    тут даташит на 74hc595 https://www.diodes.com/assets/Datasheets/74HC595.pdf

    с самой платы выходят:
    1. земля (понятно для общего логического уровня)
    2. CP (Clock Input)
    3. D (data input)
    4. OE (Output enable input) - я так понял он должен быть либо low либо hight
    5. Qs1 (serial output) для передачи сигнала на следующую плату с индикаторами

    для простого случая 74hc595 использует пины:
    SH_CP - тактовый вход регистра сдвига
    DS - "вход данных" это же аналог D (data input)???
    ST_CP - тактовый вход регистра хранения
     

    Вложения:

  2. parovoZZ

    parovoZZ Гуру

    И в чём проблема?
    D <-> DS
    CP <-> SHCP
    STR <-> STCP
    OE <-> OE
    MR <-> absent
     
    dreadfull нравится это.
  3. dreadfull

    dreadfull Гик

    ок.
    D всё же DS. хорошо
    CP <-> SHCP то же понятно
    покоя не даёт STCP, везде в скетчах используется....
    но на плате обнаружено ответвление от OE. т.е. контакт соединяется с пинами 74CH4049h, а потом уходит на затвор транзистора и возвращается на STR (strobe).

    логично ли соединять OE <-> STCP???
     
  4. dreadfull

    dreadfull Гик

    да, заработало
     
  5. dreadfull

    dreadfull Гик

    итак, OE повесил на STCP и циферки побежали)))
    использовал вот такой простецкий код:
    Код (C++):
    #define dataPin  10  // пин подключен к входу DS
    #define latchPin 11  // пин подключен к входу ST_CP
    #define clockPin 12  // пин подключен к входу SH_CP

    void setup() {
       // устанавливаем режим работы пинов OUTPUT
       pinMode(latchPin, OUTPUT);
       pinMode(clockPin, OUTPUT);
       pinMode(dataPin, OUTPUT);
       // ставим HIGH на "защёлку", чтобы регистр не принимал сигнал
       digitalWrite(latchPin, HIGH);
    }

    void loop() {
       digitalWrite(latchPin, LOW);  // цифра один
       shiftOut(dataPin, clockPin, LSBFIRST, 0b01100000);
       digitalWrite(latchPin, HIGH);
       delay(1000);

       digitalWrite(latchPin, LOW);  // цифра два
       shiftOut(dataPin, clockPin, LSBFIRST, 0b11011010);
       digitalWrite(latchPin, HIGH);
       delay(1000);

       digitalWrite(latchPin, LOW);  // цифра три
       shiftOut(dataPin, clockPin, LSBFIRST, 0b11110010);
       digitalWrite(latchPin, HIGH);
       delay(1000);

       digitalWrite(latchPin, LOW);  // цифра четыре
       shiftOut(dataPin, clockPin, LSBFIRST, 0b01100110);
       digitalWrite(latchPin, HIGH);
       delay(1000);

       digitalWrite(latchPin, LOW);  // цифра пять
       shiftOut(dataPin, clockPin, LSBFIRST, 0b10110110);
       digitalWrite(latchPin, HIGH);
       delay(1000);
    }
    теперь есть вопрос как подключить вторую плату с индикаторами (а то 3 цифры мало, а вот 6 в самый раз!)
    есть контакт Qs1 (serial output) на первой плате и его так понимаю необходимо подсоединить к контакту D (data input) на второй плате.
     
  6. dreadfull

    dreadfull Гик

    пришло понимание что в обычном случае люди подключают сдвиговый регистр для засвета только элементов индикатора, а для засвета конкретной цифры используют свободные пины ардуинки. у нас же сама плата предусматривает последовательное включение нескольких регистров со своими индикаторами. и тут что-то стало слишком сложно для меня......
    получается нужна функция обмена с SPI в который теперь нужно скармливать не один, а два бита данных, один для номера сегмента, второй для номера индикатора...:mad:
     
  7. dreadfull

    dreadfull Гик

    осознал объём проблемы.
    1. необходимо регистру скармливать не просто цифры, и цифры в двоичном формате.
    2. по-скольку у нас несколько регистров последовательно подсоединены, а нужно что бы цифра стояла на месте , а не плавала, необходимо скормить регистру ещё один байт с порядковым номером цифры))))

    ладно тут изложу что у меня получается.
    в планах часы запитать от DS3231 (или что-то в этом роде), а пока пользуемся внутренним millis().
    сейчас в мониторе порта вижу отдельными цифрами секунды, десятки секунд, минуты и т.д. а вот при вызове Serial.println(numbers_array[unit]); вижу сумму текущего значения от массива. почему вместо "0b01100000" я вижу 2???

    Код (C++):

    #define dataPin  10  // пин подключен к входу DS
    #define latchPin 11  // пин подключен к входу ST_CP
    #define clockPin 12  // пин подключен к входу SH_CP
    static uint32_t last_time, now = 0; // RTC
    const byte numbers_array[10] = { // cоздаём массив цифр 0-9 в двоичном коде
      0b00000000,
      0b01100000,
      0b11011010,
      0b11110010,
      0b01100110,
      0b10110110,
      0b10111110,
      0b11100000,
      0b11111110,
      0b11110110     // 9
    };
    int thousands;    // обзываем десятки минут
    int hundreds;     // обзываем  минуты
    int tens;         // обзываем десятки секунд
    int unit;         // обзываем секунды

    void setup()
    {
      Serial.begin(9600);
      now=millis(); // читать начальное значение RTC
      // устанавливаем режим работы пинов OUTPUT
       pinMode(latchPin, OUTPUT);
       pinMode(clockPin, OUTPUT);
       pinMode(dataPin, OUTPUT); // ставим HIGH на "защёлку", чтобы регистр не принимал сигнал
       digitalWrite(latchPin, HIGH);
    }

    void loop()
    {
        now=ceil(millis()/1000) ; // читать начальное значение RTC
        Serial.print(now ); Serial.print("   ");// выводим количество секунд
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin, LSBFIRST, numbers_array[unit]);// отправляем на регистр байт с екундой
        digitalWrite(latchPin, HIGH);
        delay(1000);
       
        int thousands = now/1000%10;  // вычисляем десятки минут
        int hundreds = now/100%10;    // вычисляем  минуты
        int tens = now/10%10;         // вычисляем десятки секунд
        int unit = now%10;            // вычисляем секунды
      Serial.print((tens)); Serial.println(numbers_array[unit]);
    }
     
  8. parovoZZ

    parovoZZ Гуру

    Я пользуюсь терминалом HTerm. Там формат вывода настраивается по клику мыши.
     
  9. dreadfull

    dreadfull Гик

    да толку то?
    мне бы подсказать как заставить из массива вытягивать определённый байт и отправлять в Serial.print
     
  10. parovoZZ

    parovoZZ Гуру

    Значит их и надо передавать в форме байта, а не ASCII символа.

    разумеется. Это же элемент двоичной логики. Сдвиговый регистр из последовательного кода делает параллельный. Больше ничего делать он не умеет.
     
  11. dreadfull

    dreadfull Гик

    ну так значения находятся в массиве формата "const byte numbers_array[10]". пробовал без "const", ситуация та же.
    пробовал поменять "0b01100000" на цифры, всё работает. т.е. конструкция numbers_array[unit] работает со временем ок, но не хочет понимать сам набор нуликов и единичек.
     
  12. akl

    akl Гуру

    зачем переменные второй раз объявлены? это уже другие переменные.

    попробуй вместо 0b01100000 писать B01100000
     
  13. dreadfull

    dreadfull Гик

    ну да, только с ними проблем нет.
    пробовал, результат тот же.
    при вызове Serial.println(numbers_array[unit]); пишет какую-то херню(
     
  14. akl

    akl Гуру

    какую конкретно? 0b01100000 это например должно быть `
     
  15. dreadfull

    dreadfull Гик

    как раз таки "0b01100000" я и хочу увидеть, а вместо этого (левый столбик :Serial.print(now );, правый Serial.println(numbers_array[unit]);)
    Код (C++):
    0   0
    1   96
    3   242
    4   102
    5   182
    6   190
    7   224
    8   254
    9   246
    10   0
    11   96
    12   218
    13   242
    14   102
    15   182
    16   190
    17   224
    18   254
    19   246
    20   0
    21   96
     
     
  16. akl

    akl Гуру

    всё правильно печатает.
    пиши
    Serial.println(numbers_array[unit], BIN);
     
    dreadfull нравится это.
  17. dreadfull

    dreadfull Гик

    окай, теперь вроде как заработало. код выглядит так:
    Код (C++):
    #define dataPin  10  // пин подключен к входу DS
    #define latchPin 11  // пин подключен к входу ST_CP
    #define clockPin 12  // пин подключен к входу SH_CP
    static uint32_t last_time, now = 0; // RTC
    byte numbers_array[10] = { // cоздаём массив цифр 0-9 в двоичном коде
      B00000000,
      B01100000,
      B11011010,
      B11110010,
      B01100110,
      B10110110,
      B10111110,
      B11100000,
      B11111110,
      B11110110     // 9
    };

    void setup()
    {
      Serial.begin(9600);
      now=millis(); // читать начальное значение RTC
      // устанавливаем режим работы пинов OUTPUT
       pinMode(latchPin, OUTPUT);
       pinMode(clockPin, OUTPUT);
       pinMode(dataPin, OUTPUT); // ставим HIGH на "защёлку", чтобы регистр не принимал сигнал
       digitalWrite(latchPin, HIGH);
    }

    void loop()
    {
        now=ceil(millis()/1000) ; // читать начальное значение RTC
        Serial.print(now ); Serial.print("   ");// выводим количество секунд
        int thousands = now/1000%10;  // вычисляем десятки минут
        int hundreds = now/100%10;    // вычисляем  минуты
        int tens = now/10%10;         // вычисляем десятки секунд
        int unit = now%10;            // вычисляем секунды
       // Serial.print((tens));
        Serial.println(numbers_array[unit], BIN);
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin, LSBFIRST, (numbers_array[unit], BIN));// отправляем на регистр байт с екундой
        digitalWrite(latchPin, HIGH);
        delay(1000);
    }
    монитор порта так:
    Код (C++):
    0   0
    1   1100000
    3   11110010
    4   1100110
    5   10110110
    6   10111110
    7   11100000
    8   11111110
    9   11110110
    10   0
    11   1100000
    12   11011010
    13   11110010
    14   1100110
    15   10110110
    16   10111110
    17   11100000
    18   11111110
    19   11110110
    20   0
    21   1100000
    22   11011010
     
    вроде хорошо, НО пропадают нули до числа. к примеру "0" должен быть "000000000", а 4 должна быть "01100110"
    и самое главное на индикаторах вместо цифр появляются только "-"......
     
  18. akl

    akl Гуру

    чтобы печатало в порт со всеми нулями и прочими свистелками и перделками придется либо использовать sprintf который будет как надо печатать в некую строку а нет в sprintf нету двоичного вида печати, так что только пилить собственную функцию.

    по индикаторам надо проверять что как подключено.
     
    Последнее редактирование: 6 апр 2021
  19. dreadfull

    dreadfull Гик

    при использовании скетча из поста №5 все цифры прыгают, мигают, всё ок. т.е. строка
    Код (C++):
    shiftOut(dataPin, clockPin, LSBFIRST, 0b11011010);
    работает чётко, а вот при смене 0b11011010 на аналог (numbers_array[unit], BIN) что-то не работает:oops:
     
  20. akl

    akl Гуру

    shiftOut(dataPin, clockPin, LSBFIRST, (numbers_array[unit], BIN));
    а тут то BIN нафига?

    как ваще такую дичь компилятор пропустил