
Привет, Хабр! Вас тоже огорчало, что PLS-разъёмы плат Arduino Uno и Mega установлены без соблюдения сетки с шагом 2.54 мм, отчего невозможно создать собственный шилд на базе обычной макетки под пайку?
А ещё обидно, что на упомянутых платах не предусмотрено никаких кнопок, кроме сброса, а программно управляемый светодиод есть, но всего один, если не считать присоединённых к линиям Tx и Rx, задействованным при загрузке скетча и обмене данными с компьютером. То есть, без подключения внешних компонентов почти ничего нельзя сделать.
Сегодня я соберу вариант Arduino Uno с тремя подключёнными к GPIO светодиодами и тремя кнопками, не считая сброса. А расположение разъёмов остаётся стандартным, чтобы не терять совместимости с шилдами.
Если вам нужны компактность и шаг 2.54 мм для паечных и беспаечных макетных плат, то лучше будет воспользоваться Arduino Nano. Но к нему не получится подключить стандартный шилд, в отличие от контроллера из набора OPEN-SMART UNO R3, сборкой которого мы займёмся.
▍ Процесс монтажа
При определении последовательности установки деталей на печатные платы обычно соблюдается простое правило: первыми монтируются компоненты с меньшей высотой.
Наш сегодняшний радиоконструктор — не исключение, и начинать мы будем с резисторов. Их здесь всего пять штук, четыре из которых номиналом 1 килоом и один 10-килоомный.

Лично я сначала устанавливаю те компоненты, которые имеются в большем количестве. Идея в том, что находить их посадочные места получается быстрее. По мере заполнения платы будет легче искать места под следующие компоненты среди меньшего числа пустых.
Далее следует припаять модуль преобразователя интерфейсов USB-UART, соблюдая ключ, который выглядит как кружочек на шелкографии платы и модуля.

Следующий этап — установка кнопки сброса, цангового разъёма под кварцевый резонатор и пяти керамических конденсаторов, три из которых служат фильтрами питания и имеют ёмкость 100 нанофарад. Два других конденсатора по 22 пикофарады задействованы в обвязке кварца.

Затем паяем кроватку под микроконтроллер, не забывая о соблюдении ключа.

Теперь настаёт очередь разъёма для внутрисхемного последовательного программирования, пищалки, электролитического конденсатора и светодиодов.
Все эти компоненты, кроме разъёма, имеют полярность. Следует быть внимательными, чтобы не установить какую-нибудь из деталей вверх ногами.

Сборка нашего Ардуино близится к завершению, и теперь нужно установить разъёмы для присоединения шилдов.

В последнюю очередь паяем разъём USB-B и три красивые большие кнопки. Останется только вставить в панельки кварц и микроконтроллер.

Производители набора положили в комплект запасной кварц, один лишний резистор на 10 килоом и два на 1 килоом. Всегда приятно получать в подарок дополнительные компоненты, особенно таких ходовых номиналов, которые обычно расходуются быстрее всего!

После подачи питания по USB-кабелю плата весело замигала светодиодом. Микроконтроллер в комплекте оказался прошит скетчем «Blink a LED», что в мире Ардуино является эквивалентом «Hello, world!» — «Привет, мир!».

Благодаря этому, для проверки работоспособности собранного устройства даже не нужен компьютер. Достаточно USB повербанка или блока питания напряжением 5 вольт.
Отметим, что стабилизатор питания на плате OPEN-SMART UNO R3, в отличие от классического Arduino Uno, не предусмотрен.
▍ Что может Ардуино?
Для дальнейшего знакомства с возможностями платы загрузим простейший демонстрационный скетч, написанный Стефаном Фамбахом.
#include "OpenSmartUnoR3.h" void setup() { Board.init(true); } void loop() { Board.loop(); }
Как видим, этот скетч просто инициализирует плату и запускает бесконечный цикл из демонстрационной библиотеки.
#ifndef OpenSmartUnoR3_h #define OpenSmartUnoR3_h #include "EasyBuzzer.h" #define BUZZER 6 class OpenSmartUnoR3 { protected: bool _test; EasyBuzzerClass eb; public: enum SWITCH { SW1 = 2, SW2 = 3, SW3 = 4 }; enum LED { LED1 = 7, LED2 = 8, LED3 = 13 }; void init(bool test = false) { _test = test; pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); pinMode(BUZZER, OUTPUT); pinMode(SW1, INPUT_PULLUP); pinMode(SW2, INPUT_PULLUP); pinMode(SW3, INPUT_PULLUP); } void loop() { if (_test) { setLED(LED1, getSwitch(SW1)); setLED(LED2, getSwitch(SW2)); setLED(LED3, getSwitch(SW3)); if(getSwitch(SW1) && getSwitch(SW2)){ eb.beep(1000); }else { eb.stopBeep(); } } } bool getSwitch(SWITCH sw) { return !digitalRead(sw); } static void setLED(LED selected, bool status) { digitalWrite(selected, status); } };
В свою очередь, библиотека определяет, к каким выводам Ардуино подключены кнопки и светодиоды, и что нужно делать в бесконечном цикле. Скетч зажигает светодиоды с номерами, соответствующими номерам нажатых кнопок. Если одновременно нажать вторую и третью кнопки, запищит зуммер, прямо как в устройстве для голосования на логических микросхемах. Для управления зуммером автор воспользовался сторонней библиотекой EasyBuzzer.
▍ Смотрим видео
Итак, мы убедились в работоспособности нашей платы. Теперь давайте сделаем что-нибудь более интересное. Для этого подключим к свежесобранному контроллеру Rich Shield Two от того же OPEN-SMART.
▍ Индикатор заряда батареи
Этот шилд содержит красивый светодиодный столбчатый индикатор, выполненный в виде батарейки с десятью светодиодами четырёх разных цветов — алого, янтарного, изумрудного и лазурного.

Для управления этим индикатором используется специализированная микросхема TM1651 — драйвер светодиодов с цифровой регулировкой яркости, функцией сканирования клавиатуры и двухпроводным последовательным интерфейсом.

Скетч устанавливает яркость светодиодов на максимум и имитирует индикацию процесса заряда аккумулятора.
#include "TM1651.h" #define CLK 10 // определяем, куда подключены выводы TM1651 #define DIO 11 TM1651 batteryDisplay(CLK,DIO); void setup() { batteryDisplay.init(); batteryDisplay.set(BRIGHTEST);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7; batteryDisplay.frame(FRAME_ON); } void loop() { charging(); } void charging() { for(uint8_t level = 0; level < 8; level ++) { batteryDisplay.displayLevel(level); delay(500); } }
Для этого используется библиотека Battery Display.
TM1651.h
// Author:Fred.Chu // Date:14 August, 2014 // // Applicable Module: // Battery Display v1.0 // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Modified record: // /*******************************************************************************/ #ifndef TM1651_H #define TM1651_H #include <inttypes.h> #include <Arduino.h> //************definitions for TM1651********************* #define ADDR_AUTO 0x40 #define ADDR_FIXED 0x44 #define STARTADDR 0xc0 /**** definitions for the frame of the battery display *******/ #define FRAME_ON 1 #define FRAME_OFF 0 /**************definitions for brightness***********************/ #define BRIGHT_DARKEST 0 #define BRIGHT_TYPICAL 2 #define BRIGHTEST 7 class TM1651 { public: uint8_t Cmd_SetData; uint8_t Cmd_SetAddr; uint8_t Cmd_DispCtrl; TM1651(uint8_t, uint8_t); void init(); void writeByte(int8_t wr_data);//write 8bit data to tm1651 void start(void);//send start bits void stop(void); //send stop bits void displayLevel(uint8_t Level); void frame(boolean FrameFlag); void clearDisplay(void); void set(uint8_t = BRIGHT_TYPICAL,uint8_t = 0x40,uint8_t = 0xc0);//To take effect the next time it displays. private: uint8_t Clkpin; uint8_t Datapin; void bitDelay(); }; #endif
TM1651.cpp
// Author:Fred.Chu // Date:14 August, 2014 // // Applicable Module: // Battery Display v1.0 // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Modified record: // /*******************************************************************************/ #include "TM1651.h" #include <Arduino.h> static int8_t LevelTab[] = {0x00,0x40,0x60,0x70,0x78,0x7c,0x7e,0x7f};//Level 0~7 TM1651::TM1651(uint8_t Clk, uint8_t Data) { Clkpin = Clk; Datapin = Data; pinMode(Clkpin,OUTPUT); pinMode(Datapin,OUTPUT); } void TM1651::init() { set(BRIGHT_TYPICAL); clearDisplay(); } void TM1651::writeByte(int8_t wr_data) { uint8_t data = wr_data; // 8 Data Bits for(uint8_t i = 0; i < 8; i++) { // CLK low pinMode(Clkpin, OUTPUT); bitDelay(); // Set data bit if (data & 0x01) pinMode(Datapin, INPUT); else pinMode(Datapin, OUTPUT); bitDelay(); // CLK high pinMode(Clkpin, INPUT); bitDelay(); data = data >> 1; } // Wait for acknowledge // CLK to zero pinMode(Clkpin, OUTPUT); pinMode(Datapin, INPUT); bitDelay(); // CLK to high pinMode(Clkpin, INPUT); bitDelay(); uint8_t ack = digitalRead(Datapin); if (ack == 0) pinMode(Datapin, OUTPUT); bitDelay(); pinMode(Clkpin, OUTPUT); bitDelay(); } //send start signal to TM1651 void TM1651::start(void) { pinMode(Datapin, OUTPUT); bitDelay(); } //End of transmission void TM1651::stop(void) { pinMode(Datapin, OUTPUT); bitDelay(); pinMode(Clkpin, INPUT); bitDelay(); pinMode(Datapin, INPUT); bitDelay(); } //****************************************** void TM1651::displayLevel(uint8_t Level) { if(Level > 7)return;//Level should be 0~7 start(); //start signal sent to TM1651 from MCU writeByte(ADDR_FIXED);// stop(); // start(); // writeByte(0xc0);// writeByte(LevelTab[Level]);// stop(); // start(); // writeByte(Cmd_DispCtrl);// stop(); // } void TM1651::frame(boolean FrameFlag) { int8_t SegData; if (FrameFlag == 1) SegData = 0x40; else SegData = 0x00; start(); //start signal sent to TM1651 from MCU writeByte(ADDR_AUTO);// stop(); // start(); // writeByte(0xc1);// for(uint8_t i=0;i < 3;i ++) { writeByte(SegData); // } stop(); // start(); // writeByte(Cmd_DispCtrl);// stop(); // } void TM1651::clearDisplay(void) { displayLevel(0); frame(FRAME_OFF); } //To take effect the next time it displays. void TM1651::set(uint8_t brightness,uint8_t SetData,uint8_t SetAddr) { Cmd_SetData = SetData; Cmd_SetAddr = SetAddr; Cmd_DispCtrl = 0x88 + brightness;//Set the brightness and it takes effect the next time it displays. } void TM1651::bitDelay() { delayMicroseconds(50); }
▍ Индикатор громкости
На плате шилда имеются простой микрофонный предусилитель и миниатюрный электретный микрофон.

А вот и скетч индикатора громкости звука. Он использует всю ту же библиотеку и просто считывает аналоговое значение с входа А2, а затем передаёт его столбчатому индикатору.
#include "TM1651.h" #define CLK 10 // определяем, куда подключены выводы TM1651 #define DIO 11 TM1651 batteryDisplay(CLK,DIO); #define SOUND_PIN A2 #define MAX_SENSORVALUE 1000 #define MIN_SENSORVALUE 8 void setup() { batteryDisplay.init(); batteryDisplay.set(BRIGHTEST);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7; } void loop() { int sensorValue = analogRead(SOUND_PIN); int level = map(sensorValue, 0, MAX_SENSORVALUE, 0, MIN_SENSORVALUE); batteryDisplay.displayLevel(level); }
▍ Светодиодная матрица
Две красные светодиодные матрицы 8x8 управляются с помощью одной микросхемы HT16K33.

Как и TM1651, она представляет собой драйвер светодиодов со сканером клавиатуры и интерфейсом I²C, только гораздо более продвинутый.

Графические библиотеки Adafruit позволяют выводить на светодиодную матрицу геометрические фигуры, текст и растровые изображения.
#include <Wire.h> #include <Adafruit_GFX.h> #include "Adafruit_LEDBackpack.h" #include <Adafruit_NeoPixel.h> #define PIN A3 #define NUM 4 Adafruit_NeoPixel rgb = Adafruit_NeoPixel(NUM, PIN, NEO_GRB + NEO_KHZ800); Adafruit_8x16matrix matrix = Adafruit_8x16matrix(); void setup() { rgb.begin(); rgb.clear(); rgb.show(); matrix.begin(0x70); // I²C адрес контроллера HT16K33 } static const uint8_t PROGMEM smile_bmp[] = { B00111100, B01000010, B10100101, B10000001, B10100101, B10011001, B01000010, B00111100 }, neutral_bmp[] = { B00111100, B01000010, B10100101, B10000001, B10111101, B10000001, B01000010, B00111100 }, frown_bmp[] = { B00111100, B01000010, B10100101, B10000001, B10011001, B10100101, B01000010, B00111100 }; void loop() { matrix.clear(); matrix.drawBitmap(0, 0, smile_bmp, 8, 8, LED_ON); matrix.writeDisplay(); delay(500); matrix.clear(); matrix.drawBitmap(0, 8, neutral_bmp, 8, 8, LED_ON); matrix.writeDisplay(); delay(500); matrix.clear(); matrix.drawBitmap(0, 0, frown_bmp, 8, 8, LED_ON); matrix.writeDisplay(); delay(500); matrix.clear(); // очищаем дисплей matrix.drawPixel(0, 0, LED_ON); // рисуем пиксель в программном буфере matrix.writeDisplay(); // выгружаем изменения в дисплей delay(500); matrix.clear(); matrix.drawLine(0,0, 7,15, LED_ON); matrix.writeDisplay(); delay(500); matrix.clear(); matrix.drawRect(0,0, 8,16, LED_ON); matrix.fillRect(2,2, 4,12, LED_ON); matrix.writeDisplay(); delay(500); matrix.clear(); matrix.drawCircle(3,8, 3, LED_ON); matrix.writeDisplay(); delay(500); matrix.setTextSize(1); matrix.setTextWrap(false); matrix.setTextColor(LED_ON); matrix.setRotation(1); for (int8_t x=7; x>=-69; x--) { matrix.clear(); matrix.setCursor(x,0); matrix.print("RUVDS @ Habr"); matrix.writeDisplay(); delay(100); } delay(2000); matrix.setRotation(0); }
▍ Энкодер
На этом аппаратные богатства нашего маленького шилда не заканчиваются. В распоряжение экспериментатора предоставляются микросхема цифрового термометра DS18B20, аналоговый джойстик и нажимной относительный энкодер.

Вращение ручки энкодера преобразуется в угол наклона линии на матричном светодиодном экране.

А если нажать эту ручку, то экран погаснет до следующего её поворота.
#include <Wire.h> #include <Adafruit_GFX.h> #include "Adafruit_LEDBackpack.h" #include <RotaryEncoder.h> #include <Adafruit_NeoPixel.h> #define PIN A3 #define NUM 4 Adafruit_NeoPixel rgb = Adafruit_NeoPixel(NUM, PIN, NEO_GRB + NEO_KHZ800); #define encoder_button 4 RotaryEncoder encoder(3, 2); #define CLOCKWISE 1 #define ANTI_CLOCKWISE -0 Adafruit_8x16matrix matrix = Adafruit_8x16matrix(); void rotatePointer(uint8_t,uint8_t); void setup() { rgb.begin(); rgb.clear(); rgb.show(); pinMode(encoder_button,INPUT); matrix.begin(0x70); matrix.setRotation(1); matrix.drawLine(0,3, 15,4, LED_ON); matrix.writeDisplay(); } void loop() { static int pos = 0; if(digitalRead(encoder_button)==1) { delay(10); if(digitalRead(encoder_button)==1) { matrix.clear(); matrix.writeDisplay(); } } encoder.tick(); int newPos = encoder.getPosition(); uint8_t pointerDirection; if (pos != newPos) { RotaryEncoder::Direction currentDirection = encoder.getDirection(); if (currentDirection == RotaryEncoder::Direction::COUNTERCLOCKWISE) { pointerDirection = ANTI_CLOCKWISE; } else pointerDirection = CLOCKWISE; rotatePointer(pointerDirection,1); rotatePointer(pointerDirection,1); pos = newPos; } // if } int8_t x1=0; int8_t x2=15; int8_t y1=3; int8_t y2=4; void rotatePointer(uint8_t direction, uint8_t steps) { if(direction==CLOCKWISE){ if(x1==0 && y1>0)y1 -= steps; else if(y1==0 && x1<15) x1 += steps; else if(x1==15 && y1<7) y1 += steps; else if(y1==7 && x1>0) x1 -= steps; if(x2==0 && y2>0)y2 -= steps; else if(y2==0 && x2<15) x2 += steps; else if(x2==15 && y2<7) y2 += steps; else if(y2==7 && x2>0) x2 -= steps; } else{ if(x1==0 && y1<7)y1 += steps; else if(y1==7 && x1<15) x1 += steps; else if(x1==15 && y1>0) y1 -= steps; else if(y1==0 && x1>0) x1 -= steps; if(x2==0 && y2<7)y2 += steps; else if(y2==7 && x2<15) x2 += steps; else if(x2==15 && y2>0) y2 -= steps; else if(y2==0 && x2>0) x2 -= steps; } matrix.clear(); matrix.drawLine(x1,y1, x2,y2, LED_ON); matrix.writeDisplay(); }
▍ Джойстик
Аналоговый джойстик представляет собой два переменных резистора, положение бегунков которых считывается аналогово-цифровыми преобразователями в виде двух напряжений и преобразуются в числа, означающие координаты по горизонтальной и вертикальной осям.

Данный скетч перемещает по матричному экрану светящуюся точку согласно командам с джойстика.
#include <OS_SingleJoystick.h> #include <Wire.h> #include <Adafruit_GFX.h> #include "Adafruit_LEDBackpack.h" #include <Adafruit_NeoPixel.h> #define PIN A3 #define NUM 4 Adafruit_NeoPixel rgb = Adafruit_NeoPixel(NUM, PIN, NEO_GRB + NEO_KHZ800); Adafruit_8x16matrix matrix = Adafruit_8x16matrix(); #define SW_PIN 0xff // Джойстик не нажимной. #define JOYSTCK_X A0 #define JOYSTCK_Y A1 SingleJoystick joystick(JOYSTCK_X, JOYSTCK_Y); uint8_t coordinate_x = 7; uint8_t coordinate_y = 3; void setup() { rgb.begin(); rgb.clear(); rgb.show(); matrix.begin(0x70); matrix.setRotation(1); matrix.clear(); matrix.drawPixel(coordinate_x, coordinate_y, LED_ON); matrix.writeDisplay(); } void loop() { joystickControlLED(); delay(100); } void joystickControlLED() { if(joystick.isChange()) { int x,y; x=joystick.nowX; y=joystick.nowY; uint8_t operation; operation = joystick.multipleRead(); switch (operation) { case MOVE_UP: if(coordinate_y>0) coordinate_y -= 1; break; case MOVE_DOWN: if(coordinate_y<7) coordinate_y += 1; break; case MOVE_RIGHT: if(coordinate_x<15) coordinate_x += 1; break; case MOVE_LEFT: if(coordinate_x>0) coordinate_x -= 1; break; default: break; } matrix.clear(); matrix.drawPixel(coordinate_x, coordinate_y, LED_ON); matrix.writeDisplay(); } }
▍ Электронный термометр

А этот скетч выводит на матричный дисплей показания температуры и отображает её изменения на столбчатом индикаторе.
#include <OneWire.h> #include <Wire.h> #include <Adafruit_GFX.h> #include "Adafruit_LEDBackpack.h" #include "TM1651.h" #include <Adafruit_NeoPixel.h> #define PIN A3 #define NUM 4 Adafruit_NeoPixel rgb = Adafruit_NeoPixel(NUM, PIN, NEO_GRB + NEO_KHZ800); #define CLK 10 #define DIO 11 TM1651 batteryDisplay(CLK,DIO); OneWire ds(5); Adafruit_8x16matrix matrix = Adafruit_8x16matrix(); uint8_t level = 2; int8_t temp0; void setup() { rgb.begin(); rgb.clear(); rgb.show(); matrix.begin(0x70); matrix.setRotation(1); batteryDisplay.init(); batteryDisplay.set(BRIGHTEST);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7; temp0 = readTemp(); batteryDisplay.displayLevel(level); } void loop() { int8_t celsius; celsius = readTemp(); displayTemp(celsius); batteryDisplay.displayLevel(level+celsius-temp0); } int8_t readTemp() { byte data[12]; float celsius; ds.reset(); ds.skip(); ds.write(0x44, 0); delay(750); ds.reset(); ds.skip(); ds.write(0xBE); for (unsigned char i = 0; i < 9; i++) { data[i] = ds.read(); } int16_t raw = (data[1] << 8) | data[0]; byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; celsius = (float)raw / 16.0; return celsius; } void displayTemp(int8_t temp) { matrix.clear(); matrix.setCursor(0,0); matrix.print(temp); matrix.print('c'); matrix.writeDisplay(); }
▍ Адресуемые RGB светодиоды
И напоследок поиграем с четырьмя умными светодиодами, внутри каждого из которых имеются три светоизлучающих кристалла и собственный микроконтроллер.

Мы будем зажигать всю линейку разными цветами, чередуя это с эффектом жёлтых бегущих огней.
#include <Adafruit_NeoPixel.h>#define PIN A3 #define NUM 4 Adafruit_NeoPixel rgb = Adafruit_NeoPixel(NUM, PIN, NEO_GRB + NEO_KHZ800); #define LEFT_TO_RIGHT 0 #define RIGHT_TO_LEFT 1 void setup() { rgb.begin(); rgb.clear(); rgb.show(); } void loop() { rgb.setBrightness(40); colorWipe(rgb.Color(100, 100, 100), 0); // Белый delay(600); colorWipe(rgb.Color(50, 0, 0), 0); // Красный delay(600); colorWipe(rgb.Color(0, 50, 0), 0); // Зелёный delay(600); colorWipe(rgb.Color(0, 0, 50), 0); // Синий delay(600); colorWipe(rgb.Color(0, 0, 0), 0); // Чёрный delay(600); runLED(0xffff00, LEFT_TO_RIGHT); // Жёлтый delay(600); colorWipe(rgb.Color(0, 0, 0), 0); // Чёрный delay(600); runLED(0xffff00, RIGHT_TO_LEFT);// Жёлтый delay(600); } // Последовательно заполняем пиксели цветом один за другим void colorWipe(uint32_t c, uint8_t wait) { for(uint16_t i=0; i<NUM; i++) { rgb.setPixelColor(i, c); } rgb.show(); } void runLED(uint32_t c, uint8_t direction) { if(direction==LEFT_TO_RIGHT) for(uint8_t i=0; i<NUM; i++) { rgb.setPixelColor(i, c); rgb.show(); delay(150); } else for(uint8_t i=NUM; i>0; i--) { rgb.setPixelColor(i-1, c); rgb.show(); delay(150); } } void theaterChase(uint32_t c, uint8_t wait) { for (int j=0; j<10; j++) { for (int q=0; q < 3; q++) { for (int i=0; i < rgb.numPixels(); i=i+3) { rgb.setPixelColor(i+q, c); // зажигаем каждый третий пиксель } rgb.show(); delay(wait); for (int i=0; i < rgb.numPixels(); i=i+3) { rgb.setPixelColor(i+q, 0); // гасим каждый третий пиксель } } } }
▍ Наблюдения и выводы
Как можно заметить на видео, при загрузке нового скетча те контроллеры светодиодов, которые в нём не задействованы, остаются в том же состоянии, в котором находились до прерывания работы старого скетча.
Нажатие кнопки сброса центрального контроллера на них также не влияет, и «лишние» светодиоды гаснут только после выключения питания платы. Так и должно быть, ведь контроллеры светодиодов работают автономно, и линия общего сброса, к которой можно было бы просто присоединить кнопку, не предусмотрена.
Напишите в комментариях свои идеи по использованию Ардуино-совместимой платы с тремя светодиодами и тремя кнопками самого по себе, а также в сочетании с Rich Shield Two.
Telegram-канал со скидками, розыгрышами призов и новостями IT ?

