Собрал я машинку: СобираемArduino машинку на Motor Shield L293D и ИКпульте
Управлять пультом дистанционного управления не очень удобно. Вторую машинку я собрал на Wi-fi: СамодельнаяWifi машинка на NodeMCU. Машина делает дрифт
Данная машинка получилась более быстрая и удобная в управлении. Но все равно чего-то не хватает: гибкости настройки программы, чувствительности джойстика и пр.
Поэтому я решил сделать машинку на радио управлении.
Что мне понадобится.
Пульт:
4. Радио модуль NRF24L01 2.4 ГГц
7. Кнопки для проектов на arduino
Машинка:
1. Arduino UNO
2.Радиомодуль NRF24L01 2.4 ГГц
3. Два мотор редуктора и два колеса
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 канале.
Понравилась статья? Поделитесь ею с друзьями:
Вернуться в раздел: Проекты на Arduino Дата публикации 2 октября , 2017
Читайте также
А для чего гироскоп? Да к тому же на пульте.
собрал все по мануалу - второй двигатель постоянно крутится и больше ни чего не происходит. куда копать? как сделать рабочие девайсы?У вас нет радио связи. Ищите причину. Проверяйте соединения. Чтобы не крутилось колесо используйте скетч отсюда. Данная проблема устранена.
Попробуем!
Приветик всем, я тут новенький
При подключении питания к Уно начинает работать один из двигателей. на команды с пульта реакции нет :( как исправить?
Когда планируется установка и подключение ковша?
Очень хочется повторить такую машинку, однако при заливке скетча постоянно выскакивает ошибка компиляции.
Некоторые другие скетчи заливаются без проблем.
Комментарии
Войдите или Зарегистрируйтесь И Вы сможете общаться на форуме и оставлять комментарии без капчи.