Роботизированная машина на Arduino, управляемая по Bluetooth: схема и программа

Роботизированная машина на Arduino, управляемая по Bluetooth: схема и программа Мультикоптеры

Основная активность, сопряжение arduino и android

Возьмем класс AppCompatActivity и объявим переменные:

publicclassMainActivityextendsAppCompatActivity{
        private BluetoothAdapter bluetoothAdapter;
        private ListView listView;
        private ArrayList<String> pairedDeviceArrayList;
        private ArrayAdapter<String> pairedDeviceAdapter;
        publicstatic BluetoothSocket clientSocket;
        private Button buttonStartControl;
}

Метод onCreate() опишу построчно:

@OverrideprotectedvoidonCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     
     Button buttonStartFind = (Button) findViewById(R.id.button_start_find); 
     
     listView = (ListView) findViewById(R.id.list_device); 
      
     
     buttonStartFind.setOnClickListener(new View.OnClickListener() { 
                                                                                                    
         @OverridepublicvoidonClick(View v){
             if(permissionGranted()) { 
               
                bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
                if(bluetoothEnabled()) { 
                    findArduino(); 
                  }
              }
         }
    });

     
     buttonStartControl = (Button) findViewById(R.id.button_start_control); 
     buttonStartControl.setOnClickListener(new View.OnClickListener() {
         @OverridepublicvoidonClick(View v){
                
                Intent intent = new Intent(); 
                
                intent.setClass(getApplicationContext(), ActivityControl.class);
                
                startActivity(intent); 
         }
     });

 }


Нижеприведенные функции проверяют, получено ли разрешение на использование блютуза (без разрешение пользователя мы не сможем передавать данные) и включен ли блютуз:

↑ что нам потребуется для сборки машинки?

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

Смотрите про коптеры:  Робот на Ардуино и машинка на Bluetooth своими руками - ArduinoMaster все об Ардуино

2. Bluetooth–модуль «HC-06» .

Управление машиной осуществляется дистанционно через канал Bluetooth. “HC-06” – это Bluetooth-мост, последовательный интерфейс, обеспечивающий двустороннюю передачу данных. Входами являются сигналы TTL последовательного интерфейса “RxD” и “TxD” для подключения к микроконтроллеру (целевой плате).

Пульт дистанционного управления будет представлять собой мобильный телефон под управлением Android. Давайте напишем нашу собственную программу!

3. Драйвер двигателя TB6612FNG является двухканальным.

Каждая пара колес имеет двухканальный драйвер. Логические входы позволяют драйверу изменять генерируемую полярность (направление вращения), а входы ШИМ позволяют управлять скоростью вращения.

4. Плата управления MOD-IO (Olimex)

Плата была выбрана, поскольку она уже некоторое время лежала в ящике стола и отлично подходит для наших целей. Для “HC-06” будут использоваться дискретные вход и выход, “RxD” и “TxD”.

Скажу, что, на мой взгляд, Olimex MOD-IO – это поиск методом грубой силы. Было бы вполне возможно использовать обычные

, о чём в продолжении истории!

Программное обеспечение для управления модулями Bluetooth для карт управления шасси.

↑ будем строить машинку с ду!

Игрушки с радиоуправлением практичны и техничны. Однако детям в возрасте 4-6 лет не стоит давать игрушки со “взрослым” пропорциональным управлением. Почти наверняка игрушка будет сломана, а деньги выброшены на ветер.

В итоге обычно получается что-то дешевое. При всей этой “дешевизне”, машины слишком быстрые или слишком медленные, танки слабые, и другие явные и скрытые недостатки. И конечно

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

В местном радиомагазине ничего подходящего не нашлось. Мои поиски микросхемного чуда привели меня в далекий край. Закончив упаковку, я набил карманы сухарями, налил себе чашку кофе, вошел в систему и поехал. Aliexpress. Я нашел подходящий по параметрам драйвер двигателя и заказал сразу два.

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

↑ передача пакета данных

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

structTxPacket
{uint8_t StartByte;
	uint8_t Rc5System;
	uint8_t Rc5Command;
	uint8_t StopByte;
} TxPacket;

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

voidsend_packet()
{
	// Запись стартового байта в регистр UDR
	UDR = START_BYTE;
}

В данном примере, в этой функции, я записываю только стартовый байт в регистр UDR. Вроде бы немного, но в этой же функции можно реализовать подготовку пакета или еще что-то полезное. И это, на мой взгляд более логично. Логично в плане самодокументирования кода. То есть, если я в коде, просто запишу значение в регистр UDR это может быть воспринято, как передача всего одного байта, а вызывая самоговорящую функцию
send_packet ()
 — я говорю о том, что я отправляю пакет данных.

Затем, когда передатчик USART отправит весь байт из регистра UDR, будет вызван обработчик прерывания для обработки передачи.

ISR(USART_TXC_vect)
{
	unsignedchar *Pointer = (unsignedchar *)&(TxPacket);

	staticunsignedchar TxIndex = 1;

	if ( TxIndex < sizeof(TxPacket) )
	{
		UDR = *(Pointer   TxIndex);
		TxIndex  ;
	}
	else TxIndex = 1;
}

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

Условие

if ( TxIndex < sizeof(TxPacket) )

Проверяет, не меньше ли индекс, чем размер пакета. Условие истинно, если мы записываем байт в регистр UDR:

UDR = *(Pointer   TxIndex);

Плата была выбрана, поскольку она уже некоторое время лежала в ящике стола и отлично подходит для наших целей. Для “HC-06” будут использоваться дискретные вход и выход, “RxD” и “TxD”.

else TxIndex = 1;

TxIndex будет инициализирован, но данные UDR не записываются. Это означает, что обработчик не будет вызван снова до тех пор, пока не будет инициирована следующая передача пакета. Процесс полностью автоматический, и даже если структура пакета изменится, нам не нужно будет переписывать обработчик.

В рамках описания программы МК будет рассмотрено управление драйверами. Драйверы управляются тремя сигналами: A1 (B1), A2 (B2) и PWMA (PWMB). С помощью регуляторов A1 и A2 можно включить/выключить драйвер и изменить полярность выхода. Используя вход PWMA, MCU подает сигнал ШИМ для управления скоростью вращения. ШИМ-сигнал генерируется с помощью двух аппаратных ШИМ-таймеров 1.

#define _WGM13 0#define _WGM12 1#define _WGM11 0#define _WGM10 1// Timer 1 init
TCCR1A = ( 1 << COM1A1 ) | ( 0 << COM1A0 ) | ( 1 << COM1B1 ) |
 ( 0 << COM1B0 ) | ( _WGM11 << WGM11 ) | ( _WGM10 << WGM10 );
TCCR1B = ( 0 << CS12 ) | ( 0 << CS11 ) | ( 1 << CS10 ) |
			 ( _WGM13 << WGM13 ) | ( _WGM12 << WGM12 );

	TCNT1 =0x0000;
	OCR1A = 0;
	OCR1B = 0;

В первую очередь, он был создан программой Android. Как выяснилось, в Java нет беззнаковых типов, и я уже наступил на эти грабли. Если бы я хотел передать число от 0 до 255, мне пришлось бы извращаться. Для простоты я решил передать 16-битное знаковое число. Следовательно, 16 бит знакового типа (от -32786 до 32768) в данном случае вполне достаточно.

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

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

Написана функция привода (int leftPWM, int rightPWM); для управления приводом.

void drive(int leftPWM, int rightPWM)
{
	// Движение ВПЕРЁД левое колесо
	if ( leftPWM > 0 ){
		ClearBit( A2_PORT, A2_PIN );
		SetBit( A1_PORT, A1_PIN );
	}
	// Движение НАЗАД левое колесо
	if ( leftPWM < 0 ){
		ClearBit( A1_PORT, A1_PIN );
		SetBit( A2_PORT, A2_PIN );
	}
	// Движение ВПЕРЁД правое колесо
	if ( rightPWM > 0 ){
		ClearBit( B2_PORT, B2_PIN );
		SetBit( B1_PORT, B1_PIN );
	}
	// Движение НАЗАД правое колесо
	if ( rightPWM < 0 ){
		ClearBit( B1_PORT, B1_PIN );
		SetBit( B2_PORT, B2_PIN );
	}
	// Остановка
	if ( leftPWM == 0 ){
		ClearBit( A1_PORT, A1_PIN );
		ClearBit( A2_PORT, A2_PIN );
	}
	// Остановка
	if ( rightPWM == 0 ){
		ClearBit( B1_PORT, B1_PIN );
		ClearBit( B2_PORT, B2_PIN );
	}

	set_PWM( (uint8_t)(abs(leftPWM)), (uint8_t)(abs(rightPWM)) );
}

В соответствии со значением ШИМ, осуществляется управление сигналами A1 (B1), A2 (B2) и устанавливается значение ШИМ вызовом функции
set_PWM (leftPWM, rightPWM)

Уфф, измучился. Вот как все происходило: мы получили посылку, разобрали ее и передали значение ШИМ в функцию привода.

↑ приём пакета данных

Кольцевой буфер заполняется автоматически байтом, который принимается в функции обработчика прерывания USART. Разбор пакета будет выполнен позже.

ISR(USART_RXC_vect)
{
	uint8_t Data = UDR;
	RB_push_char( Data );	// Складываем принятый байт в кольцевой буфер
}

До сих пор я пренебрегал всеми проверками рам.

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

ISR(TIMER0_OVF_vect)
{
	TCNT0 = 0x64;
	ReadRingBuffer = 1;
}

Проверяем флаг в главном цикле.

if ( ReadRingBuffer )
{
if ( RB_read_buffer((uint8_t*)&RxPacket) == 1 ) Чтение буфера
			{
                                          // Разбираем пакет, делаем что-нибудь
			}
			ReadRingBuffer = 0;
		}

Она проверяет кольцевой буфер, чтобы убедиться, что размер пакета, начальный и конечный байты находятся в соответствующих местах – если это так, то пакет действителен, и функция возвращает “1” (пакет действителен). В качестве аргумента функция принимает указатель, куда следует поместить полученный пакет.

↑ программа микроконтроллера

Программа М С понимает, как модуль Bluetooth передает команды через последовательный интерфейс.

И управляйте левой и правой парами приводов в соответствии с инструкциями. Управление скоростью и реверсом осуществляется с помощью ШИМ.

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

Я поместил функции кольцевого буфера в отдельную библиотеку, состоящую из: заголовочного файла ring_buffer.h и файла реализации функций ring_buffer.c Для использования библиотеки она должна быть включена в файл main.c

#include"ring_buffer.h"

Далее необходимо сконфигурировать библиотеку в заголовочном файле. Необходимо настроить только четыре директивы:

#define RX_PACKET_SIZE		7	// Размер RxD пакета#define BUFFER_SIZE			16	// Размер приёмного буфера. Должен быть в два раза больше RX_PACKET_SIZE#define START_BYTE			's'// Стартовый байт#define STOP_BYTE			'e'// Стоповый байт

На самом деле больше ничего устанавливать не нужно.

Изменив код в файле main.c, мы конфигурируем USART микроконтроллера.

USART_Init(MYUBRR);
#define BAUD 9600#define MYUBRR F_CPU/16/BAUD-1voidUSART_Init( unsignedint ubrr ){
	/* Set baud rate */
	UBRRH = (unsignedchar)( ubrr >> 8 );
	UBRRL = (unsignedchar)ubrr;
	/* Enable receiver and transmitter */
	UCSRB = (1 << TXCIE) | (1 << RXCIE)| (1 << TXEN) | (1 << RXEN);
	/* Set frame format: 8data, 2stop bit */
	UCSRC = (1 << URSEL) | (0 << USBS) | (3 << UCSZ0);
}

Cxemcar на arduino – bluetooth управление машинкой с android

#include “EEPROM.h”

#define D1 2 // направление вращения двигателя 1.

” M1 3″ // ШИМ-выход для управления двигателем 1 (слева)

Определите D2 4 как “направление вращения 2”

Направление двигателя 2 (правостороннее) определяется M2 5 (#define).

#define HORN 13       // доп. канал 1 подключен к 13 пину

#define cmdL ‘L’ // Команда UART для левого двигателя

#define cmdR ‘R’      // команда UART для правого двигателя

#define cmdH ‘H’      // команда UART для доп. канала 1 (к примеру сигнал Horn)

#define cmdF ‘F’ // команда UART для работы с памятью EEPROM микросхемы для хранения настроек

#define cmdr ‘r’ // работаем с памятью EEPROM микросхемы для считывания настроек

Cmdw ‘w’ // Используйте команду UART (запись) для доступа к памяти EEPROM (чтение) микроконтроллера для сохранения настроек.

charincomingByte;   

charL_Data[4];      

byteL_index = 0;    

charR_Data[4];      

byteR_index = 0;    

charH_Data[1];      

byteH_index = 0;    

charF_Data[8];      

byteF_index = 0;    

Шаркоман

unsignedlongcurrentTime, lastTimeCommand, autoOFF;

voidsetup() {

  Serial.begin(9600);      

  pinMode(HORN, OUTPUT);   

  pinMode(D1, OUTPUT);     

  pinMode(D2, OUTPUT);     

  timer_init();            

}

voidtimer_init() {

  uint8_t sw_autoOFF = EEPROM.read(0);  

  if(sw_autoOFF == ‘1’){                

    charvar_Data[3];

    var_Data[0] = EEPROM.read(1);

    var_Data[1] = EEPROM.read(2);

    var_Data[2] = EEPROM.read(3);

    autoOFF = atoi(var_Data)*100;       

  }

  elseif(sw_autoOFF == ‘0’){        

    autoOFF = 999999;

  }

  elseif(sw_autoOFF == 255){

    autoOFF = 2500;                     

  }

  currentTime = millis();               

}

voidloop() {

  if(Serial.available() > 0) {         

Полученный байт = Serial.read();

Если (входящий байт == cmdL) {

      command = cmdL;                   

      memset(L_Data,0,sizeof(L_Data));  

      L_index = 0;                      

    }

    elseif(incomingByte == cmdR) {     

      command = cmdR;

      memset(R_Data,0,sizeof(R_Data));

      R_index = 0;

    }

Elseif(входящийБайт == cmdH) {

      command = cmdH;

      memset(H_Data,0,sizeof(H_Data));

Индикация_Н = 0

    }   

    elseif(incomingByte == cmdF) {     

      command = cmdF;

      memset(F_Data,0,sizeof(F_Data));

Показатель_F = 0 ;

    }

    elseif(incomingByte == ‘r’) command = ‘e’;  

    elseif(incomingByte == ‘t’) command = ‘t’;  

    if(command == cmdL && incomingByte != cmdL){

L_Dane[L_index] = входящийБайт;

      L_index ;                                  

    }

    elseif(command == cmdR && incomingByte != cmdR){

R_Data[R_index] = входящий байт;

      R_index ;

    }

    elseif(command == cmdH && incomingByte != cmdH){

H_Data[H_index] = ВходящийБайт;

      H_index ;

    }   

    elseif(command == cmdF && incomingByte != cmdF){

F_Data [F_index] = входящийБайт ;

      F_index ;

    }   

    elseif(command == ‘e’){                      

      Control4WD(atoi(L_Data),atoi(R_Data),atoi(H_Data));

      delay(10);

    }

    elseif(command == ‘t’){                      

      Flash_Op(F_Data[0],F_Data[1],F_Data[2],F_Data[3],F_Data[4]);

    }

    lastTimeCommand = millis();                   

  }

  if(millis() >= (lastTimeCommand autoOFF)){    

    Control4WD(0,0,0);                            

  }

}

voidControl4WD(intmLeft, intmRight, uint8_t Horn){

  bool directionL, directionR;     

  bytevalueL, valueR;             

  if(mLeft > 0){

    valueL = mLeft;

    directionL = 0;

  }

  elseif(mLeft < 0){

    valueL = 255 – abs(mLeft);

    directionL = 1;

  }

Эллеры{

    directionL = 0;

    valueL = 0;

  }

  if(mRight > 0){

    valueR = mRight;

    directionR = 0;

  }

  elseif(mRight < 0){

    valueR = 255 – abs(mRight);

    directionR = 1;

  }

Если нет{.

    directionR = 0;

    valueR = 0;

  }

  analogWrite(M1, valueL);           

  analogWrite(M2, valueR);           

  digitalWrite(D1, directionL);      

  digitalWrite(D2, directionR);      

  digitalWrite(HORN, Horn);          

}

voidFlash_Op(charFCMD, uint8_t z1, uint8_t z2, uint8_t z3, uint8_t z4){

  if(FCMD == cmdr){          

    Serial.print(“FData:”);      

    Serial.write(EEPROM.read(0));    

    Serial.write(EEPROM.read(1));

    Serial.write(EEPROM.read(2));

    Serial.write(EEPROM.read(3));

    Serial.print(“rn”);        

  }

  elseif(FCMD == cmdw){         

    EEPROM.write(0,z1);              

    EEPROM.write(1,z2);

    EEPROM.write(2,z3);

    EEPROM.write(3,z4);

    timer_init();            

    Serial.print(“FWOKrn”);        

  }

}

Выбор моделей для покупки

Помимо продаж через официальные магазины и дистрибьюторские сети, многие производители предлагают свою продукцию по выгодной цене на ]]>Amazon, поскольку эта онлайн-площадка славится огромным притоком посетителей и старается поддерживать высокий уровень обслуживания (например, ]]>только об этом и стоит упомянуть).

Более подробно о Amazon Prime рассказывается в нашей статье). По отзывам посетителей на этом сайте легко сделать выводы о качестве продукции того или иного бренда. Самостоятельный поиск автомобилей и роверов, управляемых с помощью Android или iOS, выявит довольно много отрицательных отзывов.

Модели, управляемые по радио, не оправдывают ожиданий пользователей. Для этого мы отобрали продукты от производителей, которые, по нашему мнению, заслуживают доверия: ZenWheels, Silverlit, ]]>. “.

One ZenWheels Micro Rc Car

Компания ZenWheels производит миниатюрные автомобили с Bluetooth-управлением. Неожиданно, но их продукция не ориентирована исключительно на детей! Именно реечное рулевое управление обеспечивает плавность хода и высокую маневренность движущегося гаджета.

Кроме того, у крошечных машинок есть работающие поворотники, фары и звуковые сигналы (включая аварийные). Один ZenWheels Micro Rc Car выделяется среди других радиоуправляемых автомобилей благодаря своим приятным деталям.

Драйвер двигателей

Драйвер двигателя L298N
Драйвер двигателя L298N

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

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

Исходный код программы

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

В функции настройки (для вывода данных) необходимо задать направление работы этих контактов.

Далее мы прочитаем данные из последовательного порта Arduino, которые послал ему модуль Bluetooth, и выполним соответствующие инструкции.

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

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

Конструкция, шасси и двигатели робота на ардуино

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

Двигатель шасси ардуино
Двигатель, шасси и колеса машинки на ардуино

Даже если вы не хотите работать со стандартными наборами, вы можете создать платформу самостоятельно. Снимите шестеренки и коробку передач с игрушечных радиоуправляемых машинок или других моторов на 5-12 вольт. Колеса можно создать самостоятельно, что тоже интересно.

Метод loop() и дополнительные функции


В постоянно повторяющемся методе loop() происходит считывание данных. Сначала рассмотрим основной алгоритм, а потом функции, задействованные в нем.


void loop() {
  //если хоть несчитанные байты
  if(BTSerial.available() > 0) {
     //считываем последний несчитанный байт
     char a = BTSerial.read();
     
    if (a == '@') {
      //если он равен @ (случайно выбранный мною символ)
      //обнуляем переменную val
      val = "";
      //указываем, что сейчас считаем скорость
      readSpeed = true;

    } else if (readSpeed) {
      //если пора считывать скорость и байт не равен решетке
      //добавляем байт к val
      if(a == '#') {
        //если байт равен решетке, данные о скорости кончились
        //выводим в монитор порта для отладки
        Serial.println(val);
        //указываем, что скорость больше не считываем
        readSpeed = false;
        //передаем полученную скорость в функцию езды 
        go(val.toInt());
        //обнуляем val
        val = "";
        //выходим из цикла, чтобы считать следующий байт
        return;
      }
      val =a;
    } else if (a == '*') {
      //начинаем считывать угол поворота
      readAngle = true; 
    } else if (readAngle) {
      //если решетка, то заканчиваем считывать угол
      //пока не решетка, добавляем значение к val
      if(a == '#') {
       Serial.println(val);
       Serial.println("-----");
        readAngle = false;
        //передаем значение в функцию поворота
        turn(val.toInt());
        val= "";
        return;
      }
      val =a;
    }
    //получаем время последнего приема данных
    lastTakeInformation = millis();
  } else {
     //если несчитанных байтов нет, и их не было больше 150 миллисекунд 
     //глушим двигатели
     if(millis() - lastTakeInformation > 150) {
     lastTakeInformation = 0;
     analogWrite(angleSpeed, 0);
     analogWrite(speedRight, 0);
     analogWrite(speedLeft, 0);
     }
     
  }
}

С телефона мы отправляем байты в формате “@скорость#угол#” (например, типичная команда – “@200#60#”). Цикл повторяется каждые 100 миллисекунд, поскольку это интервал, который андроид устанавливает для отправки команд. Нет причин делать его короче, потому что они будут стоять в очереди, а если сделать его длиннее, колеса начнут двигаться рывками.

В следующем уроке вы увидите, что все задержки через delay() были выбраны не по физико-математическим расчетам, а на основе опыта. Все установленные задержки позволяют машине работать плавно, и все команды успевают выполняться (токи успевают протекать).

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

void go(int mySpeed) {
  //если скорость больше 0
  if(mySpeed > 0) {
  //едем вперед
  digitalWrite(dirRight, HIGH);
  analogWrite(speedRight, mySpeed);
  digitalWrite(dirLeft, HIGH);
  analogWrite(speedLeft, mySpeed);
  } else {
    //а если меньше 0, то назад
    digitalWrite(dirRight, LOW);
    analogWrite(speedRight, abs(mySpeed)   30);
    digitalWrite(dirLeft, LOW);
     analogWrite(speedLeft, abs(mySpeed)   30);
  }
  delay(10);
 
}

void turn(int angle) {
  //подаем ток на плюс определителя угла
  digitalWrite(pinAngleStop, HIGH);
  //даем задержку, чтобы ток успел установиться
  delay(5);
  
  //если угол 150 и больше, поворачиваем вправо 
  //если 30 и меньше, то влево 
  //промежуток от 31 до 149 оставляем для движения прямо
  if(angle > 149) {
        //если замкнут белый, но разомкнуты  черный и красный
        //значит достигнуто крайнее положение, дальше крутить нельзя
        //выходим из функции через return 
        if( digitalRead(pinWhite) == HIGH && digitalRead(pinBlack) == LOW && digitalRead(pinRed) == LOW) {
          return;
        }
        //если проверка на максимальный угол пройдена
        //крутим колеса
        digitalWrite(angleDirection, HIGH);
        analogWrite(angleSpeed, speedTurn);
  } else if (angle < 31) { 
        if(digitalRead(pinRed) == HIGH && digitalRead(pinBlack) == HIGH && digitalRead(pinWhite) == HIGH) {
          return;
        }
        digitalWrite(angleDirection, LOW);
        analogWrite(angleSpeed, speedTurn);
  }
  //убираем питание 
  digitalWrite(pinAngleStop, LOW);
  delay(5);
}

В большинстве случаев не следует поворачивать, когда андроид отправляет данные о том, что он нажал на угол 60, 90 или 120, иначе вы не сможете двигаться прямо. Да, возможно, вам не следовало бы сразу посылать команду поворота с андроида, если угол слишком мал, но я думаю, что это довольно муторно.

Настройки приложения

Скриншот настроек Android приложения CxemCar версии 1.0:

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

Точка вращения двигателя (ось Х)

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

MAC адрес

Установка MAC-адреса в настройках приложения необходима для того, чтобы установить связь с модулем Bluetooth. Ранее необходимо было настроить сопряжение в настройках Android-устройства. Для этого откройте Настройки -> Bluetooth и выберите “Поиск устройств”, появится наш Bluetooh-модуль, нажмите на него и введите пароль (обычно 1234).

Определить Bluetooth-адрес модуля можно с помощью приложения, например, Bluetooth Terminal. Для этого нажмите внизу “Подключение устройства – Безопасное”, затем в появившемся окне “Сканировать устройства”. При сканировании Bluetooth-устройств с помощью программы будут отображены MAC-адреса устройств:

Вы должны ввести MAC-адрес в настройках программы CxemCAR.

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

Общие принципы управления машиной по bluetooth

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

Конструктивно модуль Bluetooth состоит из двух блоков: модуля последовательного интерфейса (для последовательной передачи данных) и адаптера Bluetooth. Модуль последовательного интерфейса создан для преобразования данных Bluetooth в данные, которые могут быть переданы через последовательный порт.

Если вы приобрели модуль Bluetooth в магазине, нет необходимости изменять его настройки – он полностью функционален. По умолчанию скорость передачи данных составляет 9600 бод/с. Подключите его контакты rx и tx к микроконтроллеру и подайте постоянное напряжение 5 вольт.

В модулях Bluetooth существует два режима работы: режим ведущего и режим ведомого. С помощью соответствующих AT-команд можно установить любой из этих режимов. Ниже перечислены некоторые AT-команды.

Если вы используете этот модуль, первым шагом будет вход в режим AT на скорости 38400 бит/с путем нажатия кнопки EN на модуле Bluetooth или подачи сигнала высокого уровня на вывод EN. Завершите все команды клавишей rn (0x0d и 0x0a) или нажатием клавиши ENTER на клавиатуре.

Команда, отправленная на AT-модуль, будет выполнена модулем, и вы получите ответ OK.

AT → Test CommandAT ROLE=0 → Slave Mode select (выбор подчиненного режима)AT ROLE=1 → Master Mode select (выбор главного режима)AT NAME=xyz → Set Bluetooth Name (установка Bluetooth имени)AT PSWD=xyz → Set Password (установка пароля)AT UART=,, → set Baud rate (установка бодовой скорости)Eg. AT UART=9600,0,0

Распиновка модуля Bluetooth: 1. STATUS → Открыто) 2. Rx → Контакт последовательного приема3. Tx → Контакт последовательной передачи4. GND → Заземление (земля) 5. В пост. тока → 5 вольт пост. тока (5 В пост. тока)6. EN → для входа в режим AT

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

Часто в списке начинающих создателей Arduino правильная схема питания стоит на последнем месте. В настоящее время ошибки в схеме питания являются причиной большинства проблем, возникающих с интеллектуальными устройствами на 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 к ардуино машинке

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

Подключаем двигатели и плату

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

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

Ардуино робот драйвер
Драйвер двигателя для Ардуино робота

Затем установите держатель и плату BMC. Убедитесь, что вы оставили немного места спереди для последующего монтажа датчиков. То же самое относится и к модулю зарядного устройства для аккумуляторов. Для модулей зарядки аккумуляторов это одно и то же.

Питание для arduino и других электронных компонентов мы будем брать от драйвера двигателя.

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

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

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

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

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

Для реализации полного проекта требуется следующее оборудование:

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

Принцип работы

Наклоняясь или нажимая кнопку, Android генерирует команды для перемещения машины. Расчеты для левого и правого двигателей производятся в приложении Android, а значения ШИМ рассчитываются мгновенно. Приложение имеет гибкие настройки, такие как диапазон ШИМ, чувствительность к наклону, минимальный порог ШИМ и другие.

L255R120rL – левый двигатель, R указывает направление вращения для правого255 – номер ШИМ, для Arduino, максимальная скорость вращенияr – конец команды.

Такая команда, как L255rR-255r, заставит машину вращаться против часовой стрелки. При этом левый двигатель будет вращаться вперед, а правый – назад.

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

Приложение для Android позволяет пользователям установить командные символы L, R и H.

Когда двигатели отключаются по таймеру в программе контроллера, последняя команда была получена более n секунд назад. Настройка количества секунд хранится в EEPROM контроллера и может быть изменена с помощью устройства Android. В этом диапазоне вы найдете настройки от 0,1 секунды до 99,9 секунды.

Настройку также можно полностью отключить. Тем не менее, если связь нарушена, автомобиль будет продолжать работать до тех пор, пока не будет отключено питание. Wit

Простая bluetooth машинка на arduino

Широкая доступность и низкая стоимость платформ Arduino позволили любителям строить радиоуправляемые машины, соответствующие их предпочтениям. Мобильные телефоны сделали возможным управление этими машинами и с их помощью. Основной проблемой для многих любителей Arduino является отсутствие опыта в программировании под Android. Моя цель – показать вам, как можно легко решить эту проблему с помощью среды визуальной разработки приложений для Android App Inventor 2.

Постройку любой машинки надо начинать с «железа», поэтому вкратце опишу, что использовал для своей машинки:
arduino nano
bluetooth module HC-05
Z-Mini Motor Sensor Shield L293D
2WD Motor Chassis
Конфигурация «железа» не играет большой роли в этом проекте, поэтому шасси, шилд и саму ардуино можно заменить на любые аналоги.

Теперь пришло время создать приложение для Android. Среда разработки приложений для Android на основе браузера App Inventor. Нажмите “создать” и создайте новый проект. Чтобы получить доступ к своей учетной записи Google, войдите в систему. С помощью “Drag and Drop” создайте четыре кнопки для выбора направления движения и одну для подключения к ней нашего bluetooth-модуля. Примерно так:

image

Далее нажмите на кнопку “Блоки” в правом верхнем углу и перетащите логику для нашего приложения на экран, как показано на рисунке:

image

Теперь необходимо создать приложение, нажав на кнопку “Build”.

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

скетч

int val;

int IN1 = 4;

int IN2 = 7;

int EN1 = 6;

int EN2 = 5;

void setup()
{
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(EN1, OUTPUT);
pinMode(EN2, OUTPUT);

}
void loop()
{
if (Serial.available())
{
val = Serial.read();

// Задаём движение вперёд
if (val == ‘W’) // При нажатии клавиши «W»
{
// Выводы конфигурируются согласно работе Motor Shield’а
// Моторы крутятся вперед
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
}

// Задаём движение назад
if ( val == ‘S’)
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}

// Задаём движение вправо
if ( val == ‘D’)
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
}

// Задаём движение влево
if ( val == ‘A’)
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
}

// Стоп режим
// При отпускании клавиш в программе в порт шлется «T»
if ( val == ‘T’) // При нажатии клавиши «T»
{
// Выводы ENABLE притянуты к минусу, моторы не работают
digitalWrite(EN1, LOW);
digitalWrite(EN2, LOW);
}
}
}

Вот так я получил машину:

Роботизированная машина на Arduino, управляемая по Bluetooth: схема и программа

Дизайн приложений может быть изменен пользователями, которым он нравится. Нет необходимости в подробном описании того, как это сделать, вы легко разберетесь. Единственное, что я хотел бы сказать, это то, что вам следует использовать файлы .png вместо .jpeg, поскольку .jpeg не поддерживают прозрачные фоны. Человек, не подготовленный к такой задаче, может сделать такой дизайн за полчаса или час:

image

P.S. Для тех, у кого нет опыта создания приложений в App Inventor 2, я подготовил более подробное руководство по созданию этого приложения (перейдите на youtube для просмотра).

https://www.youtube.com/watch?v=y2jAJ05s2EQ

P.P.S. Сборник из более 100 обучающих материалов по ардуино для начинающих и профи тут.
Онлайн курс по ардуино на гиктаймс здесь.
UPD 1.02.2023: выложил приложение на play market.
Аналогичные проекты с другими шилдами здесь.

Робот на ардуино своими руками

В отличие от других проектов, создание Arduino car (автомобиля-робота) требует от вас умения работать сразу с несколькими важными компонентами, поэтому перед созданием автомобилей получите базовое представление о платформе Ардуино.

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

Вот несколько компонентов, которые вы найдете в проекте.

Схема сборки машинки на ардуино

Мы рассмотрим, как сделать собственный автомобиль на Arduino, если у вас есть все необходимые детали (светодиоды и резисторы не нужны). Чтобы предотвратить отсоединение контактов, убедитесь, что провода припаяны к контактам двигателя и зафиксированы электрической лентой. Вы должны подключить провода к клеммам M1 и M2 на моторном щите (полярность можно изменить позже).

Схема сборки машинки с Блютуз управлением
Схема сборки машинки с Блютуз управлением

Сервоконтакты обеспечивают питание для модуля Bluetooth, сервоприводы нам не нужны. Питание стабилизировано на 5 вольтах, что нам и нужно. Припаять разъемы “мама” для портов TX и RX, а также контакты (BLS) на Motor Shield было бы проще. Когда нужно загрузить скетч, можно легко извлечь модуль Bluetooth из Arduino.

” Pin2″ служит в качестве порта управления светодиодами. Провод может быть припаян непосредственно к этому порту. Устройство HC-05 должно иметь обновление прошивки, если вы делаете несколько машин с Bluetooth, которые будут управляться одновременно. После прошивки модуля каждая машина будет иметь свое уникальное имя на Android, чтобы вы не перепутали машины.

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

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

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

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

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

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

Добавление регулятора разряда в вашу схему потребует внесения следующих изменений:

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

Теперь батареи защищены, но их нельзя заряжать.

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

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

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

Управляем arduino-машинкой при помощи g-сенсора со смартфона

///////////////////////////////////////////// 

//        RemoteXY include library         // 

///////////////////////////////////////////// 

/* определение режима соединения и подключение библиотеки RemoteXY */ 

#define REMOTEXY_MODE__SOFTWARESERIAL 

#include <SoftwareSerial.h> 

#include <RemoteXY.h> 

/* настройки соединения */ 

#define REMOTEXY_SERIAL_RX 2 

#define REMOTEXY_SERIAL_TX 3 

#define REMOTEXY_SERIAL_SPEED 9600 

/* конфигурация интерфейса  */ 

unsigned char RemoteXY_CONF[] = 

{ 3,0,23,0,1,5,5,15,41,11

,43,43,1,2,0,6,5,27,11,5

,79,78,0,79,70,70,0 }; 

/* структура определяет все переменные вашего интерфейса управления */ 

struct { 

    /* input variable */

signed char joystick_1_x; /* =-100..100 координата x положения джойстика */

signed char joystick_1_y; /* =-100..100 координата y положения джойстика */

unsigned char switch_1; /* =1 если переключатель включен и =0 если отключен */

    /* other variable */

unsigned char connect_flag;  /* =1 if wire connected, else =0 */

} RemoteXY; 

///////////////////////////////////////////// 

//           END RemoteXY include          // 

///////////////////////////////////////////// 

/* определяем пины управления правым мотором */

#define PIN_MOTOR_RIGHT_UP 7

#define PIN_MOTOR_RIGHT_DN 6

#define PIN_MOTOR_RIGHT_SPEED 10

/* определяем пины управления левым мотором */

#define PIN_MOTOR_LEFT_UP 5

#define PIN_MOTOR_LEFT_DN 4

#define PIN_MOTOR_LEFT_SPEED 9

/* определяем пин управления светодиодом */

#define PIN_LED 13

/* определяем два массива с перечислением пинов для каждого мотора */

unsigned char RightMotor[3] = 

{PIN_MOTOR_RIGHT_UP, PIN_MOTOR_RIGHT_DN, PIN_MOTOR_RIGHT_SPEED};

unsigned char LeftMotor[3] = 

{PIN_MOTOR_LEFT_UP, PIN_MOTOR_LEFT_DN, PIN_MOTOR_LEFT_SPEED};

/*

управление скоростью мотора

motor – ссылка на массив пинов

v – скорость мотора, может принимать значения от -100 до 100

*/

void Wheel (unsigned char * motor, int v)

{

if (v>100) v=100;

if (v<-100) v=-100;

if (v>0) {

digitalWrite(motor[0], HIGH);

digitalWrite(motor[1], LOW);

analogWrite(motor[2], v*2.55);

}

else if (v<0) {

digitalWrite(motor[0], LOW);

digitalWrite(motor[1], HIGH);

analogWrite(motor[2], (-v)*2.55);

}

else {

digitalWrite(motor[0], LOW);

digitalWrite(motor[1], LOW);

analogWrite(motor[2], 0);

}

}

void setup()

{

/* инициализация пинов */

pinMode (PIN_MOTOR_RIGHT_UP, OUTPUT);

pinMode (PIN_MOTOR_RIGHT_DN, OUTPUT);

pinMode (PIN_MOTOR_LEFT_UP, OUTPUT);

pinMode (PIN_MOTOR_LEFT_DN, OUTPUT);

pinMode (PIN_LED, OUTPUT);

  /* инициализация модуля RemoteXY */

RemoteXY_Init ();

}

void loop()

{

/* обработчик событий модуля RemoteXY */

RemoteXY_Handler ();

  /* управляем пином светодиода */

digitalWrite (PIN_LED, (RemoteXY.switch_1==0)?LOW:HIGH);

  /* управляем правым мотором */

Wheel (RightMotor, RemoteXY.joystick_1_y – RemoteXY.joystick_1_x);

/* управляем левым мотором */

Wheel (LeftMotor, RemoteXY.joystick_1_y   RemoteXY.joystick_1_x);

}

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