Управляем освещением с Android устройства через Bluetooth

В статье представлен прототип устройства управления освещением или любой другой нагрузкой при помощи Android устройства: будь то планшет, смартфон, часы и т.п. Связь осуществляется по Bluetooth каналу.
В качестве модуля Bluetooth используется дешевый китайский модуль HC-06.
Целью данной статьи является:
1. Осветить работу связи Bluetooth/Android на контроллерах с .NET Micro Framework. Для этой цели я использовал FEZ Panda II (другого .NET у меня нет 🙂 ), но подойдет естественно любой контроллер с фрэймворком .NET Micro Framework. В коде нужно лишь будет подправить подключаемые библиотеки и проверить правильность указания I/O.
2. В предыдущих статьях по связи с Android STM32 и Arduino многие интересовались как передавать не по одному символу, а целую строку. Здесь я хотел бы привести пример передачи целых строк в обеих направлениях.
Для этого, мы возьмем реальную задачу — управление двумя лампочками в квартире. В качестве лампочек я буду использовать галогенные светодиодные лампочки с цоколем G4. Как известно, питание таких лампочек составляет 12 Вольт и запитываться они будут от отдельного источника питания.
Список элементов:
Android планшет или телефон
Плата FEZ Panda II (или любой другой контроллер с .NET Micro Framework)
Bluetooth модуль (HC-05, HC-06 и т.п.)
Модуль реле (или любое реле на 5В)
Схема подключения:Схема подключения
Исходный код программы для .NET Micro Framework в среде разработке Visual C# Express:

using System;
using System.Threading;
using System.IO.Ports;
using System.Text;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;                                     // библиотека для FEZ-контроллеров

namespace CxemCAR
{
    public class Program
    {
        public static void Main()
        {
            byte[] My_Data = new byte[20];                          // массив для хранения строки
            int My_index = 0;                                       // индекс массива
            byte[] rx_data = new byte[1];                           // массив UART данных

            OutputPort relay1 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di8, false);
            OutputPort relay2 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di9, false);

            SerialPort UART1 = new SerialPort("COM1", 9600);        // новый объект UART1 (порт COM1)
            UART1.Open();
            UART1.Flush();

            while (true)
            {
                int read_count = UART1.Read(rx_data, 0, 1);         // считываем данные
                if (read_count > 0)                                 // пришли данные?
                {
                    My_Data[My_index] = rx_data[0];                 // записываем принятый байт в наш массив

                    if (rx_data[0] == 'r')                         // если пришел конец строки
                    {
                        My_Data[My_index] = 0;                                               // удаляем последний элемент, т.е. внашем случае это r

                        string strMy_Data = new string(Encoding.UTF8.GetChars(My_Data));     // формируем строку из байтового массива

                        if (strMy_Data != null && strMy_Data.Equals("Start1"))               // сравниваем сформированную строку с нашей
                        {
                            byte[] buffer = Encoding.UTF8.GetBytes("LED 1 Onrn");          // подготавливаем байтовый массив Led On для вывода в UART
                            UART1.Write(buffer, 0, buffer.Length);                           // записываем в UART1 байтовый массив
                            relay1.Write(true);                                              // включаем катушку реле 1
                        }
                        else if (strMy_Data != null && strMy_Data.Equals("Stop1"))           // сравниваем сформированную строку с нашей
                        {
                            byte[] buffer = Encoding.UTF8.GetBytes("LED 1 Offrn");         // подготавливаем байтовый массив Led Off для вывода в UART
                            UART1.Write(buffer, 0, buffer.Length);                           // записываем в UART1 байтовый массив
                            relay1.Write(false);                                             // выключаем катушку реле 1
                        }
                        else if (strMy_Data != null && strMy_Data.Equals("Start2"))          // сравниваем сформированную строку с нашей
                        {
                            byte[] buffer = Encoding.UTF8.GetBytes("LED 2 Onrn");          // подготавливаем байтовый массив Led On для вывода в UART
                            UART1.Write(buffer, 0, buffer.Length);                           // записываем в UART1 байтовый массив
                            relay2.Write(true);                                              // включаем катушку реле 2
                        }
                        else if (strMy_Data != null && strMy_Data.Equals("Stop2"))           // сравниваем сформированную строку с нашей
                        {
                            byte[] buffer = Encoding.UTF8.GetBytes("LED 2 Offrn");         // подготавливаем байтовый массив Led Off для вывода в UART
                            UART1.Write(buffer, 0, buffer.Length);                           // записываем в UART1 байтовый массив
                            relay2.Write(false);                                             // выключаем катушку реле 2
                        }
                        else
                        {
                            byte[] buffer = Encoding.UTF8.GetBytes("Command Error!rn");    // формируем надпись о неправильной команде
                            UART1.Write(buffer, 0, buffer.Length);                           // выводим надпись в UART
                        }

                        Array.Clear(My_Data, 0, My_Data.Length - 1);                         // очищаем наш массив
                        My_index = -1;                                                       // сброс индекса нашего массива
                        Thread.Sleep(100);
                    }
                    if (My_index < 19) My_index++;                                           // увеличиваем индекс нашего массива
                }
            }
        }
    }
}

Алгоритм программы очень простой. Все команды мы будем отделять при помощи символа перевода строки ‘r’. Весь буфер UART мы по приходу каждого байта скидываем в массив My_Data[]. Как только пришел символ ‘r’, который означает конец команды, мы формируем строку strMy_Data и сравниваем её с заранее внесенными командами для управления реле. Всего, я определил 4 команды:
Start1 — включает реле 1
Stop1 — выключает реле 1
Start2 — включает реле 2
Stop2 — выключает реле 2
После успешного принятия команды, в Android устройство отсылаются соответствующие статусные сообщения: LED 1 On, LED 1 Off и т.д. Если команда не распознана, то передается сообщение об ошибке Command Error!
Программа для Android писалась на Java в среде Eclipse. Весь код программы я приводить не буду, т.к. он достаточно велик, но разберу ключевые моменты.
Для работы с Bluetooth сделан отдельный класс: cBluetooth.java. Прием данных от Bluetooth ведется в отдельном асинхронном потоке. В основное активити принятые данные и системные сообщения передаются при помощи класса Handler. Для формирования принятой строки от контроллера используется класс StringBuilder.
Вот кусок кода, отвечающий за формирование строки:

case cBluetooth.RECIEVE_MESSAGE:
   byte[] readBuf = (byte[]) msg.obj;
   String strIncom = new String(readBuf, 0, msg.arg1);
   sb.append(strIncom);                                                         // добавляем новые данные в sb
   int endOfLineIndex = sb.indexOf("rn");                                     // определяем конец строки
   if (endOfLineIndex > 0) {                                                    // если конец строки
      String sbprint = sb.substring(0, endOfLineIndex);
      sb.delete(0, sb.length());                                                // очищаем sb
      text_answer_txt.setText("Answer: " + sbprint);                            // обновляем TextView
   }
   break;    

В Android-приложении можно писать команду с клавиатуры (для этого предусмотрено поле ввода и кнопка отправки), а можно управлять реле при помощи двух ToggleButton. Ниже, предусмотрено текстовое поле, где отображается текст принятый с FEZ Panda II.
Выше был приведен лишь рабочий прототип устройства для показа возможностей насколько все это просто. На основе этого проекта можно построить систему умного дома, мониторинга, контроля какого-либо устройства и т.п. При использовании мощных MOSFET транзисторов можно расширить функции устройства и сделать диммирование (плавное регулирование яркости) источников света. Резюмирую можно сказать, что с Android устройством открывается широкое поле для творчества радиолюбителя.

4.5 9 голоса

Оцените статью!

guest
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии