Машинка на радиоуправлении. Arduino + nrf24l01 + пульт.
Давно
я уже не делал
радио
управляемые модели
.
Решил оживить свой старый проект:
Радиоуправлениена Arduino + NRF24L01 + гироскоп GY-521 MPU-6050.
Но
не просто оживить. Но
и доработать.
Так как у меня есть
3D
принтер
.
Раму для машины решил напечатать новую.
Так
же
с кодом решил немного поработать. За
это время знаний стало больше и на старые
проекты уже смотрю совсем
по другому.
Но обо всем по порядку.
И
так
напечаталраму для Ардуино
машинки
. Фото уже выкладывал в группе
в ВК. Вот что получилось:
Все
комплектующие лучше покупать в Китае.
Например
на сайтеaliexpress.
Потратите в 2 раза меньше. И доставка у
недорогих товаров бесплатная или очень
маленькая. А если купить у одного
проводка.
То
можно
сэкономить
на доставке
.
Для
этого берем
1 товар с платной доставкой. А остальные
с бесплатной. И вам все положат в одну
посылку и
ВСЕотправят
платной доставкой.
Вот такой небольшой
ЛайфХак.
Установить
переключатель, который будет включать
машинку некуда. Поэтому пришлось
приколхозить вот такой кусочек фанеры
и установить туда переключатель. В
дальнейшем его покрашу, или перенесу
переключатель.
Установил
2 бокса под
аккумуляторы 18650.
Соединил их последовательно и подключил
к
драйверу L298n. Так как у драйвера
есть понижающий стабилизатор на 5 вольт.
С соответствующих разъемов мы берм 5в
и
подключаемArduino UNO. Но тут есть
минус. Нужно следить, чтобы
аккумуляторы
не пере разрядились. Иначе они выйдут
из строя. Остальная часть схемы ни чем
не отличается от предыдущего проекта.
Пульт
управления
берем из предыдущего проекта. Схема
подключения пульта
управления на 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
с
пультом
управления. Который
управляет
машиной
при наклоне
пульта.
Не нужно нажимать на кнопки.
Планирую
доработку пульта
и машинки. Так что Не забывайте подписываться на канал
Youtube и вступайте в группы в Вконтакте и Facebook.Всем Пока-Пока. И до встречи в следующем проекте.
Собрал данную схему залил скетчи, но не работает. Нрф модули проверил. Двигатели свистят, а на команды пульта нет реакции. Библиотеки брал из просторов инета. Может кто нибудь дать подробную инструкцию как запустить проэкты. Заранее спасибо.
Комментарии
Войдите или Зарегистрируйтесь И Вы сможете общаться на форуме и оставлять комментарии без капчи.