Multi-function shield как управлять 4-разрядным 7-семисегментным led индикатором?

Тема в разделе "Iskra JS, Espruino, Йодо", создана пользователем Николай М, 1 июн 2023.

  1. Обучаюсь программировать на Iskra JS и Multi-function Shield.
    Довольно сложно, но удалось вывести одну цифру на одном разряде дисплея.

    Как сделать так, чтобы можно было выводить 4-х значные цифры?

    (Несколько дней уже бьюсь, но что-то никак не могу понять как заставить это работать. Библиотеки quaddisplay, quaddisplay2 смотрел, но вроде как не подходят. Применить их я не смог.)
    [​IMG]

    [​IMG]
    mc74hc595AD

    Пока вот такой код получился:

    Код (Javascript):
    var LATCH_DIO = P4;
    var CLK_DIO = P7;
    var DATA_DIO = P8;

    var digits = [
      [1, 1, 0, 0, 0, 0, 0, 0], // 0
      [1, 1, 1, 1, 1, 0, 0, 1], // 1
      [1, 0, 1, 0, 0, 1, 0, 0], // 2
      [1, 0, 1, 1, 0, 0, 0, 0], // 3
      [1, 0, 0, 1, 1, 0, 0, 1], // 4
      [1, 0, 0, 1, 0, 0, 1, 0], // 5
      [1, 0, 0, 0, 0, 0, 1, 0], // 6
      [1, 1, 1, 1, 1, 0, 0, 0], // 7
      [1, 0, 0, 0, 0, 0, 0, 0], // 8
      [1, 0, 0, 1, 0, 0, 0, 0], // 9
      [0, 1, 1, 1, 1, 1, 1, 1], // .
      [1, 1, 1, 1, 1, 1, 1, 1]  // Empty
    ];

    var segments = [
      [],
      [1, 1, 1, 1, 1, 0, 0, 0], // 1/4
      [1, 1, 1, 1, 0, 1, 0, 0], // 2/4
      [1, 1, 1, 1, 0, 0, 1, 0], // 3/4
      [1, 1, 1, 1, 0, 0, 0, 1], // 4/4
    ];

    function show_digit(d,s){
      digitalWrite(LATCH_DIO, 0);
      shiftOut(DATA_DIO, { clk : CLK_DIO}, digits[d]);
      shiftOut(DATA_DIO, { clk : CLK_DIO}, segments[s]);
      digitalWrite(LATCH_DIO, 1);
    }

    show_digit(8,1);
     
    Последнее редактирование: 1 июн 2023
  2. [​IMG]
     
    Последнее редактирование: 1 июн 2023
  3. Судя по тому как работают сдвиговые регистры и led индикатор, то надо получается "очень быстро" выводить все 4 цифры последовательно и зациклено:

    Код (Javascript):
    setInterval(function() {
      send_data(1,1);
      send_data(2,2);
      send_data(3,3);
      send_data(4,4);
    },0);
     
  4. Нашёл в интернете модуль 4-bit LED Digital Tube.
    [​IMG]
    Получается им точно также можно управлять.
    И под него есть библиотека на Arduino https://github.com/GyverLibs/SevenSegmentsDisp
     
  5. Asper Daffy

    Asper Daffy Иксперд

    Не очень. Нужно, чтобы частота полного цикла отрисовки экрана была 50+ герц. Т.е. в случае 4 знаков, нужно каждую держать на экране 5 мс.

    Обычно это делается так:
    1. Вычисляется время показа каждого знака в тактах по формуле: "N = F_CPU x 0,02 / <количество знаков>" (при любых нецелостях, результат округлять в меньшую сторону, а не в большую);
    2. Заводится таймер, который будет выдавать прерывания каждые N тактов контроллера;
    3. В обработчике прерывания показывается очередной знак (т.е. при первом прерывании - 0-ой, потом 1-ый, 2-ой, 3-й, снова 0-ой и т.д.).
    Тогда, о показе в основной программе можно забыть. В ней просто прописывать значение которое нужно показывать, а в обработчике прерывания оно само покажется.
     
    Николай М, Ariadna-on-Line и ИгорьК нравится это.
  6. a1000

    a1000 Гуру

    Есть готовый 4 разрядный модуль на ТМ1637. Есть под него и готовые библиотеки.
    А вообшем вы правильно поняли суть управления индикатором напрямую.
    Это называется динамическая индикация.
     
    Николай М нравится это.
  7. parovoZZ

    parovoZZ Гуру

    Вы про js или про что?
     
    Airbus нравится это.
  8. Airbus

    Airbus Радиохулиган Модератор

    Хороший шилд.
     
    Николай М нравится это.
  9. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Тоже купил такой шилд. Доволен вполне. Не помню уже где взял, но эта библа работает. Разархивируйте и целиком вставьте в папку библиотек.
    Прикладываю оригинал - скетч часов. По нему поймете работу с этой библой.
    Там главная фишка в распознавании короткого и долгого нажатия кнопарей.
    И в организации вложенного меню из этих нажатий.
    Могу выложить свой скетч. Но он сырой. Там прикручен вывод коротенького текста, RTC, IR датчик и DHT сенсор. Будильник и ИК-управление работают, а к сенсору не доделано меню. Доведете до ума - выложите.
    ПС. В основе работы дисплея на шилде лежит управление сдвиговыми регистрами K74HC595, и организация динамической индикации. Если делать нечего - можете поизвращаться ногодрыганьем, Нет ничего сложного. Готовую библиотеку для работы с регистрами можете найти отдельно штатными средствами IDE. Больше в шилде нет ничего интересного.
     

    Вложения:

    Последнее редактирование: 1 июн 2023
  10. Airbus

    Airbus Радиохулиган Модератор

    У меня показывает частоту настройки Fm приемника на RDA чипе. Но скетч на Си.
    Код (Text):
    // подключаем библиотеку для Multi Function Shield
    #include <MFShield.h>
    // подключаем бибилиотеку для I2C интерфейса
    #include <Wire.h>
    // подключаем библиотеку для модуля TEA5767
    #include <TEA5767N.h>

    // определяем назначение кнопок на Multi Function Shield
    #define BUTTON_START  2
    #define BUTTON_PLUS   3
    #define BUTTON_MINUS  1

    // создаем объекты для модулей
    MFShield mfs;
    TEA5767N radio = TEA5767N();

    // создаем переменную и устанавливаем начальную частоту
    // частота хранится в целых значениях, а на модуль отпарвляем ее деленную на 10
    int freq = 1029;
    uint32_t t;

    // Обрабатываем нажатия клавиш
    void keyAction (uint8_t key)
    {
      switch (key)
      {
        // увеличиваем частоту на 0.1 МГц
        case BUTTON_PLUS:
          freq += 1;
          break;

        // увеличиваем частоту на 0.1 МГц
        case BUTTON_MINUS:
          freq -= 1;
          break;

        // отпарвляем текущее значение частоты в модуль ФМ-приемника
        case BUTTON_START:
          mfs.showDisplay (false);
          radio.setStandByOn();
          radio.selectFrequency(float(freq) / 10);
          radio.setStandByOff();
          mfs.showDisplay (true);
          break;
      }
      // выводим текущую частоту на индикатор
      mfs.display(freq, true);    
    }
    /* =================================================== */
    void setup() {
      // выключаем радио, если оно было включено
      radio.setStandByOff();
      // привязываем нашу функцию обработки кнопок к объекту Multi Function Shield
      mfs.onKeyPress (keyAction);
      // отправляем текущую частоту в модуль ФМ-радио
      radio.selectFrequency(float(freq) / 10);
    }

    void loop() {
      // выводим текущую частоту на индикатор
      mfs.display(freq, true);
      mfs.loop();
    }
    А тут вроде как речь о скриптах?
     
    Последнее редактирование: 1 июн 2023
  11. parovoZZ

    parovoZZ Гуру

    я верю, что ты можешь. Но нафига он автору, если он ваяет на JS, а не на сях?
     
    Ariadna-on-Line нравится это.
  12. После нескольких дней "исследований" получилось выводить разные целые числа от -999 до 9999.

    [​IMG]

    Код (Javascript):
    var LATCH_DIO = P4;
    var CLK_DIO   = P7;
    var DATA_DIO  = P8;

    /*---------

        a
      f   b
        g
      e   c
        d
           h
         
    ----------*/



    var symbols = [
    // Общий анод(+)
    // h  g  f  e  d  c  b  a
      [1, 1, 0, 0, 0, 0, 0, 0], // 0
      [1, 1, 1, 1, 1, 0, 0, 1], // 1
      [1, 0, 1, 0, 0, 1, 0, 0], // 2
      [1, 0, 1, 1, 0, 0, 0, 0], // 3
      [1, 0, 0, 1, 1, 0, 0, 1], // 4
      [1, 0, 0, 1, 0, 0, 1, 0], // 5
      [1, 0, 0, 0, 0, 0, 1, 0], // 6
      [1, 1, 1, 1, 1, 0, 0, 0], // 7
      [1, 0, 0, 0, 0, 0, 0, 0], // 8
      [1, 0, 0, 1, 0, 0, 0, 0], // 9
      [1, 1, 1, 1, 1, 1, 1, 1], // Пусто
      [0, 1, 1, 1, 1, 1, 1, 1], // .
      [1, 0, 1, 1, 1, 1, 1, 1]  // -
    ];

    // Этот массив соответствует массиву symbols и по нему ищутся символы, которые надо отобразить на экране
    var symbols_map = [
      ["0"], // 0
      ["1"], // 1
      ["2"], // 2
      ["3"], // 3
      ["4"], // 4
      ["5"], // 5
      ["6"], // 6
      ["7"], // 7
      ["8"], // 8
      ["9"], // 9
      [ ""],  // Пусто
      ["."],  // .
      ["-"]  // -
    ];

    // Разряды
    var segments = [
      [1, 1, 1, 1, 1, 1, 1, 1], // Пусто
      [1, 1, 1, 1, 0, 0, 0, 1], // 1/4
      [1, 1, 1, 1, 0, 0, 1, 0], // 2/4
      [1, 1, 1, 1, 0, 1, 0, 0], // 3/4
      [1, 1, 1, 1, 1, 0, 0, 0], // 4/4
    ];

    // Отправка данных в сдвиговые регистры 74hc595
    function send_data(d,s){
      digitalWrite(LATCH_DIO, 0);
      shiftOut(DATA_DIO, { clk : CLK_DIO}, symbols[d]);
      shiftOut(DATA_DIO, { clk : CLK_DIO}, segments[s]);
      digitalWrite(LATCH_DIO, 1);
    }

    // Значения каждого разряда по умолчанию
    var d1=0;
    var d2=1;
    var d3=2;
    var d4=3;

    // Поиск нужного набора битов для отправки на сдвиговые регистры 74hc595
    function find(n){
      for (var x=0; x<symbols_map.length; x++){
        if (n == symbols_map[x]){
          return(x);
        }
      }
    }

    // Число, которое нужно отобразить
    var data_to_show = -123;

    // Непосредственно команда на отображение числа на дисплее
    function show_data (data_to_show){
      var arr = data_to_show.toString().split('');
      if (arr.length==4){d1=find(arr[0]);d2=find(arr[1]);d3=find(arr[2]);d4=find(arr[3]);}
      if (arr.length==3){d1=10;d2=find(arr[0]);d3=find(arr[1]);d4=find(arr[2]);}
      if (arr.length==2){d1=10;d2=10;d3=find(arr[0]);d4=find(arr[1]);}
      if (arr.length==1){d1=10;d2=10;d3=10;d4=find(arr[0]);}
      if (arr.length==0){d1=10;d2=10;d3=10;d4=10;}
      if (arr.length>4 ){d1=10;d2=10;d3=10;d4=10;}
    }

    // Пример вызова команды отображения числа, если число будет больше 5 знаков, то на дисплее ничего не отобразится. Можно отобразить целые числа положительные от 0 до 9999 и отрицательные от -1 до -999. Также можно передать строку содержащую минус.
    show_data(data_to_show);
    // show_data(-123); показ отрицательного числа
    // show_data('99-0'); показ строки с минусом

    // Динамическая индикация
    setInterval(function() {
      send_data(d1,1);
      send_data(d2,2);
      send_data(d3,3);
      send_data(d4,4);
    },0);
    Теперь хочется доделать, чтобы можно было выводить числа с запятой.

    И переделать способ хранения массива символов, так, чтобы хранить их в двоичном виде без разделения на биты. И лучше в формате JSON, чтобы не делать отдельный массив symbols_map

    Мне понравился этот онлайн редактор кода для семисегментных индикаторов. Там можно прописать свою последовательность сегментов создать таким образом свою библиотеку символов. А может получиться использовать JSON с символами из модуля quaddisplay2.js от Амперки:

    Код (Javascript):
    var SYMBOLS = {
      ' ': 255,
      '-': 127,
      '^': 253,
      _: 239,
      '*': 57,
      '0': 129,
      '1': 243,
      '2': 73,
      '3': 97,
      '4': 51,
      '5': 37,
      '6': 5,
      '7': 241,
      '8': 1,
      '9': 33,
      A: 17,
      a: 65,
      B: 1,
      b: 7,
      C: 141,
      c: 79,
      D: 67,
      d: 67,
      E: 13,
      e: 13,
      F: 29,
      f: 29,
      G: 133,
      g: 133,
      H: 19,
      h: 23,
      I: 243,
      i: 243,
      J: 227,
      j: 227,
      K: 19,
      k: 23,
      L: 143,
      l: 143,
      M: 13,
      m: 13,
      N: 87,
      n: 87,
      O: 129,
      o: 71,
      P: 25,
      p: 25,
      Q: 49,
      q: 49,
      R: 95,
      r: 95,
      S: 37,
      s: 37,
      T: 15,
      t: 15,
      U: 131,
      u: 199,
      V: 131,
      v: 199,
      W: 131,
      w: 199,
      X: 19,
      x: 23,
      Y: 35,
      y: 35,
      Z: 73,
      z: 73,
      '.': 254
    };
    PS: Если у кого-то будут советы, о том как улучшить мой код, то постараюсь разобраться и реализовать их.
     
  13. Очень мало удалось найти информации про метод shiftOut для Espruino. Только тут(рус.) и тут(eng).
    Есть ли где-то ещё инфа про него? И где можно посмотреть исходный код этого метода? (Для ардуино нашёл тут)

    C:\Program Files(x86)\Arduino\hardware\arduino\avr\cores\arduino (для функции shiftOut() — файл wiring_shift.c)
    Код (C++):
    void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
    {
        uint8_t i;

        for (i = 0; i < 8; i++)  {
            if (bitOrder == LSBFIRST)
                digitalWrite(dataPin, !!(val & (1 << i)));
            else  
                digitalWrite(dataPin, !!(val & (1 << (7 - i))));
             
            digitalWrite(clockPin, HIGH);
            digitalWrite(clockPin, LOW);      
        }
    }
    Думаю, может вместо готового shiftOut стоит свою функцию написать.
     
  14. Asper Daffy

    Asper Daffy Иксперд

    Зачем 0 в качестве задержки в setInterval? Вы так перегружаете МК, ему что-то ещё делать нужно. Я Вам там описывал как правильно посчитать задержку, которая будет разумной.
     
  15. Потому что если указать там другое число, то экран засвечивается неравномерно.

    А в целом, я пробовал уже и работу с кнопками и просто какие-то функции (типа таймера обратного отсчёта) и всё ОК. Даже несколько таймеров одновременно вполне работают.

    Насколько я знаю, в Iskra JS всё работает асинхронно и setInterval это абстракция и напрямую с прерываниями не поработаешь (я не нашёл как это сделать).

    Ещё как одно из преимуществ в докладе на ютуб как раз и говорилось, что можно просто писать программу и не париться с ресурсами.
     
  16. Asper Daffy

    Asper Daffy Иксперд

    И что 4 или 5 не работает? Вы 4 пробовали?
     
  17. Не знаю что я сделал, как по мне так ничего такого. Может потому что всё время втыкал и вынимал кабель. Но теперь Iskra JS не шьётся и выдаёт это:
    [​IMG]

    А если открыть сохранённый файл, то на месте комментов кракозябры и какие-то красные точки появились:
    [​IMG]
     
  18. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Естественно шиться не будет пока не скомпилируется.
    Вы вероятно нарушили синтаксис языка в коде. Или ваш текстовый редактор не совместим с языком. Такой фокус и с Ардуиновскими скетчами бывает, если их некоторыми сторонними редакторами делать. Например сообщение -"at line 1 col 1150". Это у вас строка команды длиной более тысячи символов ? Вряд ли компилятор проглотит такого монстра. Впрочем с JS не знаком, так что прошу не пинать.
     
    Последнее редактирование: 5 июн 2023