управление ip камерой с телефона через BT и ардуино нано

odemma
Offline
Зарегистрирован: 21.11.2015

Всем привет!

Для меня этот проект был настоящий челендж в электротехнике и программировании и на этом форуме мне очень помогли с некоторыми вопросами. Решил поделиться наработками может тоже кому пригодится. Началось с покупки IP камеры с целью поиграться/разобраться. Решил повесить ее для наблюдения за машиной во дворе. Придумал крепление в возможностью регулировки по углу влево/вправо и вниз/вверх. т.к. машина стоит там где нашлось место. Поставил подключил и быстро понял что каждый раз открывать окно, снимать москитную сетку и поворачивать камеру руками не вариант. К креплению навесил сервопривод MG-90 для поворота влево/вправо (мне этого достаточно) управляется ардуино нано через блютуз HC-06 с любого андроида.

Под андроид программа в Аппинвенторе.

в верхней части выбор угла влево/вправо

кнопка выбора устройства блютуз  /  кнопка управления в ручном режиме

в автоматическом режиме камера направлена на точку А

точки В,С,D дополнительные на эти точки камера ходит с интевалом N минут указанных во втором столбце на N секунд указанных в 3 столбце.

углы и время задаются удерживанием кнопок ABCD более 3х секунд.

если интервал 0 то на эту точку камера не поворачивается.

odemma
Offline
Зарегистрирован: 21.11.2015

Так выглядят потроха

электрика крупнее

Питается стандартным блоком питания для видеокамер 12в/2А. Для сервопривода отдельный регулятор напряжения на 5в+2 кондера и маленький радиатор из фольги. на нано и BT заклеены светодиоды черной изолентой иначе ночью кронштейн весело светится и мигает. 

Для крепления сервопривода пришлось поковырять уголок нагретым ножом и паяльником.  главное чтобы ось вращения кронштейна совпала с осью вращения сервы. серва заходит плотно, крепится на 2 шурупа, затем щели залил термоклеем.

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

перечислю детали сверху вниз : заглушка, труба, 3 крепления к стене, 2 уголка 90гр., переход 25/20.

дальше черная деталь от регулируемой мебельной ноги идеально сопрягается с фланцем камеры по диаметру и отверстиям.

к качалке сервопривода закрепил сантехнический бурт для 25 трубы который вставлен в третий кронштейн и зафиксирован с боку шуропом от поворота. 

Valerii_K
Valerii_K аватар
Offline
Зарегистрирован: 15.08.2016

Хороший проект! Скетчем не поделитесь?

odemma
Offline
Зарегистрирован: 21.11.2015
#include <Wire.h>
#include <SoftwareSerial.h> // Подключаем библиотеку для работы с Serial через дискретные порты
#include <Servo.h> //Подключаем библиотеку Servo

unsigned long timeX=777777 ; 
byte point[4]={ 150, 60, 90, 0}; //точки 
byte interval[4]={ 0, 30, 0, 0}; //интервал между просмотрами точки мин
byte expo[4]={ 0, 30, 0, 0}; //время экспозиции в точке сек
unsigned long old_time_int[4]={ 0, 0, 0, 0}; //время от начала интервала
unsigned long old_time_exp[4]={ 0, 0, 0, 0}; //время от начала экспозиции
boolean exp_status[4] = {false, false, false, false};
boolean rt = false;

 byte degmin=0;
 byte degmax=180;
 byte degstep=1;
 byte current_angle=90;  //текущий угол
 byte old_angle=90;  //старый угол
 byte speed2go=100;  //скорость перемещения
char ncmd;  // Создаем переменную для команд Bluetooth имя

Servo motor;
SoftwareSerial BTSerial(2, 4); // RX, TX

void setup() {

    // Устанавливаем скорость передачи данных по Bluetooth 
  BTSerial.begin(9600); 
  Serial.begin(9600);
  while (!Serial) ; // wait for serial
  delay(200);
  Serial.println("-------------------");
  
  motor.attach(10); // Подключаем серву на 10 пин
  motor.write(current_angle);
  motor.detach();
}

void loop() {
  
if (BTSerial.available()){   // Если есть данные BT
       
        ncmd = (char)BTSerial.read(); // Читаем команды и заносим их в переменную. char преобразует код символа команды в символ 
    Serial.println(ncmd);

    if (ncmd == 'r'){   // едем влево или вправо
      ncmd = ' ';
       old_angle=current_angle;
      while (!BTSerial.available());  // ждем данные
      current_angle= BTSerial.read(); // 
       //Serial.print("r");
       //Serial.println(current_angle);
}                            // едем влево или вправо

    if (ncmd == 'i'){   // инициализация экрана
      ncmd = ' ';
       BTSerial.write((byte)current_angle);  // предаем  по ВТ текущий угол
       BTSerial.write((byte)point[0]);     //угол 1
       BTSerial.write((byte)point[1]);     //угол 2
       BTSerial.write((byte)point[2]);     //угол 3
       BTSerial.write((byte)point[3]);     //угол 4
       BTSerial.write((byte)interval[1]);     //интервал 2
       BTSerial.write((byte)interval[2]);     //интервал 3
        BTSerial.write((byte)interval[3]);     //интервал 4
       BTSerial.write((byte)expo[1]);     // экспозиция 2
       BTSerial.write((byte)expo[2]);     // экспозиция 3
       BTSerial.write((byte)expo[3]);     // экспозиция 4
       // Serial.print("i");
      // Serial.println(current_angle);
       
}                            // инициализация экрана


       if (ncmd == 't') { // режим реального времени вкл
       rt= true;   // 
        ncmd = ' ';
        BTSerial.write(byte(current_angle));  // предаем по ВТ текущий угол
         //Serial.print("t");
         //Serial.println(current_angle);
       }              // режим реального времени вкл

   if (ncmd == 'x'){  //  выход из RT  
       ncmd = ' ';
       rt= false;   // режим реального времени  выкл
        BTSerial.write(byte(current_angle));  // предаем по ВТ текущий угол
for (int i=1; i < 4; i = i + 1){ //обнуляем счетчики и флаги
  old_time_int[i]=millis();
 old_time_exp[i]=millis();
 exp_status[i]=false;
  } //обнуляем счетчики и флаги
        //Serial.println("x");
       }            //  выход из RT
  
   if (ncmd == 'a'){  // едем на точку А
    ncmd = ' ';
 old_angle=current_angle;
 current_angle=point[0];
   //Serial.print("a");
   //Serial.println(current_angle);
   }                 // едем на точку А

      if (ncmd == 'b'){  // едем на точку B
    ncmd = ' ';
 old_angle=current_angle;
 current_angle=point[1];
   //Serial.print("b");
   //Serial.println(current_angle);
   }                 // едем на точку B

      if (ncmd == 'c'){  // едем на точку C
    ncmd = ' ';
 old_angle=current_angle;
 current_angle=point[2];
   //Serial.print("c");
   //Serial.println(current_angle);
   }                 // едем на точку C

         if (ncmd == 'd'){  // едем на точку D
    ncmd = ' ';
 old_angle=current_angle;
 current_angle=point[3];
   //Serial.print("d");
   //Serial.println(current_angle);
   }                 // едем на точку D

       if (ncmd == 'A'){   // сохранить точку A
      ncmd = ' ';
while (!BTSerial.available());  // ждем данные
point[0] = BTSerial.read(); // Читаем новый угол
//Serial.println("A");
} // сохранить точку A

       if (ncmd == 'B'){   // сохранить точку B
      ncmd = ' ';
while (!BTSerial.available());  // ждем данные
point[1] = BTSerial.read(); // Читаем новый угол
while (!BTSerial.available());  // ждем данные
interval[1] = byte(BTSerial.read()); // Читаем новый интервал 2
while (!BTSerial.available());  // ждем данные
expo[1] =  byte(BTSerial.read()); // Читаем новый экспозиция 2
   //Serial.println("B");
} // сохранить точку B

       if (ncmd == 'C'){   // сохранить точку C
      ncmd = ' ';
while (!BTSerial.available());  // ждем данные
point[2] = BTSerial.read(); // Читаем новый угол
while (!BTSerial.available());  // ждем данные
interval[2] =  byte(BTSerial.read()); // Читаем новый интервал 
while (!BTSerial.available());  // ждем данные
expo[2] =  byte(BTSerial.read()); // Читаем новый экспозиция 
   //Serial.println("C");
} // сохранить точку C

       if (ncmd == 'D'){   // сохранить точку D
      ncmd = ' ';
while (!BTSerial.available());  // ждем данные
point[3] = BTSerial.read(); // Читаем новый угол
while (!BTSerial.available());  // ждем данные
interval[3] =  byte(BTSerial.read()); // Читаем новый интервал 
while (!BTSerial.available());  // ждем данные
expo[3] =  byte(BTSerial.read()); // Читаем новый экспозиция 
    //Serial.println("D");
} // сохранить точку D

}   // Если есть данные BT

if (old_angle>current_angle){  // если новый угол меньше старого
  motor.attach(10); // Подключаем серву на 10 пин 
 for (int i=old_angle-1; i >= current_angle; i = i - degstep){
      motor.write(i);
      Serial.println(i);
     delay(speed2go);
   }
   motor.detach();
   old_angle=current_angle;
} // если новый угол меньше старого

if (old_angle<current_angle){  // если новый угол больше старого
  
  motor.attach(10); // Подключаем серву на 10 пин 
  for (int i=old_angle+1; i <= current_angle; i = i + degstep){
      motor.write(i);
     Serial.println(i);
      delay(speed2go);
   }
  motor.detach();
   old_angle=current_angle;
 } // если новый угол больше старого


if (!(rt)){ // если режим реального времени выключен крутим камеру по точкам
  
  for (int i=1; i < 4; i = i + 1){ //цикл по точкам
  if ( interval[i]>0){  // если точка задана
    timeX = (unsigned long)(old_time_int[i]+interval[i]*60000);
       if ( !(exp_status[i]) && millis()>timeX){ // если пора ехать на точку
  Serial.println(timeX);
  delay(100);
 old_angle=current_angle;
 current_angle=point[i];
 old_time_exp[i]=(unsigned long)millis();
 exp_status[i]=true;
 break;
  } // если пора ехать на точку
  timeX = (unsigned long)expo[i]*1000;
   timeX = (unsigned long)(old_time_exp[i] + timeX);
 if (exp_status[i] && millis()>timeX){ // если пора ехать на базу
  Serial.println(timeX);
  Serial.println(millis());
 old_angle=current_angle;
 current_angle=point[0];
 old_time_int[i]=millis();
 exp_status[i]=false;
     } // если пора ехать на базу
  } // если точка задана
 } //цикл по точкам
} // если режим реального времени выключен крутим камеру по точкам

 } ///-------------end---------------


 

odemma
Offline
Зарегистрирован: 21.11.2015

Пожалуйста!

Вот прога на андроид

https://yadi.sk/d/nYH67jxUyZoZz

исходник в аппинвенторе

 https://yadi.sk/d/XUtpJltiyZoYZ

Xumuk
Xumuk аватар
Offline
Зарегистрирован: 03.03.2016

хороший проектик, спасибо за исходники

DarkDaemon
Offline
Зарегистрирован: 31.10.2015

Не думали, как сделать автоматическое наведение на авто? :)

odemma
Offline
Зарегистрирован: 21.11.2015

Об этом тоже думал ;)  но пока не моего ума дело. очень уж сложно даже просто поток с камеры получить.

DarkDaemon
Offline
Зарегистрирован: 31.10.2015

А если рассмотреть другие варианты?

1. В машине установить всенаправленный радиоизлучатель (например, на 433МГц), а на камере направленнный приемник, чтобы он подстраивал камеру под максимальный уровень сигнала.

2. В машине установить Arduino + GSM + GPS модули, они будут посылать координаты на сервер. А ардуинка с камеры (c Wi-Fi или Ethernet модулем) будет мониторить сервер и поворачивать камеру исходя из полученных координат.

odemma
Offline
Зарегистрирован: 21.11.2015

Когда надоест и кнопки нажимать каждый раз, буду эти варианты пробовать.