CxemCAR на Arduino – Bluetooth управление машинкой с Android

CxemCAR на Arduino - Bluetooth управление машинкой с Android Лодки

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

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

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

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

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

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

При следующей передаче обработчик прерывания вызовет передатчик, когда тот отправит все байты из регистра UDR.

ISR(USART_TXC_vect)
{
	unsigned char *Pointer = (unsigned char *)&(TxPacket);

	static unsigned char TxIndex = 1;

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

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

Необходимые условия:

if ( TxIndex < sizeof(TxPacket) )

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

UDR = *(Pointer   TxIndex);

Инкрементировать TxIndex. Следующий байт из структуры будет передан, когда USART передаст следующий байт, и все байты структуры будут переданы. Если TxIndex больше размера структуры – условие не будет истинным и мы получим

else TxIndex = 1;

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

Описание программы МК должно также описывать реализацию управления драйвером. Управление драйвером осуществляется тремя сигналами: A1 (B1), A2 (B2) и PWMA (PWMB). Кнопки A1 и A2 управляют включением/выключением и полярностью драйвера. Сигналы ШИМ могут использоваться для управления скоростью вращения через вход PWMA. ШИМ-сигнал Я использовал два аппаратных ШИМ-таймера 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 от Google. В 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)

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

Bluetooth пульт для телевизора на arduino

#инклюд

IRsend irsend;

Длинный беззнаковый a ;

void setup() {

Serial.begin(9600);

Serial.setTimeout(4);

pinMode(ledPin, OUTPUT);

}

unsigned int A_one[78]={4450,4550,400,1800,450,650,450,1800,450,600,500,650,450,650,450,700,450,650,450,1750,450,650,500,1750,450,650,450,650,500,650,450,650,450,700,450,650,450,650,450,1750,450,650,500,650,450,650,500,650,450,650,450,1750,450,1750,500,650,450,1700,500,1750,450,1750,450,1800,450,1700,450};
unsigned int A_two[78]={4450,4550,450,1750,450,650,500,1750,500,600,450,650,450,650,500,650,450,650,500,1700,500,650,450,1800,450,600,500,650,450,650,450,650,500,650,450,1750,450,650,500,1750,450,650,450,650,450,700,450,650,450,650,450,700,450,1750,450,650,450,1700,500,1750,500,1750,450,1750,500,1650,500};
unsigned int A_three[78]={4450,4500,450,1750,450,700,450,1750,450,650,450,650,500,650,450,650,450,650,500,1750,450,650,450,1750,500,600,500,650,450,650,450,650,500,650,450,650,450,1750,500,1750,450,650,450,650,500,650,450,650,450,650,450,1750,500,650,450,650,500,1700,450,1800,450,1700,500,1750,500,1650,500};
unsigned int A_four[78]={4450,4550,450,1750,450,700,450,1750,450,650,450,650,500,650,450,650,450,650,500,1700,500,650,450,1750,500,600,500,650,450,650,450,650,500,650,450,650,450,650,500,650,450,1700,500,600,500,650,450,650,500,600,500,1750,450,1750,500,1750,450,600,500,1750,500,1700,500,1750,500,1650,500};
unsigned int A_five[78]={4450,4550,450,1750,450,650,500,1750,450,650,450,650,500,650,450,650,450,650,500,1750,450,650,450,1750,500,600,500,650,450,650,450,650,500,650,450,1750,450,650,500,650,450,1700,500,650,450,650,450,650,450,700,450,650,450,1750,500,1750,450,650,450,1750,500,1750,450,1750,500,1650,500};

unsigned int A_six[78]={4400,4550,450,1800,400,700,400,1800,450,650,450,700,400,700,450,650,450,650,500,1750,450,650,450,1750,500,600,500,650,450,650,450,700,400,700,450,650,450,1750,500,650,450,1700,500,650,450,650,450,700,400,700,450,1750,450,650,450,1800,450,650,450,1750,500,1750,450,1750,450,1700,500};
unsigned int A_seven[78]={4450,4550,450,1750,450,650,450,1800,450,650,450,650,450,650,500,650,450,650,450,1750,500,600,500,1750,500,600,500,600,500,650,450,650,500,600,500,650,450,650,500,1750,450,1700,500,600,500,650,450,650,450,650,500,1750,450,1750,500,600,500,650,450,1700,550,1700,500,1750,450,1700,500};
unsigned int A_eight[78]={4400,4550,450,1750,450,650,450,1800,450,650,450,650,450,700,400,650,500,650,450,1750,450,700,450,1750,500,600,450,700,450,650,450,650,450,700,450,1750,450,650,450,1800,450,1700,500,650,450,650,450,700,450,600,500,650,450,1750,500,650,450,650,450,1750,450,1800,400,1800,450,1700,450};
unsigned int A_nine[78]={4450,4500,450,1750,500,650,450,1800,450,600,450,650,500,650,450,650,450,700,450,1750,450,650,450,1800,450,650,450,650,450,650,500,600,500,650,450,650,500,1750,450,1750,500,1700,450,650,500,650,450,650,450,650,450,1800,450,650,450,650,450,650,450,1800,450,1750,450,1750,500,1650,500};
unsigned int A_zero[78]={4450,4500,500,1750,450,650,450,1800,450,650,450,650,450,650,500,650,450,650,450,1750,450,650,500,1750,500,600,450,650,500,650,450,650,450,650,500,1750,450,650,450,650,500,650,450,1750,450,650,450,650,500,650,450,650,450,1750,500,1750,450,1750,450,650,450,1750,500,1750,450,1700,450};

unsigned int A_w[78]={4450,4550,450,1750,450,650,500,1750,450,650,450,650,450,650,500,650,450,650,500,1700,500,600,500,1750,500,600,500,650,450,650,450,650,500,650,450,650,450,650,500,600,500,600,500,1750,500,600,500,1700,500,650,450,1750,450,1800,450,1750,450,1750,450,650,450,1750,500,650,450,1700,500};
unsigned int A_on[78]={4450,4550,450,1750,450,650,450,1800,450,650,450,650,450,650,450,700,450,650,450,1750,450,700,450,1750,500,600,450,650,500,650,450,650,450,700,450,650,450,1750,450,650,450,700,450,650,450,650,500,650,450,650,450,1750,450,700,450,1750,450,1750,400,1800,450,1800,400,1800,450,1700,450};

void S1() {irsend.sendRaw(A_one,78,38);delay(500);}
void S2() {irsend.sendRaw(A_two,78,38);delay(500);}
void S3() {irsend.sendRaw(A_three,78,38);delay(500);}
void S4() {irsend.sendRaw(A_four,78,38);delay(500);}
void S5() {irsend.sendRaw(A_five,78,38);delay(500);}

void S6() {irsend.sendRaw(A_six,78,38);delay(500);}
void S7() {irsend.sendRaw(A_seven,78,38);delay(500);}
void S8() {irsend.sendRaw(A_eight,78,38);delay(500);}
void S9() {irsend.sendRaw(A_nine,78,38);delay(500);}
void S0() {irsend.sendRaw(A_zero,78,38);delay(500);}

void Son() {irsend.sendRaw(A_on,78,38);delay(500);}

void loop()
{
if (Serial.available())
{ a = Serial.parseInt();

if (a==101) {Son ();}
if (a==102) {S2();}
if (a==103) {S3();}

if (a==1) {S1();}
if (a==2) {S2();}
if (a==3) {S3();}
if (a==4) {S4();}
if (a==5) {S5();}
if (a==6) {S6();}
if (a==7) {S7();}
if (a==8) {S8();}
if (a==9) {S9();}
if (a==10) {S1();S0();}

if (a==11) {S1();S1();}
if (a==12) {S1();S2();}
if (a==13) {S1();S3();}
if (a==14) {S1();S4();}
if (a==15) {S1();S5();}
if (a==16) {S1();S6();}
if (a==17) {S1();S7();}
if (a==18) {S1();S8();}
if (a==19) {S1();S9();}
if (a==20) {S2();S0();}

if (a==21) {S2();S1();}
if (a==22) {S2();S2();}
if (a==23) {S2();S3();}
if (a==24) {S2();S4();}
if (a==25) {S2();S5();}
if (a==26) {S2();S6();}
if (a==27) {S2();S7();}
if (a==28) {S2();S8();}
if (a==29) {S2();S9();}
if (a==30) {S3();S0();}

if (a==31) {S3();S1();}
if (a==32) {S3();S2();}
if (a==33) {S3();S3();}
if (a==34) {S3();S4();}
if (a==35) {S3();S5();}
if (a==36) {S3();S6();}
if (a==37) {S3();S7();}
if (a==38) {S3();S8();}
if (a==39) {S3();S9();}
if (a==40) {S4();S0();}

if (a==41) {S4();S1();}
if (a==42) {S4();S2();}
if (a==43) {S4();S3();}
if (a==44) {S4();S4();}
if (a==45) {S4();S5();}
if (a==46) {S4();S6();}
if (a==47) {S4();S7();}
if (a==48) {S4();S8();}
if (a==49) {S4();S9();}
if (a==50) {S5();S0();}

if (a==51) {S5();S1();}
if (a==52) {S5();S2();}
if (a==53) {S5();S3();}
if (a==54) {S5();S4();}
if (a==55) {S5();S5();}
if (a==56) {S5();S6();}
if (a==57) {S5();S7();}
if (a==58) {S5();S8();}
if (a==59) {S5();S9();}
if (a==60) {S6();S0();}

if (a==61) {S6();S1();}
if (a==62) {S6();S2();}
if (a==63) {S6();S3();}
if (a==64) {S6();S4();}
if (a==65) {S6();S5();}
if (a==66) {S6();S6();}
if (a==67) {S6();S7();}
if (a==68) {S6();S8();}
if (a==69) {S6();S9();}
if (a==70) {S7();S0();}

if (a==71) {S7();S1();}
if (a==72) {S7();S2();}
if (a==73) {S7();S3();}
if (a==74) {S7();S4();}
if (a==75) {S7();S5();}
if (a==76) {S7();S6();}
if (a==77) {S7();S7();}
if (a==78) {S7();S8();}
if (a==79) {S7();S9();}
if (a==80) {S8();S0();}

if (a==81) {S8();S1();}
if (a==82) {S8();S2();}
if (a==83) {S8();S3();}
if (a==84) {S8();S4();}
if (a==85) {S8();S5();}
if (a==86) {S8();S6();}
if (a==87) {S8();S7();}
if (a==88) {S8();S8();}
if (a==89) {S8();S9();}
if (a==90) {S9();S0();}

if (a==91) {S9();S1();}
if (a==92) {S9();S2();}
if (a==93) {S9();S3();}
if (a==94) {S9();S4();}
if (a==95) {S9();S5();}
if (a==96) {S9();S6();}
if (a==97) {S9();S7();}
if (a==98) {S9();S8();}
if (a==99) {S9();S9();}
if (a==100) {S1();S0();S0(); }

}
}

Javascript

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

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

navigator.bluetooth.requestDevice({
    filters:
      [
        { name: MY_BLUETOOTH_NAME },
        { services: [SEND_SERVICE] },
      ]
  })

После нажатия кнопки “Connect” появляется окно (рис. В нем нужно выбрать устройство, к которому вы хотите подключиться, и нажать на кнопку подключения.

Рис. (окно с устройствами, доступными для подключения)

Подключение к устройству возвращает Promise. Затем давайте сохраним его в переменной и создадим соединение.

.then(device => {
      myDevice = device;

      return device.gatt.connect();
    })

После этого мы возвращаем Promise, содержащий слово “сервер”. Затем мы запрашиваем “сервис” у “сервера”, передавая UID (который мы узнали через приложение) сервиса. После этого мы возвращаем Promise, содержащий “сервис”, который мы запрашиваем у “характеристики”, передавая ее UID (который мы также искали с помощью приложения).

.then(server => server.getPrimaryService(SEND_SERVICE))
.then(service => service.getCharacteristic(SEND_SERVICE_CHARACTERISTIC))

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

Этот код содержится в обработчиках нажатия:

const code = Number(event.target.dataset.code);

  if (code === 1) {
    toggleLigthCharacteristic.writeValue(Uint8Array.of(code));

    return;
  }

  toggleLigthCharacteristic.readValue()
    .then(currentCode => {
      const convertedCode = currentCode.getUint8(0);

      toggleLigthCharacteristic.writeValue(
        Uint8Array.of(convertedCode === code ? 0 : code)
      );
    });

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

По замыслу, код 1 заставляет светодиоды мигать тремя цветами, а затем гаснуть. Но как выключить светодиод, если ему был послан код 3, а светодиод еще не выключен? Или включить другой цвет?

Взяв значение характеристики, я конвертирую его в Uint8, и если есть какое-либо недопустимое значение (например, 0). Затем оно преобразуется в массив unit8 и записывается в характеристику, если оно действительно.

Для того чтобы решить эту проблему, нам просто нужно понять, как отключиться от устройства. На кнопку “Disconnect” мы уже добавили eventListener, который отключается от устройства Bluetooth, удаляет eventListeners, скрывает кнопки управления и записывает неопределенные значения в переменные.

myDevice.gatt.disconnect();

toggleItemsEventListeners('removeEventListener');
toggleButtonsVisible();

toggleLigthCharacteristic = undefined;
myDevice = undefined;

Отправка данных

Отправка данных на устройство осуществляется путем записи значения в характеристику, а точнее путем вызова функции

Сохранить значение ()

Свойства объектов с

Печать совета

В качестве аргумента. Чтобы преобразовать строку в

Печать правления

Самый простой метод – это использовать

Единица кодировки текста .

// Отправить данные подключенному устройству
function send(data) {
  data = String(data);

  if (!data || !characteristicCache) {
    return;
  }

  writeToCharacteristic(characteristicCache, data);
  log(data, 'out');
}

// Записать значение в характеристику
function writeToCharacteristic(characteristic, data) {
  characteristic.writeValue(new TextEncoder().encode(data));
}


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

Верёвка

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

// Отправить данные подключенному устройству
function send(data) {
  data = String(data);

  if (!data || !characteristicCache) {
    return;
  }

  data  = 'n';

  if (data.length > 20) {
    let chunks = data.match(/(.|[rn]){1,20}/g);

    writeToCharacteristic(characteristicCache, chunks[0]);

    for (let i = 1; i < chunks.length; i  ) {
      setTimeout(() => {
        writeToCharacteristic(characteristicCache, chunks[i]);
      }, i * 100);
    }
  }
  else {
    writeToCharacteristic(characteristicCache, data);
  }

  log(data, 'out');
}

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

n

В этом случае для разбиения сообщения на фрагменты используется регулярное выражение, которое правильно обрабатывает символы возврата каретки (CR, r) и перевода строки (LF, n). Первый фрагмент сообщения отправляется сразу, а остальные с задержкой в 100 миллисекунд отправляются по таймеру.

Обмен данными между терминалом и браузером, на котором можно кликнуть

Работает! Вот и все с JS; у нас есть полнофункциональная двусторонняя связь с устройством.

Получение данных

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

characteristicvaluechanged

Функции. Это следует сделать после включения уведомлений. Кроме того, целесообразно удалять обработчик при выключении устройства:

// Включение получения уведомлений об изменении характеристики
function startNotifications(characteristic) {
  log('Starting notifications...');

  return characteristic.startNotifications().
      then(() => {
        log('Notifications started');
        // Добавленная строка
        characteristic.addEventListener('characteristicvaluechanged',
            handleCharacteristicValueChanged);
      });
}

// Отключиться от подключенного устройства
function disconnect() {
  if (deviceCache) {
    log('Disconnecting from "'   deviceCache.name   '" bluetooth device...');
    deviceCache.removeEventListener('gattserverdisconnected',
        handleDisconnection);

    if (deviceCache.gatt.connected) {
      deviceCache.gatt.disconnect();
      log('"'   deviceCache.name   '" bluetooth device disconnected');
    }
    else {
      log('"'   deviceCache.name  
          '" bluetooth device is already disconnected');
    }
  }

  // Добавленное условие
  if (characteristicCache) {
    characteristicCache.removeEventListener('characteristicvaluechanged',
        handleCharacteristicValueChanged);
    characteristicCache = null;
  }

  deviceCache = null;
}

// Получение данных
function handleCharacteristicValueChanged(event) {
  let value = new TextDecoder().decode(event.target.value);
  log(value, 'in');
}

Событие.цель.ценность

– это объект

Содержащий.

В котором содержится сообщение с вашего устройства. Использование

Декодер для текста.

), мы конвертируем массив байтов в текст.

Отправка данных с терминала и получение в браузере кликабельных данных

Устройство работает стабильно при получении сообщений, как с CR, так и без CR и LF. Получатель получает длинные сообщения полностью, но они делятся на кратные 20 байтам.

Примечание:

Поскольку установленный на роботе модуль Trema Bluetooth HC-05 подключен к аппаратной шине UART, перед загрузкой скетча робота необходимо отсоединить провод либо от вывода TX модуля, либо от вывода RX на плате Tream-Power Shield, а после загрузки скетча – подключить его обратно.

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

Последняя строка кода настройки в скетче пульта дистанционного управления не должна содержать оператора “if”, оставив только тело этого оператора:

/* Было так:  */ if(varK){while(!objHC05.createMaster("QUADRUPED","1212")){;}} // Если кнопка джойстика нажата при старте ...
/* Стало так: */          while(!objHC05.createMaster("QUADRUPED","1212")){;}  // Теперь bluetooth модулю назначается роль мастера при каждом включении пульта!

В скетче робота удалите все строки, содержащие константу “pinK” или функцию “funWaitMaster()” и перепишите код setup() следующим образом

void setup(){                                                                             //
     funLimbFree();                                                                       // Ослабляем все суставы
     while( !objHC05.begin(Serial)                  ){;}                                  // Инициируем работу с bluetooth модулем, указывая имя объекта или класса для управления шиной UART. При провале инициализации функция begin() вернёт false и тогда оператор while запустит её вновь.
     while( !objHC05.createSlave("QUADRUPED","1212")){;}                                  // Устанавливаем bluetooth модулю роль ведомого с именем "QUADRUPED" и PIN-кодом 1212, ожидающего подключение мастера (список сопряжённых пар будет очищен).
     while( !objHC05.checkConnect()                 ){delay(1000);}                       // Проверка подключения к внешнему Bluetooth устройству.
}                                                                                         //

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

Проблема


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

Arduino Uno

Поэтому пусть это будет устройство на базе Arduino, хотя, конечно, нет никакой принципиальной разницы, если вы используете

STMRaspberryESP8266

Или что-то еще. Главное, чтобы ваш контроллер работал с модулем Bluetooth с помощью пользовательского интерфейса.

UART

(больше на

или в

Если вы, как и я, уже прикрутили старый добрый Bluetooth-модуль HC-05 к своему устройству, загрузили прошивку, запустили несколько примеров Google и не можете понять, почему браузер не обнаруживает ваше устройство, то я вынужден вас разочаровать: Web Bluetooth поддерживает только “стандартный Bluetooth 4”.

Это причина написать эту статью, потому что когда вы, как и я, вернетесь из ближайшего магазина с BLE-модулем (HM-10, например), вы обнаружите, что он работает совершенно по-другому и, самое главное, не поддерживает Serial Port Profile (SPP, подробнее см. библиотеку Баумана), который вы использовали для бездумной пересылки байтов туда-сюда.

Возможно, вы уже знакомы с концепцией Bluetooth Low Energy, в частности с Generic Attribute Profile (GATT), но я постараюсь кратко объяснить, что для нас сейчас важно: вместо самодельного последовательного протокола ваше устройство должно предоставлять набор “характеристик” приложения, которые могут считываться и/или изменяться подключенным устройством.

В качестве примера воспользуемся роботизированной рукой, которая движется в трех плоскостях (числа X, Y, Z) и может открывать (0) или закрывать (1) клешню. Поэтому мы должны настроить модуль BLE на чтение и запись 4 характеристик, которые подключенное устройство может распознавать, читать и записывать в них.

Это здорово, но есть одна проблема: обычные BLE модули хобби-уровня, которые можно найти в “магазинах у дома” или на Aliexpress: HM-10, JDY-08, AT-09, CC41-A, который я получил, и другие – не имеют возможности настройки каких-либо функций или сервисов.

Вместо того чтобы предоставлять несколько характеристик, они предоставляют только одну характеристику, которая эмулирует последовательный порт, и что бы вы ни записали в нее, модуль отправит вашему контроллеру на TX, а что бы контроллер ни отправил на RX модуля, он отправит на подключенное устройство. В любой характеристике BLE существует ограничение в 20 байт.

Таким образом, несмотря на то, что Web Bluetooth ограничен использованием профиля общих атрибутов, на самом деле нам нужно создать профиль последовательного порта поверх него для внутреннего использования.

Радиокот :: радиоуправление моделью через bluetooth le

РадиоКот >Схемы >Цифровые устройства >Игрушки >

Управление моделью через Bluetooth LE

В открытом пространстве система дистанционного управления, представленная в данной статье, работает на больших расстояниях, примерно до 30 м. Ее главное преимущество – меньшее потребление тока, что во многих случаях может стать решающим фактором. Управление в данном случае осуществляется моделью машины, имеющей один мотор для движения вперед и назад, и один мотор для поворота передних колес. Модель для эксперимента была куплена в местном торговом центре и была уже собрана, а также оснащена аналоговой системой радиоуправления, настроенной на 27 МГц. Она рассчитана на рабочее напряжение 3 В с двумя моторами, и в первоначальном варианте питалась от одной литиевой батареи 3,6 В. С помощью передатчика использовались два джойстика без контроля скорости. Акселерометр измерял положение платы передатчика в пространстве, позволяя нам контролировать траекторию и скорость модели. В Интернете есть примеры проектов, в которых для управления такими операциями используется смартфон, и у нас тоже есть подобный проект. Но в этот раз мы хотели сделать что-то практически не требующее энергии на передающей стороне”. Это был первый BLE-проект компании Naysen.

Ограничение дальности управления в основном связано с использованием протокола Bluetooth Low Energy (BLE), который в первую очередь предназначен для коротких расстояний. Мы использовали радиомодули EZ-BLE от Cypress с максимальной выходной мощностью 3 дБм (2 мВт). Эти модули очень просты и легко программируются с помощью программного обеспечения PSoC Creator. Я написал несколько статей о таких модулях, см. [1]. [1] и ссылки на него. Модули нашего проекта очень легко припаиваются к плате любым паяльником благодаря большому расстоянию между выводами (1,5 мм) и наличию контактных площадок на ребрах их плат. Модули выпускаются в двух вариантах – с экраном на плате и без него. Разница между этими модификациями заключается в основном в наличии сертификатов и цене. Мы использовали более дешевые и несертифицированные модули без экрана, которые подходят для домашнего использования. Микроконтроллерные модули оснащены всеми стандартными периферийными устройствами, характерными для современных микроконтроллеров, поэтому вся система может быть собрана всего из одного модуля. Микроконтроллер основан на архитектуре ARM Cortex-M0 с максимальной тактовой частотой 48 мГц от внутреннего генератора. На плате модуля находится 24-мегапиксельный кристалл для синхронизации радиосхемы и кварцевые часы для точной синхронизации стека протоколов. Для снижения энергопотребления нижние уровни стека BLE тактируются с частотой 3 мгц от кристаллического генератора, а остальные части приложения – с частотой 6 мгц.

Получатель

В схеме приемника нет ничего сложного. Она также включает в себя разъем для его программирования, драйвер двигателя на микросхеме IC2, светодиод для индикации состояния прикладной программы (см. ниже) и регулятор напряжения на микросхеме IC3. Для питания схемы было решено использовать 4 батарейки размера АА, чтобы гарантировать, что напряжение батарейки не упадет ниже 4 В во время работы.

CxemCAR на Arduino - Bluetooth управление машинкой с Android

Для управления двигателями с током до 1 А идеально подходят драйверы IC2. Благодаря технологии КМОП и низкому падению напряжения на транзисторах выходного каскада, корпус микросхемы не нагревается при работе на максимальном токе. Наш драйвер смонтирован на металлизированной подложке, что после пайки позволяет установить теплоотвод на фольгу. Однако эта мера предосторожности для трехвольтовых модельных двигателей оказалась совершенно излишней, и подложку можно было бы вообще не припаивать к плате, или даже использовать корпус без подложки. Имеется четыре сигнала управления драйвером, разделенные на две пары. Первый сигнал из каждой пары подается от модуля на двигатель, а второй управляет направлением его вращения. ШИМ для двигателя поворота колеса предполагалось использовать для снижения эффективного напряжения на нем.

P SoC содержит 3 модуля. Модуль ШИМ генерирует ШИМ-импульсы, которые управляют двигателями. После проведенных экспериментов была выбрана частота ШИМ 2 мгц / 127 = 15,7 кгц. Для того, чтобы передать только один байт при управлении скоростью, модель движется вперед при положительном значении и назад при отрицательном. Используется максимум три фиксированные скорости: низкая, средняя и высокая. Оказалось, что в модели используется дешевая коробка передач с пластмассовыми шестеренками и очень неэффективными моторами, а также пластмассовые шестеренки без обычных подшипников. После установки на пол модель не могла двигаться из-за своего большого веса и низкой скорости вращения колес в воздухе. Именно по этой причине были выбраны три скорости, чтобы даже на самой низкой скорости двигатели обеспечивали достаточный крутящий момент для запуска модели. Вот скриншот того, как подключение модуля PSoC отображается в графическом конфигураторе ресурсов. Непосредственно из программы выходы A1 и B2 управляют направлением вращения двигателей.

CxemCAR на Arduino - Bluetooth управление машинкой с Android

На схеме модуль ШИМ, расположенный внизу, управляет частотой мигания светодиода. Этот светодиод использовался в основном для сигнализации различных фаз подключения передатчика путем изменения частоты его мигания. В данном случае постоянное свечение соответствует завершению процесса подключения. В окончательном варианте соединение устанавливается практически мгновенно после включения передатчика, поэтому светодиод включается практически сразу.

Это модуль BLE в PSoC, который питает приемник. Разработанный как периферийное устройство GAP, он имеет собственный профиль GATT (пользовательский профиль) и выступает в качестве сервера. Помимо стандартных сервисов Generic Access и Generic Attribute, которые регулируются BLE SIG, существует также собственный сервис Car Control, с тремя характеристиками, Turn, Speed и Control, которые управляют поворотами и скоростью модели. Мы отличаемся от дизайна, опубликованного в [2], в котором роли GAP для приемника и передатчика противоположны нашим. Это сделано специально, чтобы Натан был более глубоко связан с миром BLE. Таким образом, логика программ приемника и передатчика, а также их взаимодействие со стеком BLE были пересмотрены.

Получение команд от передатчика, то есть запись новых значений в характеристики профиля, осуществляется путем обслуживания прерываний стека BLE в обработчике GeneralEventHandler. В этом случае происходит четыре события. CYBLE_EVT_STACK_ON – событие инициализации стека, которое используется для начала отправки прерывания с идентификатором приемника, подключенного к передатчику, после его инициации. На заводе идентификатор записывается в модуль в виде уникального 48-битного кода. Хотя при необходимости он может быть изменен, мы не стали его изменять. Далее стек генерирует CYBLE_EVT_GAP_DEVICE_CONNECTED и CYBLE_EVT_GAP_DEVICE_DISCONNECTED. Мы настраиваем светодиод в первом случае на постоянное свечение, а во втором случае мы останавливаем модель и возобновляем отправку рекламы, тем самым давая передатчику возможность восстановить соединение. При отсутствии соединения с передатчиком светодиод мигает с периодом в 1 секунду.

Последнее событие, CYBLE_EVT_GATTS_WRITE_REQ, генерируется стеком, когда серверная база данных получает команду на запись значения характеристики. Мы проверяем, какую характеристику нужно изменить, отправляем подтверждение на передатчик и вызываем соответствующую функцию Set_Turn() и/или Set_Speed() для выполнения команды путем манипулирования сигналами на входах IC2.

Согласно этой реализации протокола, соединение с передатчиком происходит каждые 100 миллисекунд. Потребляемая мощность составляет всего 4,7 мА, когда двигатели не работают, когда система отдыхает между соединениями. Светодиоды потребляют около 1,3 мА из этого общего количества. Пока PSoC находится в глубоком сне, модель не может вращаться, поскольку PSoC должен генерировать постоянный ШИМ для двигателей. Это приведет к остановке всех генераторов и работе двигателей на низкой скорости. Когда модель остановлена и система переведена в глубокий сон, возможно снижение потребляемого тока примерно в три раза.

Он установлен на печатной плате размером 37*26 мм, приклеенной к куску пластиковой упаковки, которая закреплена на шасси. В данной модели имеется центральный батарейный отсек. Несмотря на фиксацию батарей крышкой батарейного отсека, при столкновении модели с препятствием или даже при движении по неровной поверхности иногда происходит потеря контакта в пружине держателя батареи, что приводит к кратковременной потере связи с передатчиком и миганию светодиода на плате. Использование батареи с проводами, припаянными непосредственно к плате, в оригинальной модели было небезосновательно.

Отправитель: .

Он содержит тот же радиомодуль, что и приемник, 3-осевой аналоговый акселерометр IC2 и светодиод для индикации подключения к модели. ФНЧ формируется конденсатором C2 и конденсатором C4, а также резисторами внутри IC2. Этот фильтр уменьшает шум, поступающий с аналогового выхода акселерометра. Измерения сигналов на выходах X, Y и Z обрабатываются 12-разрядным АЦП на PSoC. В соответствии с периодом соединения с моделью, измерения производятся каждые 100 миллисекунд. Сторожевой таймер в PSoC обеспечивает временной интервал для измерения параметров, тактируемый от тактового кристалла на плате модуля.

А ЦП настроен на недифференциальное переключение. Сигналы акселерометра измеряются программно в начале процесса измерения. АЦП тактируется на частоте 6 МГц от собственного генератора, так что измерения по трем осям акселерометра выполняются за 36 микросекунд, включая усреднение измерений по каждой оси. При вращении карта передатчика наклоняется как влево, так и вправо не менее чем на 30°. Небольшое колебание положения карты в руке оператора предотвращает подачу ложных команд. Управление скоростью и направлением движения модели осуществляется путем наклона карты передатчика к себе или от себя. В зависимости от наклона модели скорость пропорциональна. Благодаря 3 дискретным скоростям, соответствующим порогам наклона платы, скорость не изменяется при наклоне платы между порогами.

L ED указывают фазы соединения с приемником. Устройство BLE мигает чаще от начала сканирования до обнаружения идентификатора приемника, до соединения с приемником и до окончания чтения услуг, предоставляемых приемником. На протяжении всего процесса светодиод горит постоянно, не мигая. ШИМ-генератор здесь отключен, и светодиод управляется непосредственно выводом порта PSoC.

В отличие от приемника, система могла спать между обнаружением ускорения и обработкой событий стека. Ток, потребляемый передатчиком, составлял примерно 1,6 мА, включая около 1,3 мА для светодиода. Кроме того, для дальнейшего снижения тока, потребляемого акселерометром, необходимо также подать сигнал ENA на его вход ENA.

CxemCAR на Arduino - Bluetooth управление машинкой с Android

На односторонней печатной плате размером 74*42 мм размещен передатчик. Фольга, закрывающая антенну, была удалена в соответствии с рекомендациями производителя. С помощью двух винтов M2 батарейный отсек закреплен на обратной стороне платы.

CxemCAR на Arduino - Bluetooth управление машинкой с Android

Файл BLEclient.c отвечает за обработку соединения между передатчиком (ведущим) и приемником (ведомым). Функция CYBLE_EVT_STACK_ON срабатывает после инициализации стека, как и в случае с приемником. Затем следует вызов API-функции CyBle_GapcStartScan, чтобы начать сканирование BLE-устройств, доступных передатчику. После того как устройство найдено, происходит событие CYBLE_EVT_GAPC_SCAN_PROGRESS_RESULT, и стек передает ID устройства (MAC-адрес) обработчику. Одновременно генерируется событие CYBLE_EVT_GAPC_SCAN_START_STOP. Первый обработчик события сравнивает полученный идентификатор с идентификатором модели приемника. Если он не совпадает, сканирование продолжается путем подачи соответствующей команды во втором обработчике события. Там же выдается команда CyBle_GapcConnectDevice для подключения к приемнику. В случае успешного соединения сначала генерируется событие CYBLE_EVT_GATT_CONNECT_IND, в котором обработчику передается хэндл устройства приемника, который сохраняется в переменной connHandle и затем используется обработчиком для отправки команд приемнику. В результате стек генерирует событие CYBLE_EVT_GAP_DEVICE_CONNECTED, которое указывает, что соединение завершено. С этого момента обычно начинается процесс сбора информации об услугах, предоставляемых подключенным устройством, их характеристиках и дескрипторах. Однако для упрощения кода мы этого не делаем, поскольку уже знаем, какие сервисы нам следует ожидать от нашего приемника. В нашем проекте приемника значения дескрипторов Turn, Speed и Control (в нашем случае 0x0012, 0x0016, 0x001A) можно найти в файле BLE_custom.h. Этот файл автоматически генерируется конфигуратором при создании проекта.

Поскольку передатчик работает на фоне обработки событий стека BLE, его логика предельно проста. При каждом прерывании от сторожевого таймера просыпается АЦП и производятся измерения выходного сигнала акселерометра. Значения вектора ускорения сравниваются с пороговыми значениями для поворотов и скоростей в Check_Control(), и заполняются поля характерных управляющих структур. После этого выдается команда CyBle_GattcWriteCharacteristicValue для передачи соответствующей характеристики приемнику. Эти параметры представляют собой описание связи с приемником (полученное при подключении) и описание характеристики. Они инициализируются только один раз при подаче питания в функции Init_RAM(), поскольку эти структуры требуют только адрес соответствующей характеристики. Если код скорости или вращения статически расположен в оперативной памяти, то адрес этих значений не изменится.

Массив serverAddress в программе передатчика (файл BLEclient.c) при повторении конструкции должен включать ваш MAC-адрес, а не мой. Модель приемника будет передавать свой MAC-адрес в рекламном режиме, чтобы любой сканер Bluetooth-устройств мог его прочитать. CySmart, приложение для смартфонов, которое находится в свободном доступе через веб. Файлы Eagle и исходный код прилагаются.

Если использовать модули с более высокой выходной мощностью, то можно увеличить дальность управления даже при использовании протокола BLE. Они доступны у компании Cypress, а именно модули CYBLE-224110-00 с огромной мощностью BLE в 9,5 дБм (примерно 9 мВт). С такой мощностью это точно не будет считаться низким энергопотреблением. Эти модули были любезно предоставлены нам компанией для тестирования, но о них будет написано больше в будущем. И наконец, видео, демонстрирующее управление моделью.

Литература

1. Реалиазция стандартного GATT-BLE профиля на RSoC фирмы Cypress
2. Project #047: PSoC 4 BLE – Accelerometer Controlled Car

Файлы:
Архив ZIP

Все вопросы в
Форум.



Вот некоторые другие статьи, которые могут быть вам полезны:

Схема подключения робота quadruped:

Как описано на странице Сборка четвероногих, соберите механику, подключите Tream-Power Shield, сервоприводы и датчик расстояния, а также откалибруйте робота. Калибровка электроники. После этого установите Bluetooth HC-05 и кнопку на боковые панели, первый модуль подключается к шине UART (в примере используется аппаратный UART), а второй – к любому порту Arduino Uno (в примере используется контакт D12).

Указав объект objSensor при объявлении выводов 2 и 3 HC-SR04, можно по желанию изменить подключение этих выводов.

СервоприводыTrema Power Shield
1 конечностьГоризонтальный сустав (№ 0)вывод 4 на белой колодке
Вертикальный сустав (№ 1)вывод 5 на белой колодке
2 конечностьГоризонтальный сустав (№ 2)вывод 6 на белой колодке
Вертикальный сустав (№ 3)вывод 7 на белой колодке
3 конечностьГоризонтальный сустав (№ 4)вывод 8 на белой колодке
Вертикальный сустав (№ 5)вывод 9 на белой колодке
4 конечностьГоризонтальный сустав (№ 6)вывод 10 на белой колодке
Вертикальный сустав (№ 7)вывод 11 на белой колодке

При объявлении массива объектов pinServo[8] вы можете выбрать любые другие контакты в качестве точек подключения сервопривода, указав их в скетче. Трехпроводные сервошлейфы конфигурируются следующим образом:

  • Оранжевый провод подключается к белому проводу блока.
  • Красный провод подключен к красному проводу блока.
  • Коричневый провод подключается к черному проводу блока.
BluetoothTrema Power Shield
Bluetooth HC-05вывод RXвывод TX на колодке Serial
вывод TXвывод RX на колодке Serial
вывод K (Key)вывод A0 на белой колодке
вывод V (Vcc)любой вывод на красной колодке
вывод G (GND)любой вывод на чёрной колодке

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

Выводы RX и ТХ модуля подключаются проводами к выводам TX и RX колодки с надписью Serial. Трёхпроводной шлейф подключённый к выводам K, V, G, устанавливается следующим образом:

  • Выход K (Key) подключается к клемме белого блока.
  • Контакт V (Vcc) подключен к контакту красного блока.
  • Контакт G (GND) подключен к черному контакту блока.
КнопкаTrema Power Shield
Trema-кнопкавывод S (Signal)вывод 12 на белой колодке
вывод V (Vcc)любой вывод на красной колодке
вывод G (GND)любой вывод на чёрной колодке

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

Трехпроводной шлейф подключается к контактам S, V и G следующим образом:

  • Контакт S (Сигнал) подключен к контакту на белом блоке.
  • Контакт V (Vcc) подключен к контакту на красном блоке.
  • Провод G (GND) подключается к выводу на черном блоке.

Инструкция по сборке Q UADRUPED показывает ту же схему, что и ниже. Однако добавлены два модуля: bluetooth (подключен к контактам A0, TX и RX) и кнопка (подключена к контакту D12).

Элементы схемы: “E0”. “E7” – сервоприводы, “E8”. датчик расстояния, “E9”, модуль Trema Bluetooth, и кнопка Trema “E10”.

Управление устройством по блютус

Эта статья служит продолжением предыдущей статьи “Смартфон управляет игрушечным автомобилем” и должна помочь пользователям, решившим повторить проект, управлять своим устройством с помощью Bluetooth, используя среду программирования BASIC!

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

Для этого были написаны две программы.

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

Один из них работает на смартфоне и выступает в качестве пульта дистанционного управления. Связь происходит, когда клиент отправляет команду по Bluetooth.

Команда представляет собой текстовое сообщение. Правая рука может быть интерпретирована как “вправо” и означает включение подруливающего устройства вперед на 300 миллисекунд и поворот привода руля вправо.

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

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

Сначала вы запускаете программу “Сервер”, а затем, проверив, начал ли сервер прослушивать канал, запускаете программу “Клиент” и управляете устройством.

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

Список программы “Сервера”.

FN.DEF speak(t$)
TTS.INIT
TTS.SPEAK t$
TTS.STOP
FN.END

speak("начало работы сервера")
ONERROR:
newConnection:
BT.OPEN
speak ("Жду запрос на соединение ")
DO %         
BT.STATUS s
IF s = 1
!speak("Слушаю")
ELSEIF s =2
speak( "Соединяюсь")
ELSEIF s = 3
speak( "Соединение создано")
ENDIF
PAUSE 1000
UNTIL s = 3 %       

BT.DEVICE.NAME device$

DO %---------
BT.STATUS s
IF (s<> 3)
speak( "Соединение разорвано")
GOTO new_connection
ENDIF

DO % ======
BT.READ.READY rr
IF rr
BT.READ.BYTES s$
PRINT ":";s$
s$ =mid$(s$,1,len(s$)-1)
speak(s$)
IF (s$="end") THEN GOTO xEnd
ENDIF
UNTIL rr = 0 % ======

UNTIL 0 % --------

xEnd:
speak("Сервер остановлен")
BT.CLOSE
END

Листинг программы «Клиент»

ARRAY.LOAD menucom$[], "Вперед", "Назад", "Вправо", "Влево", "Остановить клиент", "Остановить сервер"

BT.OPEN
BT.CONNECT

n = 0
DO %           
BT.STATUS s
IF s = 1
PRINT "Слушаю, секунды: ", n  
ELSEIF s =2
PRINT "Соединяюсь, секунды: ",n  
ELSEIF s = 3
PRINT "Есть соединение"
ENDIF
PAUSE 1000

UNTIL s = 3 %         

BT.DEVICE.NAME device$
PRINT device$
PAUSE 1000

x = 0
DO %#########
SELECT menu, menuCom$[], "Выбери команду"
IF menu = 1 THEN BT.WRITE "forward"
IF menu = 2 THEN BT.WRITE "backward"
IF menu = 3 THEN BT.WRITE "right"
IF menu = 4 THEN BT.WRITE "left"
IF menu = 5 THEN x=1
IF menu = 6 THEN BT.WRITE "end"
UNTIL x=1 %#########

BT.CLOSE
END

Управление:

Сразу после сборки, загрузки скетча, подачи питания на пульт и QUADRUPED суставы робота разболтаются, и он не будет отвечать на команды с пульта, поскольку модули Bluetooth нуждаются в сопряжении (pairing). После сопряжения модули Bluetooth запомнят его в своей энергонезависимой памяти и будут пытаться выполнить сопряжение автоматически при каждом включении питания.

  • Отключите питание пульта (если он входит в комплект поставки), нажмите джойстик (как кнопку) и включите питание пульта. После этого удаленному модулю Bluetooth будет присвоена роль ведущего и начнется поиск ведомого с именем “QUADRUPED” и PIN-кодом “1212”.
  • Подключите питание к роботу (если не входит в комплект поставки), нажмите и удерживайте кнопку сопряжения не менее 1 секунды (можно нажать в любое время). При нажатии кнопки модулю Bluetooth робота будет присвоена роль ведомого с именем “QUADRUPED” и PIN-код “1212”, после чего он будет ожидать соединения с ведущим.
  • Выполните те же действия для пульта дистанционного управления и робота для повторного сопряжения (при необходимости).
  • После подключения суставы робота “оживут”, и он будет выполнять команды пульта дистанционного управления. Если вы выключите пульт дистанционного управления, суставы робота расслабятся и оживут, когда вы включите пульт.

Выполните следующие шаги, чтобы управлять роботом с помощью пульта дистанционного управления:

  • Если вы наклоните джойстик вперед, робот будет двигаться вперед, а скорость зависит от того, насколько вы наклоните джойстик.
  • Если вы наклоните джойстик назад, робот будет двигаться назад, а скорость зависит от того, насколько вы наклоните джойстик.
  • Если наклонить джойстик вперед и повернуть влево или вправо, робот будет двигаться вперед, поворачиваясь влево или вправо. Скорость зависит от того, насколько вы наклоните джойстик вперед, а радиус поворота зависит от того, насколько вы наклоните джойстик влево или вправо.
  • Если наклонить джойстик назад и влево или вправо, робот будет двигаться назад влево или вправо. Скорость зависит от того, насколько джойстик наклонен назад, а радиус поворота – от того, насколько джойстик наклонен влево или вправо.
  • Если наклонить джойстик влево или вправо, но не наклонять его вперед или назад, робот будет поворачивать влево или вправо в состоянии покоя, а скорость поворота зависит от того, насколько сильно наклонен джойстик.
  • Если нажать на джойстик (при включенном питании), все конечности робота установятся в центральное положение.
  • При вращении ручки потенциометра по часовой стрелке корпус робота поднимается независимо от положения джойстика.
  • Поворот ручки потенциометра против часовой стрелки опускает корпус робота, независимо от положения джойстика.
Смотрите про коптеры:  Как сделать квадрокоптер своими руками
Оцените статью
Радиокоптер.ру
Добавить комментарий