Машинка на радиоуправлении. Arduino + nrf24l01 + пульт.

.Машинка на радиоуправлении. Arduino + nrf24l01 + пульт.

Давно я уже не делал радио управляемые модели . Решил оживить свой старый проект: Радиоуправлениена Arduino + NRF24L01 + гироскоп GY-521 MPU-6050. Но не просто оживить. Но и доработать. Так как у меня есть 3D принтер . Раму для машины решил напечатать новую. Так же с кодом решил немного поработать. За это время знаний стало больше и на старые проекты уже смотрю совсем по другому. Но обо всем по порядку.

И так напечатал раму для Ардуино машинки . Фото уже выкладывал в группе в ВК. Вот что получилось:

напечатал раму для Ардуино машинки

Исходники для печати можете скачать тут.

Установил электронику: Arduino UNO, драйвер L298n, два мотор-редуктора с колесами и конечно же радио модуль nrf24l01.

Arduino UNO, драйвер L298n, два мотор-редуктора с колесами

Все комплектующие лучше покупать в Китае. Например на сайте aliexpress. Потратите в 2 раза меньше. И доставка у недорогих товаров бесплатная или очень маленькая. А если купить у одного проводка. То можно сэкономить на доставке . Для этого берем 1 товар с платной доставкой. А остальные с бесплатной. И вам все положат в одну посылку и ВСЕ отправят платной доставкой. Вот такой небольшой ЛайфХак.

Установить переключатель

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

Установил 2 бокса под аккумуляторы 18650

Установил 2 бокса под аккумуляторы 18650. Соединил их последовательно и подключил к драйверу L298n. Так как у драйвера есть понижающий стабилизатор на 5 вольт. С соответствующих разъемов мы берм 5в и подключаем Arduino UNO. Но тут есть минус. Нужно следить, чтобы аккумуляторы не пере разрядились. Иначе они выйдут из строя. Остальная часть схемы ни чем не отличается от предыдущего проекта.

Схема подключения Ардуино машинки на радио управлении

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

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

Скетч тоже без изменений.

#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;
}

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

Пульт планирую переделывать

И ребенок у меня его модернизировал. Проводки пере подключал. Я конечно все восстановил. Но работает немного не так как раньше. Смотрите в видео всем отличие.


Искать причину почему радио пульт стал так работать нет времени и желания. Как говорил все ровно его буду переделывать.

#include <SPI.h>        
#include <nRF24L01.h>
#include <RF24.h>
const uint64_t pipe = 0xF0F1F2F3F4LL; 
RF24 radio(9, 10); 
byte msg[9];
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);
 pinMode(LED_BUILTIN, OUTPUT);
 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()){ 
radio.read(&msg, sizeof(msg));
} 
else
{
msg[1]=127;
msg[2]=127;}
int x= map(msg[2], 0, 255, -100, 100);
int y= map(msg[1], 0, 255, -100, 100);
 /* управляем правым мотором */
  Wheel (RightMotor, x - y);
  /* управляем левым мотором */
  Wheel (LeftMotor, x + y); 
//Serial.println(msg[1]);
}

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

int x= map(msg[2], 0, 255, -100, 100);
int y= map(msg[1], 0, 255, -100, 100);

При отсутствии связи данные параметры были равны 0. А ноль по коду мы приводим к -100. Вращаем колесо в обратную сторону. Вот от сюда и проблема.

машинка на Arduino радио модуле nrf24l01 с пультом управления

В итоге получилась вот такая машинка на Arduino радио модуле nrf24l01 с пультом управления. Который управляет машиной при наклоне пульта. Не нужно нажимать на кнопки.

Машинка и пульт управления на Ардуино

Планирую доработку пульта и машинки. Так что Не забывайте подписываться на канал Youtube и вступайте в группы в Вконтакте и Facebook.Всем Пока-Пока. И до встречи в следующем проекте.

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

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

Комментарии

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

Владимир
#8 Гость: Владимир (5 июля, 2022 в 22:56)

Собрал данную схему залил скетчи, но не работает. Нрф модули проверил. Двигатели свистят, а на команды пульта нет реакции. Библиотеки брал из просторов инета. Может кто нибудь дать подробную инструкцию как запустить проэкты. Заранее спасибо.

РоманСкрепкин
#6 РоманСкрепкин (6 декабря, 2020 в 23:26)
Отличная машина.Хочу повторить.Схемму плохо видно.Можно получить ссылку где есть более четкая схемма.Пожалуйста если можна.Большое Спасибо.
Степка-3003
#5 Степка-3003 (31 октября, 2019 в 09:10)
жду продолжения. Интересная реализация. 
валентин
#4 Гость: валентин (12 октября, 2019 в 19:01)

скетч для пульта не залить в ардуин (ошыбка копмиляции для платы ардуино наноОТВЕТИТЬ

Крпитер
#3 Гость: Крпитер (24 сентября, 2019 в 15:54)

идея нормальная. Пульт ужасный!

Никита-1101
#2 Гость: Никита-1101 (23 сентября, 2019 в 19:49)

Отличная машина на радио управлении. Постараюсь повторить. Спасибо!

крокодил
#1 крокодил (21 сентября, 2019 в 11:52)
Радиоуправляемая машинка супер!Не хватает корпуса. Кстати где он?

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

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

Мы в соц сетях

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

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