Скетч для Arduino IDE
Постарался сделать как можно более читабельным
Отвечу на все вопросы.
Будет доработка в плане внешнего программирующего устройства на базе Arduino Uno и LCD дисплея.
Так, благодаря хорошему человеку нашлась четвертая версия
Timer_for_Plane_v4
//*************************************************************************************************************
//
// Тагильцев Геннадий aka Marks
// версия v3
// изменения v2:
// - добавлена функция boolean Engine_Proc (int, int)
// параметры
// - требуемое положение газа
// - условная задержка (в циклах программы)
// возвращает
// true - при достижении требуемого значения
// изменения v3
// - убрал процедуру таймера, вся обработка в одном цикле.
// изменения v4
// - расчет углов только на основании данных акселерометра
//
//**************************************************************************************************************
#include <Servo.h>
//#include <SoftwareSerial.h>
#include <Wire.h>
#include "Kalman.h"
#define Landing_Gear // если ретрактов нет, ставим коммент на эту стоку строку
#define Button_Pin 12 // порт к которому подключена кнопка старт/стоп или перемычка
#define Port_Motor_ESC 2 // порт к которому подключен ESC
#define Motor_ESC_Max_THR 2200 // максимальные обороты двигателя
#define Motor_ESC_Normall_THR 1800 // номинальные (полетные) обороты
#define Motor_ESC_Landing_THR 1500 // посадочный режим
#define Motor_ESC_Min_THR 800 // двигатель стоп
#define Time_Of_Calibrate 2 // время между Макс газ и мин газ при необходимости калибровке регулятора
#define Takeoff 5 // время отведенное на взлет и уборку шасси, в течении этого времени процедура старта может быть отменена (т.е. время до уборки шасси) - 10 секунд
#define GearUp 5 // время время после старта, начало уборки шасси - 5 секунд
#define InFly 25 // время полета в секундах с момента завершения процедуры старта - сейчас стоит 60 секунд
#define Landing 10 // время отводимое на посадку, в течении этого времени будут выпущены шасси и снижены обороты мотора до посадочных - 60 секунд
#define delay_g 100 // коэффициент торможения ))
#ifdef Landing_Gear
#define Port_Left_Wheel 6 // порт к которому подключена серва ретракта левого шасси
#define Port_Right_Wheel 7 // порт к которому подключена серва ретракта правого шасси
#define Left_Wheel_Down 2000
#define Left_Wheel_Up 1000
#define Right_Wheel_Down 1000
#define Right_Wheel_Up 2000
#define Up 1
#define Down 0
#endif
Servo Motor_ESC; // объект Servo для регулятора мотора
#ifdef Landing_Gear
Servo Left_Wheel; // объект Servo для ретракта левого шасси
Servo Right_Wheel; // объект Servo для ретракта правого шасси
#endif
// SoftwareSerial softSerial(2, 3); // RX, TX>
//**************************************************************************************
// переменные определяющие ветвление программы
// проще говоря, состояние модели
//**************************************************************************************
boolean Abort = false; // процедура старта может быть прервана повторным нажатием кнопки
//************************************************************************************
// блок объявления переменных для процедуры кальман
//************************************************************************************
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;
//************************************************************************************
//
//************************************************************************************
int Stack [] {
Motor_ESC_Min_THR,
Motor_ESC_Landing_THR,
Motor_ESC_Normall_THR,
Motor_ESC_Max_THR,
Time_Of_Calibrate,
Takeoff,
GearUp,
InFly,
Landing
};
//************************************************************************************
// временные переменные
//************************************************************************************
unsigned long Current_Time; // текущее время, мало ли где то пригодится
unsigned long Start_Time; // время старта по таймеру (т.е. момент нажатия на кнопку)
unsigned long Takeoff_Time; // время начала полета, шасси уже убраны
unsigned long GearUp_Time; // время начала уборки шасси (т.е. с момента нажатия на кнопку)
unsigned long Fly_Time; // время завершения полета
unsigned long Landing_Time; // время останова двигателя
//*************************************************************************************
//*************************************************************************************
// эти переменные нужны что бы не задаваться вопросом "А как у нас работают сервы"
//*************************************************************************************
int Step_Left;
int Step_Right;
//*************************************************************************************
void setup() {
pinMode(Button_Pin, INPUT); // привязали кнопку старт к порту
digitalWrite(Button_Pin, HIGH); // подтянули кнопку к +5V
Motor_ESC.attach(Port_Motor_ESC,Motor_ESC_Min_THR,Motor_ESC_Max_THR); // привязали регулятор к каналу
//**********************************************************************************
// если при включении нажата кнопка
// программа войдет в режим настройки
//**********************************************************************************
if (digitalRead(Button_Pin) == LOW) Prog_Mode();
while (digitalRead(Button_Pin) == LOW) {
}
Motor_ESC.writeMicroseconds(Motor_ESC_Min_THR);
delay (300);
//**********************************************************************************
//************************************************************************************
int i = Left_Wheel_Down-Left_Wheel_Up;
if (i>0) {
Step_Left = -1;
}
else {
Step_Left = 1;
}
i = Right_Wheel_Down-Right_Wheel_Up;
if (i>0) {
Step_Right = -1;
}
else {
Step_Right = 1;
}
/*
при подключении питания сервы встанут в крайнее положение, соответствующее Down
*/
#ifdef Landing_Gear
Left_Wheel.attach(Port_Left_Wheel);
delay(500);
Right_Wheel.attach(Port_Right_Wheel);
delay(500);
while (!Gear_Proc(Down));
#endif
//**********************************************************************************
// вышли из режима программирования
//*********************************************************************************
while (digitalRead(Button_Pin) == HIGH) {
}
delay (500);
Start_Time = millis();
Takeoff_Time = Start_Time + Stack [5]*1000;
GearUp_Time = Takeoff_Time + Stack [6]*1000;
Fly_Time = GearUp_Time + Stack [7]*1000;
Landing_Time = Fly_Time + Stack [8]*1000;
//*********************************************************************************
//**********************************************************************************
// блок setup для kalman
//**********************************************************************************
Serial.begin(115200);
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() {
while (millis() < Takeoff_Time) Engine_Proc(Stack[2],10);
while (millis() < GearUp_Time) Gear_Proc(Up);
while (millis() < Fly_Time) {
int currentTHR = Motor_ESC.readMicroseconds();
Angel();
if (accXangle>190 && accXangle<350) {
if (currentTHR != Stack[3]) {
Motor_ESC.writeMicroseconds(Stack[3]);
}
}
else if (accXangle<170 && accXangle>10) {
if (currentTHR != Stack[1]) {
Motor_ESC.writeMicroseconds(Stack[1]);
}
}
else {
Motor_ESC.writeMicroseconds(Stack[2]);
}
}
while(millis() < Landing_Time) {
if (Engine_Proc(Stack[1],10)) Gear_Proc(Down);
}
while (millis() >= Landing_Time) Engine_Proc(Stack[0],10) ;
}
// вошли в режим программирования
// пока тут только калибровка регулятора
//*************************************************************************************
void Prog_Mode () {
Motor_ESC.writeMicroseconds(Stack[3]);
delay (Stack [4]*1000); // немного ждем и газ в ноль
Motor_ESC.writeMicroseconds(Stack[0]);
delay (500);
}
//*************************************************************************************
// процедура уборки/выпуска шасси
// результат
// - TRUE - завершено
// - FALSE - не завершена
// параметр - int -
// - 0 - выпускам
// - 1 - убираем
//*************************************************************************************
boolean Gear_Proc(int l) {
static int i = delay_g;
int j = Left_Wheel.readMicroseconds();
int k = Right_Wheel.readMicroseconds();
if (l == 0) {
// шасси выпускаем
if (j == Left_Wheel_Down && k == Right_Wheel_Down) return true;
if (i==0) {
if (j > Left_Wheel_Down) j--;
else j++;
Left_Wheel.writeMicroseconds(j);
}
if (i==0) {
if (k > Right_Wheel_Down) k--;
else k++;
Right_Wheel.writeMicroseconds(k);
}
if (!i--) i=delay_g;
}
else {
// шасси выпускаем
if (j == Left_Wheel_Up && k == Right_Wheel_Up) return true;
if (i==0) {
if (j > Left_Wheel_Up) j--;
else j++;
Left_Wheel.writeMicroseconds(j);
}
if (i==0) {
if (k > Right_Wheel_Up) k--;
else k++;
Right_Wheel.writeMicroseconds(k);
}
if (!i--) i=delay_g;
}
return false;
}
//*************************************************************************************
// Процедура работы с регуляторм
// возвращает true когда результат достигнут
// первый параметр - int - значение до которого надо изменить газ
// второй параметр - int - задержка
//*************************************************************************************
boolean Engine_Proc(int j1, int i1) {
static int i = 0;
int j = Motor_ESC.readMicroseconds();
if (j==j1) return true;
if (i == i1 && j<j1) {
j++;
Motor_ESC.writeMicroseconds(j);
}
if (i == i1 && j>j1) {
j--;
Motor_ESC.writeMicroseconds(j);
}
if (!i--) i=i1;
if (digitalRead(Button_Pin) == LOW) Abort = true ;
return false;
}
//***************************************************************************************
// кальман для гироскопа
// считает углы ))
//***************************************************************************************
void Angel() {
uint8_t* data = i2cRead(0x3B,14);
accX = ((data[0] << 8) | data[1]);
accY = ((data[2] << 8) | data[3]);
accZ = ((data[4] << 8) | data[5]);
/* 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;
delay (1);
}
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;
}
Как это работает в настоящее время можно посмотреть на видео.
Геннадий, у вас личка закрыта. Может подскажет кто, как програмно задать возможность реверса одной из серв шасси?
Локально, тригонометрией решил О_о -alpha=pi-alpha, alphaЭ[0;pi].
#define InFly 25 // время полета в секундах с момента завершения процедуры старта - сейчас стоит 25 секунд
Помогите ???
Приветствую.
А схему подключения можете опубликовать?
малость со скетчем не разобрался…
12 // порт к которому подключена кнопка старт/стоп или перемычка
2 // порт к которому подключен ESC
6 // порт к которому подключена серва ретракта левого шасси
7 // порт к которому подключена серва ретракта правого шасси
а вот куда гироскоп прицепить не нашёл.
Не, Роман тута нет никого))))))))
GIRO
SDA-A4
SCL-A5
+5-+5
GND-GND
INT-не нужно подкл.по умолчанию как нужо.
Автор в теме, готов ответить на любые вопросы
Будет доработка в плане внешнего программирующего устройства на базе Arduino Uno и LCD дисплея.
эта ветка продвигается? Вопросы будут чуть позже, гироскоп в путю.
Будет необходимость, продвинем, все в моих силах
Прикрутить программирование, делов на пару-тройку вечеров.
Главное, что бы была необходимость, опять же, с целью удешевления вполне можно программировать как регули, по пикам.
{"assets_hash":"a8b26fa7f6e768b07a72c8c9aadb9422","page_data":{"users":{"4439f4673df955007778bc22":{"_id":"4439f4673df955007778bc22","hid":13325,"name":"dENISCA","nick":"dENISCA","avatar_id":null,"css":""},"4f3e22e13df955007774805c":{"_id":"4f3e22e13df955007774805c","hid":114200,"name":"Маркс","nick":"Маркс","avatar_id":null,"css":""},"4f6f5ba63df95500777464b2":{"_id":"4f6f5ba63df95500777464b2","hid":116709,"name":"RandomJ","nick":"RandomJ","avatar_id":null,"css":""},"518613cc3df9550077736f12":{"_id":"518613cc3df9550077736f12","hid":151429,"name":"Zolotoy_al","nick":"Zolotoy_al","avatar_id":null,"css":""},"592f31fb3df955007770635b":{"_id":"592f31fb3df955007770635b","hid":286907,"name":"Svetoslav","nick":"Svetoslav","avatar_id":null,"css":""},"5d45c2c53df95500776f8062":{"_id":"5d45c2c53df95500776f8062","hid":346562,"name":"Гена_Большой","nick":"Гена_Большой","avatar_id":null,"css":""},"5f9446973df95500776f4313":{"_id":"5f9446973df95500776f4313","hid":359955,"name":"Yan72","nick":"Yan72","avatar_id":null,"css":""}},"settings":{"blogs_can_create":false,"blogs_mod_can_delete":false,"blogs_mod_can_hard_delete":false,"blogs_mod_can_add_infractions":false,"can_report_abuse":false,"can_vote":false,"can_see_ip":false,"blogs_edit_comments_max_time":30,"blogs_show_ignored":false,"blogs_reply_old_comment_threshold":30,"votes_add_max_time":168},"entry":{"_id":"579665f59970730077115389","hid":22016,"title":"Продвинутый таймер для кордовых моделей","html":"<p>Скетч для Arduino IDE<br>\nПостарался сделать как можно более читабельным<br>\nОтвечу на все вопросы.<br>\nБудет доработка в плане внешнего программирующего устройства на базе Arduino Uno и LCD дисплея.<br>\nТак, благодаря хорошему человеку нашлась четвертая версия</p>\n<p><strong data-nd-pair-src=\"**\">Timer_for_Plane_v4</strong></p>\n<!--cut-->\n<pre class=\"hljs\"><code>//*************************************************************************************************************\n//\n// Тагильцев Геннадий aka Marks\n// версия v3\n// изменения v2:\n// - добавлена функция boolean Engine_Proc (int, int)\n// параметры\n// - требуемое положение газа\n// - условная задержка (в циклах программы)\n// возвращает\n// true - при достижении требуемого значения\n// изменения v3\n// - убрал процедуру таймера, вся обработка в одном цикле.\n// изменения v4\n// - расчет углов только на основании данных акселерометра\n//\n//**************************************************************************************************************\n#include <Servo.h>\n//#include <SoftwareSerial.h>\n#include <Wire.h>\n#include "Kalman.h"\n\n#define Landing_Gear // если ретрактов нет, ставим коммент на эту стоку строку\n\n#define Button_Pin 12 // порт к которому подключена кнопка старт/стоп или перемычка\n#define Port_Motor_ESC 2 // порт к которому подключен ESC\n\n#define Motor_ESC_Max_THR 2200 // максимальные обороты двигателя\n#define Motor_ESC_Normall_THR 1800 // номинальные (полетные) обороты\n#define Motor_ESC_Landing_THR 1500 // посадочный режим\n#define Motor_ESC_Min_THR 800 // двигатель стоп\n#define Time_Of_Calibrate 2 // время между Макс газ и мин газ при необходимости калибровке регулятора\n#define Takeoff 5 // время отведенное на взлет и уборку шасси, в течении этого времени процедура старта может быть отменена (т.е. время до уборки шасси) - 10 секунд\n#define GearUp 5 // время время после старта, начало уборки шасси - 5 секунд\n#define InFly 25 // время полета в секундах с момента завершения процедуры старта - сейчас стоит 60 секунд\n#define Landing 10 // время отводимое на посадку, в течении этого времени будут выпущены шасси и снижены обороты мотора до посадочных - 60 секунд\n#define delay_g 100 // коэффициент торможения ))\n\n\n#ifdef Landing_Gear\n#define Port_Left_Wheel 6 // порт к которому подключена серва ретракта левого шасси\n#define Port_Right_Wheel 7 // порт к которому подключена серва ретракта правого шасси\n#define Left_Wheel_Down 2000\n#define Left_Wheel_Up 1000\n#define Right_Wheel_Down 1000\n#define Right_Wheel_Up 2000\n#define Up 1\n#define Down 0\n#endif\n\n Servo Motor_ESC; // объект Servo для регулятора мотора\n#ifdef Landing_Gear\n Servo Left_Wheel; // объект Servo для ретракта левого шасси\n Servo Right_Wheel; // объект Servo для ретракта правого шасси\n#endif\n// SoftwareSerial softSerial(2, 3); // RX, TX>\n\n//**************************************************************************************\n// переменные определяющие ветвление программы\n// проще говоря, состояние модели\n//**************************************************************************************\n boolean Abort = false; // процедура старта может быть прервана повторным нажатием кнопки\n//************************************************************************************\n// блок объявления переменных для процедуры кальман\n//************************************************************************************\n\nKalman kalmanX;\nKalman kalmanY;\n\nuint8_t IMUAddress = 0x68;\n\n/* IMU Data */\nint16_t accX;\nint16_t accY;\nint16_t accZ;\nint16_t tempRaw;\nint16_t gyroX;\nint16_t gyroY;\nint16_t gyroZ;\n\ndouble accXangle; // Angle calculate using the accelerometer\ndouble accYangle;\ndouble temp;\ndouble gyroXangle = 180; // Angle calculate using the gyro\ndouble gyroYangle = 180;\ndouble compAngleX = 180; // Calculate the angle using a Kalman filter\ndouble compAngleY = 180;\ndouble kalAngleX; // Calculate the angle using a Kalman filter\ndouble kalAngleY;\n\nuint32_t timer;\n\n\n\n\n\n//************************************************************************************\n//\n//************************************************************************************\nint Stack [] {\n Motor_ESC_Min_THR,\n Motor_ESC_Landing_THR,\n Motor_ESC_Normall_THR,\n Motor_ESC_Max_THR,\n Time_Of_Calibrate,\n Takeoff,\n GearUp,\n InFly,\n Landing\n };\n\n//************************************************************************************\n// временные переменные\n//************************************************************************************\n unsigned long Current_Time; // текущее время, мало ли где то пригодится\n unsigned long Start_Time; // время старта по таймеру (т.е. момент нажатия на кнопку)\n unsigned long Takeoff_Time; // время начала полета, шасси уже убраны\n unsigned long GearUp_Time; // время начала уборки шасси (т.е. с момента нажатия на кнопку)\n unsigned long Fly_Time; // время завершения полета\n unsigned long Landing_Time; // время останова двигателя\n//*************************************************************************************\n\n//*************************************************************************************\n// эти переменные нужны что бы не задаваться вопросом "А как у нас работают сервы"\n//*************************************************************************************\n int Step_Left;\n int Step_Right;\n//*************************************************************************************\n\nvoid setup() {\n\n pinMode(Button_Pin, INPUT); // привязали кнопку старт к порту\n digitalWrite(Button_Pin, HIGH); // подтянули кнопку к +5V\n Motor_ESC.attach(Port_Motor_ESC,Motor_ESC_Min_THR,Motor_ESC_Max_THR); // привязали регулятор к каналу\n\n\n\n//**********************************************************************************\n// если при включении нажата кнопка\n// программа войдет в режим настройки\n//**********************************************************************************\n if (digitalRead(Button_Pin) == LOW) Prog_Mode();\n while (digitalRead(Button_Pin) == LOW) {\n }\n Motor_ESC.writeMicroseconds(Motor_ESC_Min_THR);\n delay (300);\n//**********************************************************************************\n\n//************************************************************************************\n int i = Left_Wheel_Down-Left_Wheel_Up;\n if (i>0) {\n Step_Left = -1;\n }\n else {\n Step_Left = 1;\n }\n i = Right_Wheel_Down-Right_Wheel_Up;\n if (i>0) {\n Step_Right = -1;\n }\n else {\n Step_Right = 1;\n }\n/*\n при подключении питания сервы встанут в крайнее положение, соответствующее Down\n*/\n#ifdef Landing_Gear\n Left_Wheel.attach(Port_Left_Wheel);\n delay(500);\n Right_Wheel.attach(Port_Right_Wheel);\n delay(500);\n while (!Gear_Proc(Down));\n#endif\n//**********************************************************************************\n// вышли из режима программирования\n//*********************************************************************************\n while (digitalRead(Button_Pin) == HIGH) {\n }\n delay (500);\n Start_Time = millis();\n Takeoff_Time = Start_Time + Stack [5]*1000;\n GearUp_Time = Takeoff_Time + Stack [6]*1000;\n Fly_Time = GearUp_Time + Stack [7]*1000;\n Landing_Time = Fly_Time + Stack [8]*1000;\n//*********************************************************************************\n\n\n//**********************************************************************************\n// блок setup для kalman\n//**********************************************************************************\n Serial.begin(115200);\n Wire.begin();\n i2cWrite(0x6B,0x00); // Disable sleep mode\n if(i2cRead(0x75,1)[0] != 0x68) { // Read "WHO_AM_I" register\n Serial.print(F("MPU-6050 with address 0x"));\n Serial.print(IMUAddress,HEX);\n Serial.println(F(" is not connected"));\n while(1);\n }\n kalmanX.setAngle(180); // Set starting angle\n kalmanY.setAngle(180);\n timer = micros();\n// **********************************************************************************\n}\n\nvoid loop() {\n while (millis() < Takeoff_Time) Engine_Proc(Stack[2],10);\n\n while (millis() < GearUp_Time) Gear_Proc(Up);\n\n while (millis() < Fly_Time) {\n int currentTHR = Motor_ESC.readMicroseconds();\n Angel();\n if (accXangle>190 && accXangle<350) {\n if (currentTHR != Stack[3]) {\n Motor_ESC.writeMicroseconds(Stack[3]);\n }\n }\n else if (accXangle<170 && accXangle>10) {\n if (currentTHR != Stack[1]) {\n Motor_ESC.writeMicroseconds(Stack[1]);\n }\n }\n else {\n Motor_ESC.writeMicroseconds(Stack[2]);\n }\n }\n\n while(millis() < Landing_Time) {\n if (Engine_Proc(Stack[1],10)) Gear_Proc(Down);\n }\n\n while (millis() >= Landing_Time) Engine_Proc(Stack[0],10) ;\n\n}\n\n\n\n\n// вошли в режим программирования\n// пока тут только калибровка регулятора\n//*************************************************************************************\nvoid Prog_Mode () {\n Motor_ESC.writeMicroseconds(Stack[3]);\n delay (Stack [4]*1000); // немного ждем и газ в ноль\n Motor_ESC.writeMicroseconds(Stack[0]);\n delay (500);\n}\n\n\n\n\n\n//*************************************************************************************\n// процедура уборки/выпуска шасси\n// результат\n// - TRUE - завершено\n// - FALSE - не завершена\n// параметр - int -\n// - 0 - выпускам\n// - 1 - убираем\n//*************************************************************************************\nboolean Gear_Proc(int l) {\n static int i = delay_g;\n int j = Left_Wheel.readMicroseconds();\n int k = Right_Wheel.readMicroseconds();\nif (l == 0) {\n// шасси выпускаем\n if (j == Left_Wheel_Down && k == Right_Wheel_Down) return true;\n\n if (i==0) {\n if (j > Left_Wheel_Down) j--;\n else j++;\n Left_Wheel.writeMicroseconds(j);\n }\n\n if (i==0) {\n if (k > Right_Wheel_Down) k--;\n else k++;\n Right_Wheel.writeMicroseconds(k);\n }\n\n if (!i--) i=delay_g;\n}\nelse {\n // шасси выпускаем\n if (j == Left_Wheel_Up && k == Right_Wheel_Up) return true;\n\n if (i==0) {\n if (j > Left_Wheel_Up) j--;\n else j++;\n Left_Wheel.writeMicroseconds(j);\n }\n\n if (i==0) {\n if (k > Right_Wheel_Up) k--;\n else k++;\n Right_Wheel.writeMicroseconds(k);\n }\n if (!i--) i=delay_g;\n}\n return false;\n}\n\n\n\n\n\n\n//*************************************************************************************\n// Процедура работы с регуляторм\n// возвращает true когда результат достигнут\n// первый параметр - int - значение до которого надо изменить газ\n// второй параметр - int - задержка\n//*************************************************************************************\nboolean Engine_Proc(int j1, int i1) {\n static int i = 0;\n int j = Motor_ESC.readMicroseconds();\n\n if (j==j1) return true;\n\n if (i == i1 && j<j1) {\n j++;\n Motor_ESC.writeMicroseconds(j);\n }\n if (i == i1 && j>j1) {\n j--;\n Motor_ESC.writeMicroseconds(j);\n }\n if (!i--) i=i1;\n if (digitalRead(Button_Pin) == LOW) Abort = true ;\n return false;\n}\n\n\n\n\n\n\n//***************************************************************************************\n// кальман для гироскопа\n// считает углы ))\n//***************************************************************************************\nvoid Angel() {\n uint8_t* data = i2cRead(0x3B,14);\n accX = ((data[0] << 8) | data[1]);\n accY = ((data[2] << 8) | data[3]);\n accZ = ((data[4] << 8) | data[5]);\n /* Calculate the angls based on the different sensors and algorithm */\n accYangle = (atan2(accX,accZ)+PI)*RAD_TO_DEG;\n accXangle = (atan2(accY,accZ)+PI)*RAD_TO_DEG;\n delay (1);\n}\n\nvoid i2cWrite(uint8_t registerAddress, uint8_t data){\n Wire.beginTransmission(IMUAddress);\n Wire.write(registerAddress);\n Wire.write(data);\n Wire.endTransmission(); // Send stop\n}\n\nuint8_t* i2cRead(uint8_t registerAddress, uint8_t nbytes) {\n uint8_t data[nbytes];\n Wire.beginTransmission(IMUAddress);\n Wire.write(registerAddress);\n Wire.endTransmission(false); // Don't release the bus\n Wire.requestFrom(IMUAddress, nbytes); // Send a repeated start and then release the bus after reading\n for(uint8_t i = 0; i < nbytes; i++)\n data[i] = Wire.read();\n return data;\n}\n\n</code></pre>\n<p>Как это работает в настоящее время можно посмотреть на видео.</p>\n<div class=\"ez-player ez-domain-youtube_com ez-block\" data-placeholder=\"<iframe class="ez-player-frame" src="https://www.youtube.com/embed/yQ3KyVNsnvo?feature=oembed&amp;autoplay=1" allowfullscreen></iframe>\" data-nd-link-orig=\"https://www.youtube.com/watch?v=yQ3KyVNsnvo\" data-nd-link-type=\"linkify\">\n <div class=\"ez-player-container\" style=\"padding-bottom: 56.5%;\">\n <a class=\"ez-player-placeholder\" target=\"_blank\" href=\"https://www.youtube.com/watch?v=yQ3KyVNsnvo\" rel=\"nofollow\">\n <div class=\"ez-player-picture\" style=\"background-image: url('https://i.ytimg.com/vi/yQ3KyVNsnvo/hqdefault.jpg');\"></div>\n \n <div class=\"ez-player-header\">\n <div class=\"ez-player-title\">\n Таймер для кордовых электрических моделей\n </div>\n </div>\n \n <div class=\"ez-player-button\"></div>\n <div class=\"ez-player-logo\"></div>\n \n </a>\n </div>\n</div>\n","user":"4f3e22e13df955007774805c","ts":"2016-07-25T19:18:13.000Z","st":1,"cache":{"comment_count":11,"last_comment":"64d8bf503627b35af4042bbf","last_comment_hid":12,"last_ts":"2023-08-13T11:32:32.315Z","last_user":"4f3e22e13df955007774805c"},"views":3371,"bookmarks":0,"votes":0},"subscription":null},"locale":"en-US","user_id":"000000000000000000000000","user_hid":0,"user_name":"","user_nick":"","user_avatar":null,"is_member":false,"settings":{"can_access_acp":false,"can_use_dialogs":false,"hide_heavy_content":false},"unread_dialogs":false,"footer":{"rules":{"to":"common.rules"},"contacts":{"to":"rco-nodeca.contacts"}},"navbar":{"tracker":{"to":"users.tracker","autoselect":false,"priority":10},"forum":{"to":"forum.index"},"blogs":{"to":"blogs.index"},"clubs":{"to":"clubs.index"},"market":{"to":"market.index.buy"}},"recaptcha":{"public_key":"6LcyTs0dAAAAADW_1wxPfl0IHuXxBG7vMSSX26Z4"},"layout":"common.layout"}