Автор Тема: Простое подключение Arduino к Android-телефону по Bluetooth  (Прочитано 8065 раз)

Оффлайн Ann

  • Глобальный модератор
  • Habanero
  • *****
  • Сообщений: 1847
  • Лайков: 10
    • Просмотр профиля
Давно меня терзали мысли перевести интерфейс (отображение информации и управление) Ардуины в Андроид-телефон, уж больно он разросся, но как подумаешь, что для этого Java штурмовать придется, желание делать это как-то сразу пропадало.
И вот на днях набрел случайно на совершенно потрясную штуку - MIT App Inventor 2.
Написание Андроид-программы для людей, совсем не знакомых с программированием. Очень похоже на хорошо мне знакомый Scratch (с дочкой занимаюсь).
Среда разработки - онлайн в браузере.
Как и во "взрослой" Android Studio, написание состоит из двух частей, в первом окне с помощью драг&дропа набрасываем компоненты, вторая - написание логики. Просто до неприличия.
В общем стряхнул я пыль с давно валявшегося HC-05 уже практически через полчаса в телефон пошла первая информация с Ардуины.
Подключается он по Serial, все стандартно, передаю данные с Ардуины в таком виде:
<24.5, 40, 200, 14:10:08, 12, 10, 1, 1>
Данные, разделенные запятыми, т.н. CSV-формат. Температура, влажность, текущее время, люксы, количество часов красных диодов, и то же для синих, включен ли красный, и синий. Ну и по краям символы начала и конца строки, чтоб можно было проверить ее целостность.
Сначала накидали компонентов:


Подключаемся, MAC-адрес сразу прописал, чтоб не заморачиваться с поиском-выбором устройств. Повесил на таймер, срабатывающий через полсекунды после старта программы.


Раз в секунду считываем все байты, стоящие в очереди и отправляем на обработку в функцию trim_start.


Поскольку полученные данные могут быть повреждены, в функции trim_start делаем простейшую проверку (проверяем наличие символов начала и конца строки, чтобы символ начала шел впереди символа конца)
Разбиваем строку на элементы и наполняем ими массив data_list.


И затем раз в секунду разносим наши данные по нужным компонентам (в температуре и влажности вычисляем угол поворота стрелки)


Ну и параллельно проверяем и меняем состояние кнопок (включено/выключено, ставит соотв. картинку).


Отправлять данные в Ардуину будем в следующем формате:
R_12>
Первый символ, что именно меняем (R-для красных диодов, B-для синих, T-для времени).
Вот к примеру для красных (формируем строку для отправки и выставляем флаг transmit, показыающий, что есть что оправить):


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


Теперь принимаем их в Ардуине:
    char reb_array[20] ;
    int lll=0;
    while (Serial1.available() > 0) {  //если пришли данные
      reb_array[lll]=Serial1.read(); // считываем байты и заполняем ими массив reb_array
      lll++;
    }

Далее парсим строку и в зависимости от первой буквы меняем нужные переменные:
    char * pch;
    pch = strtok (reb_array,"_");
    String pp = (String)pch;
    if(pp == "R"){ pch = strtok (NULL, ">");
                  String r1=(String)pch;
                  time_red_duration = r1.toInt();}
    if(pp == "B"){pch = strtok (NULL, ">");
                  String r1=(String)pch;
                  time_blue_duration=r1.toInt();}

Вот итоговый вид программы (пока сделал только основное, мелоча потом добавлю):

Сверху два "спидометра" температуры и влажности, ниже люксометр, далее кнопки красных и синих диодов (выполняют три функции: 1 - показывают включены или нет, 2-текущий режим, 3-при нажатии принудительно включают/выключают их). Ниже время, далее слайдеры установки режима работы диодов. И в самом низу кнопка установки времени на Ардуине, т.е. его синхронизации со временем телефона (у меня сгорел модуль часов, поэтому после каждого включения приходилось вручную его устанавливать, теперь я лишен этой "радости").

В общем архиудобная штука, теперь нет необходимости тулить громоздкое каскадное меню для отображения и управление (они уже сейчас занимают около 60% кода в Ардуине), намного удобнее, можно проверять, управлять дистанционно, значительно красивше, здорово экономит время при написании кода, возможно деньги (управляющие элементы и дисплей теперь не обязательно покупать и тулить к устройству), громадный простор для фантазии (построение графиков, передача в интернет, сложная логика на стороне телефона и т.д. и т.п.). И на удивление о такой интересной штуке довольно мало информации в интернете. Надеюсь кому пригодится, здесь уже не только я Ардуиной страдаю :)
« Последнее редактирование: 09 Сентябрь 2016, 23:32:49 от Ann »

Оффлайн Ann

  • Глобальный модератор
  • Habanero
  • *****
  • Сообщений: 1847
  • Лайков: 10
    • Просмотр профиля
Немного разовью тему.
Теперь программа выглядит вот так:

Что изменилось:
Убрал слайдеры управления режимами ламп и повесил их на стрелки по бокам.
Немного изменил протокол общения по Bluetooth. Раньше просто раз в секунду считывал буфер входящих данных, но часто получались разорванные строки (около 20%), фильтр их отсеивал безупречно и никаких глюков не было, но хотелось чуть большей стабильности. Сделал по принципу master-slave: раз в секунду отсылаю запросную команду в Ардуину, при ее получении Ардуина сразу же отсылает пакет, в телефоне жду 400мс его получения и затем уже принимаю. На порядок стабильнее получилось, хотя все равно случаются порванные строки (1-2%), пока не могу объяснить их причину.
Добавил значок установки связи (рядом с люксами)
Добавил кнопку начала и остановки записи на SD-карту.
Добавил кнопку выключения-включения экрана Ардуины (чтобы в темноте не отсвечивал).

Добавил передачу в интернет.
Сначала попробовал сервис ThingSpeak. Он может многое (отображение графиков, управление через сайт), но все-равно ограничен да и не легко с ним разобраться, что к чему, легче уже на своем сервере написать.
Поэтому сделал отправку на свой сервер данных с помощью GET-запроса.
Очень просто, выглядит так:

Первая строка там - отправка POST-запроса на ThingSpeak, вторая - GET-запрос на мой. Желательно еще пароль туда добавить, чтоб не DDosили.
На сервере заношу данные в базу MySQL.
Сделал еще динамическое создание изображения с градусником и влагометром (отображаются на моем аватаре в случайном порядке, если пообновлять страницу, можно видеть, как меняются).
До этого еще делал такое только в цифровом формате (стояло в подписи):

Не буду приводить PHP-код, кому нужно, спросят, но все довольно просто (обработка запроса - 12 строк кода, создание изображения - около 25, с наложением стрелки и её поворотом немного правда повозиться пришлось).
Нужно будет как-нибудь туда графики прилепить.
Данные сервере обновляются только тогда, когда на телефоне запущена программа, поэтому нужно взять WiFi-модуль, чтоб было в постоянном режиме.
« Последнее редактирование: 19 Сентябрь 2016, 00:13:12 от Ann »

Оффлайн diman0407

Ann, подскажите пожалуйста, как реализована синхронизация времени с телефоном? Arduino через bluetooth подключил к android, а вот с синхронизацией беда, даже не знаю в какую сторону копать(

Оффлайн Ann

  • Глобальный модератор
  • Habanero
  • *****
  • Сообщений: 1847
  • Лайков: 10
    • Просмотр профиля
Ann, подскажите пожалуйста, как реализована синхронизация времени с телефоном? Arduino через bluetooth подключил к android, а вот с синхронизацией беда, даже не знаю в какую сторону копать(
Да ничего там сложного.
В телефоне у меня каждый полсекунды тикает таймер

Если выставлен флаг, обозначающий, что есть что отправить, то отправляется по БТ содержимое переменной transmit_data.

А вот при нажатии на кнопку я выставляю флаг, что есть что отправить, и заножу в transmit_data текущее время, с префиксом "Т_", чтоб в Ардуине потом понять, что это время.


А в Ардуине принимаю следующим образом:

void  Receive_bluetooth(){
if (Serial1.available() > 0) {
    reb_array[lll]=Serial1.read(); // считываем байт
    String ll = (String)reb_array[lll];
    lll++;
    if (ll == ">") {
              char * pch;
              pch = strtok (reb_array,"_");
              String pp = (String)pch;
               
           
              if(pp == "T"){pch = strtok (NULL, "_");                                   //Время
                            String r1=(String)pch;
                            time.settime(-1,-1,r1.toInt());
                            pch = strtok (NULL, "_");
                            r1=(String)pch;
                            time.settime(-1,r1.toInt(),-1);
                            pch = strtok (NULL, ">");
                            r1=(String)pch;
                            time.settime(r1.toInt(),-1,-1);
                            Transmit(); 
                            tone (10, 4000, 50);}
             
     
            lll=0;}
}



Не стесняйтесь, спрашивайте, всегда рад помочь :)

Оффлайн sFiret

Тема получила свое развитие?

Большое спасибо Chi-chi, КВН и Mr. Smet за семена.

Оффлайн Ann

  • Глобальный модератор
  • Habanero
  • *****
  • Сообщений: 1847
  • Лайков: 10
    • Просмотр профиля
Тема получила свое развитие?
Тема умерла.
Ввиду того, что связка Ардуина+Блютуз была заменена на Wemos c Wi-Fi. Получилось вдвое дешевле и с куда бОльшими возможностями.
Но если есть какие вопросы - не стесняйтесь.

Оффлайн sFiret

Тема получила свое развитие?
Тема умерла.
Ввиду того, что связка Ардуина+Блютуз была заменена на Wemos c Wi-Fi. Получилось вдвое дешевле и с куда бОльшими возможностями.
Но если есть какие вопросы - не стесняйтесь.
Вопросы буду как я дорасту до этого морально и материально. А пока что читаем ваши темы

Большое спасибо Chi-chi, КВН и Mr. Smet за семена.