Собрал я
машинку:
Собираем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[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 выглядит вот таким
образом.
Скетч среде
программирования 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.
Спасибо за внимание!
Понравилась статья? Поделитесь ею с друзьями:
Комментарии
Войдите или Зарегистрируйтесь И Вы сможете общаться на форуме и оставлять комментарии без капчи.