Новогодняя bluetooth НС-06 гирлянда на Ардуино. WS2811. Библиотека FastLed. Android. 4

Всех с наступающим Новым Годом!

Bluetooth гирлянда

гирлянда

В преддверии праздника речь пойдет о новогодней гирлянде, управляемой с планшета или смартфона по bluetooth.

Список компонентов проекта:

  1. RGB светодиодная лента(гирлянда) с микросхемой управления
  2. Ардуино pro mini
  3. Bluetooth модуль
  4. Планшет(смартфон) на базе Андроид

В продаже существует очень много разных RGB лент, на разных микросхемах. Ниже список микросхем, с которыми мы сможем работать.

Список микросхем управления светодиодами RGB

1 — Ленты, подключаемые к контроллеру при помощи одного провода(данные):

  • TM1803
  • TM1804
  • TM1809
  • WS2811
  • WS2812
  • WS2812B
  • NEOPIXEL
  • APA104
  • UCS1903
  • UCS1903B
  • GW6205
  • GW6205_400

2 — Ленты, подключаемые к контроллеру при помощи 2х проводов(данные, счетчик):

  • WS2801
  • SM16716
  • LPD8806
  • P9813
  • APA102
  • DOTSTAR

В нашем случае — это готовая гирлянда на WS2811.

Гирлянда на WS2811

потребление тока одного диода — 50мА
напряжение питания — 5v

Схема подключения гирлянды к Ардуино

ws2811_arduino

FastLed Library — Библиотека управления лентой

Ссылка на библиотеку https://github.com/FastLED/FastLED
Простой пример использования библиотеки:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "FastLED.h"
#define LEDS 2 //количество светодиодов
#define DATA_P 2//пин подключения провода данных
#define CLOCK_P 13//пин подключения провода счетчика
CRGB leds[LEDS];//массив цветов
 
void setup() {
//инициализируем нашу ленту
FastLED.addLeds<WS2811, DATA_P>(leds, LEDS);
// FastLED.addLeds<WS2801, DATA_P, CLOCK_P, RGB>(leds, LEDS);
}
void loop() {
leds[0] = CRGB::Red;//устанавливаем цвет для первого светодиода
leds[1] = CRGB(0,255,0)//или так задаем цвет
FastLED.show();//Посылаем данные на гирлянду
delay(500);//задержка
}
#include "FastLED.h"
#define LEDS 2 //количество светодиодов
#define DATA_P 2//пин подключения провода данных
#define CLOCK_P 13//пин подключения провода счетчика
CRGB leds[LEDS];//массив цветов

void setup() {
//инициализируем нашу ленту
FastLED.addLeds<WS2811, DATA_P>(leds, LEDS);
// FastLED.addLeds<WS2801, DATA_P, CLOCK_P, RGB>(leds, LEDS);
}
void loop() {
leds[0] = CRGB::Red;//устанавливаем цвет для первого светодиода
leds[1] = CRGB(0,255,0)//или так задаем цвет
FastLED.show();//Посылаем данные на гирлянду
delay(500);//задержка
}

Закончим работу с Ардуиной подключением bluetooth модуля и написания скетча для обработки сигнала.
В нашем случае используется модуль HC-06
IMG_0308[1]

Схема подключения модуля НС-06 к Ардуино

hc-06_arduino

Библиотека Ардуино для работы с модулем bluetooth HC-06

Для получения и отправки данных через bluetooth модуль, достаточно использовать обычное сериал соединение. Но мы используем Ардуино pro mini, и единственный сериал нам нужен для работы в системе «Умный дом». Данная библиотека позволяет подключить несколько bluetooth модулей.

Поэтому воспользуемся программным сериалом. Для этого необходимо загрузить и установить библиотеку SoftwareSerial https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/libraries/SoftwareSerial

Скетч управления светодиодной лентой на микросхеме WS2811 через bluetooth

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include 
SoftwareSerial mySerial(10, 11); // RX, TX - пины подключения bluetooth модуля
#include "FastLED.h"
#define NUM_LEDS 50//количество светодиодов/микросхем
#define DATA_PIN 2//пин подключения ленты
CRGB leds[NUM_LEDS];//создаем массив цветов
uint8_t  b_r;//значение красного цвета
uint8_t  b_g;//значение зеленого цвета
uint8_t  b_b;//значение синего цвета
void setup()  
{
  mySerial.begin(9600);//открываем программный сериал
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);//инициализируем управление светодиодной лентой
}
void loop() 
{
  if (mySerial.available()){//если получили данные по bluetooth
    
    b_r=mySerial.read();//читаем первый байт данных
    while  (!mySerial.available());//ожидаем следующий байт
    b_g=mySerial.read();//читаем второй байт данных
    while  (!mySerial.available());//ожидаем следующий байт
    b_b=mySerial.read();//читаем третий байт данных
    mySerial.flush();//очищаем буфер, т.к. больше ничего мы не передаем
    for (int i=0; i<NUM_LEDS; i++){//устанавливаем полученный цвет для всех светодиодов
    leds[i] = CRGB(b_r,b_g,b_b);}
    FastLED.show(); //обновляем состояние ленты
  }
}
#include 
SoftwareSerial mySerial(10, 11); // RX, TX - пины подключения bluetooth модуля
#include "FastLED.h"
#define NUM_LEDS 50//количество светодиодов/микросхем
#define DATA_PIN 2//пин подключения ленты
CRGB leds[NUM_LEDS];//создаем массив цветов
uint8_t  b_r;//значение красного цвета
uint8_t  b_g;//значение зеленого цвета
uint8_t  b_b;//значение синего цвета
void setup()  
{
  mySerial.begin(9600);//открываем программный сериал
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);//инициализируем управление светодиодной лентой
}
void loop() 
{
  if (mySerial.available()){//если получили данные по bluetooth
    
    b_r=mySerial.read();//читаем первый байт данных
    while  (!mySerial.available());//ожидаем следующий байт
    b_g=mySerial.read();//читаем второй байт данных
    while  (!mySerial.available());//ожидаем следующий байт
    b_b=mySerial.read();//читаем третий байт данных
    mySerial.flush();//очищаем буфер, т.к. больше ничего мы не передаем
    for (int i=0; i<NUM_LEDS; i++){//устанавливаем полученный цвет для всех светодиодов
    leds[i] = CRGB(b_r,b_g,b_b);}
    FastLED.show(); //обновляем состояние ленты
  }
}

Вот и все. Осталось написать программу для Андроид.

Программа на Андроид управления светодиодной лентой через bluetooth

Программу будем писать в Андроид Студио.
AndroidStudio
Загружаем и устанавливаем последнюю версию Studio(на момент написания статьи это 1.5.1) http://tools.android.com/download/studio/stable

1.Установка и настройка Android Studio

Перед написанием программы необходимо загрузить дополнительные пакеты для вашей версии Андроид. Делается это в настройках SDK.

Описание установки(жми, чтобы открыть)

2. Делаем программу для отправки данных по блютус.

— Настройка разрешений
— Написание метода всплывающих сообщений
— Написание метода обработки состояния блютус при запуске или восстановления приложения
— Написание метода обработки состояния блютус при сворачивании приложения
— Написание метода для отправки по блютус строки
— Написание метода для отправки по блютус массива байт
— Создание интерфейса для выбора цвета для нашей ленты
— Написание метода для выбора цвета и отправки его по блютус

Настройка разрешений

Для начала необходимо указать разрешения нашему приложению использовать bloetooth. Для этого добавляем в файл «AndroidManifest.xml» следующие строки.

Далее все новые методы, а также переменные будем создавать в файле «MainActivity» внутри

1
public class MainActivity extends AppCompatActivity
public class MainActivity extends AppCompatActivity

Метод всплывающих сообщений

Данный метод необходим как для отладки приложения, так и для взаимодействия приложения с пользователем

1
2
3
4
5
 private void showMessage(Boolean err, String msg) {//Метод всплывающих сообщений и логирования
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();//всплывающее сообщение
Log.d("Мое приложение", msg);//сообщение в Android Monitor
if (err) finish();//если ошибка то закрываем приложение
}
 private void showMessage(Boolean err, String msg) {//Метод всплывающих сообщений и логирования
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();//всплывающее сообщение
Log.d("Мое приложение", msg);//сообщение в Android Monitor
if (err) finish();//если ошибка то закрываем приложение
}

Метод обработки состояния блютус при запуске или восстановления приложения

Создадим несколько переменных для работы с bluetooth смартфона

1
2
3
4
5
 BluetoothAdapter MyBluetoothAdapter = null;//блютус планшета
BluetoothDevice MyBluetoothDevice = null;//модуль нс-06
BluetoothSocket MyBluetoothSocket = null;//интерфейс для обмена данными
UUID MYUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //ID сервиса для соединения https://www.bluetooth.com/specifications/assigned-numbers/service-discovery
OutputStream MyOutputStream = null;//поток данных
 BluetoothAdapter MyBluetoothAdapter = null;//блютус планшета
BluetoothDevice MyBluetoothDevice = null;//модуль нс-06
BluetoothSocket MyBluetoothSocket = null;//интерфейс для обмена данными
UUID MYUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //ID сервиса для соединения https://www.bluetooth.com/specifications/assigned-numbers/service-discovery
OutputStream MyOutputStream = null;//поток данных

При создании будет предложено добавить необходимые классы в import. Все добавляем.

В метод public void onCreate(Bundle savedInstanceState) добавляем создание нашего блютус

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//подключаемся к блютус смартфона
if (MyBluetoothAdapter == null) {
showMessage(true,"Bluetooth не поддерживается устройством");
} else {
if (MyBluetoothAdapter.isEnabled()) {
showMessage(false,"Bluetooth активен");
} else {
MyBluetoothAdapter.enable();//включаем блютус
}
}
}
 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//подключаемся к блютус смартфона
if (MyBluetoothAdapter == null) {
showMessage(true,"Bluetooth не поддерживается устройством");
} else {
if (MyBluetoothAdapter.isEnabled()) {
showMessage(false,"Bluetooth активен");
} else {
MyBluetoothAdapter.enable();//включаем блютус
}
}
}

Жмем alt+insert выбираем Overrade Methods.. и из списка выбираем onResume()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 @Override
protected void onResume() {
super.onResume();
if (!MyBluetoothAdapter.isEnabled()) {
showMessage(true, "Bluetooth выключен, включаем");
} else {
showMessage(false, "Bluetooth включен");
}
showMessage(false, "Создание сокета подключения к HC-06");
MyBluetoothDevice = MyBluetoothAdapter.getRemoteDevice("00:14:03:18:19:10");//mac адрес модуля hc-06
try {
MyBluetoothSocket = MyBluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
showMessage(true, "Ошибка создания сокета");
}
MyBluetoothAdapter.cancelDiscovery();//отменяем поиск устройств
showMessage(false, "Установка соединения");
try {
if (!MyBluetoothSocket.isConnected())
{MyBluetoothSocket.connect();}//
 
showMessage(false, "Все готово к созданию сокета");
} catch (IOException e) {
showMessage(false, "Ошибка сокета " + e.getMessage() + ".");
try {
MyBluetoothSocket.close();//
} catch (IOException e2) {
showMessage(true, "Ошибка соединения " + e2.getMessage() + ".");
}
}
showMessage(false, "Создание сокета");
 
try {
MyOutputStream = MyBluetoothSocket.getOutputStream();
} catch (IOException e) {
showMessage(true, "Ошибка создания сокета" + e.getMessage() + ".");
}
}
 @Override
protected void onResume() {
super.onResume();
if (!MyBluetoothAdapter.isEnabled()) {
showMessage(true, "Bluetooth выключен, включаем");
} else {
showMessage(false, "Bluetooth включен");
}
showMessage(false, "Создание сокета подключения к HC-06");
MyBluetoothDevice = MyBluetoothAdapter.getRemoteDevice("00:14:03:18:19:10");//mac адрес модуля hc-06
try {
MyBluetoothSocket = MyBluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
showMessage(true, "Ошибка создания сокета");
}
MyBluetoothAdapter.cancelDiscovery();//отменяем поиск устройств
showMessage(false, "Установка соединения");
try {
if (!MyBluetoothSocket.isConnected())
{MyBluetoothSocket.connect();}//

showMessage(false, "Все готово к созданию сокета");
} catch (IOException e) {
showMessage(false, "Ошибка сокета " + e.getMessage() + ".");
try {
MyBluetoothSocket.close();//
} catch (IOException e2) {
showMessage(true, "Ошибка соединения " + e2.getMessage() + ".");
}
}
showMessage(false, "Создание сокета");

try {
MyOutputStream = MyBluetoothSocket.getOutputStream();
} catch (IOException e) {
showMessage(true, "Ошибка создания сокета" + e.getMessage() + ".");
}
}

Проверим приложение Shift+F10 и продолжим

В принципе все готово к передачи данных, но давайте напишем метод обработки перехода приложения в состояние Pause

Метода обработки состояния блютус при сворачивании приложения

Жмем alt+insert выбираем Overrade Methods.. и из списка выбираем onPause().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
protected void onPause() {
super.onPause();
 
if (MyOutputStream != null) {
try {
MyOutputStream.flush();//очищаем поток
} catch (IOException e) {
showMessage(true,"Ошибка очистки потока" + e.getMessage() + ".");
}
}
 
try {
MyBluetoothSocket.close();//закрываем сокет
} catch (IOException e2) {
showMessage(true,"Ошибка закрытия потока" + e2.getMessage() + ".");
}
 
}
@Override
protected void onPause() {
super.onPause();

if (MyOutputStream != null) {
try {
MyOutputStream.flush();//очищаем поток
} catch (IOException e) {
showMessage(true,"Ошибка очистки потока" + e.getMessage() + ".");
}
}

try {
MyBluetoothSocket.close();//закрываем сокет
} catch (IOException e2) {
showMessage(true,"Ошибка закрытия потока" + e2.getMessage() + ".");
}

}

Метод для отправки по блютус строки

1
2
3
4
5
6
7
8
9
private void sendData(String str) {//метод отправки строки
byte[] buf = str.getBytes();//преобразуем строку к байтам
 
try {
MyOutputStream.write(buf);
} catch (IOException e) {
showMessage(true, "Ошибка отправки" + e.getMessage());
}
}
private void sendData(String str) {//метод отправки строки
byte[] buf = str.getBytes();//преобразуем строку к байтам

try {
MyOutputStream.write(buf);
} catch (IOException e) {
showMessage(true, "Ошибка отправки" + e.getMessage());
}
}

Метод для отправки по блютус массива байт

1
2
3
4
5
6
7
8
private void sendData(byte[] str) {//метод отправки массива байт
 
try {
MyOutputStream.write(str);
} catch (IOException e) {
showMessage(true, "Ошибка отправки" + e.getMessage());
}
}
private void sendData(byte[] str) {//метод отправки массива байт

try {
MyOutputStream.write(str);
} catch (IOException e) {
showMessage(true, "Ошибка отправки" + e.getMessage());
}
}

Прошу заметить что имена методов одинаковые, при вызове метода Андроид сам выберет необходимый в зависимости от типа посылаемых данных.

Создание интерфейса для выбора цвета для нашей ленты

Выбор цвета будем осуществлять при помощи круговой палитры цветов, для чего воспользуемся готовым классом. Ссылка на класс https://github.com/chiralcode/Android-Color-Picker/blob/master/src/com/chiralcode/colorpicker/ColorPicker.java

Создаем новый класс

Создаем новый класс

Создаем новый класс

Копируем содержимое файла по ссылке и полностью заменяем им содержимое нашего класса, за исключением

1
package com.chiralcode.colorpicker;
package com.chiralcode.colorpicker;

Вместо нее должна остаться наша строка

1
package ...
package ...
Создание нового класса

Создание нового класса

Открываем «activity_main.xml«, удаляем с него TextView и добавляем CustomView, в всплывающем окне выбираем наш класс ColorPicker, id нового элемента ставим — «colorp»
Android_bluetooth_ws2811_hc-06_14
Android_bluetooth_ws2811_hc-06_15

С интерфейсом закончили. Можно переходить к обработке выбора цвета.

Метод для выбора цвета и отправки его по блютус

Создадим еще несколько переменных для работы с палитрой цветов.

1
2
3
 ColorPicker colorPicker;//цветовая палитра
private int color_old;//старое значение выбранного цвета
private byte[] bsd = new byte[3];//массив отправляемых цветов
 ColorPicker colorPicker;//цветовая палитра
private int color_old;//старое значение выбранного цвета
private byte[] bsd = new byte[3];//массив отправляемых цветов

Жмем alt+insert выбираем Overrade Methods.. и из списка выбираем onTouchEvent(MotionEvent event).
Этот метод возникает при событиях сенсора.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 @Override
public boolean onTouchEvent(MotionEvent event) {
 
if (event.getAction() == MotionEvent.ACTION_UP) {//если касание сенсора завершилось
colorPicker = (ColorPicker) findViewById(R.id.colorp);//наша палитра
 
int color = colorPicker.getColor();//получаем цвет выбранный на палитре
if (color != color_old) {//если цвет изменился
int c_r, c_g, c_b;//переменные для разбивки цвета на RGB
c_r = Color.red(color);//красный
c_g = Color.green(color);//зеленый
c_b = Color.blue(color);//синий
bsd[0] = (byte) c_r;//заполняем массив
bsd[1] = (byte) c_g;
bsd[2] = (byte) c_b;
color_old = color;//обновляем переменную цвета
sendData(bsd);//посылаем данные
}
}
return super.onTouchEvent(event);
}
 @Override
public boolean onTouchEvent(MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_UP) {//если касание сенсора завершилось
colorPicker = (ColorPicker) findViewById(R.id.colorp);//наша палитра

int color = colorPicker.getColor();//получаем цвет выбранный на палитре
if (color != color_old) {//если цвет изменился
int c_r, c_g, c_b;//переменные для разбивки цвета на RGB
c_r = Color.red(color);//красный
c_g = Color.green(color);//зеленый
c_b = Color.blue(color);//синий
bsd[0] = (byte) c_r;//заполняем массив
bsd[1] = (byte) c_g;
bsd[2] = (byte) c_b;
color_old = color;//обновляем переменную цвета
sendData(bsd);//посылаем данные
}
}
return super.onTouchEvent(event);
}

Ну вот и все, запускаем приложение и пробуем изменить цвет.

Все файлы проекта

PS. Проект тестировался на Андроид 4.4+

Еще раз поздравляю всех с Наступающим! Чтобы все Ваши задумки воплотились в жизнь.

Подписываемся, чтобы не пропустить интересного:

Мы в Facebook — https://www.facebook.com/bigbarrelru/
Мы в Twitter — https://twitter.com/bigbarrelru
МЫ в Instagram — http://instagram.com/bigbarrelru
Мы в Youtube — http://www.youtube.com/user/bigbarrelru
Мы в Контакте — https://vk.com/bigbarrelru

Поддержка проекта — Donate

4 комментс для “Новогодняя bluetooth НС-06 гирлянда на Ардуино. WS2811. Библиотека FastLed. Android.

  1. Ответить Евгений Фев 23, 2017 11:52

    А возможно ли сделать что бы при получении плюсового или минусового сигнала на andruino запускался один из эффектов? Например Поворотник в авто. т.е. Включение желтого цвета светодиодов.

  2. Ответить кеек Мар 31, 2017 19:32

    Лень компилить положите готовую апкашку, пожалуйста.

Добавить комментарий