(управляет Arduino и передает данные на сервер умного дома).
Отступление
Все началось 2 года, когда я подумывал сделать умный пылесос, долго проектировал, написал пару алгоритмов, чтобы
избежать столкновений, но все это мне показалось наивным, (ведь это уже кто-то сделал), чтобы, действительно, правильно убирать, он должен думать хотя бы немного как человек(он должен знать, что пол - это пол и т.д.). Работа продвигалась и я начал понимать, что робота этого можно использовать не только как "уборщика", но и создать нечто вроде "умного" дома.
Как это все работает
Чтобы робот знал, что пол - это пол, а так же мог определять некоторые вещи, я купил Kinect. Начал писать WPF приложение (так как под WPF куча примеров и информации про Kinect). Недолго думая я наладил общение Arduino и своего WPF приложения:
Так как Arduino будет постоянно находиться в роботе, разумно подключить его через USB и общаться с ним через COM-порт.
Логика общения довольна проста: из программы будем писать "фразы" в сериал монитор, а в ардуино на определенную "фразу" действие.
Сразу покажу код, чтобы не томить:
Код: Выделить всё
char inData[20]; // кол-во считываемых символов c Serial Monitorа
char inChar=-1; // записываем прочтенный символ
byte index = 0; // куда пишем
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600);
}
char key(char* This) {
while (Serial.available() > 0) // не считывать до тех пор, пока данные не придут
{
if(index < 19)
{
inChar = Serial.read(); // чтение символа
inData[index] = inChar; // запись символа
index++; // место для следующего символа
inData[index] = '\0';
}
}
if (strcmp(inData,This) == 0) {
for (int i=0;i<19;i++) {
inData[i]=0;
}
index=0;
return(0);
}
else {
return(1);
}
}
void loop()
{
if (key("led on")==0) {
digitalWrite(13,HIGH);
}
if (key("led off")==0) {
digitalWrite(13,LOW);
}
}
Ниже немного кода приложения для понимания:
Код: Выделить всё
using System.IO; // подключаем библиотеку для работы c COM портом
private static readonly SerialPort SerialPort1 = new SerialPort();
SerialPort1.BaudRate = 9600;
SerialPort1.Open();
public static void LEDoN()
{
SerialPort1.Write("led on"); //пишем в сериал монитор
}
Итак, с первой проблемой общения мы разобрались. Разберемся с сервером:
Покажу на примере "выключателя" MajorDoMo. Допустим, нам нужно выключателем переключать чекбокс в WPF, и обратно (чекбоксом выключатель).
Логика общения заключается в следующем: WPF приложение посылает get/post запросы на сервер, один из запросов показывает текущее состояние выключателя, другой переключает выключатель, если значение изменилось, т.е. мы одним действием убиваем двух зайцев (не нужно посылать запросы с сервера).
Прежде чем переходить к WPF, сначала подготовим сервер.
Создаем выключатель и подключаем к нему объект.свойство (при изменении значения выключателя его значение будет записываться в свойство данного объекта, которое уже легко можно мониторить запросом). Все, сервер готов, переходим к WPF:
Создадим форму, на нее бросим 2 кнопки и 2 текстбокса, а также чекбокс.
Так же объявим глобальную переменную int status (можно сделать без глобальной переменной, я пишу лишь для примера)
POST запрос: POST("http://адрес/" , "данные");
Код: Выделить всё
public static string POST(string Url, string Data)
{
System.Net.WebRequest req = System.Net.WebRequest.Create(Url);
req.Method = "POST";
req.Timeout = 100000;
req.ContentType = "application/x-www-form-urlencoded";
byte[] sentData = Encoding.GetEncoding(1251).GetBytes(Data);
req.ContentLength = sentData.Length;
System.IO.Stream sendStream = req.GetRequestStream();
sendStream.Write(sentData, 0, sentData.Length);
sendStream.Close();
System.Net.WebResponse res = req.GetResponse();
System.IO.Stream ReceiveStream = res.GetResponseStream();
System.IO.StreamReader sr = new System.IO.StreamReader(ReceiveStream, Encoding.UTF8);
//Кодировка указывается в зависимости от кодировки ответа сервера
Char[] read = new Char[256];
int count = sr.Read(read, 0, 256);
string Out = String.Empty;
while (count > 0)
{
String str = new String(read, 0, count);
Out += str;
count = sr.Read(read, 0, 256);
}
return Out;
}
Код: Выделить всё
public static string GET(string Url, string Data)
{
System.Net.WebRequest req = System.Net.WebRequest.Create(Url + "?" + Data);
System.Net.WebResponse resp = req.GetResponse();
System.IO.Stream stream = resp.GetResponseStream();
System.IO.StreamReader sr = new System.IO.StreamReader(stream);
string Out = sr.ReadToEnd();
sr.Close();
return Out;
}
1) кнопка включить:
Код: Выделить всё
string Request = POST("http://192.168.0.106/index.php", "pd=Y29tbWFuZHM6e3BhcmVudF9pdGVtPTk3fQ%3D%3Dpz_YXBwbGljYXRpb246e2FjdGlvbj1tZW51fQ%3D%3Dpz_&md=commands&inst=&ajax=1&op=value_changed&item_id=103&new_value=1"); // value 1 - включаем выключатель =)
xcoord_Copy.Text = Request;
Код: Выделить всё
string Request = POST("http://192.168.0.106/index.php", "pd=Y29tbWFuZHM6e3BhcmVudF9pdGVtPTk3fQ%3D%3Dpz_YXBwbGljYXRpb246e2FjdGlvbj1tZW51fQ%3D%3Dpz_&md=commands&inst=&ajax=1&op=value_changed&item_id=103&new_value=0"); // value 0 - выключаем выключатель =)
xcoord_Copy.Text = Request;
Код: Выделить всё
private void FollowStatus()
{
string Answer = GET("http://192.168.0.106/pChart/", "op=value&p=ThisComputer.FollowMode");
xcoord_Copy1.Text = Answer;
status = Convert.ToInt32(Answer);
if (status == 1)
{
folowmod.IsChecked = true; // если галочка стоит на чекбоксе
}
if (status == 0)
{
folowmod.IsChecked = false; // если галочку сняли
}
}
Код: Выделить всё
private void folowmod_Checked(object sender, RoutedEventArgs e)
{
if (folowmod.IsChecked == true)
{
string Request = POST("http://192.168.0.106/index.php", "pd=Y29tbWFuZHM6e3BhcmVudF9pdGVtPTk3fQ%3D%3Dpz_YXBwbGljYXRpb246e2FjdGlvbj1tZW51fQ%3D%3Dpz_&md=commands&inst=&ajax=1&op=value_changed&item_id=103&new_value=1");
status = 1;
xcoord_Copy.Text = Request;
}
if (folowmod.IsChecked == false)
{
string Request = POST("http://192.168.0.106/index.php", "pd=Y29tbWFuZHM6e3BhcmVudF9pdGVtPTk3fQ%3D%3Dpz_YXBwbGljYXRpb246e2FjdGlvbj1tZW51fQ%3D%3Dpz_&md=commands&inst=&ajax=1&op=value_changed&item_id=103&new_value=0");
status = 0;
xcoord_Copy.Text = Request;
}
}
Питание
Arduino питается от двух 2400mAh аккумуляторов, Kinect = аккумулятор + стабилизатор, а для MicroITX (для моих требований) подойдет это
Сейчас
Мой робот способен распознавать голос, отвечать (независимо от сервера), распознавать людей и рисовать их "скелет", есть функция следования за человеком (ее можно активировать через MajorDoMo, т.е. с любого устройства), снимать видео, видеть в абсолютной темноте (можно использовать как прибор ночного виденья), делать фото, его легко подключить к любому телевизору (hdmi) и посмотреть любимый фильм, или послушать музыку. В дальнейшем я планирую докупить датчиков (газа, температуры и подобные) и наконец встроить в него пылесос)).
Так же можно настроить инфракрасные передатчики и управлять телевизором и кондиционером, но для каждого устройства придется предварительно посканировать коды(отследить сигнал определенной кнопки пульта управления, например, телевизором), пусть это займет много времени, но зато 1 раз посканировать и без проводов =)
Скрины
![Изображение](http://clip2net.com/clip/m232938/1373552672-31bd2-375kb.png?nocache=1)
![Изображение](http://clip2net.com/clip/m232938/1373552737-792b7-324kb.png?nocache=1)
Помощь
Мне 18 лет и я недавно закончил школу, у меня неплохие знания, но мне нужна помощь в программировании, кому несложно пишите
skype: antoshka741