Радиоуправление на ардуино

ARDUINO Машинка на nrf24l01

/* Данный скетч модернизация скетча AlexGyver * исходник тут https://github.com/AlexGyver/nRF24L01 */ #include <SPI.h> #include «nRF24L01.h» #include «RF24.h» RF24 radio(9,10); // «создать» модуль на пинах 9 и 10 Для Уно //RF24 radio(9,53); // для Меги byte address = {«1Node»,»2Node»,»3Node»,»4Node»,»5Node»,»6Node»}; //возможные номера труб byte recieved_data; void setup(){ Serial.begin(9600); //открываем порт для связи с ПК pinMode(4, OUTPUT); pinMode(A0, OUTPUT); pinMode(A1, OUTPUT); pinMode(5, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(6, OUTPUT); radio.begin(); //активировать модуль radio.setAutoAck(0); //режим подтверждения приёма, 1 вкл 0 выкл radio.setRetries(0,15); //(время между попыткой достучаться, число попыток) radio.enableAckPayload(); //разрешить отсылку данных в ответ на входящий сигнал radio.setPayloadSize(32); //размер пакета, в байтах radio.openReadingPipe(1,address); //хотим слушать трубу 0 radio.setChannel(0x60); //выбираем канал (в котором нет шумов!) radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX radio.setDataRate (RF24_1MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS //должна быть одинакова на приёмнике и передатчике! //при самой низкой скорости имеем самую высокую чувствительность и дальность!! radio.powerUp(); //начать работу radio.startListening(); //начинаем слушать эфир, мы приёмный модуль } void loop() { byte pipeNo; while( radio.available(&pipeNo)){ // слушаем эфир со всех труб radio.read( &recieved_data, sizeof(recieved_data) ); //читаем присланный массив digitalWrite(4, HIGH); int x1p = constrain(map(recieved_data, 128, 255, 0, 255), 0, 255); //обрезаем и переворачиваем значения int x1b = constrain(map(recieved_data, 128, 0, 0, 255), 0, 255); //обрезаем и переворачиваем значения int y2r = constrain(map(recieved_data, 122, 255, 100, 1), 0, 100); //обрезаем и переворачиваем значения int y2l = constrain(map(recieved_data, 122, 0, 100, 1), 0, 100); //обрезаем и переворачиваем значения int stl = constrain(map(recieved_data, 123, 255, 0, 255), 0, 255); //обрезаем и переворачиваем значения int str = constrain(map(recieved_data, 122, 0, 0, 255), 0, 255); //обрезаем и переворачиваем значения //Serial.print(x1p); Serial.print(» | «); Serial.print(x1b); Serial.print(» | «); Serial.print(y2r); Serial.print(» | «); Serial.print(y2l); Serial.println(); int spr = constrain(x1p * y2r / 100, 0, 255); //скорость правого колеса int spl = constrain(x1p * y2l / 100, 0, 255); //скорость левого колеса int bspr = constrain(x1b * y2r / 100, 0, 255); //скорость правого колеса назад int bspl = constrain(x1b * y2l / 100, 0, 255); //скорость левого колеса назад Serial.print(stl); Serial.print(» | «); Serial.print(str); Serial.println(); //Serial.print(recieved_data); Serial.println(); if (recieved_data>138) { digitalWrite(A1, LOW); digitalWrite(A0, HIGH); analogWrite(5, spr); digitalWrite(7, LOW); digitalWrite(8, HIGH); analogWrite(6, spl); } else if (recieved_data<118) { digitalWrite(A1, !LOW); digitalWrite(A0, !HIGH); analogWrite(5, bspr); digitalWrite(7, !LOW); digitalWrite(8, !HIGH); analogWrite(6, bspl); }else if (118<recieved_data<138) { digitalWrite(A1, LOW); digitalWrite(A0, HIGH); analogWrite(5, str); digitalWrite(7, LOW); digitalWrite(8, HIGH); analogWrite(6, stl); } } }

Cлучайные товары

Собрал я машинку: СобираемArduino машинку на Motor Shield L293D и ИКпульте

Управлять пультом дистанционного управления не очень удобно. Вторую машинку я собрал на Wi-fi: СамодельнаяWifi машинка на NodeMCU. Машина делает дрифт

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

Поэтому я решил сделать машинку на радио управлении.

Что мне понадобится.

Пульт:

1.Arduino Nano

2. Джойстик модуль KY-023

3 Гироскоп GY-521

4. Радио модуль NRF24L01 2.4 ГГц

5.Контроллер заряда 18650

6. MT3608 DC-DC Step Up

7. Кнопки для проектов на arduino

Машинка:

1. Arduino UNO

2.Радиомодуль NRF24L01 2.4 ГГц

3. Два мотор редуктора и два колеса

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

5. Источник питания. Я использовал power bank

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

Схема подключения пульта управления на Arduino + NRF24L01 + гироскоп GY-521 MPU-6050 выглядит вот так.

Скетч в среде программирования Arduino IDE выглядит вот так.

#include <SPI.h> #include <nRF24L01.h> #include <RF24.h> const uint64_t pipe = 0xF0F1F2F3F4LL; RF24 radio(9, 10); byte button_jostik = 8; // кнопка джостика byte button_1 = 2; // кнопка byte button_2 = 3; // кнопка byte button_3 = 4; // кнопка byte button_4 = 4; // кнопка byte button_5 = 5; // кнопка byte button_6 = 7; // кнопка byte transmit_data; // массив, хранящий передаваемые данные byte latest_data; // массив, хранящий последние переданные данные boolean flag; // флажок отправки данных // Гироскоп /// #include <Wire.h> #include «Kalman.h» Kalman kalmanX; Kalman kalmanY; uint8_t IMUAddress = 0x68; /* IMU Data */ int16_t accX; int16_t accY; int16_t accZ; int16_t tempRaw; int16_t gyroX; int16_t gyroY; int16_t gyroZ; double accXangle; // Angle calculate using the accelerometer double accYangle; double temp; double gyroXangle = 180; // Angle calculate using the gyro double gyroYangle = 180; double compAngleX = 180; // Calculate the angle using a Kalman filter double compAngleY = 180; double kalAngleX; // Calculate the angle using a Kalman filter double kalAngleY; uint32_t timer; /* переменные */ boolean lastButten = LOW; // предыдущее состояние кнопки boolean currentButten = LOW; // текущее состояние кнопки int status = 0; // текущий статус void setup() { Serial.begin(9600); //открываем порт для связи с ПК pinMode(button_jostik, INPUT_PULLUP); // настроить пин кнопки pinMode(button_1, INPUT_PULLUP); // настроить пин кнопки pinMode(button_2, INPUT_PULLUP); // настроить пин кнопки pinMode(button_3, INPUT_PULLUP); // настроить пин кнопки pinMode(button_4, INPUT_PULLUP); // настроить пин кнопки pinMode(button_5, INPUT_PULLUP); // настроить пин кнопки pinMode(button_6, INPUT_PULLUP); // настроить пин кнопки radio.begin(); delay(50); radio.setChannel(9); radio.setPayloadSize(8); radio.setRetries(1,1); radio.setDataRate(RF24_250KBPS); radio.setPALevel(RF24_PA_HIGH); radio.openWritingPipe(pipe); /// Гтроскоп Wire.begin(); i2cWrite(0x6B,0x00); // Disable sleep mode if(i2cRead(0x75,1) != 0x68) { // Read «WHO_AM_I» register Serial.print(F(«MPU-6050 with address 0x»)); Serial.print(IMUAddress,HEX); Serial.println(F(» is not connected»)); while(1); } kalmanX.setAngle(180); // Set starting angle kalmanY.setAngle(180); timer = micros(); } void loop() { currentButten = debvance (lastButten); // Передаем функции дребезга значение по умолчанию LOW if (lastButten == LOW && currentButten == HIGH) // Проверяем отпускали мы кнопку или нет { status = !status; // инвертируем Статус } lastButten = currentButten; // Переприсваеваем прошлое состояние кнопки if (status == true) { transmit_data = map(analogRead(A0), 0, 1023, 0, 255); // получить значение // в диапазоне 0..1023, перевести в 0..180, и записать на 1 место в массиве transmit_data = map(analogRead(A1), 0, 1023, 0, 255); } else { /* Update all the values */ uint8_t* data = i2cRead(0x3B,14); accX = ((data << 8) | data); accY = ((data << 8) | data); accZ = ((data << 8) | data); tempRaw = ((data << 8) | data); gyroX = ((data << 8) | data); gyroY = ((data << 8) | data); gyroZ = ((data << 8) | data); /* Calculate the angls based on the different sensors and algorithm */ accYangle = (atan2(accX,accZ)+PI)*RAD_TO_DEG; accXangle = (atan2(accY,accZ)+PI)*RAD_TO_DEG; double gyroXrate = (double)gyroX/131.0; double gyroYrate = -((double)gyroY/131.0); gyroXangle += gyroXrate*((double)(micros()-timer)/1000000); // Calculate gyro angle without any filter gyroYangle += gyroYrate*((double)(micros()-timer)/1000000); //gyroXangle += kalmanX.getRate()*((double)(micros()-timer)/1000000); // Calculate gyro angle using the unbiased rate //gyroYangle += kalmanY.getRate()*((double)(micros()-timer)/1000000); compAngleX = (0.93*(compAngleX+(gyroXrate*(double)(micros()-timer)/1000000)))+(0.07*accXangle); // Calculate the angle using a Complimentary filter compAngleY = (0.93*(compAngleY+(gyroYrate*(double)(micros()-timer)/1000000)))+(0.07*accYangle); kalAngleX = kalmanX.getAngle(accXangle, gyroXrate, (double)(micros()-timer)/1000000); // Calculate the angle using a Kalman filter kalAngleY = kalmanY.getAngle(accYangle, gyroYrate, (double)(micros()-timer)/1000000); timer = micros(); temp = ((double)tempRaw + 12412.0) / 340.0; Serial.print(kalAngleX);Serial.print(«\t»); Serial.print(kalAngleY);Serial.print(«\t»); //Serial.print(temp);Serial.print(«\t»); Serial.print(«\n»); int y = compAngleY; if (y>250) y=250; if (y< 110) y= 110; int x = compAngleX; if (x>250) x=250; if (x< 110) x= 110; transmit_data = map(x, 110, 250, 0, 255); // получить значение // в диапазоне 0..1023, перевести в 0..180, и записать на 1 место в массиве transmit_data = map(y, 110, 250, 0, 255); } transmit_data = !digitalRead(button_jostik); // инвертированный (!) сигнал с кнопки transmit_data = !digitalRead(button_1); // инвертированный (!) сигнал с кнопки transmit_data = !digitalRead(button_2); // инвертированный (!) сигнал с кнопк transmit_data = !digitalRead(button_3); // инвертированный (!) сигнал с кнопки transmit_data = !digitalRead(button_4); // инвертированный (!) сигнал с кнопки transmit_data = !digitalRead(button_5); // инвертированный (!) сигнал с кнопки transmit_data = !digitalRead(button_6); // инвертированный (!) сигнал с кнопки for (int i = 0; i < 9; i++) { // в цикле от 0 до числа каналов if (transmit_data != latest_data) { // если есть изменения в transmit_data flag = 1; // поднять флаг отправки по радио latest_data = transmit_data; // запомнить последнее изменение } } //if (flag == 1) { // radio.powerUp(); // включить передатчик radio.write(&transmit_data, sizeof(transmit_data)); // отправить по радио // flag = 0; //опустить флаг // radio.powerDown(); // выключить передатчик // } } boolean debvance (boolean last) //убираем дребизг { boolean current = digitalRead (button_jostik); // считываем данные с кнопки if (last != current) // Если текущее состояни еотличететься от предыдущего { delay (5); // Ждем 5 милисек. current = digitalRead (button_jostik); // Присваеваем текущее состояние кнопки return current; } } void i2cWrite(uint8_t registerAddress, uint8_t data){ Wire.beginTransmission(IMUAddress); Wire.write(registerAddress); Wire.write(data); Wire.endTransmission(); // Send stop } uint8_t* i2cRead(uint8_t registerAddress, uint8_t nbytes) { uint8_t data; Wire.beginTransmission(IMUAddress); Wire.write(registerAddress); Wire.endTransmission(false); // Don’t release the bus Wire.requestFrom(IMUAddress, nbytes); // Send a repeated start and then release the bus after reading for(uint8_t i = 0; i < nbytes; i++) data = Wire.read(); return data; }

Схема подключения Ардуино машинки на на радио управлении NRF24L01 выглядит вот таким образом.

Скетч среде программирования Arduino IDE для радио Arduino машинки.

#include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #include <Servo.h> const uint64_t pipe = 0xF0F1F2F3F4LL; RF24 radio(9, 10); byte msg; unsigned long time; int data; int pos; int fspeed; // forward speed int bspeed; // backward speed const int in1 = 2; // direction pin 1 const int in2 = 4; // direction pin 2 const int in3 = 7; // PWM pin to change speed const int in4 = 8; // direction pin 2 const int ena = 5; // PWM pin to change speed const int enb = 6; // PWM pin to change speed /* определяем два массива с перечислением пинов для каждого мотора */ unsigned char RightMotor = {in1, in2, ena}; unsigned char LeftMotor = {in3, in4, enb}; /* управление скоростью мотора 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, HIGH); digitalWrite(motor, LOW); analogWrite(motor, v*2.55); } else if (v<0) { digitalWrite(motor, LOW); digitalWrite(motor, HIGH); analogWrite(motor, (-v)*2.55); } else { digitalWrite(motor, LOW); digitalWrite(motor, LOW); analogWrite(motor, 0); } } void setup(){ pinMode(in1, OUTPUT); // connection to L298n pinMode(in2, OUTPUT); // connection to L298n pinMode(in3, OUTPUT); // connection to L298n pinMode(in4, OUTPUT); // connection to L298n pinMode(ena, OUTPUT); // connection to L298n; pinMode(enb, OUTPUT); // connection to L298n; Serial.begin(9600); delay(50); radio.begin(); radio.setChannel(9); radio.setPayloadSize(8); radio.setDataRate(RF24_250KBPS); radio.setPALevel(RF24_PA_HIGH); radio.openReadingPipe(1,pipe); radio.startListening(); } void loop() { if (radio.available()){ time = millis(); radio.read(&msg, sizeof(msg));} if (millis() — time > 1000){ msg=0; msg=0;} int x= map(msg, 0, 255, -100, 100); int y= map(msg, 0, 255, -100, 100); /* управляем правым мотором */ Wheel (RightMotor, y — x); /* управляем левым мотором */ Wheel (LeftMotor, y + x); Serial.println(msg); Serial.println(msg); }

У Вас наверное возник вопрос, а для чего 6 тактовых кнопок на пульте управлении. Данными кнопками я планирую управлять ковшом который установлю на данную Ардуино машинку . Также есть возможность поставить еще один джойстик. Я его поставлю когда буду собирать уже в нормальный корпус. Также установлю модуль NRF24L01 с внешней антенной . За всеми переделка следите на сайте Portal-PK.ru и на YouTube канале.

Характеристики модуля nRF24L01

На плате nRF24L01 встроен демодулятор, синтезатор частот и усилитель сигнала. Дальность действия модуля Arduino nRF24L01+ до 30 метров, а в версии с усилителем и антенной до 1000 метров в прямой видимости. Модуль может использовать 127 каналов связи, отличающихся частотой сигнала — от 2,4 ГГц до 2,483 ГГц. Скорость беспроводного соединения можно настраивать: 250kbps, 1Mbps или 2Mbps.

Дальность действия модуля сравнима с блютуз модулем HC-05/06, но с помощью nRF24L01 можно создать многоканальную связь. Т.е. можно объединить в общую сеть до 7 устройств, которые могут одновременно принимать и отправлять сигнал.

Распиновка радиомодуля nRF24L01+

Подключение nrf24l01 к Arduino MEGA 2560 (Arduino UNO)

Кроме сложной схемы подключения nrf24l01 к Arduino NANO и MEGA2560, плата требовательна к питанию (так утверждается на многих форумах и сайтах). Поэтому необходимо припаять к портам питания модуля (GND и VCC) конденсатор до 10мкФ — это снизит помехи. Если вы несколько раз проверили подключение и загрузили скетч с этой страницы, но модуль отказывается работать — то все дело в питании.

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

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

Схема подключения nRF24L01 к Arduino

Модуль работает по интерфейсу SPI, соответственно подключать модуль nRF24L01 следует к определенным портам микроконтроллера (не забывайте, что у Arduino Mega интерфейс SPI находится на других портах). Для наладки связи между двумя Ардуино, потребуется, как минимум два беспроводных радио модуля. Одну плату нужно настроить, как приемник сигнала (receiver), а вторую, как передатчик (transmitter).

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

  • плата Arduino Uno;
  • радио модуль;
  • USB-кабель;
  • Провода «папа-мама».

Радиомодуль nRF24L01 datasheet на русском

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

Скачать готовый скетч можно с Google Диск по ссылке .

#include <SPI.h> // библиотека для обмена данными по протоколу SPI #include <nRF24L01.h> // библиотека для nRF24L01+ #include <RF24.h> // библиотека для радио модуля RF24 radio(9,10); // Для MEGA2560 замените на RF24 radio(9,53); const uint8_t num_channels = 128; uint8_t values; int serial_putc( char c, FILE * ) { Serial.write( c ); return c; } void printf_begin(void) { fdevopen( &serial_putc, 0 ); } void setup(void) { Serial.begin(9600); printf_begin(); radio.begin(); radio.setAutoAck(false); radio.startListening(); // включаем прием сигнала radio.printDetails(); // если правильно соединили, то увидите настройки модуля delay(10000); // задержка на 10 секунд radio.stopListening(); // выключаем прием сигнала int i = 0; // вывод заголовков всех 127 каналов while ( i < num_channels ) { printf(«%x»,i>>4); ++i; } printf(«\n\r»); i = 0; while ( i < num_channels ) { printf(«%x»,i&0xf); ++i; } printf(«\n\r»); } const int num_reps = 100; void loop(void) { memset(values, 0, sizeof(values)); int rep_counter = num_reps; while (rep_counter—) { int i = num_channels; while (i—) { radio.setChannel(i); radio.startListening(); // включаем прием сигнала delayMicroseconds(128); radio.stopListening(); // выключаем прием сигнала if ( radio.testCarrier() ) ++values; } } int i = 0; while ( i < num_channels ) { printf(«%x», min(0xf, values & 0xf)); ++i; } printf(«\n\r»); }

Пояснения к коду:

  1. Скетч выводит на последовательный порт информацию о модуле nRF24L01+;
  2. Далее выводится информация о всех частотах на которых работает модуль и информацию об их загруженности, выбирайте частоту для работы без помех;

Вывод характеристик nRF24L01+. Сканер и проверка модуля

Если скетч успешно загрузился на Arduino NANO или UNO, но вы не видите похожую информацию на мониторе последовательного порта, то еще раз проверьте соединение платы с микроконтроллером (возможно где-то просто нет контакта). Возможно у вас модуль от другого производителя, тогда советуем вам ознакомиться с информацией на форуме: forum.amperka.ru/threads/nrf24l01-побеждаем-модуль.3205/.

nRF24L01. Сканирование радио каналов связи на помехи

Через 10 секунд после получения информации о характеристиках nRF24L01+ вы получите информацию о помехах на всех 127 каналах связи. Первые две строчки — это имена каналов, состоящие из двух символов на первой и второй строке (выделены красным квадратом). Далее идет информация о помехах. На скриншоте видно, что с 4 по 22 канал лучше не использовать для соединения устройств по радиосигналу.

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