Использование CraftDuino в капинге


Здравствуйте. Извините меня пожалуйста, если кому то мой вопрос покажется слишком «детским», но я не специалист в области робототехники. Я занимаюсь созданием Воздушных змеев и попутно пытаюсь приобщиться к КАП (фотографирование с воздушных змеев).
А для создания 360°-панорамной съёмки нужно чтобы камера поворачивалась по горизонту на все 360° и по вертикали на 180°, а также это должно происходить послойно с остановками на съёмку и в момент остановки нажимается кнопка затвора. Выглядит это приспособление держащее камеру вот так

Программное действие установки:
1. Камера повёрнута до максимума в верх, первый снимок.
2. Камера проворачивается по горизонтальной на определённый угол. Угол зависит от фокусного угла камеры, то есть например если это «мыльница» ею приходиться делать около 20 и более снимков чтоб охватить горизонт вокруг полностью. На каждой такой остановке идёт нажим кнопки сервой.
3. Когда камера проходит полностью круг по горизонту, она перемещается относительно вертикали в низ также на определённый угол зависящий от камеры. От максимума до полного полного низа около пяти получается. И на каждом таком повороте по вертикали происходит полный цикл проворота по горизонтали.

Управление должно производиться двумя сервмашинками и одним двигателем. Электродвигатель проворачивает по горизонтали, одна сервмашинка разворачивает по вертикали и одна сервмашинка делает нажим на кнопку затвора.

Также хотелось бы чтоб запуск производился с дистанционки на расстоянии около 200 метров, на такую высоту примерно поднимается камера. Команда одна единственная «старт», а остановка производиться уже по завершению полного цикла. Или на крайний случай таймер который будет запускать установку с задержкой времени, пока камера поднимается в воздух.

Теперь вопросы. Сможет ли CraftDuino управлять сразу тремя объектами: двумя сервами и двигателем? (не пинайтесь пожалуйста 🙂 ) Если не трудно то подскажите как собрать электрически всю эту штуку, то есть схемку если можно. Я так понял у вас как раз всё есть то что мне нужно:
1. https://robocraft.ru/store/catalog/1 САМ мозг 🙂
2. https://robocraft.ru/store/catalog/3 не очень сильная серва для кнопки
3. https://robocraft.ru/store/catalog/7 серва по мощней для поворота по вертикали (жаль что её нет у вас в наличии сейчас, но думаю это временно)
4. https://robocraft.ru/store/catalog/32 электродвигатель для поворота платформы по горизонтали. Но вот здесь возникает ещё один вопрос: можно ли управлять таким двигателем чтоб он останавливался в точном месте, — мне кажется для таких целей нужен шаговый электродвигатель??? Хотя можно использовать на сколько я знаю серву переделав её немного, так чтоб она крутилась на 360°.
Рад всё это у вас заказать и ни я один буду так как нас много, но мучают вопросы…
Помогите с решением этих вопросов пожалуйста если вам не трудно. Заранее благодарен. 🙂


18 комментариев на «“Использование CraftDuino в капинге”»

  1. Интересное увлечение=)
    Крафтдуины(Ардуины) в качестве мозгов, конечно же, более чем хватит.
    С спуском по дистанционке готового решения предложить не могу… Может по проводку?=) Ну а по таймеру — легко.
    Как работать с сервой описано тут и тут.
    Как подключить моторчик — тут.
    Использование шагового двигателя, ИМХО, весьма избыточное решение — точность такая вам, похоже, необязательна, а вес коснрукции выйдет больший.Тяжёлые они — КПД низкий и при одинаковом усилии шаговик будет тяжелее и крупнее моторредуктора или сервы.
    Да, серву можно переделать(не оч сложно, но и не слишком легко=)
    Да, можно заставить моторчик останавливатся в определённых положениях но это сложнее, тем более что его и подключить сложнее(понадобится драйвер)
    Помоему проще с сервой.
    Кстати, т.к. вес вам, похоже, важен, стоит посмотреть в сторону сервы полегче.

    • Спасибо за подробный ответ. 🙂 Ответ на самый главный вопрос: сколько можно подключить серв — был получен, то есть до 12 и мне это хватит за глаза 🙂 Что касается «старта» для начала буду использовать таймер, и если найду передатчик/приёмник на 200 метров и лёгкий, то можно будет подключить его через реле.
      Пойду на страницу заказов. Друг тоже загорелся так что сразу два CraftDuino заказывать будем 🙂

  2. Возможно, будет удобнее использовать модуль XBeePro? Его заявленная дальность больше километра.-) Правда, тут придётся сравнивать вес шилда с этим модулем (плюс, возможно, более ёмкий аккумулятор) и нить/корд, которой Вы пользуетесь.
    http://www.linuxcenter.ru/shop/embedded/arduino/XBee_Pro_50mW_Series_2_5_RPSMA/
    gsm.contrel.ru/wireless/zigbee/xbee/
    catalog.compel.ru/blog/tag/xbee-pro/
    Ну и, возможно, цена сыграет какую-то роль. Но зато какая гибкость всего устройства приобретается!
    Удачи!

  3. Как мало человеку надо для полного счастья 🙂 Я сегодня получил посылочку с детальками среди которых две платки CraftDuino, одна мне, другая другу. От радости не знаю теперь с какой стороны к ним подходить 🙂 Оперативненько так. Даже и не думал что за шесть дней придёт посылка. Спасибо 🙂

    sanders, да интересная штука, спасибо что подсказали. По поводу цены… знаете уж очень хочется чтоб моё «дитятко» ну хоть капельку не хуже забугорных было, поэтому на цену наверно придётся закрыть глаза 🙂

    Начинаю собирать результаты обязательно выложу здесь, если интересно.

    • Круто=)))
      Когда боевые испытания?
      Проблемы все решились?

    • Прошу прощение, что очень долго не отвечал, я думал что мой топик ни кто не читает ну и сам перестал здесь появляться 🙂
      Да все вопросы решил сам. Код переписал полностью по другому, была переделана серва под 180гр и ещё очень чего много.
      «Боевые» испытания прошёл и уже во всю хожу снимаю 🙂
      kitevlad.ucoz.ru/forum/29-157-1
      kitevlad.ucoz.ru/forum/29-158-2932-16-1300896505
      kitevlad.ucoz.ru/forum/29-152-1

      Сейчас новый вопрос возник, а задавать здесь уже боюсь… похоже здесь на вопросы отвечать не любят 🙂

    • О как зацепило то 🙂 Ну тогда может у кого нибудь найдётся немного времени на меня? Про управление инфракрасниками здесь на сайте есть темы но они немного не о том… У меня в фотоаппарате находиться датчик инфракрасный, который предназначен чтоб управлять фотоаппаратом с пульта. Хочу отказаться от сервы которая нажимает на кнопку затвора и поставить инфракрасный диод(?)
      Напрямую к ардуинко я так понимаю диод не подключишь… тогда что за блочёк нужен, какая схема? Что за сигнал нужно подавать с ардуино? Ну и может что-то ещё не знаю… Буду очень благодарен за помощь. Спасибо.

    • найдётся=)
      также раздуплюсь ответить на предыдущие вопросы и мож койчего ещё полезного подсоветую=)
      В хронологическом порядке:
      Чтоб СРАЗУ реогировало на концевик надо использовать прерывания.
      Чтоб уменьшить инерцию двигателя (на видео работы платформы видно, что имеется выбег) надо использовать динамическое торможение — на все входы драйвера(EN1, IN1, IN2) — еденицы.
      Про эмулятор — низнаю=)
      К дуинам светодиоды можно подключать напрямую, но ненужно=) В простейшем случае просто через резистор 100-200ом. TSAL4400, например, может пропускать ток до 100мА — чтоб наполную засветить понадобится транзистор. Но вам на полную и не надо — будет же впритык к фотоаппрату, да?
      Проблемней узнать/поймать/воспроизвести нужную команду для фотика. Пульт то хоть есть?
      Кстати, тогда в голову не пришло — можно и команду на старт подавать по ИК-каналу — на змея к дуине TSOP, в руки пульт самодельный (МК+кнопка+ИК-светодиод(ы)через транзистор)), тот же TSAL4400 можно разогнать до ампера в импульсе, ещё можно поставить несколько светодиодов… добьёт в ясную погоду я думаю=)

    • Любят-любят, но иногда не успеваем, иногда и забЫваем=(
      Кстати, классные фотки=)

    • Супер=)
      может опишете своё решение — скетч, схема (в отдельном посте=)?
      Да и про вашу систему подвеса вцелом многим былобы интересно почитать поподробней.

  4. может опишете своё решение — скетч, схема (в отдельном посте=)?

    К сожалению это не моё решение и приписывать к себе я не буду 🙂 Управление ИК портом фотоаппарата через Ардуину разработал Sebastian Setz я лишь взял готовое. Там у него всё подробно расписано.
    А в целом о риге (тоже не моё изобритение 🙂 ) в принципе можно, только нужно время чтоб собраться, хотя о нём всё и так уже расписано на форуме змеенавтов 🙂 И не только о моём но о ригах других участников идут более подробные обсуждения.

  5. Помогите пожалуйста написать код или правильно подсоединить детали.
    На эмуляторе в замен драйвера (нет в библиотеке) поставил светодиоды, а концевик — кнопка:

    Увеличить

    Это электрическая схема:

    Увеличить

    #include <Servo.h> 
    //Сервы
    Servo servo_big;                // создаём объект для контроля сервы вертикального наклона
    Servo servo_sm;                 // создаём объект для контроля сервы затвора
     
    int pos = 0;                    // переменная для счётчика
    int angle = 6;                  // количество горизонтальных проходов
    int valserv = 0;                // перемнная для определения положения серв
    
    //мотор
    int in1 = 7;                    //INPUT1 драйвера двигателя подключен к 7 пину
    int in2 = 8;                    //INPUT2 драйвера двигателя подключен к 8 пину
    int enable = 11;                //ENABLE1 драйвера двигателя подключен к 11 пину
        
    //концевик
    int btnPin = 12;                //концевик подключен к 12 пину
    int btnval = LOW;               //положение концевика (LOW - разомкнут, HIGH - замкнут)
    int btn = 0;                    //перменная счётчика нажатия концевика 
         
    //---
    void setup()                   
       {
        servo_big.attach(5);        // серва вертикальная подключена к 5-му пину
        servo_sm.attach(6);         // серва затвора подключена к 6-му пину
        
        pinMode(in1, OUTPUT);       // выходы на драйвер
        pinMode(in2, OUTPUT);
        pinMode(enable, OUTPUT);
        
        pinMode(btnPin, INPUT);     // вход концевика
    	
        Serial.begin(9600);         // общение с COM портом (на всякий случай для проверок)
    	
        digitalWrite(in1, HIGH);    // подача сигналов на контакты драйвера двигателя
        digitalWrite(in2, LOW);   
       }
    //----
    void loop()                     
       { 
       //----
       if(btn == 0)                                  // если нулевой (верхний) уровень                
         {
         servo_sm.write(0);                          // выставляем серву затвора в ноль
         valserv = servo_big.read();                 // и проверяем положение вертикальной сервы
         if(valserv>0)                               // если не в нулевом положении
           {
           for(pos = valserv; pos > 0; pos -= 1)     // медленно выводим в ноль 
    	  {
              servo_big.write(pos);              
    	  delay(100);                       
              }
           }
         } 
       //----
    	
       if(btn < angle)                               // контроль количества срабатывания концевика
         {
         analogWrite(enable, 255);                   // запуск двигателя горизонтального разворота
         delay(2000);                                // пауза для обработки снимка 
         //---
         for(pos = 0; pos < 90; pos += 1)            // малая серва нажимает на спуск затвора
            {
    	servo_sm.write(pos);
    	delay(15);
    	} 
         servo_sm.write(0);                          // возвращаеться назад
         //----
    		
         btnval = digitalRead(btnPin);               // проверяем состояние концевика
         if(btnval == HIGH)                          // если замкнут
           { 
           analogWrite(enable, 0);                   // останавливаем двигатель
           for(pos = btn * (180 / angle); pos < btn * (180 / angle) + 180 / angle; pos += 1)
    	  {
    	  servo_big.write(pos);                  // переводим серву на заданный угол 
    	  delay(100); 
    	  } 
    	  btn += 1;                              // подщитываем количество раз нажатий на концевик
    	  delay(100);                            // пауза передначалом движения по горизонту
    	  analogWrite(enable, 255);              // запускаем двигатель
    	  }
           }
         //----
    
         if(btn >= angle)                            // если весь цикл пройден
           {
           analogWrite(enable, 0);                   // двигатель отключаеться
    		
           servo_sm.write(0);                        // сервы возвращаються в нулевые состояния
           valserv = servo_big.read(); 
           for(pos = valserv; pos > 0; pos -= 1)
    	  {
    	  servo_big.write(pos);                  // серва наклона камеры возвращаеться медлено
    	  delay(100);
              } 
           }
         //----
       }

    Проблема в том, что идёт обработка данных по ступенькам, а это не очень нравиться… если нажат концевик то всё должно останавливаться и занимать новую позицию… а здесь получается, что пока не пройдёт чтение всего кода, система не среагирует на концевик. То есть надо жать на концевик пока система не определит, что концевик нажат, а за это время двигатель прокрутит платформу ещё дальше, разумеется концевик от пустится и система его уже не увидит…
    Ка сделать, чтоб по нажатию концевика система начинала сразу же обрабатывать данные.

    Концевик показывает что платформа развернулась на 360°. В этот момент останавливается двигатель горизонтального движения, и серва вертикального поворота передвигается на следующий уровень. Двигатель запускается и идёт следующий круг. Вместе с движением платформы по кругу срабатывает серва кнопки затвора, нажимая на кнопку с заданным интервалом.
    По эмуляции вроде серва кнопки работает одновременно с движением двигателя, но на практике ещё не проверил, так как платформа ещё не собрана. Но двигатель и концевик уже подсоединены и двигатель останавливается если удерживать концевик при этом двигатель проворачивается почти на целый оборот иногда на полтора.

    И ещё, тоже в эмуляторе, на нулевой позиции серва вертикального поворота почему то становиться на 90° ???

    Пожалуйста помогите, кроме вас обратиться не к кому, а у самого уже свой мозг начинает плавиться. 🙂

  6. Я так и знал что про меня забыли 🙂 вот и стал ножками стучать чтоб меня увидели 🙂
    Не могу понять как же это пропустил статью про прерывания… а я решил эту часть с помощью разбивки на шаги движение двигателя. Хотя может и моё решение лучше (?) было по причине того, что на морозе двигатель отказывался крутиться, если на него подавалось небольшое напряжение, при уменьшении скорости его движения. Скажем при подаче от 200 и ниже двигатель отказывался крутиться (может смазка замерзала не знаю, но в тепле начинал двигаться) А так как мне надо было регулировать скорость поворота платформы то я просто стал его разбивать на импульсы с полной подачей напряжения. Можно было менять скорость разворота платформы, отсчитывать также, опираясь на шаги двигателя, количество раз нажимания на затвор в круге. А чтоб двигатель не дёргал платформу и не протягивался, подача импульса происходит с плавным нарастанием/убыванием, используется for():

    void Moto()
    {
      int dpos;
      for(dpos=0; dpos<255; dpos+=5)
      {
        analogWrite(moto_pin,dpos);
      }
      delay(10);
      for(dpos=255; dpos>0; dpos-=5)
      {
        analogWrite(moto_pin,dpos);
      }
      delay(10);
    }

    Естественно в момент остановки проверяется замкнуты ли контакты геркона(за место концевика поставил геркон) если замкнуты то производиться действие, и фиксируется запрет на дальнейшую проверку геркона на замыкание, пока платформа не выйдет в разомкнутую зону. При выходе — запрет снимается.

    • Спасибо Zoltberg но на прошлые вопросы уже можно не отвечать 🙂 на главный с прерыванием вы уже ответили, остальные я уже решил 🙂 Если интересно приведу код который сейчас управляет ригом:

      // Pekavet v4
      
      #include <Servo.h> 
      
      //----
      int TimeDelayStart  = 300;                 // время задержки старта в секундах      
      
      int Cycle           = 5;                   // количество полных циклов
      int cycleStep;
      
      Servo servosm;                             // создаём объект для контроля сервы затвора
      int ZatvStep        = 10;                   // задержка между срабатываниями сервы затвора в шагах двигателя
      int zatv;
      unsigned long time;                        // переменная отсчитавающая время
      int servosm_pin     = 5;                   // пин для сервы затвора
      
      Servo servobig;                            // создаём объект для контроля сервы вертикального поворота
      // 809, 2180
      int min_servo       = 1200;
      int max_servo       = 2180;
      
      int LevelStep       = 4;                   // количество круговых уровней сделанных платформой
      int levelval;                              // переменная для хранения количиства уровней
      int servobig_pin    = 6;                   // пин для сервы вертекального поворота камеры
      //----
      int moto_pin        = 11;                  // пин для управления двигателем горизонтальногоразворота камеры
      int motoIN2_pin     = 8;                   // пин для драйвера IN2 двигателем горизонтальногоразворота камеры
      int motoIN1_pin     = 7;                   // пин для драйвера IN1 двигателем горизонтальногоразворота камеры
      int motostep;                              // шаги двигателя
      //---- 
      int btnval;                                // переменная состояния концевика
      int btn_pin         = 12;                  // пин для концевика 
      
      boolean btn_block = false;                 // контроль концевика от удержания
      boolean foto_go = false;
      int kadr;
      //------------------------------------------------------------------------------------------------------
      void setup() 
      { 
        //----
        pinMode(motoIN2_pin, OUTPUT);                         // назначение выход 8-му пину для IN2 драйвера двигателя
        pinMode(motoIN1_pin, OUTPUT);                         // назначение выход 7-му пину для IN1 драйвера двигателя
        digitalWrite(motoIN2_pin, LOW);                       // назначение направление движения
        digitalWrite(motoIN1_pin, HIGH);                      // для двигателя
        analogWrite(moto_pin,0);
        //----
        pinMode(btn_pin, INPUT);                              // назначение входа для концевика
        //----     
        Serial.begin(9600);                                   // инициализация работы с COM-портом
      } 
      //------------------------------------------------------------------------------------------------------
      void loop() 
      {
        //-----------------------
        if(cycleStep > Cycle-1)                                                   // если циклы пройдены полностью то останавливаем программу  
        {
          ServoBig (809);
          return;
        }   
        //-----------------------
        if(TimeDelayStart > 0)                                                   // задержка работы перед стартом для поднятия камеры
        {
          delay(1000);  
          TimeDelayStart--;
          ServoBig (2000);
          kadr++;
          if(kadr>=30)
          {
            kadr=0;
            ServoSmall();
          }
        }
        else 
        {
          //-----------------------                                                     // запуск двигателя
          Moto ();
          //-----------------------
          btnval = digitalRead(btn_pin);                                                // узнаём состояние концевика
          if(btnval==HIGH && btn_block==false)                                          // если концевик зажат и не стоит блокировка
          {
            if(levelval==LevelStep)                                                     // подсчитываем уровни и циклы
            { 
              levelval=0;
              cycleStep++; 
            }
            if(levelval <LevelStep)
            { 
              analogWrite(moto_pin,0);
      
              levelval++;
              ServoBig (min_servo + ((max_servo-min_servo)/(LevelStep-1))*(levelval-1));    // выставление вертикальной сервы на угол согластно уровня 
              ServoSmall();                                                                 // делаем снимок 
              foto_go=true;                                                                 // разрешаем делать съёмку
            }
      
            btn_block=true;                                                                 // ставим блокировку от зажима концевика
          }
          if(btnval==LOW)                                                                   // если концевик отпущен
          {
            btn_block=false;                                                                // снимаем блокировку
          }
      
          //-----------------------
          if(foto_go==true)
          {
            motostep++;
            if(levelval==1 || levelval==LevelStep)
            {
              zatv=ZatvStep*3;
            }
            if(levelval>1 && levelval<LevelStep)
            {
              zatv=ZatvStep;
            }
      
            if(motostep >= zatv)                                // если наступил момент для срабатывания сервы для затвора
            {
              ServoSmall();                                         // делаем снимок
              motostep=0;
            }
          }
          //-----------------------
        }
      }
      //------------------------------------------------------------------------------------------------------
      void Moto()
      {
        int dpos;
        for(dpos=0; dpos<255; dpos+=5)
        {
          analogWrite(moto_pin,dpos);
        }
        delay(10);
        for(dpos=255; dpos>0; dpos-=5)
        {
          analogWrite(moto_pin,dpos);
        }
        delay(10);
      }
      
      //------------------------------------------------------------------------------------------------------
      void ServoBig (int posAngle)                       // функция поворота вертикальной сервы
      {
        servobig.attach(servobig_pin, min_servo, max_servo); 
        int pos = servobig.readMicroseconds();           // определение положения сервы вертикального наклона
        while(pos > posAngle)
        {
          pos--;
          delay(5);
          servobig.writeMicroseconds(pos);
        }
        while(pos < posAngle)
        {
          pos++;
          delay(5);
          servobig.writeMicroseconds(pos);
        }
        servobig.detach();                               // отключаем серву
      }
      //------------------------------------------------------------------------------------------------------
      void ServoSmall()                                  // функция поворота сервы затвора
      {  
        servosm.attach(servosm_pin);                     // подключаем серву кнопки затвора к 5-му пину
        int pos;
        //----
        for(pos = 580; pos <= 800; pos +=5)              // делаем нажим на кнопку затвора
        {                                                // здесь нужно проработать код 
          servosm.writeMicroseconds(pos);                // для подстройки к параметрам фотоаппарата 
          delay(5);
        }
        delay(700);  
        //----
        for(pos = 800; pos >= 580; pos -=5)              // делаем нажим на кнопку затвора
        {                                                // здесь нужно проработать код 
          servosm.writeMicroseconds(pos);                // для подстройки к параметрам фотоаппарата 
          delay(5);
        }
        //----
        servosm.detach();                                // отключаем серву
      }
      

      В коде пока реализована задержка на срабатывание кода для того чтоб успеть поднять камеру на высоту. Скоро должны придти передатчики на 300 метров и тогда перепишу уже код. Управлять стартом диодом может и можно было бы но
      не на большое расстояние, поэтому как-то сразу откинул.

    • А вот управлять кнопкой затвора ИК диодом это в самый раз, меньше городить арматуру подвески.
      Но вот с ним то как раз таки и возник вопрос. Весь прикол в этих импульсах. Есть конечно уже готовые решения например GentLED Shutter но когда я увидел цену меня чуть кикоз не скрутил, это ж надо люди десяти рублёвый диод за такие бабки продают, хотя бы уж какой нибудь корпусик соорудили да проводки, как на сервах спаяли бы в лапшу. Есть ещё один вариант (точнее варианты на ебау)http://viewitem.eim.ebay.ru/15M-Remote-Sony-NEX-5-A550-A380-A330-A850—RMTDSLR1/270697615827/item здесь уже более менее цена адекватная да и девайс по приличней :). Диод закрепить на стойке возле глазка фотоаппарата, платку спрятать вместе с Ардуинкой, ну и естественно подключит управление замыканием контактов кнопок.
      Но вот всё таки хочу сначала попробовать сам собрать, но для этого нужно выяснить на какой чистоте идёт приём у фотоаппарата, каким образом добиться выдачу этой чистоты с Ардуинки. И какой импульс нужен для срабатывания в фотоаппарате затвора.
      И ещё чем отличаются ИК-диоды в пультах от TSAL4400? Можно ли пультовые использовать? И почему они прозрачные в пультах, а TSAL4400 с голубоватым оттенком?
      Про подключение на прямую я имел ввиду без того блочка который виднеется под кембриком у gentlesовцев. Кстати спасибо я понял теперь зачем транзистор: для усиления свечения диода. Это разуметься не нужно, диод в плотную будет стоять к ИК-порту.

      Спасибо за оценку фоток 🙂

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение