Espruino:Примеры/Индивидуальный доступ к светодиодам: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
Нет описания правки
 
(не показаны 3 промежуточные версии 2 участников)
Строка 7: Строка 7:
[[File:Individually_Addressable_LEDs_string.jpg|center]]
[[File:Individually_Addressable_LEDs_string.jpg|center]]


В последнее время светодиоды с индивидуальным доступом становятся всё дешевле и дешевле. Эти светодиоды (помимо самого RGB-светодиода) оснащены маленьким управляющим чипом, с помощью которого и задается нужный цвет. Эти управляющие чипы умеют принимать и отправлять последовательные данные и их можно последовательно подсоединить друг к другу (по принципу гирляндного подключения, которое также называют «daisy-chain»). Это позволяет управлять большим количеством светодиодов при помощи всего нескольких управляющих проводов, т.е. избавляет вас от необходимости использовать по проводу для каждого светодиода.
В последнее время светодиоды с индивидуальным доступом становятся всё дешевле и дешевле. Эти светодиоды (помимо самого [[RGB-светодиод]]а) оснащены маленьким управляющим чипом, с помощью которого и задается нужный цвет. Эти управляющие чипы умеют принимать и отправлять последовательные данные и их можно последовательно подсоединить друг к другу (по принципу гирляндного подключения, которое также называют ''«daisy-chain»''). Это позволяет управлять большим количеством [[светодиод]]ов при помощи всего нескольких управляющих проводов, т.е. избавляет вас от необходимости использовать по проводу для каждого [[светодиод]]а.


[[File:Individually_Addressable_LEDs_use_england.jpg|center]]
[[File:Individually_Addressable_LEDs_use_england.jpg|center]]


[[File:Individually_Addressable_LEDs_use_celebrate.jpg|center]]
[[File:Individually_Addressable_LEDs_use_celebrate.jpg|center]]


Сейчас есть два главных типа светодиодов с индивидуальным доступом – с 3 и 4 проводами.
Сейчас есть два главных типа [[светодиод]]ов с индивидуальным доступом – с 3 и 4 проводами.


Светодиоды вроде WS2801 оснащены 4 проводами – для заземления, питания, тактовой частоты и передачи данных. Ими можно управлять с помощью шины SPI, которая есть на большинстве микроконтроллеров. Но у этого метода есть пара маленьких недостатков:
Светодиоды вроде [[WS2801]] оснащены 4 проводами – для заземления, питания, тактовой частоты и передачи данных. Ими можно управлять с помощью шины [[SPI]], которая есть на большинстве микроконтроллеров. Но у этого метода есть пара маленьких недостатков:


* Между каждой парой светодиодов должно быть 4 провода, что увеличивает затраты
* Между каждой парой светодиодов должно быть 4 провода, что увеличивает затраты
* Устройству, состоящему из управляющего чипа и светодиода, нужно больше проводов, что увеличивает его размер и затраты на него
* Устройству, состоящему из управляющего чипа и светодиода, нужно больше проводов, что увеличивает его размер и затраты на него


Многие более современные управляющие чипы используют 3 провода – например, WS2811/WS2812/APA104/APA106 и SK6812. Управление ими осуществляется при помощи 1-проводного протокола последовательной передачи данных, в котором (как подсказывает его название) для передачи данных используется только 1 провод. Это значит:
Многие более современные управляющие чипы используют 3 провода – например, [[WS2811]]/[[WS2812]]/[[APA104]]/[[APA106]] и [[SK6812]]. Управление ими осуществляется при помощи 1-проводного протокола последовательной передачи данных, в котором (как подсказывает его название) для передачи данных используется только 1 провод. Это значит:


* Для каждого светодиода нужно только 3 провода
* Для каждого светодиода нужно только 3 провода
* Управляющий чип будет более компактным, как и его печатная плата. Соответственно, само устройство тоже будет меньше
* Управляющий чип будет более компактным, как и его печатная плата. Соответственно, само устройство тоже будет меньше
* У многих светодиодов (по сути, у всех, кроме WS2811) управляющий чип находится внутри самого светодиода
* У многих светодиодов (по сути, у всех, кроме [[WS2811]]) управляющий чип находится внутри самого светодиода


В результате проект, создаваемый при помощи 3-проводных RGB-светодиодов, будет значительно дешевле проекта, создаваемого с помощью светодиодов WS2801.
В результате проект, создаваемый при помощи 3-проводных [[RGB-светодиод]]ов, будет значительно дешевле проекта, создаваемого с помощью светодиодов WS2801.


В этом руководстве мы расскажем, как управлять этими 3-проводными светодиодами при помощи Espruino. Управление ими будет осуществляться при помощи серии импульсов на частоте 800 КГц, где коротким импульсом будет бит 0, а длинным – бит 1. Для управления этими устройствами есть специальная библиотека neopixel.
В этом руководстве мы расскажем, как управлять этими 3-проводными светодиодами при помощи [[Espruino]]. Управление ими будет осуществляться при помощи серии импульсов на частоте [[800 КГц]], где коротким импульсом будет бит 0, а длинным – бит 1. Для управления этими устройствами есть специальная библиотека neopixel.


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


* Цепь RGB-светодиодов вроде WS2811. Я воспользуюсь не светодиодной лентой, а 25 отдельными светодиодами, подключенными друг к другу
* Цепь [[RGB-светодиод]]ов вроде [[WS2811]]. Я воспользуюсь не светодиодной лентой, а 25 отдельными светодиодами, подключенными друг к другу
* Плата Espruino
* Плата [[Espruino]]


== Подсоединение ==
== Подсоединение ==


Ознакомьтесь документацией к библиотеке neopixel – светодиоды вроде WS2811 могут быть очень привередливы касаемо напряжения на линии для передачи данных. Если вы используете Espruino Original или Pico, то проблем возникнуть не должно, но при использовании других плат может понадобиться чуть более высокое напряжение.
Ознакомьтесь документацией к библиотеке neopixel – светодиоды вроде [[WS2811]] могут быть очень привередливы касаемо напряжения на линии для передачи данных. Если вы используете [[Espruino Original]] или [[Pico]], то проблем возникнуть не должно, но при использовании других плат может понадобиться чуть более высокое напряжение.


У цепи светодиодов WS2811 должно быть два конца по 3 провода на каждом (некоторые из них могут быть продублированы) – красный, белый и зелёный. Красный – это 5-вольтовое питание, белый – это заземление, а зелёный – это передача сигнала (данных). Если к вашей светодиодной цепи есть какая-то документация, то советуем сначала ознакомиться с ней.
У цепи светодиодов [[WS2811]] должно быть два конца по 3 провода на каждом (некоторые из них могут быть продублированы) – красный, белый и зелёный. Красный – это 5-вольтовое питание, белый – это заземление, а зелёный – это передача сигнала (данных). Если к вашей светодиодной цепи есть какая-то документация, то советуем сначала ознакомиться с ней.


Сигнальный провод с одной стороны будет использоваться для ввода данных, а с другой – для вывода. Так вы сможете подключить друг к другу более 50 светодиодов. На моих светодиодах коннектор типа «мама» был входным. Но если на ваших светодиодах есть пометки «DI»/«DO» или в документации есть какое-то специальное упоминание об обозначениях, то используйте их.
Сигнальный провод с одной стороны будет использоваться для ввода данных, а с другой – для вывода. Так вы сможете подключить друг к другу более 50 светодиодов. На моих светодиодах коннектор типа «мама» был входным. Но если на ваших светодиодах есть пометки [[«DI»]]/[[«DO»]] или в документации есть какое-то специальное упоминание об обозначениях, то используйте их.


Итак, само подключение выполняется очень просто.
Итак, само подключение выполняется очень просто.


Просто подсоедините белый (0 вольт) и красный (5 вольт) провода к 5-вольтовому источнику питания. Наверно, USB лучше не использовать, потому что когда всё будет включено, 50 светодиодов будут тянуть около 1 ампера, а это очень много!
Просто подсоедините белый ([[0 вольт]]) и красный ([[5 вольт]]) провода к 5-вольтовому источнику питания. Наверно, [[USB]] лучше не использовать, потому что когда всё будет включено, 50 [[светодиод]]ов будут тянуть около [[1 ампер]]а, а это очень много!


Подключите белый провод к контакту GND, а зелёный – к контакту SPI MOSI на Espruino. Для этих целей подойдёт, например, B15 (но есть и другие варианты). На платах Discovery это обычно A7, а на платах Maple/Olimexino – D11. Если сомневаетесь, лучше сверьтесь с документацией платы.
Подключите белый провод к контакту '''GND''', а зелёный – к контакту [[SPI]] [[MOSI]] на [[Espruino]]. Для этих целей подойдёт, например, '''B15''' (но есть и другие варианты). На платах [[Discovery]] это обычно '''A7''', а на платах [[Maple]]/[[Olimexino]] '''D11'''. Если сомневаетесь, лучше сверьтесь с документацией платы.


== Код ==
== Код ==
Строка 53: Строка 54:
Теперь, когда всё подключено, давайте попробуем отправить какие-нибудь данные. Например, на первый светодиод. Передаваемые данные будут трёхсоставными – по байту для красного, зелёного и синего значений:
Теперь, когда всё подключено, давайте попробуем отправить какие-нибудь данные. Например, на первый светодиод. Передаваемые данные будут трёхсоставными – по байту для красного, зелёного и синего значений:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
require("neopixel").write(B15, [255,0,0]);
require("neopixel").write(B15, [255,0,0]);
</syntaxhighlight>
</syntaxhighlight>
Строка 59: Строка 60:
В результате первый светодиод загорится красным цветом.
В результате первый светодиод загорится красным цветом.


Обратите внимание, что в строчке кода выше используется контакт B15. Если вы хотите использовать какой-то другой контакт (см. раздел «Подсоединение» выше), то этот аргумент нужно будет поменять, но на большинстве устройств вам также надо будет убедиться, что нужный контакт можно использовать как MOSI-контакт для аппаратной SPI. При использовании Puck.js подойдёт абсолютно любой контакт.
Обратите внимание, что в строчке кода выше используется контакт '''B15'''. Если вы хотите использовать какой-то другой контакт ([http://wikihandbk.com/wiki/Espruino:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B/%D0%98%D0%BD%D0%B4%D0%B8%D0%B2%D0%B8%D0%B4%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF_%D0%BA_%D1%81%D0%B2%D0%B5%D1%82%D0%BE%D0%B4%D0%B8%D0%BE%D0%B4%D0%B0%D0%BC#.D0.9F.D0.BE.D0.B4.D1.81.D0.BE.D0.B5.D0.B4.D0.B8.D0.BD.D0.B5.D0.BD.D0.B8.D0.B5 см. раздел «Подсоединение» выше]), то этот аргумент нужно будет поменять, но на большинстве устройств вам также надо будет убедиться, что нужный контакт можно использовать как [[MOSI-контакт]] для аппаратной [[SPI]]. При использовании [[Puck.js]] подойдёт абсолютно любой контакт.


Разумеется, мы можем задать и другие цвета:
Разумеется, мы можем задать и другие цвета:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
require("neopixel").write(B15, [0,255,0]);    // зелёный
require("neopixel").write(B15, [0,255,0]);    // зелёный
require("neopixel").write(B15, [0,0,255]);    // синий
require("neopixel").write(B15, [0,0,255]);    // синий
Строка 69: Строка 70:
</syntaxhighlight>
</syntaxhighlight>


Теперь давайте дополнительно зададим цвета для второго и третьего светодиодов. Для этого нам просто нужно отправить больше данных:
Теперь давайте дополнительно зададим цвета для второго и третьего [[светодиод]]ов. Для этого нам просто нужно отправить больше данных:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
require("neopixel").write(B15, [255,0,0, 0,255,0, 0,0,255]);
require("neopixel").write(B15, [255,0,0, 0,255,0, 0,0,255]);
</syntaxhighlight>
</syntaxhighlight>


Теперь мы можем создать функцию с циклом for(), которая будет создавать цвета для всех светодиодов. Код ниже делает так, чтобы все 50 светодиодов загорались всё более ярким белым цветом (первый светодиод будет выключен):
Теперь мы можем создать функцию с циклом [[for()]], которая будет создавать цвета для всех [[светодиод]]ов. Код ниже делает так, чтобы все 50 [[светодиод]]ов загорались всё более ярким белым цветом (первый [[светодиод]] будет выключен):


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var rgb = new Uint8ClampedArray(25*3);
var rgb = new Uint8ClampedArray(25*3);


Строка 89: Строка 90:
</syntaxhighlight>
</syntaxhighlight>


Обратите внимание, что в самом верху при помощи класса Uint8ClampedArray мы задали массив rgb. Мы можем воспользоваться и обычным массивом, но типизированные массивы быстрее и занимают меньше памяти, если вам нужно хранить лишь значения в диапазоне между 0 и 255. Использование Uint8ClampedArray также означает, что все значения больше 255 и меньше 0 будут «обрезаны». При использовании Uint8Array у значения будут просто удалены старшие биты, из-за чего 256 станет 0, 257 станет 1 и так далее.
Обратите внимание, что в самом верху при помощи класса [[Uint8ClampedArray]] мы задали массив '''rgb'''. Мы можем воспользоваться и обычным массивом, но типизированные массивы быстрее и занимают меньше памяти, если вам нужно хранить лишь значения в диапазоне ''между 0 и 255''. Использование [[Uint8ClampedArray]] также означает, что все значения ''больше 255 и меньше 0 будут «обрезаны»''. При использовании [[Uint8Array]] у значения будут просто удалены старшие биты, из-за чего ''256'' станет ''0'', ''257'' станет ''1'' и так далее.


Затем мы можем создать функцию, которая будет отправлять эту информацию светодиодам, а затем вызывать её:
Затем мы можем создать функцию, которая будет отправлять эту информацию [[светодиод]]ам, а затем вызывать её:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
function doLights() {
function doLights() {
   getPattern();
   getPattern();
Строка 104: Строка 105:
Теперь у нас получился приятный оттенок серого. Но его также можно заанимировать:
Теперь у нас получился приятный оттенок серого. Но его также можно заанимировать:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var pos = 0;
var pos = 0;
function getPattern() {
function getPattern() {
Строка 118: Строка 119:
</syntaxhighlight>
</syntaxhighlight>


В коде выше используется синусоида, с помощью которой светодиод занимает промежуточное положение между максимальной яркостью и выключением. Позиция анимации хранится в переменной pos. Теперь при каждом вызове doLights() цвет будет меняться. Мы можем заанимировать это при помощи setInterval().
В коде выше используется синусоида, с помощью которой светодиод занимает промежуточное положение между максимальной яркостью и выключением. Позиция анимации хранится в переменной '''pos'''. Теперь при каждом вызове '''doLights()''' цвет будет меняться. Мы можем заанимировать это при помощи [[setInterval()]].


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
setInterval(doLights,50);
setInterval(doLights,50);
</syntaxhighlight>
</syntaxhighlight>
Строка 126: Строка 127:
Теперь давайте попробуем что-нибудь ещё. Например, мы можем воспользоваться синусоидными волнами разной частоты, чтобы сделать анимацию радужными цветами:
Теперь давайте попробуем что-нибудь ещё. Например, мы можем воспользоваться синусоидными волнами разной частоты, чтобы сделать анимацию радужными цветами:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
function getPattern() {
function getPattern() {
   pos++;
   pos++;
Строка 139: Строка 140:
Или мы можем воспользоваться генератором случайных чисел, чтобы светодиод попеременно мигал разными случайными оттенками синего.
Или мы можем воспользоваться генератором случайных чисел, чтобы светодиод попеременно мигал разными случайными оттенками синего.


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
function getPattern() {
function getPattern() {
   for (var i=0;i<rgb.length;i+=3) {
   for (var i=0;i<rgb.length;i+=3) {
Строка 149: Строка 150:
</syntaxhighlight>
</syntaxhighlight>


Теперь мы можем сохранить все наши разные функции getPattern() в массив, а затем переключаться между ними при нажатии на кнопку на Espruino:
Теперь мы можем сохранить все наши разные функции getPattern() в массив, а затем переключаться между ними при нажатии на кнопку на [[Espruino]]:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var patterns = [];
var patterns = [];
patterns.push(function() {
patterns.push(function() {
Строка 186: Строка 187:
</syntaxhighlight>
</syntaxhighlight>


Теперь, если нажать на кнопку на Espruino (не кнопку сброса!), паттерн изменится. Вы можете вернуться и отредактировать getPattern(), чтобы создать собственный паттерн:
Теперь, если нажать на кнопку на [[Espruino]] (не кнопку сброса!), паттерн изменится. Вы можете вернуться и отредактировать getPattern(), чтобы создать собственный паттерн:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
edit(getPattern);
edit(getPattern);
</syntaxhighlight>
</syntaxhighlight>


Отредактируйте его, перейдите к концу функции при помощи клавиши «Стрелочка вниз» или Page Down и нажмите Enter. Паттерн мигания светодиодов изменится. Теперь впишите строчку ниже и ваш новый паттерн будет сохранен в массив с паттернами (и в результате он тоже будет активирован при нажатии на кнопку Espruino, когда до него дойдёт очередь):
Отредактируйте его, перейдите к концу функции при помощи клавиши ''«Стрелочка вниз»'' или {{клавиша|Page Down}} и нажмите {{клавиша|Enter}}. Паттерн мигания [[светодиод]]ов изменится. Теперь впишите строчку ниже и ваш новый паттерн будет сохранен в массив с паттернами (и в результате он тоже будет активирован при нажатии на кнопку [[Espruino]], когда до него дойдёт очередь):


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
patterns.push(getPattern)
patterns.push(getPattern)
</syntaxhighlight>
</syntaxhighlight>
Строка 200: Строка 201:
Весь код полностью (если вы просто хотите разом скопировать его и вставить) выглядит вот так:
Весь код полностью (если вы просто хотите разом скопировать его и вставить) выглядит вот так:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var rgb = new Uint8ClampedArray(25*3);
var rgb = new Uint8ClampedArray(25*3);


Строка 248: Строка 249:
Вот и всё! Если вы создали какой-то клёвый паттерн, можете поделиться им с другими!
Вот и всё! Если вы создали какой-то клёвый паттерн, можете поделиться им с другими!


О том, где купить WS2811, читайте последнем разделе этой статьи. Там же можно почитать о том, какие типы светодиодов тоже работают по этому принципу.
О том, где купить [[WS2811]], читайте последнем разделе этой статьи. Там же можно почитать о том, какие типы [[светодиод]]ов тоже работают по этому принципу.


=См.также=
=См.также=


{{ads}}
 


=Внешние ссылки=
=Внешние ссылки=
Строка 258: Строка 259:
<references />
<references />


{{Навигационная таблица/Espruino}}
{{Навигационная таблица/Портал/Espruino}}
{{Навигационная таблица/Телепорт}}

Текущая версия от 15:06, 20 мая 2023

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


Индивидуальный доступ к светодиодам[1]

В последнее время светодиоды с индивидуальным доступом становятся всё дешевле и дешевле. Эти светодиоды (помимо самого RGB-светодиода) оснащены маленьким управляющим чипом, с помощью которого и задается нужный цвет. Эти управляющие чипы умеют принимать и отправлять последовательные данные и их можно последовательно подсоединить друг к другу (по принципу гирляндного подключения, которое также называют «daisy-chain»). Это позволяет управлять большим количеством светодиодов при помощи всего нескольких управляющих проводов, т.е. избавляет вас от необходимости использовать по проводу для каждого светодиода.


Сейчас есть два главных типа светодиодов с индивидуальным доступом – с 3 и 4 проводами.

Светодиоды вроде WS2801 оснащены 4 проводами – для заземления, питания, тактовой частоты и передачи данных. Ими можно управлять с помощью шины SPI, которая есть на большинстве микроконтроллеров. Но у этого метода есть пара маленьких недостатков:

  • Между каждой парой светодиодов должно быть 4 провода, что увеличивает затраты
  • Устройству, состоящему из управляющего чипа и светодиода, нужно больше проводов, что увеличивает его размер и затраты на него

Многие более современные управляющие чипы используют 3 провода – например, WS2811/WS2812/APA104/APA106 и SK6812. Управление ими осуществляется при помощи 1-проводного протокола последовательной передачи данных, в котором (как подсказывает его название) для передачи данных используется только 1 провод. Это значит:

  • Для каждого светодиода нужно только 3 провода
  • Управляющий чип будет более компактным, как и его печатная плата. Соответственно, само устройство тоже будет меньше
  • У многих светодиодов (по сути, у всех, кроме WS2811) управляющий чип находится внутри самого светодиода

В результате проект, создаваемый при помощи 3-проводных RGB-светодиодов, будет значительно дешевле проекта, создаваемого с помощью светодиодов WS2801.

В этом руководстве мы расскажем, как управлять этими 3-проводными светодиодами при помощи Espruino. Управление ими будет осуществляться при помощи серии импульсов на частоте 800 КГц, где коротким импульсом будет бит 0, а длинным – бит 1. Для управления этими устройствами есть специальная библиотека neopixel.

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

  • Цепь RGB-светодиодов вроде WS2811. Я воспользуюсь не светодиодной лентой, а 25 отдельными светодиодами, подключенными друг к другу
  • Плата Espruino

Подсоединение

Ознакомьтесь документацией к библиотеке neopixel – светодиоды вроде WS2811 могут быть очень привередливы касаемо напряжения на линии для передачи данных. Если вы используете Espruino Original или Pico, то проблем возникнуть не должно, но при использовании других плат может понадобиться чуть более высокое напряжение.

У цепи светодиодов WS2811 должно быть два конца по 3 провода на каждом (некоторые из них могут быть продублированы) – красный, белый и зелёный. Красный – это 5-вольтовое питание, белый – это заземление, а зелёный – это передача сигнала (данных). Если к вашей светодиодной цепи есть какая-то документация, то советуем сначала ознакомиться с ней.

Сигнальный провод с одной стороны будет использоваться для ввода данных, а с другой – для вывода. Так вы сможете подключить друг к другу более 50 светодиодов. На моих светодиодах коннектор типа «мама» был входным. Но если на ваших светодиодах есть пометки «DI»/«DO» или в документации есть какое-то специальное упоминание об обозначениях, то используйте их.

Итак, само подключение выполняется очень просто.

Просто подсоедините белый (0 вольт) и красный (5 вольт) провода к 5-вольтовому источнику питания. Наверно, USB лучше не использовать, потому что когда всё будет включено, 50 светодиодов будут тянуть около 1 ампера, а это очень много!

Подключите белый провод к контакту GND, а зелёный – к контакту SPI MOSI на Espruino. Для этих целей подойдёт, например, B15 (но есть и другие варианты). На платах Discovery это обычно A7, а на платах Maple/OlimexinoD11. Если сомневаетесь, лучше сверьтесь с документацией платы.

Код

Теперь, когда всё подключено, давайте попробуем отправить какие-нибудь данные. Например, на первый светодиод. Передаваемые данные будут трёхсоставными – по байту для красного, зелёного и синего значений:

require("neopixel").write(B15, [255,0,0]);

В результате первый светодиод загорится красным цветом.

Обратите внимание, что в строчке кода выше используется контакт B15. Если вы хотите использовать какой-то другой контакт (см. раздел «Подсоединение» выше), то этот аргумент нужно будет поменять, но на большинстве устройств вам также надо будет убедиться, что нужный контакт можно использовать как MOSI-контакт для аппаратной SPI. При использовании Puck.js подойдёт абсолютно любой контакт.

Разумеется, мы можем задать и другие цвета:

require("neopixel").write(B15, [0,255,0]);     // зелёный
require("neopixel").write(B15, [0,0,255]);     // синий
require("neopixel").write(B15, [255,255,255]); // белый

Теперь давайте дополнительно зададим цвета для второго и третьего светодиодов. Для этого нам просто нужно отправить больше данных:

require("neopixel").write(B15, [255,0,0, 0,255,0, 0,0,255]);

Теперь мы можем создать функцию с циклом for(), которая будет создавать цвета для всех светодиодов. Код ниже делает так, чтобы все 50 светодиодов загорались всё более ярким белым цветом (первый светодиод будет выключен):

var rgb = new Uint8ClampedArray(25*3);

function getPattern() {
  for (var i=0;i<rgb.length;i+=3) {
     rgb[i  ] = i*10;
     rgb[i+1] = i*10;
     rgb[i+2] = i*10;
  }
}

Обратите внимание, что в самом верху при помощи класса Uint8ClampedArray мы задали массив rgb. Мы можем воспользоваться и обычным массивом, но типизированные массивы быстрее и занимают меньше памяти, если вам нужно хранить лишь значения в диапазоне между 0 и 255. Использование Uint8ClampedArray также означает, что все значения больше 255 и меньше 0 будут «обрезаны». При использовании Uint8Array у значения будут просто удалены старшие биты, из-за чего 256 станет 0, 257 станет 1 и так далее.

Затем мы можем создать функцию, которая будет отправлять эту информацию светодиодам, а затем вызывать её:

function doLights() {
  getPattern();
  require("neopixel").write(B15, rgb);
}

doLights();

Теперь у нас получился приятный оттенок серого. Но его также можно заанимировать:

var pos = 0;
function getPattern() {
  pos++;
  for (var i=0;i<rgb.length;i+=3) {
     var col = (Math.sin(i+pos*0.2)+1) * 127;
     rgb[i  ] = col;
     rgb[i+1] = col;
     rgb[i+2] = col;
  }
}
doLights();

В коде выше используется синусоида, с помощью которой светодиод занимает промежуточное положение между максимальной яркостью и выключением. Позиция анимации хранится в переменной pos. Теперь при каждом вызове doLights() цвет будет меняться. Мы можем заанимировать это при помощи setInterval().

setInterval(doLights,50);

Теперь давайте попробуем что-нибудь ещё. Например, мы можем воспользоваться синусоидными волнами разной частоты, чтобы сделать анимацию радужными цветами:

function getPattern() {
  pos++;
  for (var i=0;i<rgb.length;i+=3) {
     rgb[i  ] = (1 + Math.sin((i+pos)*0.1324)) * 127;
     rgb[i+1] = (1 + Math.sin((i+pos)*0.1654)) * 127;
     rgb[i+2] = (1 + Math.sin((i+pos)*0.1)) * 127;
  }
}

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

function getPattern() {
  for (var i=0;i<rgb.length;i+=3) {
     rgb[i  ] = 0;
     rgb[i+1] = 0;
     rgb[i+2] = Math.random()*255;
  }
}

Теперь мы можем сохранить все наши разные функции getPattern() в массив, а затем переключаться между ними при нажатии на кнопку на Espruino:

var patterns = [];
patterns.push(function() {
  pos++;
  for (var i=0;i<rgb.length;i+=3) {
     var col = (Math.sin(i+pos*0.2)+1) * 127;
     rgb[i  ] = col;
     rgb[i+1] = col;
     rgb[i+2] = col;
  }
});
patterns.push(function() {
  pos++;
  for (var i=0;i<rgb.length;i+=3) {
     rgb[i  ] = (1 + Math.sin((i+pos)*0.1324)) * 127;
     rgb[i+1] = (1 + Math.sin((i+pos)*0.1654)) * 127;
     rgb[i+2] = (1 + Math.sin((i+pos)*0.1)) * 127;
  }
});
patterns.push(function() {
  for (var i=0;i<rgb.length;i+=3) {
     rgb[i  ] = 0;
     rgb[i+1] = 0;
     rgb[i+2] = Math.random()*255;
  }
});

var patternNumber = 0;
function changePattern() {
  patternNumber = (patternNumber+1) % patterns.length;
  getPattern = patterns[patternNumber];
}
setWatch(changePattern, BTN, { repeat: true, edge:'falling' });

Теперь, если нажать на кнопку на Espruino (не кнопку сброса!), паттерн изменится. Вы можете вернуться и отредактировать getPattern(), чтобы создать собственный паттерн:

edit(getPattern);

Отредактируйте его, перейдите к концу функции при помощи клавиши «Стрелочка вниз» или  Page Down  и нажмите  ↵ Enter . Паттерн мигания светодиодов изменится. Теперь впишите строчку ниже и ваш новый паттерн будет сохранен в массив с паттернами (и в результате он тоже будет активирован при нажатии на кнопку Espruino, когда до него дойдёт очередь):

patterns.push(getPattern)

Весь код полностью (если вы просто хотите разом скопировать его и вставить) выглядит вот так:

var rgb = new Uint8ClampedArray(25*3);

var pos=0;

var patterns = [];
patterns.push(function() {
  pos++;
  for (var i=0;i<rgb.length;i+=3) {
     var col = (Math.sin(i+pos*0.2)+1) * 127;
     rgb[i  ] = col;
     rgb[i+1] = col;
     rgb[i+2] = col;
  }
});
patterns.push(function() {
  pos++;
  for (var i=0;i<rgb.length;i+=3) {
     rgb[i  ] = (1 + Math.sin((i+pos)*0.1324)) * 127;
     rgb[i+1] = (1 + Math.sin((i+pos)*0.1654)) * 127;
     rgb[i+2] = (1 + Math.sin((i+pos)*0.1)) * 127;
  }
});
patterns.push(function() {
  for (var i=0;i<rgb.length;i+=3) {
     rgb[i  ] = 0;
     rgb[i+1] = 0;
     rgb[i+2] = Math.random()*255;
  }
});
var getPattern = patterns[0];
function doLights() {
  getPattern();
  require("neopixel").write(B15, rgb);
}

var patternNumber = 0;
function changePattern() {
  patternNumber = (patternNumber+1) % patterns.length;
  getPattern = patterns[patternNumber];
}

setWatch(changePattern, BTN, { repeat: true, edge:'falling' });
setInterval(doLights,50);

Вот и всё! Если вы создали какой-то клёвый паттерн, можете поделиться им с другими!

О том, где купить WS2811, читайте последнем разделе этой статьи. Там же можно почитать о том, какие типы светодиодов тоже работают по этому принципу.

См.также

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