Радиоуправление на Arduino + NRF24L01 + гироскоп GY-521 MPU-6050

.Радиоуправление на Arduino + NRF24L01 + гироскоп GY-521 MPU-6050

Собрал я машинку: Собираем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 + NRF24L01 + гироскоп GY-521

Скетч в среде программирования 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[9]; // массив, хранящий передаваемые данные
byte latest_data[9]; // массив, хранящий последние переданные данные
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)[0] != 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[1] = map(analogRead(A0), 0, 1023, 0, 255); // получить значение
    // в диапазоне 0..1023, перевести в 0..180, и записать на 1 место в массиве
    transmit_data[2] = map(analogRead(A1), 0, 1023, 0, 255);
    }
  else
  {
    /* Update all the values */
    uint8_t* data = i2cRead(0x3B,14);
    accX = ((data[0] << 8) | data[1]);
    accY = ((data[2] << 8) | data[3]);
    accZ = ((data[4] << 8) | data[5]);
    tempRaw = ((data[6] << 8) | data[7]);
    gyroX = ((data[8] << 8) | data[9]);
    gyroY = ((data[10] << 8) | data[11]);
    gyroZ = ((data[12] << 8) | data[13]);
  
    /* 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[1] = map(x, 110, 250, 0, 255); // получить значение
    // в диапазоне 0..1023, перевести в 0..180, и записать на 1 место в массиве
    transmit_data[2] = map(y, 110, 250, 0, 255);
  
  }
  
  transmit_data[0] = !digitalRead(button_jostik); // инвертированный (!) сигнал с кнопки

  transmit_data[3] = !digitalRead(button_1); // инвертированный (!) сигнал с кнопки
   transmit_data[4] = !digitalRead(button_2); // инвертированный (!) сигнал с кнопк
   transmit_data[5] = !digitalRead(button_3); // инвертированный (!) сигнал с кнопки
   transmit_data[6] = !digitalRead(button_4); // инвертированный (!) сигнал с кнопки
   transmit_data[7] = !digitalRead(button_5); // инвертированный (!) сигнал с кнопки
   transmit_data[8] = !digitalRead(button_6); // инвертированный (!) сигнал с кнопки
            
  for (int i = 0; i < 9; i++) { // в цикле от 0 до числа каналов
    if (transmit_data[i] != latest_data[i]) { // если есть изменения в transmit_data
      flag = 1; // поднять флаг отправки по радио
      latest_data[i] = transmit_data[i]; // запомнить последнее изменение
    }
  }

  //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[nbytes];
  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[i] = Wire.read();
  return data;
}

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

Схема подключения Ардуино машинки на на радио управлении 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[9];
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[3] =   {in1, in2, ena};
unsigned char LeftMotor[3] =   {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[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(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]=0;
msg[1]=0;}
int x= map(msg[2], 0, 255, -100, 100);
int y= map(msg[1], 0, 255, -100, 100);
 /* управляем правым мотором */
  Wheel (RightMotor, y - x);
  /* управляем левым мотором */
  Wheel (LeftMotor, y + x); 
Serial.println(msg[1]);
Serial.println(msg[2]);
}

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

Подписывайтесь на мой канал на Youtube и вступайте в группы в Вконтакте и Facebook.

Спасибо за внимание!


Понравилась статья? Поделитесь ею с друзьями:

Вернуться в раздел: Проекты на Arduino Дата публикации 2 октября , 2017

Комментарии

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

Дмитрий
#22 Гость: Дмитрий (8 февраля, 2021 в 20:04)

А для чего гироскоп? Да к тому же на пульте.

Admin
#11 Admin (8 февраля, 2020 в 18:22)
собрал все по мануалу - второй двигатель постоянно крутится и больше ни чего не происходит. куда копать? как сделать рабочие девайсы?
У вас нет радио связи. Ищите причину. Проверяйте соединения.  Чтобы не крутилось колесо используйте скетч отсюда. Данная проблема устранена.

Машинка на радиоуправлении. Arduino + nrf24l01 + пульт.
Feelleen
#8 Feelleen (7 февраля, 2020 в 11:25)
собрал все по мануалу - второй двигатель постоянно крутится и больше ни чего не происходит. куда копать? как сделать рабочие девайсы?
Серёга
#7 Гость: Серёга (30 января, 2020 в 16:04)

Попробуем!

мармок
#6 мармок (2 октября, 2019 в 14:36)

Какая то она странная вы сделали ее из доски.

ThomasPlersGK
#4 Гость: ThomasPlersGK (20 августа, 2019 в 12:41)

Приветик всем, я тут новенький

аЛЕКСАНДР
#3 Гость: аЛЕКСАНДР (12 апреля, 2019 в 21:32)

При подключении питания к Уно начинает работать один из двигателей. на команды с пульта реакции нет :( как исправить?

Саша Радюк
#2 Гость: Саша Радюк (20 февраля, 2019 в 12:47)

Когда планируется установка и подключение ковша?

Антон Кузнецов
#1 Гость: Антон Кузнецов (20 февраля, 2019 в 12:46)

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

Некоторые другие скетчи заливаются без проблем.


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

Посмотреть товар в Магазине »

Мы в соц сетях

Подпишись на канал Telegram

Portal-PK (Портал ПК) © 2015 - 2024
Разработка проектов
AT Block
DWIN Box