Подключение четырехразрядного индикатора

Тема в разделе "Iskra JS, Espruino, Йодо", создана пользователем Филипп, 1 окт 2017.

  1. Филипп

    Филипп Нерд

    Речь идет о http://amperka.ru/product/troyka-quad-display?utm_source=man&utm_campaign=quad-v2&utm_medium=wiki
    У него подключение происходит по SPI и одному пину. Я в этом деле совсем нуб, но очень сильно хочу разобраться. В данный момент даже не знаю с какого конца смотреть.
    По поводу SPI нашел только лишь это https://www.espruino.com/SPI и это http://wiki.amperka.ru/js:spi
    Моя задача, сделать так, что бы на этот индикатор выводились данные с датчика температуры и влажности. При чем так, что бы они сменялись между собой по нажатию кнопки.
    Библиотек к сожалению к этому индикатору нет, следовательно я тыкаю пальцем в небо. Наставьте на путь истинный.)
     
  2. Филипп

    Филипп Нерд

    Я не в коем случае не прошу за меня написать код, мне важно самому во всем разобраться.
    Спасибо большое за ссылку на библиотеки. Мне просто нужна пара советов.)

    У меня получилось так
    Код (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
    };

    var QuadDisplay = function(opts) {
      if (typeof opts === 'number') {
        SPI1.setup({mosi: B5, miso: B4, sck: B3});
        this._spi = SPI1;
        this._cs = opts;
      } else {
        opts = opts || {};
        this._spi = opts.spi;
        this._cs = opts.cs;
      }
      this._intervalID = null;
      this._shift = 0;
      this.display('    ');
    };

    QuadDisplay.prototype.display = function(str, alignRight) {
      alignRight = alignRight || false;
      var s = str.toString();
      this._data = [];

      for (var i = 0, d = -1; i < s.length; i++) {
        if (s[i] !== '.') {
          d++;
          this._data[d] = SYMBOLS[s[i]];
        } else {
          // prevent dot-dot and space-dot collapsing
          if (d !== -1 && (this._data[d] !== 0xFE && this._data[d] !== 0xFF)) {
            this._data[d] &= 0xFE;
          } else {
            d++;
            this._data[d] = SYMBOLS['.'];
          }
        }
      }

      if (alignRight) {
        if (this._data.length < 4) {
          this._data = [].fill(SYMBOLS[' '], 0, 4 - this._data.length).concat(this._data);
        }
        this.frame(this._data.length - 4);  
      } else {
        if (this._data.length < 4) {
          this._data = this._data.concat([].fill(SYMBOLS[' '], 0, 4 - this._data.length))
        }
        this.frame(0);
      }
    };

    QuadDisplay.prototype.marquee = function(str, period) {
      period = period || 300;
      if (this._intervalID) {
        this._intervalID = clearInterval(this._intervalID);
        this._shift = 0;
      }
      this.display('   '+str+'   ', false);
      var self = this;
      this._intervalID = setInterval(function() {
        self._shift++;
        if (self._shift > self._data.length - 4) {
          self._shift = 0;
        }
        self.frame.call(self, self._shift);
      }, period);
    };

    QuadDisplay.prototype.frame = function(shift) {
      this._shift = shift;
      if (this._shift < 0) {
        this._shift = 0;
      }
      if (this._shift > this._data.length - 4) {
        this._shift = this._data.length;
      }
      this._spi.send(this._data.slice(this._shift, this._shift + 4), this._cs);
    };

    new QuadDisplay(P9);
    SPI1.setup({mosi: B5, miso: B4, sck: B3});
    new QuadDisplay({spi: SPI1, cs: P9});
    QuadDisplay('1.2');
     
    Верней не получилось, это то, к чему я пришел с попытками завести индикатор. Но ничего не выходит.
    Не понимаю в чем косяк
    И еще я не уверен что правильно расписал mosi, miso, sck
     
    Последнее редактирование: 1 окт 2017
  3. sys

    sys Злобный Буратино Модератор

    Мне показалось или вставили код библиотеки прямо в код?
    Не лучше ли подключить как положено? http://wiki.amperka.ru/js:quaddisplay

    Во-вторых. У Вас Espruino board или Iskra JS? Если Искра, то SPI1 это не B5,B4,B3, а P3,P2,A5 http://wiki.amperka.ru/js:iskra_js
    [​IMG]
    Код (Javascript):
    SPI1.setup({mosi: P3, miso: P2, sck: A5});
    var quad2 = require('@amperka/quaddisplay2').connect({spi: SPI1, cs: P9});
     
    arkadyf нравится это.
  4. Филипп

    Филипп Нерд

    Спасибо. Я вчера весь день проковырялся, но тем не менее сделал. Я не сразу понял как работать с локальными библиотеками. Оставлю результат для будущих пытливых умов.

    1.Файл библиотеки (.js) кладем в папку modules (папка автоматически создается при указании пути в Espruino IDE, в настройках, в вкладке Project.
    2. Пишем код отталкиваясь от того, что библиотека локальна.
    Код (Javascript):
    var quad2 = require('QuadDisplay2')
    .connect(A0);

    SPI2.setup({mosi: B15, miso: B14, sck: B13});
    var quad2 = require('QuadDisplay2').connect({spi: SPI2, cs: A0});
    QuadDisplay2 - это название файла библиотеки, которая лежит у нас в папке modules

    3. В моем случае нужно было вывести на индикатор показания с датчика DHT11. Сначала я хотел чередовать отображение температуры и влажности по нажатию на кнопку, но в итоге сделал отображение в виде бегущей строки.
    Код (Javascript):
    setInterval( function () {
      dht.read(function (a) {quad2.marquee("T "+a.temp.toString()+"   R "+a.rh.toString());});
               }, 12000);
    setInterval применен для того, что бы показания датчика обновлялись, если этого не сделать, то датчик будет показывать только те значения, которые он снял при включении питания. Интервал 12000 (12 секунд) сделан для того, что бы бегущая строка не прерывалась. Например если поставить интервал 1000, то бегущая строка не будет успевать добегать до конца.

    С этим я разобрался.)
    Теперь мне нужно сделать так, что бы реле включалось в определенное время, например в 1:00, и выключалось в 21:00. Часы реального времени подключены. По средством чего мне это сделать, я даже и не представляю. Буду благодарен за помощь в этом вопросе.)
     
    arkadyf нравится это.
  5. Филипп

    Филипп Нерд

    Код (Javascript):
    PrimaryI2C.setup({ sda: SDA, scl: SCL, bitrate: 100000 });
    var rtc = require('@amperka/rtc').connect(PrimaryI2C);
    rtc.setTime('2017-10-2T13:30:00');
    print(rtc.getTime('iso'));
    Когда я использую этот код, Искра пишет следующую чушь: 2017-91-1T13:30:0
    Что за 91 месяц и 1 число?)
     
    sys нравится это.
  6. Филипп

    Филипп Нерд

    Ладно. Поставленную задачу я выполнил. Вопрос про странную дату актуален, но не принципиален. Просто интересно было бы узнать почему так и как это пофиксить.
    задачу решил следующим образом.
    Код (Javascript):

    PrimaryI2C.setup({ sda: SDA, scl: SCL, bitrate: 100000 });
    var rtc = require('@amperka/rtc').connect(PrimaryI2C);
    print(rtc.getTime('iso'));
    setInterval(function () {
     print(rtc.getTime('iso'));
    }, 1000);

    var myRelay = require('@amperka/relay').connect(P0);

    var relayState = false;
    myRelay.turnOff();

    setInterval(
    function ()
    {
        var ts = new Date(rtc.getTime('iso'));
      console.log(ts.getHours(), relayState);
     if (
          (
            (ts.getHours() >= 13 && ts.getHours() <= 15)
              || (ts.getHours() >= 0 && ts.getHours() < 2)
        )
      )
      {
          if (!relayState)
        {
          myRelay.turnOn();
          relayState = true;
        }
      }
      else if(relayState)
      {
          myRelay.turnOff();
        relayState = false;
      }
    },
    1000);
     
    Важный момент при установке часов, когда нужно выставить время мы пишем setTime и указываем дату и время. Если эту строчку не удалить после первой заливки скетча, то каждый раз при перезапуски контроллера будет исполняться setTime, то есть каждый раз время будет начинать отсчет сначала.
     
    sys нравится это.
  7. sys

    sys Злобный Буратино Модератор

    походу косяк в библиотеке rtc в методе getTime ...
    Код (Javascript):
    Rtc.prototype.getTime = function(unit) {
      var time = this.read(0x00, 7);
      this._time = new Date(
        this._bcdToDec(time[6]) + 2000,
        this._bcdToDec(time[5]) - 1,
        this._bcdToDec(time[4]),
        this._bcdToDec(time[2] & 0x3f),
        this._bcdToDec(time[1]),
        this._bcdToDec(time[0] & 0x7f)
      );

      var res = this._time;
      switch (unit) {
        case 'unixtime':
          res = Math.ceil(res.getTime() / 1000);
          break;
        case 'iso':
          res = res.getFullYear() + '-'  + res.getMonth() + 1 +  // походу не хватает скобок:  "... + (res.getMonth() + 1) + ..."
             '-' + res.getDay() + 'T' + res.getHours() +
             ':' + res.getMinutes() + ':' + res.getSeconds();
          break;
        default: break;
      }
      return res;
    };
    походу не хватает скобок: "... + (res.getMonth() + 1) + ..."
    Код (Javascript):
          res = res.getFullYear() + '-' + (res.getMonth() + 1) +
             '-' + res.getDay() + 'T' + res.getHours() +
    ':' + res.getMinutes() + ':' + res.getSeconds();
    попробуйте сохранить локально и исправить, либо можно попробовать использовать библиотеку от DS3231
    Код (Javascript):
    PrimaryI2C.setup({ sda: SDA, scl: SCL, bitrate: 100000 });
    var rtc = require("DS3231").connect(PrimaryI2C);
    и еще: старайтесь не использовать print и console.log если плата не подключена к консоли (IDE или serial)... могут быть глюки
     
    Последнее редактирование: 3 окт 2017
  8. rantiev

    rantiev Нерд

    Было ли у вас такое что при повторном вызове `.display(` не обновляется экран? Пробовал выводить поочередно температуру дату и время, выводит только то, что вывели первым, проблема вроде в том что меньше символов при повторном вызове. (если обновлять время раз в секунду на протяжении определенного времени оно обновляется, но вот если за этим нужно отобразить дату и там на символ меньше, уже ничего не меняется) вот код

    Код (Javascript):

    // PrimaryI2C.setup({sda: SDA, scl: SCL, bitrate: 10000});
    // E.setTimeZone(3);

    var t = require('@amperka/thermometer').connect(A0);
    var qd = require('@amperka/quaddisplay2').connect(P9);
    var rtc = require('@amperka/rtc').connect();

    var updateDelay = 500;

    var passed = 0;
    var changeDelay = 3000;

    var clockDelay = changeDelay * 2;
    var dateDelay = clockDelay + changeDelay * 1;
    var thermDelay = dateDelay + changeDelay * 1;

    var showDot = false;

    // var timeZone = 3 * 60 * 60;
    // var curTime = Date() / 1000 + timeZone;
    // rtc.setTime(curTime);
    // rtc.setTime();

    setInterval(function () {
      var time = rtc.getTime();
      var displayValue;

      var hrs;
      var min;
      var m;
      var d;

      if (passed <= clockDelay) {
        hrs = time.getHours();
        min = time.getMinutes();
     
        if (min < 10) min = '0' + min;
     
        if (showDot) {
          displayValue = hrs + '.' + min;
        } else {
          displayValue = hrs + '' + min;
        }
      } else if (passed <= dateDelay) {
        m = time.getMonth() + 1;
        d = time.getDate();

        if (d < 10) d = '0' + d;
     
        displayValue = m + '.' + d;
      } else {
        displayValue = t.read('C').toFixed(0) + 'c';
      }
     
      passed += updateDelay;
      showDot = !showDot;
      if (passed > thermDelay) {
        passed = 0;
      }
      qd.display(displayValue, true);
    }, updateDelay);
     
    (сс @sys @Филипп )
     
  9. rantiev

    rantiev Нерд

    sys нравится это.