Тормозит радио пульт или автор скетча ?
- Войдите на сайт для отправки комментариев
Доброго времени суток!
Помогите понять, почему так не сразу реагирует робот на команды с пульта.
кнопка не всегда срабатывает, иногда ее состояние вообще не передается.
Серва - пока не закончит движение по одной команде - на другие не реагирует. На пульте серва уже пару раз туда-обратно сгоняла, а на машинке через раз.
Однозначно где-то лоханулся в коде, что, в прочем, закономерно. Подскажите, что поправить. Желательно, доходчиво, как для чайника. И еще вопрос: Я Правильно понимаю, что у меня прерывание по кнопке на пульте - до одного места, так как данные все равно пакетом общим передаются ?
И еще один вопрос: В моем случае прерывание на пульте до одного места, так как данные передаются общим пакетом?
Скетч Пульта
/* Пульт радиоуправляемой машинки
- Arduino NANO
Подключены устройства
вывода
- LCD 128x64 i2c
- серво
ввода
- Джойстик 2 шт
- Кнопка
*/
/* Подключаем передатчик и библиотеку RadioHead - не пашет совместно с Adafruit_SSD1306. как и VirtualWire
Добавим Серво без библиотек, уберем дисплей
*/
//подключаем библиотеки ////////////////////////////
#include <Wire.h>
#include <SPI.h> //Библиотека (Serial Peripheral Interface), или последовательный периферийный интерфейс
//#include <Servo.h>
int servoPin_1 = 6;
float pos_1 ;
float pos_2 ;
int myAngle; // будет хранить угол поворота
int pulseWidth; // длительность импульса
//#include <Adafruit_GFX.h> //Библиотека экрана
//#include <Adafruit_SSD1306.h> //Библиотека экрана
#include <RH_ASK.h>
#include <SPI.h>
RH_ASK driver (2000, 12);;
////Определение Экрана
//#define OLED_RESET 4
//Adafruit_SSD1306 display(OLED_RESET);
//#define NUMFLAKES 10
//#define XPOS 0
//#define YPOS 1
//#define DELTAY 2
//#if (SSD1306_LCDHEIGHT != 64)
//#error("Height incorrect, please fix Adafruit_SSD1306.h!");
//#endif
// Пины и переменные
#define Joy_1_Pin_X A0 // Джойстик 1 Ось Х
#define Joy_1_Pin_Y A1 // Джойстик 1 Ось Y
#define Joy_1_Pin_Sw 7 // Джойстик 1 SW
#define Joy_2_Pin_X A2 // Джойстик 2 Ось Х
#define Joy_2_Pin_Y A3 // Джойстик 2 Ось Y
#define Joy_2_Pin_Sw 8 // Джойстик 2 SW
#define Sw_1_Pin 10 // Кнопка 1
int Joy_1_Val_X ;
int Joy_1_Val_Y ;
int Joy_1_Val_Sw ;
int Joy_2_Val_X ;
int Joy_2_Val_Y ;
int Joy_2_Val_Sw ;
int Sw_1_Val ;
/// Определяем передатчик
struct SEND_DATA_STRUCTURE{
int Joy_1_Val_X ;
int Joy_1_Val_Y ;
int Joy_1_Val_Sw ;
int Joy_2_Val_X ;
int Joy_2_Val_Y ;
int Joy_2_Val_Sw ;
int Sw_1_Val ;
};
SEND_DATA_STRUCTURE mydata;
byte tx_buf[sizeof(mydata)] = {};
////******убираем к чертям DELAY****Спасибо г-н Клапауций 322 http://arduino.ru/forum/programmirovanie/klass-titanovyi-velosiped-dlya-...
long previousMillis = 0; // храним время последнего действия чтением датчиков
long interval = 200; // интервал между чтением датчиков
void setup() {
Serial.begin(9600);
Serial.println("test start!");
// только для отладки
if (!driver.init())
Serial.println("init failed");
// myservo_1.attach(servoPin_1); // attaches the servo on pin 6
pinMode(servoPin_1, OUTPUT); // конфигурируем пин сервы, как выход
pinMode (Joy_1_Pin_Sw, INPUT);
pinMode (Joy_2_Pin_Sw, INPUT);
digitalWrite(Joy_1_Pin_Sw, HIGH); // включаем встроенный подтягивающий резистор
digitalWrite(Joy_2_Pin_Sw, HIGH); // включаем встроенный подтягивающий резистор
pinMode (Sw_1_Pin, INPUT);
digitalWrite(Sw_1_Pin, HIGH); // включаем встроенный подтягивающий резистор
// display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3С (for the 128x64)
// display.display();
// delay(200);
// display.clearDisplay();
// display.setTextSize(1);
// display.setTextColor(WHITE);
// display.clearDisplay();
} /* --(end setup )-- */
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// READ_DATA();
previousMillis = currentMillis; // сохраняем время последнего переключения
}
// LCD_PRINT ();
READ_DATA();
myAngle = map (Joy_1_Val_X, 0, 1021 , 0, 180);
servoPulse(servoPin_1, myAngle);
mydata.Joy_1_Val_X = Joy_1_Val_X;
mydata.Joy_1_Val_Y = Joy_1_Val_Y;
mydata.Joy_1_Val_Sw = Joy_1_Val_Sw;
mydata.Joy_2_Val_X = Joy_2_Val_X;
mydata.Joy_2_Val_Y = Joy_2_Val_Y;
mydata.Joy_2_Val_Sw = Joy_2_Val_Sw;
mydata.Sw_1_Val = Sw_1_Val;
memcpy(tx_buf, &mydata, sizeof(mydata) );
byte size_mydata = sizeof(mydata);
driver.send((uint8_t *)tx_buf, size_mydata);
driver.waitPacketSent();
Serial.print ("Joy_1_Val_X : ");
Serial.print (Joy_1_Val_X);
Serial.print (" Joy_1_Val_Y : ");
Serial.print (Joy_1_Val_Y);
Serial.print (" Joy_1_Val_Sw : ");
Serial.print (Joy_1_Val_Sw);
Serial.print (" Joy_2_Val_X : ");
Serial.print (Joy_2_Val_X);
Serial.print (" Joy_2_Val_Y : ");
Serial.print (Joy_2_Val_Y);
Serial.print (" Joy_2_Val_Sw : ");
Serial.print (Joy_2_Val_Sw);
Serial.print (" Sw_1_Val : ");
Serial.print (Sw_1_Val);
Serial.print ("\n");
// Serial.print ("myAngle :");
// Serial.print (myAngle);
// Serial.print ("pulseWidth :");
// Serial.print (pulseWidth);
Serial.print ("\n");
// delay (200);
} /* --(end main loop )-- */
//////////////////////////////////////////////////////////////////////////////////////////////////
/*-----( Declare User-written Functions )-----*/
void servoPulse(int servoPin_1, int myAngle)
{
pulseWidth = (myAngle * 10) + 400; // конвертируем угол в микросекунды
digitalWrite(servoPin_1, HIGH); // устанавливаем серве высокий уровень
delayMicroseconds(pulseWidth); // ждём
digitalWrite(servoPin_1, LOW); // устанавливаем низкий уровень
delay(20); //
}
void READ_DATA ()
{
Joy_1_Val_X = analogRead(Joy_1_Pin_X); //// Джойстик 1 Ось Х
// delay(10); //recomanen posar-ho
Joy_1_Val_Y = analogRead(Joy_1_Pin_Y); //// Джойстик 1 Ось Х
// delay(10); //recomanen posar-ho
Joy_1_Val_Sw = digitalRead (Joy_1_Pin_Sw); //Джойстик 1 SW
Joy_2_Val_X = analogRead(Joy_2_Pin_X); //// Джойстик 2 Ось Х
// delay(10); //recomanen posar-ho
Joy_2_Val_Y = analogRead(Joy_2_Pin_Y); //// Джойстик 2 Ось Х
// delay(10); //recomanen posar-ho
Joy_2_Val_Sw = digitalRead (Joy_2_Pin_Sw); //Джойстик 2 SW
Sw_1_Val = digitalRead (Sw_1_Pin); //Кнопка 1
}
//void LCD_PRINT ()
//{
// display.setCursor(0,0);
// display.print("Joy_1_X: ");
// display.print(Joy_1_Val_X);
// display.setCursor(0,15);
// display.print("Joy_1_Y: ");
// display.print(Joy_1_Val_Y);
// display.setCursor(80,15);
// display.print("SW_1: ");
// display.print(Joy_1_Val_Sw);
//
// display.setCursor(0,30);
// display.print("Joy_2_X: ");
// display.print(Joy_2_Val_X);
// display.setCursor(0,45);
// display.print("Joy_2_Y: ");
// display.print(Joy_2_Val_Y);
// display.setCursor(80,45);
// display.print("SW_2: ");
// display.print(Joy_2_Val_Sw);
//
// display.setCursor(0,55);
// display.print("Swich_1: ");
// display.print(Sw_1_Val);
//
// display.display();
// display.clearDisplay();
//}
Скетч машинки
/* ИСТОРИЯ ДОБАВЛЕНИЙ, ИЗМЕНЕНИЙ И НОВЫХ МОДУЛЕЙ
01
Подключаем радио приемник 433 и библиотеку RadioHead с прерыванием 2
-RF 433 Mhz
02
Управляем моторами
Ещу будут
/ - PIR движения
/ - Photo фоторезистор + 10 kOm
- Ir препятствий 4 шт
/ - КТ 973 (2 шт) , резистор 2.2kOm, диод на обратный ток, на линии 12В
/ - КТ 972 (2 шт) резистор 10kOm,на линии 12В
*/
/* ОПИСАНИЕ ПОДКЛЮЧЕННЫХ УСТРОЙСТВ И МОДУЛЕЙ
Подключены устройства
- Arduino MEGA 2560
- L298N motor driver
- LCD 16x2 i2c
- 4 x Geared motor
- Servo
// - RTC DS1307 i2c
Подключены датчики и сенсоры
- Ultrasonic
- Джойстик 2 шт
Ну и еще
- Спикер с конденсатором на 10 mf
Силовая часть
- 4х1500mA Li-ion - 8,4В
- 3х1800mA Li-ion - 12,2В
- 2 шт Mini Red LED Panel Voltage Meter 3-Digital Adjustment Voltmeter - для двух батарей
- Стабилизаторы напряжения на 9, 5 и 3,3в
- несколько линеек светодиодов на 12В - Фары, днище, задний свет
- Двухцветные светодиоды 3В на колеса
*/
//В начале было слово:
/* --- подключаем библиотеки --- */
#include <Motor.h> //Motor.h - Library for powering robot motors.
#include <LiquidCrystal_I2C.h> //A library for I2C LCD displays
#include <Wire.h>
#include "Ultrasonic.h"
#include <RH_ASK.h>
#include <SPI.h>
/* --- Назначаем PIN подключения девайсов --- */
// ВХОДЫ
#define Sonic_1_Pin1 22 // 22->trig, 23->echo
#define Sonic_1_Pin2 23
int Rec_Pin = 11;
int Servo_1_Pin = 31;
/// Приемник радио 433 Mhz
RH_ASK driver (2000, Rec_Pin); /// Which will initialise the driver at 2000 bps
//#define Receiver_Pin 12 // Радио Приемник
//#define PirPin A3 // Датчик движения
//#define Ir_1_Pin A8 // IR препятствие 1
//#define Ir_2_Pin A8 // IR препятствие 2
//#define Ir_3_Pin A8 // IR препятствие 3
//#define Ir_4_Pin A8 // IR препятствие 4
// ВЫХОДЫ
#define SpkPin 8 // Спикер
//#define LazerPin 0 // определение управления лазером и подсветкой CONTROL_PIN 8
//#define LedFrontPin 0 // Фара
//#define LedBackPin 0 // Задний свет
//#define LedBottomPin 0 // Свет на днище
//#define LedWheelPin 0 // Свет на колесах
#define Led_1_Pin 49 // Кнопка 1 - светодиод
/* --- Объявляем что можем --- */
Ultrasonic ultrasonic(Sonic_1_Pin1, Sonic_1_Pin2);
Motor motor;
LiquidCrystal_I2C lcd(0x27, 20, 2); // адрес LCD
/// Приемник радио 433 Mhz
//RH_ASK driver (2000, Rec_Pin); /// Which will initialise the driver at 2000 bps
struct SEND_DATA_STRUCTURE { // структура данных должна быть в точности одинакова для передатчика и для приемника!
int Joy_1_Val_X ;
int Joy_1_Val_Y ;
int Joy_1_Val_Sw ;
int Joy_2_Val_X ;
int Joy_2_Val_Y ;
int Joy_2_Val_Sw ;
int Sw_1_Val ;
};
SEND_DATA_STRUCTURE mydata;
byte tx_buf[sizeof(mydata)] = {
};
/* --- И переменные --- */
//Для и Ultrasonic
const int STEP = 5; //
const int SIZE = 37; // Size of distance array =(180/STEP) +1
int dist[SIZE];
////Для Servo
int myAngle; // будет хранить угол поворота
int pulseWidth; // длительность импульса
//для Motor
int rDelay;
int s = 16; // rotation time ms/degree (16 on carpet and 8 on wooden floor)
//int s = 32; // rotation time ms/degree (16 on carpet and 8 on wooden floor)
// для джойстиков
int Joy_1_Val_X = 0;//valor X
int Joy_1_Val_Y = 0;//valor Y
int Joy_1_Val_Sw = 0;//valor X
int Joy_2_Val_X = 0;//valor X
int Joy_2_Val_Y = 0;//valor Y
int Joy_2_Val_Sw = 0;//valor X
int Sw_1_Val = 0;
////******убираем DELAY************
long previousMillis = 0; // храним время последнего действия чтением датчиков
long interval = 10; // интервал между чтением датчиков
/////***************************************************************************************
void setup() {
Wire.begin();
motor.stop(motor.Motor_LR);
Serial.begin(9600);
if (!driver.init())
Serial.println("init failed");
pinMode(SpkPin, OUTPUT);
pinMode (Led_1_Pin , OUTPUT);
pinMode(Servo_1_Pin, OUTPUT);
// pinMode(LazerPin, OUTPUT);
/* --- Запускаем приветствие на LCD --- */
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" P R I V E T ");
lcd.setCursor(0, 1);
lcd.print(" M A S T E R ");
delay (1000);
/* --- выводим на LCD постоянный текст --- */
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("X1:");
lcd.setCursor(0, 1);
lcd.print("Y1:");
lcd.setCursor(8, 0);
lcd.print("X2:");
lcd.setCursor(8, 1);
lcd.print("Y2:");
} /* --(end setup )-- */
/////***************************************************************************************
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis; // сохраняем время последнего переключения
// пока тут ничего нет
}
///////Получение данных с пульта
uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
uint8_t buflen = sizeof(buf);
if (driver.recv(buf, &buflen)) // Non-blocking
{
memcpy(&mydata, buf, sizeof(mydata));
}
READ_DATA(); ///* Преобразование данных, полученных с пульта*/
digitalWrite(Led_1_Pin, Sw_1_Val);
if (Joy_1_Val_X > 510 || Joy_1_Val_X < 490) { //убираем колебания джойстика
SERVO_1(Servo_1_Pin, myAngle);
}
else {Joy_1_Val_X = 500;}
SERVO_1(Servo_1_Pin, myAngle);
LCD_PRINT ();
SerMon_PRINT();
// GoGO();
} /* --(end main loop )-- */
//////////////////////////////////////////////////////////////////////////////////////////////////
/*-----( Declare User-written Functions )-----*/
void READ_DATA () ///* Преобразование данных, полученных с пульта*/
{
Joy_1_Val_X = mydata.Joy_1_Val_X ;
Joy_1_Val_Y = mydata.Joy_1_Val_Y;
Joy_1_Val_Sw = mydata.Joy_1_Val_Sw;
Joy_2_Val_X = mydata.Joy_2_Val_X;
Joy_2_Val_Y = mydata.Joy_2_Val_Y;
Joy_2_Val_Sw = mydata.Joy_2_Val_Sw;
Sw_1_Val = mydata.Sw_1_Val;
}
void SERVO_1 (int Servo_1_Pin, int myAngle)
{
myAngle = map (Joy_1_Val_X, 0, 1021 , 0, 180);
pulseWidth = (myAngle * 10) + 400; // конвертируем угол в микросекунды
digitalWrite(Servo_1_Pin, HIGH); // устанавливаем серве высокий уровень
delayMicroseconds(pulseWidth); // ждём
digitalWrite(Servo_1_Pin, LOW); // устанавливаем низкий уровень
delay(10); //
}
void LCD_PRINT () ////* вывод значений на LCD */
{
lcd.setCursor(3, 0);
lcd.print(Joy_1_Val_X);
lcd.print (" ");
lcd.setCursor(3, 1);
lcd.print(Joy_1_Val_Y);
lcd.print (" ");
lcd.setCursor(11, 0);
lcd.print(Joy_2_Val_X);
lcd.print (" ");
lcd.setCursor(11, 1);
lcd.print(Joy_2_Val_Y);
lcd.print (" ");
}
void SerMon_PRINT() ////*вывод значений на Serial_Monitor*/
{
Serial.print ("Joy_1_Val_X : ");
Serial.print (Joy_1_Val_X);
Serial.print (" Joy_1_Val_Y : ");
Serial.print (Joy_1_Val_Y);
Serial.print (" Joy_1_Val_Sw : ");
Serial.print (Joy_1_Val_Sw);
Serial.print (" Joy_2_Val_X : ");
Serial.print (Joy_2_Val_X);
Serial.print (" Joy_2_Val_Y : ");
Serial.print (Joy_2_Val_Y);
Serial.print (" Joy_2_Val_Sw : ");
Serial.print (Joy_2_Val_Sw);
Serial.print (" Sw_1_Val : ");
Serial.print (Sw_1_Val);
Serial.print ("\n");
}
Вы теряете часть сообщений. Посмотрите на строки 189-192. Вы проверяеете, что "что-то" пришло. И всё. А кто Вам сказал, что пришла структура целиком а не кусочек от неё?
Если пришла целиком, то Вам повезло, а если нет, то Вы хватаете этот кусочек, работаете с ним, как с целым (т.е. хвост структуры используете "с прошлого раза"), потом, когда приходит оставшая часть структуры, Вы её снова держите за целую и т.д.
Вам нужно не просто проверять, что "что-то пришло", а заодно ещё и то, что длин пришедших данных равна sizeof(SEND_DATA_STRUCTURE). Если длина меньше, то не дергаться сразу исполнять, а подождать до следующего прохода, когда структруа придёт целиком и только тогда уже что-то исполнять.
Спасибо.
ЕвгенийП,
посмотрите, пожалуйста, правильно ли я понял Вашу подсказку. В программировании я нуб, а примеров с такой проверкой не нашел... поэтому в силу своего понимания. Компиллятор не ругается, но может там вообще бред?
///////Получение данных с пульта uint8_t buf[RH_ASK_MAX_MESSAGE_LEN]; uint8_t buflen = sizeof(buf); do { if (driver.recv(buf, &buflen) ) // Non-blocking { memcpy(&mydata, buf, sizeof(mydata)); } } while (sizeof(buf) == sizeof(SEND_DATA_STRUCTURE));может там вообще бред?
///////Получение данных с пульта uint8_t buf[RH_ASK_MAX_MESSAGE_LEN]; uint8_t buflen = sizeof(buf); do { if (driver.recv(buf, &buflen) ) // Non-blocking { memcpy(&mydata, buf, sizeof(mydata)); } } while (sizeof(buf) == sizeof(SEND_DATA_STRUCTURE));К сожалению, он самый.
Чтобы Вам можно было помочь, дайте мне сслку на ту самую библиотеку RH_ASK.h, которую Вы используете. А то уж сколько раз было - трахаешься, трахаешься, а после уймы убитого времени, выясняется. что у человека можифицирована быблиотека (не сто го сайта брал, что я). Давайте точно Вашу библиотеку - посмотрим.
/* ИСТОРИЯ ДОБАВЛЕНИЙ, ИЗМЕНЕНИЙ И НОВЫХ МОДУЛЕЙ 01 Подключаем радио приемник 433 и библиотеку RadioHead с прерыванием 2 -RF 433 Mhz 02 Управляем моторами Ещу будут / - PIR движения / - Photo фоторезистор + 10 kOm - Ir препятствий 4 шт / - КТ 973 (2 шт) , резистор 2.2kOm, диод на обратный ток, на линии 12В / - КТ 972 (2 шт) резистор 10kOm,на линии 12В */ /* ОПИСАНИЕ ПОДКЛЮЧЕННЫХ УСТРОЙСТВ И МОДУЛЕЙ Подключены устройства - Arduino MEGA 2560 - L298N motor driver - LCD 16x2 i2c - 4 x Geared motor - Servo // - RTC DS1307 i2c Подключены датчики и сенсоры - Ultrasonic - Джойстик 2 шт Ну и еще - Спикер с конденсатором на 10 mf Силовая часть - 4х1500mA Li-ion - 8,4В - 3х1800mA Li-ion - 12,2В - 2 шт Mini Red LED Panel Voltage Meter 3-Digital Adjustment Voltmeter - для двух батарей - Стабилизаторы напряжения на 9, 5 и 3,3в - несколько линеек светодиодов на 12В - Фары, днище, задний свет - Двухцветные светодиоды 3В на колеса */ //В начале было слово: /* --- подключаем библиотеки --- */ #include <Motor.h> //Motor.h - Library for powering robot motors. #include <LiquidCrystal_I2C.h> //A library for I2C LCD displays #include <Wire.h> #include "Ultrasonic.h" #include <RH_ASK.h> #include <SPI.h> /* --- Назначаем PIN подключения девайсов --- */ // ВХОДЫ #define Sonic_1_Pin1 22 // 22->trig, 23->echo #define Sonic_1_Pin2 23 int Rec_Pin = 11; int Servo_1_Pin = 31; /// Приемник радио 433 Mhz RH_ASK driver (2000, Rec_Pin); /// Which will initialise the driver at 2000 bps //#define Receiver_Pin 12 // Радио Приемник //#define PirPin A3 // Датчик движения //#define Ir_1_Pin A8 // IR препятствие 1 //#define Ir_2_Pin A8 // IR препятствие 2 //#define Ir_3_Pin A8 // IR препятствие 3 //#define Ir_4_Pin A8 // IR препятствие 4 // ВЫХОДЫ #define SpkPin 8 // Спикер //#define LazerPin 0 // определение управления лазером и подсветкой CONTROL_PIN 8 //#define LedFrontPin 0 // Фара //#define LedBackPin 0 // Задний свет //#define LedBottomPin 0 // Свет на днище //#define LedWheelPin 0 // Свет на колесах #define Led_1_Pin 49 // Кнопка 1 - светодиод /* --- Объявляем что можем --- */ Ultrasonic ultrasonic(Sonic_1_Pin1, Sonic_1_Pin2); Motor motor; LiquidCrystal_I2C lcd(0x27, 20, 2); // адрес LCD /// Приемник радио 433 Mhz //RH_ASK driver (2000, Rec_Pin); /// Which will initialise the driver at 2000 bps struct SEND_DATA_STRUCTURE { // структура данных должна быть в точности одинакова для передатчика и для приемника! int Joy_1_Val_X ; int Joy_1_Val_Y ; int Joy_1_Val_Sw ; int Joy_2_Val_X ; int Joy_2_Val_Y ; int Joy_2_Val_Sw ; int Sw_1_Val ; }; SEND_DATA_STRUCTURE mydata; byte tx_buf[sizeof(mydata)] = { }; /* --- И переменные --- */ //Для и Ultrasonic const int STEP = 5; // const int SIZE = 37; // Size of distance array =(180/STEP) +1 int dist[SIZE]; ////Для Servo int myAngle; // будет хранить угол поворота int pulseWidth; // длительность импульса //для Motor int rDelay; int s = 16; // rotation time ms/degree (16 on carpet and 8 on wooden floor) //int s = 32; // rotation time ms/degree (16 on carpet and 8 on wooden floor) int LMS = 0; int RMS = 0; int AMS = 0; int AMS1 = 0; int MooveDir = 0; int RMS1; int LMS1; // для джойстиков int Joy_1_Val_X = 0;//valor X int Joy_1_Val_Y = 0;//valor Y int Joy_1_Val_Sw = 0;//valor X int Joy_2_Val_X = 0;//valor X int Joy_2_Val_Y = 0;//valor Y int Joy_2_Val_Sw = 0;//valor X int Sw_1_Val = 0; ////******убираем DELAY************ long previousMillis = 0; // храним время последнего действия чтением датчиков long interval = 2000; // интервал между чтением датчиков /////*************************************************************************************** void setup() { Wire.begin(); motor.off(motor.Motor_LR); Serial.begin(9600); if (!driver.init()) Serial.println("init failed"); pinMode(SpkPin, OUTPUT); pinMode (Led_1_Pin , OUTPUT); pinMode(Servo_1_Pin, OUTPUT); // pinMode(LazerPin, OUTPUT); /* --- Запускаем приветствие на LCD --- */ lcd.init(); lcd.backlight(); lcd.clear(); lcd.setCursor(0, 0); lcd.print(" P R I V E T "); lcd.setCursor(0, 1); lcd.print(" M A S T E R "); delay (1000); /* --- выводим на LCD постоянный текст --- */ lcd.clear(); lcd.setCursor(0, 0); lcd.print("X2:"); lcd.setCursor(0, 1); lcd.print("Y2:"); // lcd.setCursor(7, 0); // lcd.print("D:"); // lcd.setCursor(8, 1); // lcd.print("Y2:"); } /* --(end setup )-- */ /////*************************************************************************************** void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis > interval) { //Joy_1_Val_X = 500; // SERVO_1(Servo_1_Pin, myAngle); // пока тут ничего нет previousMillis = currentMillis; // сохраняем время последнего переключения } ///////Получение данных с пульта uint8_t buf[RH_ASK_MAX_MESSAGE_LEN]; uint8_t buflen = sizeof(buf); do { if (driver.recv(buf, &buflen) ) // Non-blocking { memcpy(&mydata, buf, sizeof(mydata)); } } while (sizeof(buf) == sizeof(SEND_DATA_STRUCTURE)); READ_DATA(); ///* Преобразование данных, полученных с пульта*/ /// ---- Свет ---- digitalWrite(Led_1_Pin, Sw_1_Val); /// --- Серво ---------/// if (Joy_1_Val_X > 510 || Joy_1_Val_X < 490) //убираем колебания джойстика { SERVO_1(Servo_1_Pin, myAngle); } else { Joy_1_Val_X = 500; } SERVO_1(Servo_1_Pin, myAngle); ////------ Motor ------ if (Joy_2_Val_X == 0 & Joy_2_Val_Y == 0) { motor.off(motor.Motor_LR); } else { GoGo (); } /// ---- Print ----------- LCD_PRINT (); SerMon_PRINT(); } /* --(end main loop )-- */ ////////////////////////////////////////////////////////////////////////////////////////////////// /*-----( Declare User-written Functions )-----*/ void READ_DATA () ///* Преобразование данных, полученных с пульта*/ { Joy_1_Val_X = mydata.Joy_1_Val_X ; Joy_1_Val_Y = mydata.Joy_1_Val_Y; Joy_1_Val_Sw = mydata.Joy_1_Val_Sw; Joy_2_Val_X = mydata.Joy_2_Val_X; Joy_2_Val_Y = mydata.Joy_2_Val_Y; Joy_2_Val_Sw = mydata.Joy_2_Val_Sw; Sw_1_Val = mydata.Sw_1_Val; } void GoGo() { if (Joy_2_Val_X > 450 & Joy_2_Val_X <550 & Joy_2_Val_Y > 450 & Joy_2_Val_Y < 550 ) { MooveDir = 0; } if (Joy_2_Val_X < 450 & Joy_2_Val_Y > 450 & Joy_2_Val_Y < 550 ) { MooveDir = 1; } else { if (Joy_2_Val_X < 450 ) { MooveDir = 5; } } if (Joy_2_Val_X > 550 & Joy_2_Val_Y > 450 & Joy_2_Val_Y < 550 ) { MooveDir = 2; } else { if (Joy_2_Val_X > 550 ) { MooveDir = 6; } } if (Joy_2_Val_X > 450 & Joy_2_Val_X < 550 & Joy_2_Val_Y < 450 ) { MooveDir = 3; } if (Joy_2_Val_X > 450 & Joy_2_Val_X <550 & Joy_2_Val_Y > 550 ) { MooveDir = 4; } switch (MooveDir) { case 0: motor.off(motor.Motor_LR); break; case 1: ///////////------------------/НЕ готово AMS = (1023 - Joy_2_Val_X) ; AMS1 = AMS; AMS = map (AMS, 550, 1023, 50, 100); motor.onFwd(motor.Motor_LR, AMS); break; case 2: ///////////------------------/НЕ готово AMS = (Joy_2_Val_X) ; AMS1 = AMS; AMS = map (AMS, 550, 1023, 50, 100); motor.onRev(motor.Motor_LR, AMS); break; case 3: motor.turnRight(100); break; case 4: motor.turnLeft (100); break; case 5: ///////////------------------/НЕ готово RMS = (1023 - Joy_2_Val_X) + (Joy_2_Val_Y - 525); RMS1 = RMS; RMS = map (RMS, 550, 1550, 20, 100); LMS = (1023 - Joy_2_Val_X) - (Joy_2_Val_Y - 525); LMS1 = LMS; LMS = map (LMS, 550, 1550, 20, 100); motor.onFwd(motor.Motor_L, LMS); motor.onFwd(motor.Motor_R, RMS); break; case 6: ///////////------------------/НЕ готово RMS = (Joy_2_Val_X) - (Joy_2_Val_Y - 525); RMS1 = RMS; RMS = map (RMS, 550, 1550, 20, 100); LMS = (Joy_2_Val_X) + (Joy_2_Val_Y - 525); LMS1 = LMS; LMS = map (LMS, 550, 1550, 20, 100); motor.onRev(motor.Motor_L, LMS); motor.onRev(motor.Motor_R, RMS); break; default: break; } } void SERVO_1 (int Servo_1_Pin, int myAngle) { myAngle = map (Joy_1_Val_X, 0, 1021 , 0, 180); pulseWidth = (myAngle * 10) + 400; // конвертируем угол в микросекунды digitalWrite(Servo_1_Pin, HIGH); // устанавливаем серве высокий уровень delayMicroseconds(pulseWidth); // ждём digitalWrite(Servo_1_Pin, LOW); // устанавливаем низкий уровень delay(10); // } void LCD_PRINT () ////* вывод значений на LCD */ { lcd.setCursor(3, 0); lcd.print(Joy_2_Val_X); lcd.print (" "); lcd.setCursor(3, 1); lcd.print(Joy_2_Val_Y); lcd.print (" "); // lcd.setCursor(9, 0); // lcd.print(MooveDir); lcd.setCursor(8, 0); lcd.print ("R: "); lcd.print(RMS); lcd.print (" "); lcd.setCursor(8, 1); lcd.print ("L: "); lcd.print(LMS); lcd.print (" "); } void SerMon_PRINT() ////*вывод значений на Serial_Monitor*/ { // Serial.print ("Joy_1_Val_X : "); // Serial.print (Joy_1_Val_X); // Serial.print (" Joy_1_Val_Y : "); // Serial.print (Joy_1_Val_Y); // Serial.print (" Joy_1_Val_Sw : "); // Serial.print (Joy_1_Val_Sw); Serial.print (" Joy_2_Val_X : "); Serial.print (Joy_2_Val_X); Serial.print (" "); Serial.print (" Joy_2_Val_Y : "); Serial.print (Joy_2_Val_Y); Serial.print (" "); Serial.print (" MooveDir : "); Serial.print (MooveDir); Serial.print (" AMS_1 "); Serial.print (AMS1); Serial.print (" AMS "); Serial.print (AMS); Serial.print (" RMS_1 "); Serial.print (RMS1); Serial.print (" RMS "); Serial.print (RMS); Serial.print (" LMS_1 "); Serial.print (LMS1); Serial.print (" LMS "); Serial.print (LMS); // Serial.print (" Joy_2_Val_Sw : "); // Serial.print (Joy_2_Val_Sw); // Serial.print (" Sw_1_Val : "); // Serial.print (Sw_1_Val); Serial.print ("\n"); }Для пульта :
/* Пульт радиоуправляемой машинки - Arduino NANO Подключены устройства ввода - Джойстик 2 шт - Кнопка */ /* Убрал все лишнее */ //подключаем библиотеки //////////////////////////// #include <Wire.h> #include <SPI.h> //Библиотека (Serial Peripheral Interface), или последовательный периферийный интерфейс #include <RH_ASK.h> #include <SPI.h> RH_ASK driver (2000, 12); // Пины и переменные #define Joy_1_Pin_X A0 // Джойстик 1 Ось Х #define Joy_1_Pin_Y A1 // Джойстик 1 Ось Y #define Joy_1_Pin_Sw 7 // Джойстик 1 SW #define Joy_2_Pin_X A2 // Джойстик 2 Ось Х #define Joy_2_Pin_Y A3 // Джойстик 2 Ось Y #define Joy_2_Pin_Sw 8 // Джойстик 2 SW #define Sw_1_Pin 10 // Кнопка 1 int Joy_1_Val_X ; int Joy_1_Val_Y ; int Joy_1_Val_Sw ; int Joy_2_Val_X ; int Joy_2_Val_Y ; int Joy_2_Val_Sw ; int Sw_1_Val ; /// Определяем передатчик struct SEND_DATA_STRUCTURE { int Joy_1_Val_X ; int Joy_1_Val_Y ; int Joy_1_Val_Sw ; int Joy_2_Val_X ; int Joy_2_Val_Y ; int Joy_2_Val_Sw ; int Sw_1_Val ; }; SEND_DATA_STRUCTURE mydata; byte tx_buf[sizeof(mydata)] = {}; ////******убираем к чертям DELAY**** long previousMillis = 0; // храним время последнего действия чтением датчиков long interval = 200; // интервал между чтением датчиков void setup() { Serial.begin(9600); // только для отладки if (!driver.init()) Serial.println("init failed"); pinMode (Joy_1_Pin_Sw, INPUT); pinMode (Joy_2_Pin_Sw, INPUT); digitalWrite(Joy_1_Pin_Sw, HIGH); // включаем встроенный подтягивающий резистор digitalWrite(Joy_2_Pin_Sw, HIGH); // включаем встроенный подтягивающий резистор pinMode (Sw_1_Pin, INPUT); digitalWrite(Sw_1_Pin, HIGH); // включаем встроенный подтягивающий резистор } /* --(end setup )-- */ void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis > interval) { /////тут пока ничего нет previousMillis = currentMillis; // сохраняем время последнего переключения } READ_DATA(); mydata.Joy_1_Val_X = Joy_1_Val_X; mydata.Joy_1_Val_Y = Joy_1_Val_Y; mydata.Joy_1_Val_Sw = Joy_1_Val_Sw; mydata.Joy_2_Val_X = Joy_2_Val_X; mydata.Joy_2_Val_Y = Joy_2_Val_Y; mydata.Joy_2_Val_Sw = Joy_2_Val_Sw; mydata.Sw_1_Val = Sw_1_Val; memcpy(tx_buf, &mydata, sizeof(mydata) ); byte size_mydata = sizeof(mydata); driver.send((uint8_t *)tx_buf, size_mydata); driver.waitPacketSent(); // Serial.print ("Joy_1_Val_X : "); // Serial.print (Joy_1_Val_X); // Serial.print (" Joy_1_Val_Y : "); // Serial.print (Joy_1_Val_Y); // Serial.print (" Joy_1_Val_Sw : "); // Serial.print (Joy_1_Val_Sw); // // Serial.print (" Joy_2_Val_X : "); // Serial.print (Joy_2_Val_X); // Serial.print (" Joy_2_Val_Y : "); // Serial.print (Joy_2_Val_Y); // Serial.print (" Joy_2_Val_Sw : "); // Serial.print (Joy_2_Val_Sw); // Serial.print (" Sw_1_Val : "); // Serial.print (Sw_1_Val); // // Serial.print ("\n"); } /* --(end main loop )-- */ ////////////////////////////////////////////////////////////////////////////////////////////////// /*-----( Declare User-written Functions )-----*/ void READ_DATA () { Joy_1_Val_X = analogRead(Joy_1_Pin_X); //// Джойстик 1 Ось Х // delay(10); //recomanen posar-ho Joy_1_Val_Y = analogRead(Joy_1_Pin_Y); //// Джойстик 1 Ось Х // delay(10); //recomanen posar-ho Joy_1_Val_Sw = digitalRead (Joy_1_Pin_Sw); //Джойстик 1 SW Joy_2_Val_X = analogRead(Joy_2_Pin_X); //// Джойстик 2 Ось Х // delay(10); //recomanen posar-ho Joy_2_Val_Y = analogRead(Joy_2_Pin_Y); //// Джойстик 2 Ось Х // delay(10); //recomanen posar-ho Joy_2_Val_Sw = digitalRead (Joy_2_Pin_Sw); //Джойстик 2 SW Sw_1_Val = digitalRead (Sw_1_Pin); //Кнопка 1 }Знаете, попробуйте посмотреть что происходит с питанием в момент включения двигателей. Мы с внуком сидели с осциллографом несколько дней, вставляли фильтры питания, не помогало. Тогда просто разделили питание: моторы от одной батареи, а контроллер, приёмник и остальная логика - от другой. Как рукой сняло. Там стоит скромный, один из самых дешёвых приёмников и отлично работает - никаких нареканий.
Это правильно, потому, что нет никакой разницы, принимать сообщение от приёмника или "от телевизора" - надо просто уметь его принимать.
После этого Вы можете использовать переменную newDataArrived. Т.е. пишете if (newDataArrived ) и делаете что нужно делать, если новые данные поступили. Это понятно?
Осталось написать функцию receiveData.
Её специфика в том, что возможны разные варианты:
1. Сообщение пришло не полностью
2. Сообщение пришло полностью
3. Пришло сразу два (или полтора) сообщения (это если Вы уж очень быстро джойстиком крутите).
4. ...
Она в любом случае должна работать корректно. Вот давайте её и напишем.
#define STRUCT_LEN sizeof(SEND_DATA_STRUCTURE) bool receiveData(void) { // В dataHolder будут храниться и накапливаться полученные данные // Длина буфера dataHolder должна быть достаточной, чтобы вместить // все данные полученные между обработками. Думаю, никак не меньше, // чем STRUCT_LEN * 2. static byte dataHolder[STRUCT_LEN * 3]; // Эта переменная содержит текущее количество байтов хранящихся // в dataHolder и ещё не обработанных static uint8_t bytesRead = 0; // Длина данных, которые мы готовы получить. // Равна остатку свободного места в dataHolder // После вызова driver.recv - здесь будет длина реально полученных данных. uint8_t buflen = sizeof(dataHolder) - bytesRead; // Вызываем driver.recv и, если что-то получено, увеличиваем bytesRead // Таким образом bytesRead у нас всегда содержит количество необработанных // байтов, хранящихся в dataHolder if (driver.recv(dataHolder + bytesRead, &buflen)) bytesRead += buflen; // Начинаем обработку // Заметьте, мы делаем это всегда, независимо от того, получили мы что-то или нет // потому, что мы могли в прошлый раз получить сразу два пакета. В этом случае, // один уже обработан, а второй ждёт обработки // Если в dataHolder полный пакет ещё не накопился, возвращаем false // и ничего не делаем (ждём прихода новых данных) if (bytesRead < STRUCT_LEN) return false; // Если же уже накопилось, копируем полную структруру // в mydata, а остаток данных оставляем в dataHolder для // обработки в следующий раз. // 1. Копируем memcpy(& mydata, dataHolder, STRUCT_LEN); // 2. Теперь у нас в dataHolder осталось на STRUCT_LEN байтов меньше. чем было bytesRead -= STRUCT_LEN; // 3. Если остались необработанные данные, переносим их в начало dataHolder if (bytesRead) memcpy(dataHolder, dataHolder + STRUCT_LEN, bytesRead); // возвращаем true - признак того, что мы скопировали данные в mydata return true; }Ну, вот как-то так.
Здесь есть одна неэффективность. В строке 40 мы копируем данные с места на место ("возим" по памяти). Это не самая лучшая операция. Но, здесь она не настолько долгая, т.к. структура небольшая. А сделать "по уму" - через кольцевой буффер, будет стоить с десяток-полтора строк очень аккуратного (опасного ошибками) кода. До тех пор, пока быстродействие не является МЕГАкритичным, лучше не выпендриваться и оставить как здесь.