Espruino:Примеры/Цифровые кости

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Цифровые кости[1]

Espruino Project - Digital Dice

В этом руководстве мы расскажем, как сделать устройство на видео выше – многофункциональные цифровые кости.

Нам понадобятся

  • Чистая и пустая банка от Pringles
  • Плата Espruino
  • Батарея
  • Переключатель и два провода для него
  • Гирлянда светодиодов WS2811
  • Обёрточная бумага, изолента и двусторонняя изолента (не показаны на фото выше)

Что надо сделать

Отмерьте 4 см с обоих концов банки, а затем отрежьте их как можно прямее с помощью монтажного ножа.

Также вырежьте ещё одно кольцо из середины банки шириной около 3 см и сделайте в нём один поперечный разрез. Это кольцо поможет закрепить светодиоды внутри банки.

Затем проделайте в донном конце банки 12 отверстий (8 мм) так, чтобы они находились на одинаковом расстоянии друг от друга и примерно в 2 мм от края банки. Также нужно будет проделать отверстие в середине – для переключателя. Я сначала при помощи маркера отметил места для отверстий, а уже потом просверлил их.

Теперь примкните оба конца банки друг к другу и скрепите изолентой изнутри.

Прилепите снаружи банки двустороннюю изоленту, а затем приклейте на него обёрточную бумагу с узором, чтобы закрыть обёртку Pringles.

Теперь повнимательнее приглянитесь к обоим концам светодиодной гирлянды. Светодиоды сделаны из прозрачного пластика, поэтому вы должны увидеть надписи на печатной плате в тех местах, куда подключены провода. На одном конце должны быть отчётливые надписи «5V, DI, GND», а на другом, возможно, «D0» (а иногда на нём вообще ничего нельзя разобрать). Пометьте провода, идущие от конца с надписями «5V, DI, GND», а оставшийся провод нам не важен – просто отогните его в сторону.

Теперь просуньте все 12 светодиодов в их отверстия в донной части банки (по порядку). Их также можно закрепить на месте при помощи клея Blu Tack или двусторонней изоленты.

Поместите третье кольцо банки внутрь, чтобы закрепить светодиоды на месте. Также можно прилепить немного изоленты, чтобы всё держалось ещё крепче.

Теперь подсоедините два провода к переключателю. Чтобы контакты не замыкали, я одел на них изоляционную термоусадочную трубку, но подойдёт и обычная изолента. Если контакты замкнут, это не вызовет никаких повреждений, но Espruino будет думать, что мы нажали на кнопку.

Теперь припаяйте эти провода к Espruino:

  • Первый провод – к контакту A1 на Espruino.
  • Второй провод – к контактной площадке 3.3v (она должна быть рядом с A1).

Теперь возьмите помеченный конец гирлянды (тот, что с надписями «5V, DI, GND») и разделите его на 3 провода, каждый из которых будет соответствовать какой-либо из пометок:

  • Подключите провод 5V к контакту VBAT на Espruino.
  • Подключите провод GND к контакту GND на Espruino.
  • Подключите провод DI к контакту B5 на Espruino (для этого провода вам понадобится контакт, помеченный как SPI#_MOSI).

Готово! Теперь можно подключать батарею.

Теперь мы можем поместить всё это внутрь. Espruino и батарея должны плотно сесть между светодиодами. USB-коннектор должен смотреть наружу – чтобы вы могли подключить его к ПК.

Код

Теперь код! Подключите ваш ПК к Espruino как объясняется здесь. Вы также можете поэкспериментировать с примерами кода из статьи о светодиодах WS2811, но не забывайте использовать контакт B5 для шины SPI.

Теперь просто скопируйте и вставьте код ниже, в результате чего на костях начнёт вращаться светодиодной «волчок» как показано в видео выше:

SPI1.setup({baud:3200000, mosi:B5});
var FRONT_BUTTON = A1;

var slowdown;
var speed;
var running;
var timePressed;
var pos=0;

// Нажатие на кнопку:
setWatch(function(e) {
  if (e.time < timePressed+0.01) return; // убираем «дребезг»
  timePressed = e.time;
  // Удаляем анимацию, если она выполняется в данный момент:
  clearInterval();
  // Задаём начальные значения:
  speed = 20; 
  slowdown = 1.1 + Math.random()*0.1;
  running = true;
  // Запускаем анимацию...
  setInterval(function() { 
    if (!running) { // если кнопка была отпущена...
      speed = speed * slowdown; // замедляем
      changeInterval(1,speed);  // используем это,
                                // чтобы замедлить таймер
      if (speed > 500) clearInterval(); // если стало совсем медленно,
                                        // останавливаем анимацию
    }
    pos++; // крутим
    if (pos>11) pos = 0; // дойдя до последнего светодиода,
                         // обнуляем счётчик
    // Теперь рассчитываем то, какой паттерн показать -
    // включаем один светодиод (с красным и синим огнями):
    var leds = new Uint8Array(12*3);
    leds[0+(11-pos)*3] = 255; // красный
    leds[2+(11-pos)*3] = 255; // синий
    SPI1.send4bit(leds, 0b0001, 0b0011); // отправляем на светодиоды
  }, speed); // скорость для setInterval()
}, FRONT_BUTTON, { repeat: true, edge: "rising" });

// Отпускание кнопки:
setWatch(function(e) {
  timePressed = e.time;
  // Сигнал для замедления и остановки анимации:
  running = false;
}, FRONT_BUTTON, { repeat: true, edge: "falling" });

function onInit() {
  // Притягиваем переключатель к значению «0»,
  // чтобы не использовать внешний резистор:
  pinMode(FRONT_BUTTON, "input_pulldown");
}
onInit();

Или же вы можете загрузить на Espruino код ниже, умеющий работать во всех режимах, которые были показаны на видео в самом начале статьи:

clearWatch();
SPI1.setup({baud:3200000, mosi:B5});
var FRONT_BUTTON = A1;

var hours = 3,mins = 20,secs = 0;
var slowdown;
var speed;
var running;
var mode = 0;
var timePressed;
var pos=0;

// Нажатие на кнопку:
setWatch(function(e) {
  if (e.time < timePressed+0.01) return; // убираем «дребезг»

  timePressed = e.time;
  clearInterval();
  if (mode == 0) { // часы
    setInterval(function() {
      secs++;
      if (secs>59) {
       secs = 0;
       mins++;
       if (mins>59) {
         mins = 0;
         hours++;
         if (hours>11) {
          hours = 0;
         }
       }
      }
      var leds = new Uint8Array(12*3);
      var secled = parseInt(secs/5);
      leds[1+(11-secled)*3] = 255; // зелёный
      var minled = parseInt(mins/5);
      leds[2+(11-minled)*3] = 255; // синий
      leds[0+(11-hours)*3] = 255; // красный
      SPI1.send4bit(leds, 0b0001, 0b0011);
    }, 1000);
  } else if (mode == 1) { // вращение
    speed = 20;
    slowdown = 1.1 + Math.random()*0.1;
    running = true;
    setInterval(function() {
      if (!running) {
        speed = speed * slowdown;
        changeInterval(1,speed);
        if (speed > 500) clearInterval();
      }
      pos++;
      if (pos>11) {
       pos = 0;
      }
      var leds = new Uint8Array(12*3);
      leds[0+(11-pos)*3] = 255; // красный
      leds[2+(11-pos)*3] = 255; // синий
      SPI1.send4bit(leds, 0b0001, 0b0011);
    }, speed);
  } else if (mode == 2) { // случайное число 
                          // в диапазоне между 1 и 6
    speed = 20;
    slowdown = 1.1 + Math.random()*0.1;
    running = true;
    setInterval(function () {
      if (!running) {
        speed = speed * slowdown;
        changeInterval(1,speed);
        if (speed > 500) clearInterval();
      }
      pos = parseInt(Math.random()*6)*2;
      var leds = new Uint8Array(12*3);
      var r = 1+parseInt(Math.random()*6);
      leds[0+(11-pos)*3] = (r&1)?0:255; // красный
      leds[1+(11-pos)*3] = (r&2)?0:255; // зелёный
      leds[2+(11-pos)*3] = (r&4)?0:255; // синий
      SPI1.send4bit(leds, 0b0001, 0b0011);
    }, speed);
  } else if (mode == 3) {
    speed = 20;
    slowdown = 1.2 + Math.random()*0.1;
    running = true;
    setInterval(function () {
      if (!running) {
        speed = speed * slowdown;
        changeInterval(1,speed);
        if (speed > 500) clearInterval();
      }
      var patterns = [
        [0],
        [0,5],
        [0,4,8],
        [0,3,6,9],
        [0,2,4,6,9],
        [0,2,4,6,8,10],
      ];
      var r = parseInt(Math.random()*patterns.length);
      var leds = new Uint8Array(12*3);
      for (i in patterns[r]) {   
        leds[1+patterns[r][i]*3] = 255; // зелёный
        leds[2+patterns[r][i]*3] = 255; // синий
      }
      SPI1.send4bit(leds, 0b0001, 0b0011);  
    }, speed);
  }
}, FRONT_BUTTON, { repeat: true, edge: "rising" });

// Отпускание кнопки:
setWatch(function(e) {
  if (e.time < timePressed+0.01) return; // убираем «дребезг»
  if (e.time > timePressed+1) { // долгое нажатие
    clearInterval();
    // Переходим в следующий режим:
    mode++;
    if (mode>3) mode=0;
    print(mode);
    // Выключаем все светодиоды:
    SPI1.send4bit(new Uint8Array(12*3), 0b0001, 0b0011); 
  } else {
    // Короткое нажатие – 
    // это сигнал для замедления и остановки анимации:
    running = false;
  }
  timePressed = e.time;
}, FRONT_BUTTON, { repeat: true, edge: "falling" });

function onInit() {
  // Притягиваем контакт, к которому подключена кнопка, к «0»,
  // чтобы не использовать внешний резистор:
  pinMode(FRONT_BUTTON, "input_pulldown");
}
onInit();

Вот и всё – мы сделали цифровые кости! Теперь напечатайте save(), и весь этот код будет сохранён на flash-память. В результате при следующем запуске Espruino автоматически загрузит этот код для цифровых костей!

См.также

Внешние ссылки