Управляем освещением с 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 On\r\n");          // подготавливаем байтовый массив 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 Off\r\n");         // подготавливаем байтовый массив 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 On\r\n");          // подготавливаем байтовый массив 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 Off\r\n");         // подготавливаем байтовый массив Led Off для вывода в UART
                            UART1.Write(buffer, 0, buffer.Length);                           // записываем в UART1 байтовый массив
                            relay2.Write(false);                                             // выключаем катушку реле 2
                        }
                        else
                        {
                            byte[] buffer = Encoding.UTF8.GetBytes("Command Error!\r\n");    // формируем надпись о неправильной команде
                            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("\r\n");					// определяем конец строки
   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 устройством открывается широкое поле для творчества радиолюбителя.

На этом все, будут вопросы — задавайте!

Скачать APK файл для андроид
Скачать архив с проектом для Eclipse и для Visual C#2010 Express

3 комментария

avatar
Ну уж!!! Как все просто!!!-) и для общего развития интересно, и не более того
avatar
Хотя статья рассказывает о связи андройд по блютуз, добавлю здесь что .NET Framework для микроконтроллеров это, по правде говоря, мощный инструмент в руках разработчика. Благодаря удобному редактору и умному компилятору, которые практически полностью исключают ошибки разработчика, скорость разработки повышается, а стоимость существенно снижается. Какой бы не был крутой микропроцессор, а среда разработки все же играет даже большую роль, чем свойства процессора. Это потому что зарплата разработчика сейчас составляет основную часть стоимости продукта. Спасибо за статью!
avatar
Tadalafil Online India Pastiglie Cialis [url=http://rxbill7.com]where to buy cialis online safely[/url] Buy Vigora Online Propecia Cost Rite Aid Le Viagra En Egypte
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.