Как настроить Bluetooth в старом и новом автомобиле

Как настроить Bluetooth в старом и новом автомобиле Мультикоптеры

Гоночная машинка на bluetooth управлении.

Всем привет. Представляю вашему вниманию знакомство с детскими машинками, управляемыми по bluetooth через смартфон или планшет.

После того, как я отправила продавцу ссылку на обзор конструктора, он сделал мне скидку, поэтому я поставила p.18. Честно говоря, думала, что посылка потерялась или я привыкла, что почта в последнее время работает хорошо. Когда коробка приходит, она не помята, поэтому ее можно дарить в качестве подарка. Коробка также служит витриной с любой упаковкой китайской игрушки. На каждой стороне коробки показаны все опции, которые можно использовать с машиной. QR-код со ссылкой на загрузку для Android и iOS – одна из полезных функций.

Как настроить Bluetooth в старом и новом автомобиле

Что же предлагает производитель?

● Масштаб 1:20
● Два ведущих колеса
● Управление через блютуз
● Голосовое управление
● Программируемое движение

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

Как настроить Bluetooth в старом и новом автомобиле

Начнем с рассмотрения самого автомобиля. Она выглядит интересно для ребенка, благодаря своим ярким цветам и гоночному виду. Пластик составляет корпус автомобиля, и нет защиты от влаги, поэтому он больше подходит для квартиры или для сухой погоды.

Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле

В нижней части автомобиля находятся отсеки для батареек, в каждом из которых находится аккумулятор NiCd AA емкостью 700 мАч 4,8V. Кроме того, на дне есть регулятор поворота, когда машина не едет прямо, и кнопка, включающая игрушку.

Как настроить Bluetooth в старом и новом автомобиле

У автомобиля резиновые шины, сменные, хотя никто явно не будет их менять. Спереди и сзади подвески независимые, есть рессоры, хотя они чисто декоративные.

Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле

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

Как настроить Bluetooth в старом и новом автомобиле

После снятия верхней половины корпуса, которая держится на шести винтах, там находится простая плата управления с чипом Bluetooth, к которому подключены все провода, и управление двигателем. Сервопривода там нет.

Как настроить Bluetooth в старом и новом автомобиле

На фотографии видна старая микросхема управления двигателем, а также микросхема Bluetooth. В корпусе заднего моста установлен коллекторный двигатель и коробка передач. На шестернях имеется смазка.

Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле

Загрузив QR-код, я протестировал аппарат. Приложение, похоже, написано на стенде. Оно работает, хотя это случается нечасто. Кроме того, на экране есть кнопки для управления приложением, а также возможность голосового управления (для особых извращенцев), с простыми командами типа бежать, влево, стоп. Мои команды были получены через пень, поэтому, видимо, у меня не очень хорошее произношение. Также есть интересная функция – конструктор маршрутов, где вы можете добавить кусок маршрута, например, 2-секундный отрезок прямо направо 2 секунды, и машина будет следовать по нему. Голосовое управление оказалось не столь удачным. На скриншотах ниже показано приложение в действии.

Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле
Как настроить Bluetooth в старом и новом автомобиле

На главном экране приложения расположены все значки органов управления. В левой колонке находится индикатор заряда батареи, но, похоже, он просто нарисован, поскольку, когда автомобиль не двигался, он показывал 100% заряда. В меню настроек есть описание расположения кнопок, а также как пользоваться голосовым управлением. Рядом расположены кнопки активации голосового управления, смены управления, включения музыкального трека, активации генератора маршрутов и смены фона рабочего стола. Чтобы подключиться к машине, нажмите на крайнюю правую кнопку.

Такая игрушка будет хорошим выбором для ребенка, если вы скинете с нее пять долларов. Однако изначально я купил ее за $16. И на ковре, и на асфальте, особенно если покрытие ровное, машина работает хорошо. Пороги в квартире преодолевает. (Не волнуйтесь, телефон можно пропустить). Примерно на 20 минут автономной работы можно рассчитывать. По плану подарок должен был сразу получить мой племянник, но сын решил сделать первым. Вашему ребенку это понравится просто как игрушка, а не как гоночный автомобиль для заядлых RC-спортсменов. Пожалуй, и все, так как на видео видно, как она катается. Есть возможность привести ребенка, если снова будет скидка. Спасибо всем за прочтение.

Я получил продукт в обмен на написание обзора. В соответствии с пунктом 18 правил сайта, данный отзыв опубликован.

Питание робота

Обеспечение правильной схемы питания часто является последним, о чем думают начинающие ардуиноводы. Во время работы умных устройств на Arduino проблемы часто возникают из-за ошибок в схеме питания.

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

Питание робота
Питание робота на Ардуино

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

  • Обычные батарейки типа АА. Обратите внимание, что Arduino Uno, Nano и большинство двигателей, используемых в робототехнике Arduino, требуют напряжения в диапазоне 6-9 вольт. Поэтому необходимо последовательно соединить как минимум четыре батарейки 1,5 В, причем сами батарейки должны быть хорошего качества и обеспечивать достаточный для работы ток. Например, большинство солевых батарей не соответствуют этим критериям. Батарейки AAA редко используются для сборки машин arduino из-за их низкой емкости (хотя их можно использовать в миниатюрных моделях, где размер наиболее важен).
  • Батарея AA. Здесь существует еще большее ограничение по напряжению и току. Большинство батарей обеспечивают напряжение 1,2 вольта, поэтому для “захвата” необходимых 6-9 вольт требуется больше. Возможность перезарядки является несомненным преимуществом.
  • Литиевые батареи 18650. Это уже “серьезная артиллерия”, обеспечивающая длительное время автономной работы, возможность перезарядки и приемлемые характеристики тока и напряжения. Рабочее напряжение батарей этого типа составляет 3,7 В, что позволяет собрать полную цепь питания всего из двух элементов.
  • Другие источники питания. Это могут быть как более мощные и громоздкие никель-металл-гидридные батареи, так и многочисленные “плоские” литий-ионные варианты, используемые в дронах, смартфонах и другом портативном цифровом оборудовании.

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

Подключаем bluetooth к машинке

Мы собираемся использовать модуль Bluetooth через SoftwareSerial (библиотеку SoftwareSerial.h), поэтому подключаем модуль блютуз к 3 и 4 цифровым пинам ардуино. RX к D3, TX к D4

Схема ардуино робота машинки 5
Схема подключения Bluetooth к ардуино машинке

Платформа робота готова! Теперь необходимо загрузить приложение для смартфона RC CAR и прошивку контроллера Arduino. Обзор приложений для Android для Arduino можно найти на нашем сайте.

Пример платформы робота-машины на ардуино

Приведены инструкции по созданию универсальной платформы, которая затем может позволить создавать разнообразные проекты, независимо от выбранного контроллера или типа шасси. Вместо того чтобы использовать стандартные опции AliExpress, как в видео, можно установить гусеницы и создать вездеход, а можно сконструировать что-то совершенно новое.

Робот на Ардуино
Робот на Ардуино

Для осуществления проекта нам понадобятся

  • Контроллер Arduino (в нашем случае Arduino Nano).
  • Контроллер двигателя L298N.
  • Мотор-редукторы.
  • Корпус и шасси для установки колес и оборудования
  • Корпус для аккумуляторов 18650 с контактом.
  • Запасные кабели.

Дополнительное оборудование, которое понадобится для создания полного проекта

  • Датчик расстояния и привод, на котором он установлен.
  • Инфракрасные линейные датчики.
  • Индикатор и лампочки “красоты”.
  • Пьезоэлектрический динамик – пищалка.
  • Модуль Bluetooth (если вы собираетесь управлять машиной дистанционно).
  • Экранирование датчика (облегчает переключение).
  • Зарядка аккумулятора и зарядный модуль.
  • Сами батареи.
Схема ардуино-робота машинки 1
Общая схема машинки на Ардуино

Роботизированная машина. часть iii: bluetooth

Это особенно полезно с точки зрения программирования и управления с помощью Bluetooth. В предыдущей статье мы подробно рассмотрели вопросы сборки.

Начните с подключения модуля связи HC-06 Bluetooth к роботу. Для HC-06 требуется предварительная настройка. Можно использовать HC-05, но он дороже, и его функциональность не может быть использована для этой задачи.

Следующим шагом будет загрузка бесплатного программного обеспечения Bluetooth RC Controller. Имитирует основные элементы управления пульта дистанционного управления и отправляет текстовые команды по Bluetooth.

Как настроить Bluetooth в старом и новом автомобиле

Интерфейс программы интуитивно понятен, как вы можете видеть. В верхнем левом углу вы можете видеть индикатор подключения HCM-06 (зеленый цвет означает успешное подключение). Здесь же находится компас, который показывает выбранное направление движения, а также элементы управления по периметру. Наша машина будет построена с использованием всего имеющегося. Перечисляем слева направо.

Смотрите про коптеры:  Рейтинг ТОП-15 лучших автосигнализаций - 2021-2022 года | Экспертные руководства по выбору техники

Благодаря этому почти все кнопки пульта дистанционного управления напрямую соответствовали командам машины. Правда, пришлось написать и отладить отдельный код управления скоростью. Еще одну нетривиальную вещь мы сделали с диагональными направлениями. Их реализация осуществляется путем изменения скорости между левой и правой сторонами.

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

*

// 4WD RoboCar
// Sonar   Bluetooth
// 2022-January-20
// v.11a (bluetooth)
// (c) 2022, Vladimir E. DRACH

// Global variables:
int  Critical = 14;     // Критическое расстояние до препятствия в [см]
int  BT_Step  = 10;     // Время движения при получении одного СИМВОЛА по BT [мс]
byte randomNumber;      // Случайное число
byte Cost = 60;         // Штраф (назначается за неспособность ехать вперёд)
byte Profit = 180;      // Очки, т.е. "прибыль", которая плавно растёт при движении вперёд
byte velocity = 220;    // Скорость моторов [1..255]
                            // Подобрать экспериментально:
const byte SPEED_MIN = 100; // минимальная скорость моторов, если меньше - моторы не смогут вращаться
const byte SPEED_MAX = 250; // максимальная скорость моторов

// для управления по Bluetooth
char btCommand = 'S';
// счетчики для определения потери связи с Bluetooth
unsigned long btTimer0 = 2000;  //Stores the time (in millis since execution started)
unsigned long btTimer1 = 0;     //Stores the time when the last command was received from the phone

// Описываем подключение драйвера двигателей
// A - правый борт
// В -  левый борт

int enableB = 3; //~ 
int pinB2   = 4; // 
int pinB1   = 5; // 
int enableA = 6; //~ 
int pinA1   = 7; //~ 
int pinA2   = 8; //

#define illumination A0 // подключаем составной светодиод

// Подключаем ультразвуковой датчик
#define trigPin 9
#define echoPin 10

#define light 11 // На этот вывод подключены фары

int Buzzer = 12;// Подключаем зуммер 12 (!)

// Фоторезистор подключен к АЦП
#define PHOTO_SENSOR A5

#define Sweep 8000 // скорость нарастания и убывания частоты
#define Woo_wait_sec 2 // сколько с. длится гудение на макс. частоте

void setup() {
  // Определяем направление работы линий
   pinMode (enableA, OUTPUT);
   pinMode (pinA1,   OUTPUT);
   pinMode (pinA2,   OUTPUT);
   pinMode (enableB, OUTPUT);
   pinMode (pinB1,   OUTPUT);
   pinMode (pinB2,   OUTPUT); 
   pinMode (13 ,     OUTPUT);
   pinMode (light ,  OUTPUT);
   pinMode (trigPin, OUTPUT);
   pinMode (echoPin, INPUT) ;
   pinMode (illumination, OUTPUT);
 enableMotors();
 SayBeep();
 delay(2000);
 bii();
 digitalWrite(13,  LOW);    // Выключаем встроенный диод
 Serial.begin(9600);        // Инициализация последовательного порта
}

// Описываем варианты работы моторов
void motorAforward() {
 digitalWrite (pinA1, HIGH);
 digitalWrite (pinA2, LOW);
}
void motorBforward() {
 digitalWrite (pinB1, LOW);
 digitalWrite (pinB2, HIGH);
}
void motorAbackward() {
 digitalWrite (pinA1, LOW);
 digitalWrite (pinA2, HIGH);
}
void motorBbackward() {
 digitalWrite (pinB1, HIGH);
 digitalWrite (pinB2, LOW);
}
void motorAstop() {
 digitalWrite (pinA1, HIGH);
 digitalWrite (pinA2, HIGH);
}
void motorBstop() {
 digitalWrite (pinB1, HIGH);
 digitalWrite (pinB2, HIGH);
}
void motorAon() {
 digitalWrite (enableA, HIGH);
}
void motorBon() {
 digitalWrite (enableB, HIGH);
}
void motorAoff() {
 digitalWrite (enableA, LOW);
}
void motorBoff() {
 digitalWrite (enableB, LOW);
}

// Описываем варианты движения машины
void goForward (int duration) {
 motorAforward();
 motorBforward();
 delay (duration);
}
void goBackward (int duration) {
 motorAbackward();
 motorBbackward();
 delay (duration);
}
void rotateRight (int duration) {
 motorAbackward();
 motorBforward();
 delay (duration);
}
void rotateLeft (int duration) {
 motorAforward();
 motorBbackward();
 delay (duration);
}
void FullStop (int duration) {
 motorAstop();
 motorBstop();
 delay (duration);
}
void disableMotors() {
 motorAoff();
 motorBoff();
}
void enableMotors() {
 motorAon();
 motorBon(); 
 // SetVelocity(SPEED_MAX, SPEED_MAX); не очень работает :(
}

void SetVelocity(int A, int B)
{         analogWrite (enableA, A);
          analogWrite (enableB, B); }

void CheckLight () {
  int val = analogRead(PHOTO_SENSOR);
  if (val < 500) {
    // Темновато, включаем фары
    digitalWrite(light, HIGH);
   } else {
    // Светло, выключаем фары
    digitalWrite(light,  LOW);
   }
}

// Пользуемся УЗ датчиком расстояния
int distance() {
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1; // Переводим в сантиметры
  return distance;
}

// Функция запуска автомобиля
void launch() {
     int distance_measured;
     distance_measured = distance();
      // Serial.print(distance_0);
      // Serial.println(" сантиметров. ");
     SetVelocity (velocity, velocity);
      // Движемся вперёд, пока расстояние до преграды > критического [cm]
     while (distance_measured > Critical)
     {
     CheckLight ();  // проверяем, не пора ли зажигать фары?
     goForward(30); // Едем вперёд некоторое время
     randomNumber = random(1,100); // передёрнули затвор генератора ПСЧ
     if (Profit < 254 ) { Profit  ; };
     // Serial.print(Profit);
     // Serial.println(" очков. ");
     distance_measured = distance();
     }
     FullStop(100); // Останов, т.к. впереди помеха
}

void Woo(int freq, long duration){ // первый параметр частота, чем ниже он тем выше частота, второй длительность
  long time = duration/2/freq;
  for(long t = 0; t < time; t  )
  { digitalWrite(Buzzer, HIGH);
    delayMicroseconds(freq);
    digitalWrite(Buzzer, LOW);
    delayMicroseconds(freq); }
}

void Syren() {
    for(int i = 0; i <= 1; i  ){         // делаем виу-виу 2 раза
    for(int f = 2000; f >= 100; f=f-40){ // нарастание частоты
    Woo(f, Sweep); }
    // Woo(400, Woo_wait_sec*100);    // сколько длится гудение на максимальной частоте
    for(int f = 100; f <= 2000; f=f 40){ // убывание частоты
    Woo(f, Sweep); }
    }
    }

void panic() {
 int distance_tmp;
 int distance_new = 32000;
 int angle = 600;  // угол поворота, измеряем в [мс]
    FullStop(100); // Сначала останавливаемся
    Profit = 255;  // Забываем про старые штрафы!
    // Serial.print(Profit);
    // Serial.println(" очков. ");
    digitalWrite(illumination, HIGH); // включаем мигалку
    Syren ();
    Syren ();
    Syren ();
    delay(1000);  // пауза, для отдыха
    // Выполняем манёвры на высокой скорости (ведь паника!)
    analogWrite (enableA, velocity);
    analogWrite (enableB, velocity);
    // 0) Начинаем крутиться волчком в какую-то сторону:
    randomNumber = random(1,100);
    if (randomNumber < 50) { motorAbackward(); motorBforward(); }
                      else { motorBbackward(); motorAforward(); };
    // Истерично продолжаем крутиться, пока гудит сирена:
    Syren ();
    delay (1000); // Ждём 
    FullStop(1000);
    delay (100); // Ждём 
    // 1) Ищем хоть какое-то направление, куда вообще можно ехать
    distance_tmp = distance();
    do {
     rotateRight(angle); // Крутимся
     FullStop(1000); // Ждём и смотрим вдаль
     distance_tmp = distance();
     } while(distance_tmp < Critical); // повторяем поворот, если расстояние всё ещё мало

     SayBeep();
     // rotateLeft(angle); // Возвращаемся на один шаг
 
    // 2) Пытаемся выбрать лучшее направление!
     
    do {
    distance_tmp = distance();
    rotateRight(angle); // Крутимся и проверяем дистанцию
    FullStop(900); // Ждём и смотрим вдаль
    distance_new = distance();
    delay (800); // Ждём и смотрим вдаль
    } while( distance_new > distance_tmp );
                                   // Не угадали, раньше было лучше,
    rotateLeft(angle);             // поэтому поворачиваемся обратно
    FullStop(1000); // Восстанавливаем дыхание, успокаиваемся
    digitalWrite(illumination, LOW); // успокоились, выключаем мигалку
    delay (410); // Ждём
    SayBeep();
    }

void rollBack()
    {
    digitalWrite(13,  HIGH); // Включаем встроенный диод!
    // Сначала откатываемся назад на случайное количество шагов
    randomNumber = random(700,2100);
    //analogWrite (enableA, 150);
    //analogWrite (enableB, 189);
    goBackward(randomNumber);
    FullStop(200); // Восстанавливаем дыхание, успокаиваемся
        
    // Случайным образом выбираем направление поворота:
    randomNumber = random(1,100);
       
     do { // поворачиваемся в выбранную сторону на случайный угол
     if (randomNumber < 50) { rotateRight(random(450,1300)); } else { rotateLeft(random(350,1400)); };
     FullStop(1000); // Выключаем моторы
     tone(Buzzer, 600, 333);
     delay (700); // передышка!
     } while( distance() < Critical ); // повторяем поворот, если расстояние всё ещё мало

    analogWrite (enableA, velocity);
    analogWrite (enableB, velocity);
    FullStop(600); // Восстанавливаем дыхание, успокаиваемся
    digitalWrite(13,  LOW); // Выключаем встроенный диод
    // SayBeep();
    delay (200); // передышка!
    } 

void avoid() {
    CheckLight ();  // проверяем, не пора ли зажигать фары?
    tone(Buzzer, 2100, 110);
    delay (700); // передышка!
    // Штрафуем сами себя:
    if (Profit > Cost) {
    Profit = Profit - Cost; // Ещё есть возможность оплатить штраф,
    rollBack();             // тогда откат назад с разворотом
     // Serial.print(Profit);
     // Serial.println(" очков. ");
    } else {
    // Нельзя штрафовать, всё плохо, значит запутались - паникуем
    panic();
    }
}

void SayBeep(){
    tone(Buzzer, 700, 109);
    delay(200);
    tone(Buzzer, 1200, 109);
    delay(200);
    tone(Buzzer, 2600, 240);
    delay(350);
    noTone(Buzzer);
}

void boo(){
      tone(Buzzer, 600, 200);
      delay (300);
      tone(Buzzer, 410, 600);
      delay (600);
}

void bii(){
      tone(Buzzer, 1611, 90);
      delay (150);
      tone(Buzzer, 1611, 90);
      delay (150);
      tone(Buzzer, 2111, 400);
      delay (440);
}

void SafeForward (int duration){
  int distance_measured;
  distance_measured = distance();
  if ( distance_measured > Critical )
      {goForward(duration);}
      else {
      FullStop(10);
      boo(); }
}

void BluetoothControl() {
     for(int i = 0; i <= 4; i  ){
     // digitalWrite(illumination, HIGH); // включаем мигалку
     digitalWrite(13,  HIGH); // Включаем встроенный диод!
     FullStop(80);
     // digitalWrite(illumination, LOW); // вЫключаем мигалку
     digitalWrite(13,  LOW); // Включаем встроенный диод!
     FullStop(900);
     velocity = SPEED_MIN   10;         // Выставлям скорость поменьше, т.к.
     SetVelocity(velocity, velocity);   // на Android будет миниальная скорость по умолчанию!
     }
     do{
     // CheckLight ();  // проверяем, не пора ли зажигать фары?
     aquire();
     }
     while ( 1==1 );
}

void SelfControl() {
     do{
     randomNumber = random(2,5); // вхолостую выбираем псевдо-случайное число
     launch(); // запускаем автомобиль вперёд до встречи с преградой
     avoid();  // откатываемся от препятствия и как-то поворачиваемся
     CheckLight (); // проверяем, не пора ли зажигать фары?
     }
     while ( 1==1 );
}

void aquire ()
{
  if (Serial.available() > 0) {
    btTimer1 = millis();
    btCommand = Serial.read();
    switch (btCommand){
    case 'F':
      goForward(BT_Step); // Можно просто ехать вперёд наобум,
      // SafeForward (BT_Step); // а можно включить сонар
      break;
    case 'B':
      goBackward(BT_Step);
      break;
    case 'L':
      rotateLeft(BT_Step);
      break;
    case 'R':
      rotateRight(BT_Step);
      break;
    case 'S':
      FullStop(BT_Step);
      break;
    case 'G':  // Вперёд, подкручивая вправо
      if (velocity < SPEED_MAX-99) {
      SetVelocity((velocity 99), (velocity-99));}
      else {SetVelocity(SPEED_MAX, SPEED_MIN);} // выставили дифференциал
      goForward (BT_Step);
      SetVelocity(velocity, velocity); // вернули скорость
      break;
    case 'I':  // Вперёд, подкручивая влево
      if (velocity < SPEED_MAX-99) {
      SetVelocity((velocity-99), (velocity 99));}
      else {SetVelocity(SPEED_MIN,SPEED_MAX);} // выставили дифференциал
      goForward (BT_Step);
      SetVelocity(velocity, velocity); // вернули скорость
      break;
    /*case 'J':  //BR
      if (velocity < SPEED_MAX-80) {
      SetVelocity((velocity-80), (velocity 80));}
      else {SetVelocity((velocity-80),SPEED_MAX);} // выставили дифференциал
      goBackward(BT_Step);
      SetVelocity(velocity, velocity); // вернули скорость
      break;
    case 'H':  //BL
      if (velocity < SPEED_MAX-80) {
      SetVelocity((velocity 80), (velocity-80));}
      else {SetVelocity(SPEED_MAX, (velocity-80));} // выставили дифференциал
      goBackward(BT_Step);
      SetVelocity(velocity, velocity); // вернули скорость
      break;
      */
    case 'W':  //  Зажгли фары
      digitalWrite(light, HIGH);
      break;
   case 'w':  // Погасили фары
      digitalWrite(light, LOW);
      break;
   case 'D':  // Everything OFF
      FullStop(100);
      break;
   case 'X': // аварийка
      digitalWrite(illumination, HIGH);
      break;
   case 'x': // аварийка
      digitalWrite(illumination, LOW);
      break;      
   case 'U':  // Back ON
      digitalWrite(13,  HIGH);  // Включаем встроенный диод
      break;
   case 'u':  // Back OFF
      digitalWrite(13,  LOW);    // Выключаем встроенный диод
      break;
   case 'V': // Пискнуть весело (в оригинале - гудок ВКЛ)
      bii();
      break;
   case 'v': // Пискнуть грустно (в оригинале (гудок ВЫКЛ)
      boo();
      break; 
   default:  // Get SPEED_CURRENT
      if ( btCommand == 'q' ){
         velocity = SPEED_MAX;
         SetVelocity(velocity, velocity);
         } else {
        // Символы '0' - '9' эквивалентны кодам integer 48 - 57 соответственно
        if ( (btCommand >= 48) && (btCommand <= 57) ) {
          // Subtracting 48 changes the range from 48-57 to 0-9.
          // Multiplying by 25 changes the range from 0-9 to 0-225.
          velocity = SPEED_MIN   (btCommand - 48) * 15;
          SetVelocity(velocity, velocity);
        }
      } // else
    } // switch
  } // if (Serial.available() > 0)
  else {
    btTimer0 = millis();  // Узнаём текущее время (millis since execution started)
    //Check if it has been 500ms since we received last btCommand.
    if ((btTimer0 - btTimer1) > 800)   {
      //More than 800 ms have passed since last btCommand received, car is out of range.
      FullStop(1000);
      digitalWrite(illumination, HIGH); // включаем мигалку
      boo ();
      FullStop(4000);
      Syren();
      FullStop(8000);
    }
  }
}

void loop() {
     CheckLight ();  // проверяем, не пора ли зажигать фары?
     // Serial.println("System ready...");
     if ( distance() > Critical )
        {                     // Путь вперёд свободен,
          SelfControl();      // робот отправляется в самостоятельное путешествие
        } else {
          BluetoothControl(); // Впереди преграда, отдаём управление водителю
        }
     }

*

Проверив расстояние до препятствия, можно выбрать режим (ручной или демонстрационный). В выключенном состоянии машина обращена к стене – ручное управление через Bluetooth. Когда машина включена, перед ней нет препятствий – самостоятельное движение (демонстрационный режим).

Смотрите про коптеры:  Как сделать реверсивный кораблик для рыбалки своими руками: чертежи для изготовления прикормочного кораблика для ловли

§

Корпус для устройства был сделан из коробки из-под конфет. В него на латунных стойках встроен микроконтроллер Arduino UNO, который будет управлять трехцветным (сверхъярким) светодиодом. Кроме того, был сделан корпус для батареек типа АА, причем батарейки от радиоуправляемой машинки тоже отлично подошли – в общем, их можно пустить в переработку.

Как настроить Bluetooth в старом и новом автомобиле

Мне пришла в голову неожиданная идея, а можно ли как-то дополнительно управлять лампой? Меня привлек миниатюрный джойстик. Это нам точно нужно!

Так, при нажатой кнопке джойстика светильник плавно меняет цвета с красного-зеленого-синего, но при нажатии на джойстик переходит в режим ручного управления (при котором величина яркости каждого цвета определяется расположением ручки джойстика). Повторное нажатие кнопки завершает ручной режим.

Как настроить Bluetooth в старом и новом автомобиле

Как настроить Bluetooth в старом и новом автомобиле

Оригинальный текст для программы был взят из открытых источников, но сильно изменен. В итоге получился более мягкий и нежный ночник.

const int pinRed    = 11;
const int pinGreen  =  9;
const int pinBlue   = 10;
const int swPin     = A5; 
const int pinX      = A4; // X 
const int pinY      = A3; // Y 
const int ledPin    = 13;
boolean ledOn  = false; // текущее состояние кнопки
boolean prevSw = false; // предыдущее состояние кнопки

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(pinRed, OUTPUT);
  pinMode(pinGreen, OUTPUT);
  pinMode(pinBlue, OUTPUT);
  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(swPin, INPUT);  
  digitalWrite(swPin, HIGH); // включаем встроенный подтягивающий резистор
}

boolean isLedOn() { // ОПРЕДЕЛЯЕМ НАЖАТИЕ КНОПКИ
  if (digitalRead(swPin) == HIGH && prevSw == LOW) {
    ledOn = !ledOn;
    prevSw = HIGH;
  }
  else  prevSw = digitalRead(swPin); 
  digitalWrite(ledPin, ledOn); // включаем светодиод на пине 13
  return ledOn;
}

void CtlMode() { // РЕЖИМ "Ручное управление"
  int X = analogRead(pinX); // считываем положение джойстика
  int Y = analogRead(pinY);
  int BLUE  = map(Y, 000, 1023, 0, 255); // маппинг значений
  int GREEN = map(X, 512, 1023, 0, 255);
  int RED   = map(X, 511, 0, 0, 255);
  analogWrite(pinRed, RED);     // включение каналов R,G,B
  analogWrite(pinGreen, GREEN);
  analogWrite(pinBlue, BLUE);
}

void DemoMode() { // РЕЖИМ "Демонстрация"
    for (int i=0; i <= 255; i  ) {
      if (isLedOn()) { break; } // при нажатии кнопки выходим из цикла
      analogWrite(pinRed, i); // работает канал RED
      analogWrite(pinGreen, 0);
      analogWrite(pinBlue, 0);  
      delay(7);
    }
    for (int i=255; i >= 0; i--) {
      if (isLedOn()) { break; } // при нажатии кнопки выходим из цикла
      analogWrite(pinRed, i);   // работает канал RED
      analogWrite(pinGreen, 0);
      analogWrite(pinBlue, 0);  
      delay(7);
    }
    for (int i=0; i <= 255; i  ) {
      if (isLedOn()) { break; } // при нажатии кнопки выходим из цикла
      analogWrite(pinRed, 0);
      analogWrite(pinGreen, 0);
      analogWrite(pinBlue, i);  // работает канал BLUE
      delay(7);
    }
    for (int i=255; i >= 0; i--) {
      if (isLedOn()) { break; } // при нажатии кнопки выходим из цикла
      analogWrite(pinRed, 0);
      analogWrite(pinGreen, 0);
      analogWrite(pinBlue, i);  // работает канал BLUE
      delay(7);
    }
    for (int i=0; i <= 255; i  ) {
      if (isLedOn()) { break; } // при нажатии кнопки выходим из цикла
      analogWrite(pinRed, 0);
      analogWrite(pinGreen, i); // работает канал GREEN
      analogWrite(pinBlue, 0);  
      delay(7);
    }
    for (int i=255; i >= 0; i--) {
      if (isLedOn()) { break; } // при нажатии кнопки выходим из цикла
      analogWrite(pinRed, 0);
      analogWrite(pinGreen, i); // работает канал GREEN
      analogWrite(pinBlue, 0);  
      delay(7);
    }
}

void loop() { // если нажата кнопка и горит светодиод на пине 13, включаем режим "Ручое управление"
  if (isLedOn()) CtlMode(); 
  else DemoMode(); // иначе включаем демонстрационный режим
}


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

§

Серво акселерометр

Акселерометр ADXL345 отлично подходит для измерения статического ускорения при свободном падении, когда требуется измерение наклона. Он также подходит для измерения динамического ускорения в результате движения или удара. Высокое разрешение (4 мг/ЛСБ) позволяет измерять изменение наклона менее чем на 1 градус.

Вот как работает собранное устройство. Через шину I2C (также можно работать через SPI) акселерометр ADXL345, работающий в диапазоне -16g, посылает данные о положении на модуль микроконтроллера. Микроконтроллеры выполняют преобразование данных акселерометра с помощью специализированной функции atan2, декодируя данные, которые они получают от акселерометра.

Это производит управляющее воздействие на серводвигатель. Его важной особенностью является то, что серводвигатели не имеют библиотек.

Ниже приведен тест-листинг для программы.

/*
  Подключение акселерометра по шине I2C:
  VCC: 5V
  GND: ground
  SCL: UNO SCL (А5?)
  SDA: UNO SDA (А4?)
*/

#include <Servo.h>
Servo motor; // Определяем имя серво-привода
#include <Math.h> // Вроде, нужна для atan2
#include <Wire.h>
// Registers for ADXL345
#define ADXL345_ADDRESS (0xA6 >> 1)  // address for device is 8 bit but shift to the
// right by 1 bit to make it 7 bit because the
// wire library only takes in 7 bit addresses
#define ADXL345_REGISTER_XLSB (0x32)

float Angle;      // угол поворота мотора
float prev_Angle; // временная переменная для угла
float value; // промежуточное значение Y

int accelerometer_data[3];
// void because this only tells the chip to send data to its output register
// writes data to the slave's buffer
void i2c_write(int address, byte reg, byte data) {
  // Send output register address
  Wire.beginTransmission(address);
  // Connect to device
  Wire.write(reg);
  // Send data
  Wire.write(data); //low byte
  Wire.endTransmission();
}

// void because using pointers
// microcontroller reads data from the sensor's input register
void i2c_read(int address, byte reg, int count, byte* data) {
  // Used to read the number of data received
  int i = 0;
  // Send input register address
  Wire.beginTransmission(address);
  // Connect to device
  Wire.write(reg);
  Wire.endTransmission();
  // Connect to device
  Wire.beginTransmission(address);
  // Request data from slave
  // Count stands for number of bytes to request
  Wire.requestFrom(address, count);
  while (Wire.available()) // slave may send less than requested
  {
    char c = Wire.read(); // receive a byte as character
    data[i] = c;
    i  ;
  }
  Wire.endTransmission();
}

void init_adxl345() {
  byte data = 0;
  i2c_write(ADXL345_ADDRESS, 0x31, 0x0B);   // 13-bit mode   - 16g
  i2c_write(ADXL345_ADDRESS, 0x2D, 0x08);   // Power register
  i2c_write(ADXL345_ADDRESS, 0x1E, 0x00);   // X
  i2c_write(ADXL345_ADDRESS, 0x1F, 0x00);   // Y
  i2c_write(ADXL345_ADDRESS, 0x20, 0x05);   // Z
  // Проверка работоспособности
  i2c_read(ADXL345_ADDRESS, 0X00, 1, &data);
  if (data == 0xE5)
    Serial.println("It works well!");
  else
    Serial.println("Failure... :(");
}

void read_adxl345() {
  byte bytes[6];
  memset(bytes, 0, 6);
  // Чтение шести байтов из ADXL345
  i2c_read(ADXL345_ADDRESS, ADXL345_REGISTER_XLSB, 6, bytes);
  // Распаковка данных
  for (int i = 0; i < 3;   i) {
    accelerometer_data[i] = (int)bytes[2 * i]   (((int)bytes[2 * i   1]) << 8);
  }
}

void setup() {
  motor.attach(9); // Прицепили серво-мотор (9 or 10)
  Wire.begin();
  Serial.begin(9600);
  for (int i = 0; i < 3;   i)   {
    accelerometer_data[i]  = 0;
  }
  init_adxl345();
}

void react() {
  // Теперь посылаем данные в мотор
  // Angle = map(value, 0, 1.0, 0, 180); // диапазон акселерометра отображается на 0..180 или 0..20 градусов
  Angle = value * 180.0;
  // Angle = constrain(Angle, 1, 180); // ограничиваем значения диапазоном от 1 до 180

  Serial.print("t");
  Serial.print("Угол: ");
  Serial.print(Angle);
  Serial.println("t");
  if (Angle != prev_Angle)
  {
    motor.write(Angle); // установить угол поворота мотора
    prev_Angle = Angle; // запомнить текущий угол
  }
}

void loop() {
  read_adxl345();
  Serial.print("ACCEL: ");
  Serial.print(float(accelerometer_data[0]) * 3.9 / 1000); // 3.9mg/LSB scale factor in 13-bit mode
  Serial.print("t");
  Serial.print(float(accelerometer_data[1]) * 3.9 / 1000);
  Serial.print("t");
  Serial.print(float(accelerometer_data[2]) * 3.9 / 1000);
  Serial.print("n");

  // value = float((accelerometer_data[1]) * 3.9 / 1000);

  value = atan2(float((accelerometer_data[1]) * 3.9 / 1000), float((accelerometer_data[0]) * 3.9 / 1000));
  if ( (value > 0) && (value < 1.0)) {
    react ();
   }
  delay(100);
}


§

Смотрите про коптеры:  Колонка JBL инструкция на русском, как включить и пользоваться: описываем по порядку

Типовые характеристики дисплея следующие
Display Capacity: 16 × 2 characters.
Chip Operating Voltage: 4.5 ~ 5.5V.
Working Current: 2.0mA (5.0V).
Optimum working voltage of the module is 5.0V.
Character Size: 2.95 * 4.35 (W * H) mm.

Это схема подключения Arduino Uno и микроконтроллерного модуля Mega 2560.

 

 

Для проведения тестов можно использовать следующий листинг программы

/* __________________
   1602 LCD 8-bit bus control
   __________________ */

int DI = 12;
int RW = 11;
int DB[] = {3, 4, 5, 6, 7, 8, 9, 10}; // use array to select pin for bus
int Enable = 2;

void LcdCommandWrite(int value) {
  // define all pins
  int i = 0;
  for (i = DB[0]; i <= DI; i  ) // assign value for bus
  {
    digitalWrite(i, value & 01); // for 1602 LCD, it uses D7-D0( not D0-D7) for signal identification; here, itΓÇÖs used for signal inversion.
    value >>= 1;
  }
  digitalWrite(Enable, LOW);
  delayMicroseconds(1);
  digitalWrite(Enable, HIGH);
  delayMicroseconds(1);  // wait for 1ms
  digitalWrite(Enable, LOW);
  delayMicroseconds(1);  // wait for 1ms
}

void LcdDataWrite(int value) {
  // initialize all pins
  int i = 0;
  digitalWrite(DI, HIGH);
  digitalWrite(RW, LOW);
  for (i = DB[0]; i <= DB[7]; i  ) {
    digitalWrite(i, value & 01);
    value >>= 1;
  }
  digitalWrite(Enable, LOW);
  delayMicroseconds(1);
  digitalWrite(Enable, HIGH);
  delayMicroseconds(1);
  digitalWrite(Enable, LOW);
  delayMicroseconds(1);  // wait for 1ms
}

void setup (void) {
  int i = 0;
  for (i = Enable; i <= DI; i  ) {
    pinMode(i, OUTPUT);
  }
  delay(100);
  // initialize LCD after a brief pause
  // for LCD control
  LcdCommandWrite(0x38);  // select as 8-bit interface, 2-line display, 5x7 character size
  delay(64);
  LcdCommandWrite(0x38);  // select as 8-bit interface, 2-line display, 5x7 character size
  delay(50);
  LcdCommandWrite(0x38);  // select as 8-bit interface, 2-line display, 5x7 character size
  delay(20);
  LcdCommandWrite(0x06);  // set input mode
  // auto-increment, no display of shifting
  delay(20);
  LcdCommandWrite(0x0E);  // display setup
  // turn on the monitor, cursor on, no flickering
  delay(20);
  LcdCommandWrite(0x01);  // clear the scree, cursor position returns to 0
  delay(100);
  LcdCommandWrite(0x80);  //  display setup
  //  turn on the monitor, cursor on, no flickering
  delay(20);
}

void loop (void) {
  LcdCommandWrite(0x01);  // clear the screen, cursor position returns to 0
  delay(10);
  LcdCommandWrite(0x80   3);
  delay(10);
  // Show welcome message
  LcdDataWrite('W');
  LcdDataWrite('e');
  LcdDataWrite('l');
  LcdDataWrite('c');
  LcdDataWrite('o');
  LcdDataWrite('m');
  LcdDataWrite('e');
  LcdDataWrite(' ');
  LcdDataWrite('t');
  LcdDataWrite('o');
  delay(10);
  LcdCommandWrite(0xc0   1); // set cursor position at second line, second position
  delay(10);
  LcdDataWrite('M');
  LcdDataWrite('G');
  LcdDataWrite('T');
  LcdDataWrite('U');
  LcdDataWrite('-');
  LcdDataWrite('w');
  LcdDataWrite('o');
  LcdDataWrite('r');
  LcdDataWrite('k');
  LcdDataWrite('s');
  LcdDataWrite('h');
  LcdDataWrite('o');
  LcdDataWrite('p');
  delay(3300);
  LcdCommandWrite(0x01);  // clear the screen, cursor returns to 0
  delay(10);
  LcdDataWrite('I');
  LcdDataWrite(' ');
  LcdDataWrite('a');
  LcdDataWrite('m');
  LcdDataWrite(' ');
  LcdDataWrite('a');
  LcdDataWrite(' ');
  LcdDataWrite('b');
  LcdDataWrite('o');
  LcdDataWrite('s');
  LcdDataWrite('s');
  delay(3000);
  LcdCommandWrite(0x02); // set mode as new characters replace old ones, where there is no new ones remain the same
  delay(10);
  LcdCommandWrite(0x80   5); // set cursor position at first line, sixth position
  delay(10);

  LcdDataWrite('V');
  LcdDataWrite('.');
  delay(220);
  LcdDataWrite('E');
  delay(220);
  LcdDataWrite('.');
  delay(220);
  LcdDataWrite(' ');
  LcdDataWrite('D');
  delay(220);
  LcdDataWrite('r');
  delay(220);
  LcdDataWrite('a');
  delay(220);
  LcdDataWrite('c');
  delay(220);
  LcdDataWrite('h');
  delay(5000);
}

После прошивки мы можем наблюдать, что на дисплее появляется текст

 

В результате мы видим пример жидкокристаллического дисплея

Как настроить Bluetooth в старом и новом автомобиле

Это решение имеет очевидный недостаток – чрезвычайно интенсивное использование линий ввода/вывода микроконтроллера. Подключение 4-битной шины позволит уменьшить количество необходимых выводов.

Схема электропитания робота автомобиля

Адекватный источник питания – один из самых важных аспектов любого проекта. В нашей модели используется рекомендованная нами схема питания на основе литий-ионных аккумуляторов формата 18650 и платы их защиты от перегрузки и перезарядки.

Мы рассмотрим самый простой способ питания электродвигателей. Чтобы облегчить сборку, перед началом работы припаяйте провода к двигателям.

Схема ардуино робота машинки 2
Схема питания и подключения двигателей в ардуино автомобиле

Это стандартная схема, и в Интернете можно найти десятки подобных примеров. Однако у этой схемы есть существенный недостаток – если батареи полностью разрядятся, они станут бесполезными.

Машинка на Ардуино
Машинка на Ардуино

Для включения регулятора разряда схема должна быть модифицирована следующим образом:

Схема ардуино робота машинки 3
Схема питания с контролем разряда аккумулятора

Теперь батареи будут защищены, но зарядка не может быть произведена.

Питание ардуино
Питание робота Ардуино

Если вы хотите зарядить аккумуляторы, можно использовать модуль повышения напряжения с 5 В до нужного уровня, в зависимости от количества используемых аккумуляторов. Устройство поставляется только с одним портом micro USB, и при частом использовании он может сломаться, поэтому мы рекомендуем добавить дополнительный разъем для последующей зарядки пятивольтовым источником питания. При использовании выходного напряжения два литий-ионных аккумулятора должны заряжаться при напряжении 8,4 В.

Схема питания ардуино робота машинки
Схема питания с модулем зарядки для ардуино робота машинки

Технология bluetooth в автомобиле

Наша жизнь становится все более цифровой и беспроводной. Мыши и клавиатуры для ПК больше не должны быть проводными. Функция Bluetooth на смартфонах позволяет пользователям подключаться к наушникам или беспроводной колонке.

Технология Bluetooth в автомобиле

Кроме того, автомобильная промышленность продолжает развиваться. Многие новые автомобили оснащены Bluetooth, поэтому вы можете легко передавать музыку с телефона на динамики автомобиля, подключив телефон к Bluetooth автомобиля.

Сопряжение Bluetooth сохраняет данные при обмене информацией между двумя устройствами. Между двумя устройствами существует соединение, которое регистрирует данные. Сопряжение устройств Bluetooth (в нашем случае телефона) требует сопряжения их с другим устройством (в нашем случае автомобилем). Радиус действия Bluetooth составляет 10-15 метров. Сопряженные смартфон и автомобиль с поддержкой Bluetooth будут переподключаться при переходе от квартиры к автомобилю. В автомобиле никаких дополнительных процедур не потребуется. Оба устройства хранят в своей памяти необходимые данные для быстрого соединения. Вы можете держать смартфон на лобовом стекле с помощью автомобильного держателя телефона на присоске. Поместите смартфон в держатель. Установите смартфон в удобном для вас положении.

Технология Bluetooth в автомобиле 3

Как вы можете установить с ними связь? Все очень просто. Самое главное, чтобы Bluetooth был включен в настройках оборудования автомобиля и чтобы вы выполнили поиск устройств Bluetooth на своем смартфоне. Выберите из списка устройство, название которого более похоже на марку вашего автомобиля. При сопряжении смартфон, скорее всего, запросит пароль, обычно простой, например “1234” или “0000”.

Ваш смартфон может воспроизводить и музыку. Установив приложение “Яндекс Навигатор”, вы сможете путешествовать в безопасности, слушая подсказки через акустику вашего смартфона. Большинство смартфонов оснащены модулями GPS или ГЛОНАСС.

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

U X не менее полезен, поэтому вам не нужен интерфейс Bluetooth, если в вашем автомобиле есть AUX. Имеется адаптер “Bluetooth to AUX”. Телефон с Bluetooth (или любое другое устройство) может общаться с этим адаптером через AUX, преобразуя аудиосигналы через Bluetooth. Недорогое устройство, подобное этому, позволит вам делать все вышеперечисленное (и даже больше) с помощью вашего смартфона.

В конце концов, мир не стоит на месте. С каждым днем он развивается все больше и больше, совершается множество открытий и изобретений, и все они – для нашего удобства. Важно соответствовать требованиям времени, чтобы жизнь была более приятной!

Оцените статью
Радиокоптер.ру
Добавить комментарий

Adblock
detector