Питание Arduino в авто

MadToha
Offline
Зарегистрирован: 16.04.2012

Каковы варианты решения правильного питание ардуины в авто?

Заказываю Arduino Mega ADK, хочу, пока будет ехать, решить вопрос с питанием. По ссылке пишут:

Input Voltage (recommended) 9V
Input Voltage (limits) 7-18V

The board can operate on an external supply of 5.5 to 16 volts. If supplied with less than 7V, however, the 5V pin may supply less than five volts and the board may be unstable. If using more than 12V, the voltage regulator may overheat and damage the board. The recommended range is 7 to 12 volts.

Надо именно 9В, жрать будет 0.7-1.5А.

maksim
Offline
Зарегистрирован: 12.02.2012

Если вы просто подключите дуину к бортой сети автомобиля, то стабилизатор на дуине будет очень сильно греться. Можно поставить промежуточный стабилизатор на 9 вольт, например LM7809.

Mastino
Offline
Зарегистрирован: 03.12.2011
garmoska89
Offline
Зарегистрирован: 20.12.2011
kadushkin
Offline
Зарегистрирован: 18.12.2011

Купил http://item.taobao.com/item.htm?id=13688667509 , выставил 9V, но при включении Arduino виснет, приходится жать RESET.

Такое чувство, что источник питания плавно и медленно набирает напряжение и ардуина виснет, а может что-то еще...

Подскажите реальный вариант для питания ардуины в авто.

Во втором посту - аналог моему.

В третьем посту - выдает 5-6В, а для ардуины нужно минимум 7.

maksim
Offline
Зарегистрирован: 12.02.2012

Ну почему же, дуину можно питать и от 5 вольт. А преобразователь вещь хорошая, но дорогая по сравнению со стабилизатором. Что бы дуина стартовала с задержкой попробуйте поставить конденсатор между землей и ресетом, чем выше емкость тем позже дуина будет стартовать.

polter
Offline
Зарегистрирован: 20.06.2012

 а как быть если необходимо управлять именно 12 вольтовым оборудованием?

maksim
Offline
Зарегистрирован: 12.02.2012

 Смотря чем управлять

polter
Offline
Зарегистрирован: 20.06.2012

фарой к примеру, без реллея тут видимо не обойтись. Пытаемся связать мотоцикл и андоройд, если со входими все боль менее понятно , то с силовым оборудованием и как лучше подавать питание на саму ардуину, а то начитался про глюки с запуском что мол только через выпрямитель.

ourlive
Offline
Зарегистрирован: 26.05.2012

по ссылке из первого поста

Input Voltage (recommended) 7-12V
Input Voltage (limits) 6-20V

или у вас какая то особенная мега?

и не ставьте вы китайские dc-dc преобразователи, если нет возможности проверить, что на выходе.

а управлять нагрузкой, получилось, что РЭС80 -03 можно сажать прям на цифровой выход дуины без ограничительных резисторов (ток 35мА), но ток коммутации не более 1 А

carduino.ru
Offline
Зарегистрирован: 06.12.2011

Думаю что Вам Relay Module нужно использовать 

polter
Offline
Зарегистрирован: 20.06.2012

ничего особенног мега адк, думаю просто поставить советский стабилизатор крен-9.  по поводу рэс80 маловато в описании подцветки in 0.12A (Ipulse 1,2) 

polter
Offline
Зарегистрирован: 20.06.2012

 как раз вчера нашел, жалко что нет в продаже таких реллейев сразу выхода на 4, во всяком случаи на российских сайтах. 

ourlive
Offline
Зарегистрирован: 26.05.2012

для автомобильной коммутации нужно 5-10А и более, а это в любом случае одноступенчатым решением не осилить, маленькое реле должно управлять большим, маленький транзистор раскачивать большойм и т.п.. разве что на каких нибудь твердотельных удастся вырулить(но я пока приемлемых не нашел, или дорогие или параметры г.)

polter
Offline
Зарегистрирован: 20.06.2012

По-моему, реллеймодуль очень даже, и не надо ни каких многоступенчатых решений.

ourlive
Offline
Зарегистрирован: 26.05.2012

так посмотрите конструкцию модуля, она как раз многоступенчатая и есть. если для вас оно легко доступно и не нужно 2 месяца с ебэя ждать, то почему бы и нет.. но для моего города это не так (или по тройной цене).

maksim
Offline
Зарегистрирован: 12.02.2012

Кстати, если хотите преобретать релейный модуль с питанием реле от 12 вольт советую почитать вот эту тему.

axill
Offline
Зарегистрирован: 05.09.2011

polter пишет:

фарой к примеру, без реллея тут видимо не обойтись. Пытаемся связать мотоцикл и андоройд, если со входими все боль менее понятно , то с силовым оборудованием и как лучше подавать питание на саму ардуину, а то начитался про глюки с запуском что мол только через выпрямитель.

про релейный модуль написали уже, кроме этого еще как вариант MOSFET транзистор, они позволяют управлять многоамперными нагрузками

kadushkin
Offline
Зарегистрирован: 18.12.2011

При питании ардуины от USB мой скетч работает отлично.
при питании от VIN (~7,7 V) идут задержки в выполнении скетча, т.е. шаговый двигатель запускается с задержкой около 1 сек после нажатия кнопки, потом при нажатии кнопки опять 1 сек. думает и запускает двигатель. При питании от USB задержек нет вообще...

Как такое может быть?

maksim
Offline
Зарегистрирован: 12.02.2012

 А скейтч можно посмотреть? и опишите подробнее что и как подключено к дуине.

kadushkin
Offline
Зарегистрирован: 18.12.2011

 

Скетч управления КПП. Состав: два шаговых двигателя и два контроллера для них, 6 датчиков холла, блок питания ардуины, актуатор, блок из 8ми реле, также подключен шифтер для переключения КПП от игрового руля Logitech. Питание шаговых двигателей и блока питания ардуины пока от старого блока питания ПК.

Все работает отлично при питании ардуины от USB, при питании от блока питания ардуины - идут задержки.

Фотки, для лучшего понимания:

http://big-e.ru/images/Gallery/preview_ex.php?dir=Robot

Подробное описание в самом коде ниже.

#include <EEPROM.h>
#include <SPI.h>
#include <Mystepper.h>
#include <MsTimer2.h>
#include <avr/wdt.h>  

// Программа для управления МКПП FM42 автомобиля
// В качестве привода используются: шаговый двигатель с редуктором (первый привод) и шаговый двигатель с винтовой передачей (второй привод)
// Первый привод необходим непосредственно для переключения вилок КПП, он является силовым
// Второй привод - для перемещения между вилками КПП
// Каждый привод контролируется тремя датчиками холла - для отстеживания положений
// Кроме того, для блокировки включения задней и пятой передачи (от случайного попадания) имеется актуатор

#define DEBUG 1  // используется при отладке

////// ********Описание периферии********** ///////////
// Контакт 0 для  - зарезервировано, не использовать!!!
// Контакт 1 для  - зарезервировано, не использовать!!!
#define  TahometrPin 2  // Контакт 2 для тахометра !!!!!!!!! ПРЕРЫВАНИЕ 0 
#define  SpeedSensorPin 3  // Контакт 3 для датчика скорости !!!!!!!!!ПРЕРЫВАНИЕ 1
#define  Motor1_RelayPin 4// Контакт 4 для  реле 1 блока-реле1 - реле включения контроллера шаг. двигателя первого привода
#define  GearBlock5R_RelayPin 5// Контакт 5 для  реле 2 блока-реле1
// Контакт 6 для  реле 3 блока-реле1
// Контакт 7 для  реле 4 блока-реле1
// Контакт 8 для !!!!!!!!! свободно 
// Контакт 9 для !!!!!!!!! свободно 
// Контакт 10 для динамика
// Контакт 11 для !!!!!!!!! свободно 
// Контакт 12 для !!!!!!!!! свободно 
#define  LedPin 13  // Контакт 13 для светодиода
#define  HandBreakPin 14  // Контакт 4 для сигнала от ручного тормоза
#define  SmallLightPin 15  // Контакт 5 для сигнала от габаритов
#define  LeftTurnPin 16  // Контакт 6 для сигнала от левого поворотника
#define  RightTurnPin 17  // Контакт 7 для сигнала от правого поворотника
// Контакт 18 для !!!!!!!!!ПРЕРЫВАНИЕ 5 !!!!!!!!! свободно 
// Контакт 19 для !!!!!!!!!ПРЕРЫВАНИЕ 4 !!!!!!!!! свободно 
#define  ClutchONButtonPin 20 // Контакт 20 для кнопки выжима сцепления NO !!!!!!!!!ПРЕРЫВАНИЕ 3
#define  ClutchOFFButtonPin 21 // Контакт 21 для кнопки отжима сцепления NC !!!!!!!!!ПРЕРЫВАНИЕ 2
#define  Motor1HallSensor1Pin 22 // Контакт 22 для датчика холла1 первого привода
#define  Motor1HallSensor2Pin 23 // Контакт 23 для датчика холла2 первого привода
#define  Motor1HallSensor3Pin 24 // Контакт 24 для датчика холла3 первого привода
// Контакт 25 для !!!!!!!!! свободно 
#define  REG_LATCH 26 // Контакт 26 для "Защелка" для опроса кнопок шифтера 
#define  Motor2HallSensor4Pin 27 // Контакт 27 для датчика холла4 второго привода
#define  Motor2HallSensor5Pin 28 // Контакт 28 для датчика холла5 второго привода
#define  Motor2HallSensor6Pin 29 // Контакт 29 для датчика холла6 второго привода
#define  Motor2A1Pin 30 // Контакт 30 для второго привода
#define  Motor2B1Pin 31 // Контакт 31 для второго привода
#define  Motor2A2Pin 32 // Контакт 32 для второго привода
#define  Motor2B2Pin 33 // Контакт 33 для второго привода
// Контакт 34 для реле 5 блока-реле1
// Контакт 35 для реле 6 блока-реле1
// Контакт 36 для реле 7 блока-реле1
// Контакт 37 для реле 8 блока-реле1
#define  LCDGear1_Indicate_Pin 38 // Контакт 38 для индикации Передачи 1 на ЖКИ
#define  LCDGear2_Indicate_Pin 39 // Контакт 39 для индикации Передачи 2 на ЖКИ
#define  LCDGear3_Indicate_Pin 40 // Контакт 40 для индикации Передачи 3 на ЖКИ
#define  LCDGear4_Indicate_Pin 41 // Контакт 41 для индикации Передачи 4 на ЖКИ
#define  LCDGearD_Indicate_Pin 42 // Контакт 42 для индикации Передачи D на ЖКИ
#define  LCDGearN_Indicate_Pin 43 // Контакт 43 для индикации Передачи N на ЖКИ
#define  LCDGearR_Indicate_Pin 44 // Контакт 44 для индикации Передачи R на ЖКИ
#define  LCDGearP_Indicate_Pin 45 // Контакт 45 для индикации Передачи P на ЖКИ
#define  Motor1_Rotate_Side_Pin 46 // Контакт 46 для первого привода - направление вращения
#define  Motor1_Online_Direct_Pin 47 // Контакт 47 для первого привода - прямое управление
#define  Motor1_Frequency_Pin 48 // Контакт 48 для первого привода - частота импульсов
// Контакт 49 !!!!!!!!! свободно 
// Контакт 50 MISO - занято для опроса кнопок шифтера
// Контакт 51 MOSI - занято для опроса кнопок шифтера  - зарезервировано, не использовать!!!
// Контакт 52 SCK - занято для опроса кнопок шифтера 
// Контакт 53 SS - занято для опроса кнопок шифтера - зарезервировано, не использовать!!!

//Stepper Motor1(200, Motor1_Rotate_Side_Pin, Motor1_Frequency_Pin, Motor1_Online_Direct_Pin,   Motor1B2Pin);
//Stepper Motor1(200, Motor1_Rotate_Side_Pin,  Motor1_Online_Direct_Pin, Motor1_Frequency_Pin,  Motor1B2Pin);
Stepper Motor2(200, Motor2A1Pin, Motor2B1Pin, Motor2A2Pin,   Motor2B2Pin);

//аналоговые входы

#define  Shifter_AxeY 0 //A0 // Шифтер ось 1 Y
#define  Shifter_AxeX 1 //A1 // Шифтер ось 2 X
#define  CurrentSensor1Pin 2 //A2 //датчик тока1
#define  CurrentSensor2Pin 3 //A3 //датчик тока2
#define  WheelButtonsPin 6 //A6 // кнопки руля

//кнопки шифтера
byte Shifter_Button_Array[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
byte Shifter_Button_UP=0;
byte Shifter_Button_DOWN=1;
byte Shifter_Button_LEFT=2;
byte Shifter_Button_RIGHT=3;
byte Shifter_Button_Black3=4;
byte Shifter_Button_Black1=5;
byte Shifter_Button_Black4=6;
byte Shifter_Button_Black2=7;
byte Shifter_Button_Red1=8;
byte Shifter_Button_Red4=9;
byte Shifter_Button_Red2=10;
byte Shifter_Button_Red3=11;
byte Shifter_PlusMinusMode=12; //режим +-
byte Shifter_Button_Uknwn1=13;
byte Shifter_RearGearMode=14; //режим задней передачи (рычаг утоплен)
byte Shifter_Button_Uknwn2=15;

int CurrentSensor1Value=0;
int CurrentSensor2Value=0;

//описание переменных
//boolean RelayOn = false;

volatile unsigned long Speed_ImpulseTime = 0; // время между импульсами датчика скорости
volatile unsigned long Speed_time=0;  // время для отсчета импульсов
volatile int Speed_impulse_count = 0;  // кол-во импульсов датчика скорости
volatile float Speed=0; // скорость с датчика скорости

volatile unsigned long Taho_ImpulseTime = 0; // время между импульсами тахометра
volatile unsigned long Taho_time=0;  // время для отсчета импульсов
volatile int Tahometr_impulse_count = 0;  // кол-во импульсов тахометра
volatile float Taho=0; // обороты двигателя

char CurGear='0';
char LastGear='0';
char RecommendGear='0';

//byte GearLastName=0;
byte P_1=1;
byte P_2=2;
byte P_3=3;
byte P_4=4;
byte P_5=5;
byte P_R=255;
byte P_N12=12;
byte P_N34=34;
byte P_N5R=250;
byte P_MINUS=127;
byte P_PLUS=128;

int EEPROMaddrLastMotor1HallSensorNum=0; //адрес в энергонезавсимой памяти куда заносится значение положение привода 1 согласно датчикам холла 1,2 или 3 
int EEPROMaddrLastMotor2HallSensorNum=1; //адрес в энергонезавсимой памяти куда заносится значение положение привода 2 согласно датчикам холла 4,5 или 6
int EEPROMaddrLastSuccessGearPosition=2; //адрес в энергонезавсимой памяти куда заносится значение последней удачно включенной передачи
int EEPROMaddrLastFrontGearPosition=3; //адрес в энергонезавсимой памяти куда заносится значение последней удачно включенной передачи в режиме ( без нейтрали и задней передачи)

// переменные нажатия рулевых кнопок
unsigned long math_time,old_time,real_time, res_dt1, res_d;     
int LIMIT=10;
char ButtonName='X'; // +, -, >, R=>>|, L=|<<, S=SRC, X=None
// переменные нажатия рулевых кнопок - конец



//###################################################################
//общие настройки 
void setup() 
{
  wdt_enable (WDTO_8S); // сторожевой таймер от зависания
 // Shifter_Button_Array[Shifter_Button_UP]=1;
 
// MsTimer2::set(500, Timer2_Timer); // таймер будет срабатывать через каждые 500ms 
// MsTimer2::start();//запустить таймер

//*************************Описание пинов**************************
// Контакт 0 для  - зарезервировано, не использовать!!!
// Контакт 1 для  - зарезервировано, не использовать!!!
//2
pinMode(TahometrPin, INPUT); // Контакт для тахометра !!!!!!!!!ПРЕРЫВАНИЕ 0
digitalWrite(TahometrPin, HIGH); //внутренняя подтяжка входа тахометра 
attachInterrupt(0, TahometrImpulse_on, FALLING); // настройка прерывания и функции на него
//3
pinMode(SpeedSensorPin, INPUT); // Контакт для датчика скорости !!!!!!!!!ПРЕРЫВАНИЕ 1
digitalWrite(SpeedSensorPin, HIGH); //внутренняя подтяжка входа датчика скорости 
attachInterrupt(1, SpeedImpulse_on, FALLING); // настройка прерывания и функции на него

// Контакт 4 для реле 1 блока-реле1
pinMode(Motor1_RelayPin, OUTPUT);
// Контакт 5 для реле 2 блока-реле1
pinMode(GearBlock5R_RelayPin, OUTPUT);
// Контакт 6 для реле 3 блока-реле1
// Контакт 7 для реле 4 блока-реле1
// Контакт 8 для !!!!!!!!! свободно 
// Контакт 9 для !!!!!!!!! свободно 
// Контакт 10 для динамика
// Контакт 11 для !!!!!!!!! свободно 
// Контакт 12 для !!!!!!!!! свободно 
//13
pinMode(LedPin, OUTPUT); // Контакт для светодиода
//14
pinMode(HandBreakPin, INPUT);// Контакт для сигнала от ручного тормоза
digitalWrite(HandBreakPin, HIGH); //внутренняя подтяжка входа +++++ 
//15
pinMode(SmallLightPin, INPUT);// Контакт для сигнала от габаритов
digitalWrite(SmallLightPin, HIGH); //внутренняя подтяжка входа +++++ 
//16
pinMode(LeftTurnPin, INPUT);// Контакт 6 для сигнала от левого поворотника
digitalWrite(LeftTurnPin, HIGH); //внутренняя подтяжка входа +++++ 
//17
pinMode(RightTurnPin, INPUT);// Контакт 7 для сигнала от правого поворотника
digitalWrite(RightTurnPin, HIGH); //внутренняя подтяжка входа +++++ 
// Контакт 18 для !!!!!!!!!ПРЕРЫВАНИЕ 5 !!!!!!!!! свободно 
// Контакт 19 для !!!!!!!!!ПРЕРЫВАНИЕ 4 !!!!!!!!! свободно 
//20
pinMode(ClutchONButtonPin, INPUT);// Контакт для кнопки выжима сцепления NO !!!!!!!!!ПРЕРЫВАНИЕ 3
digitalWrite(ClutchONButtonPin, HIGH); //внутренняя подтяжка входа +++++ 
//21
pinMode(ClutchOFFButtonPin, INPUT);// Контакт для кнопки отжима сцепления NC !!!!!!!!!ПРЕРЫВАНИЕ 2
digitalWrite(ClutchOFFButtonPin, HIGH); //внутренняя подтяжка входа +++++ 
//22
pinMode(Motor1HallSensor1Pin, INPUT);// Контакт для датчика холла1 первого привода
digitalWrite(Motor1HallSensor1Pin, HIGH); //внутренняя подтяжка входа +++++ 
//23
pinMode(Motor1HallSensor2Pin, INPUT);// Контакт для датчика холла2 первого привода
digitalWrite(Motor1HallSensor2Pin, HIGH); //внутренняя подтяжка входа +++++ 
//24
pinMode(Motor1HallSensor3Pin, INPUT);// Контакт для датчика холла3 первого привода
digitalWrite(Motor1HallSensor3Pin, HIGH); //внутренняя подтяжка входа +++++ 
// Контакт 25 для !!!!!!!!! свободно 
//26 
pinMode(REG_LATCH, OUTPUT); // Контакт 26 для "Защелка" для опроса кнопок шифтера 
digitalWrite(REG_LATCH, HIGH); //внутренняя подтяжка входа +++++ 
//27
pinMode(Motor2HallSensor4Pin, INPUT);// Контакт для датчика холла4 второго привода
digitalWrite(Motor2HallSensor4Pin, HIGH); //внутренняя подтяжка входа +++++ 
//28
pinMode(Motor2HallSensor5Pin, INPUT);// Контакт для датчика холла5 второго привода
digitalWrite(Motor2HallSensor5Pin, HIGH); //внутренняя подтяжка входа +++++ 
//29
pinMode(Motor2HallSensor6Pin, INPUT);// Контакт для датчика холла6 второго привода
digitalWrite(Motor2HallSensor6Pin, HIGH); //внутренняя подтяжка входа +++++ 
//30
pinMode(Motor2A1Pin, OUTPUT);// Контакт для второго привода
//31
pinMode(Motor2B1Pin, OUTPUT);// Контакт для второго привода
//32
pinMode(Motor2A2Pin, OUTPUT);// Контакт для второго привода
//33
pinMode(Motor2B2Pin, OUTPUT);// Контакт для второго привода
// Контакт 34 для реле 5 блока-реле1
// Контакт 35 для реле 6 блока-реле1
// Контакт 36 для реле 7 блока-реле1
// Контакт 37 для реле 8 блока-реле1
//38
pinMode(LCDGear1_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи 1 на ЖКИ
//39
pinMode(LCDGear2_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи 2 на ЖКИ
//40
pinMode(LCDGear3_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи 3 на ЖКИ
//41
pinMode(LCDGear4_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи 4 на ЖКИ
//42
pinMode(LCDGearD_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи D на ЖКИ
//43
pinMode(LCDGearN_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи N на ЖКИ
//44
pinMode(LCDGearR_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи R на ЖКИ
//45
pinMode(LCDGearP_Indicate_Pin, OUTPUT);// Контакт для индикации Передачи P на ЖКИ
//46
pinMode(Motor1_Rotate_Side_Pin, OUTPUT);// Контакт  для первого привода - направление вращения
//47
pinMode(Motor1_Online_Direct_Pin, OUTPUT);// Контакт  для первого привода - прямое управление
//48
pinMode(Motor1_Frequency_Pin, OUTPUT);// Контакт  для первого привода - частота импульсов
// Контакт 49 !!!!!!!!! свободно 
SPI.begin(); //задействуем пины 50-53
// Контакт 50 MISO - занято для опроса кнопок шифтера
// Контакт 51 MOSI - занято для опроса кнопок шифтера  - зарезервировано, не использовать!!!
// Контакт 52 SCK - занято для опроса кнопок шифтера 
// Контакт 53 SS - занято для опроса кнопок шифтера - зарезервировано, не использовать!!!


// параметры моторов, скорости вращения об/мин
//Motor1.setSpeed(100);  
Motor2.setSpeed(300);  

//гасим ЖКИ 
Gear_LCD_Clear();
//


#if DEBUG
Serial.begin(115200); 
#endif
  
}

//###################################################################       
//функция возвращает положение рычага шифтера КПП       
byte GetShifterPosition()
{
uint16_t ShifterButtonsStatus=Read_ShifterButtonsStatus();
ShifterButtonsStatus >>= Shifter_PlusMinusMode; 
byte Shifter_PlusMinusModeStatus=ShifterButtonsStatus & 1;  
//Serial.println(analogRead(0)); //Y
// Serial.println(analogRead(1)); //X
byte ShifterPosition=0;
int X_Position=analogRead(Shifter_AxeX); 
int Y_Position=analogRead(Shifter_AxeY);

/*
Serial.print("X=");
Serial.println(X_Position);
Serial.print("Y=");
Serial.println(Y_Position);
*/

//uint16_t ButtonsStatus=Read_ShifterButtonsStatus();
//ButtonsStatus[]
if (Shifter_PlusMinusModeStatus==0) // обычный режим переключения КПП - ручной (не +-)
{
if ((X_Position<320) && (Y_Position>600)) {ShifterPosition=P_1;}
if ((X_Position<320) && (Y_Position<100)) {ShifterPosition=P_2;}
if (((X_Position>320) && (X_Position<520)) && (Y_Position>600)) {ShifterPosition=P_3;}
if (((X_Position>320) && (X_Position<520)) && (Y_Position<100)) {ShifterPosition=P_4;}
if ((X_Position>520) && (Y_Position>600)) {ShifterPosition=P_5;}
if ((X_Position>520) && (Y_Position<100)) {ShifterPosition=P_R;}
//if ((Y_Position>100) && (Y_Position<600)) {ShifterPosition=P_N;}
if ((X_Position<320) && ((Y_Position>100) && (Y_Position<600))) {ShifterPosition=P_N12;}
if (((X_Position>320) && (X_Position<520)) && (Y_Position>100) && (Y_Position<600)) {ShifterPosition=P_N34;}
if ((X_Position>520) && ((Y_Position>100) && (Y_Position<600))) {ShifterPosition=P_N5R;}
}

//+-
if (Shifter_PlusMinusModeStatus==1) // режим переключения КПП - спортивный (+-)
{
if (Y_Position>500) {ShifterPosition=P_MINUS;}
if (Y_Position<300) {ShifterPosition=P_PLUS;}
//if ((Y_Position>300) && (Y_Position<500)) {ShifterPosition='N';}
}

return ShifterPosition;
} 

//###################################################################
//функция возвращает состояние изменившихся кнопок шифтера
uint16_t Read_ShifterButtonsStatus() 
  {

static  uint16_t Last_Shifter_Buttons_States = 0; // статус четырех нижних (красных) кнопок и восьми верхних и средних (черных) кнопок
  uint16_t Shifter_Buttons_Changes =0;
  
  digitalWrite(REG_LATCH, LOW);  //Выставим на защёлке сначала низкий, потом - высокий уровни.
  digitalWrite(REG_LATCH, HIGH); //Сдвиговый регистр запомнит уровни сигналов на входах и сможет их нам потом отдать бит за би

  uint16_t Shifter_Buttons_States= (SPI.transfer(0) <<8 ) | SPI.transfer(0); //Читаем запомненные состояния четырех нижних (красных) кнопок и восьми верхних и средних (черных) кнопок

  if (Shifter_Buttons_States != Last_Shifter_Buttons_States)
  {
    Shifter_Buttons_Changes = Shifter_Buttons_States ^ Last_Shifter_Buttons_States;
    Last_Shifter_Buttons_States = Shifter_Buttons_States; // запоминаем текущие состояния
    
//#if DEBUG      
//Serial.println(Shifter_Buttons_States, BIN);
//#endif


  /*
    for (int i = 0; i < 16; ++i)
    {
      if (Shifter_Buttons_Changes & 1) // если состояние кнопки изменилось…
      {
        
     /*  Serial.print("#");
        Serial.print(i); // шлём номер кнопки
        Serial.print(" -> ");
        Serial.println(states & 1); // … и новое состояние
      }

      Shifter_Buttons_Changes >>= 1; // Сдвигаем биты вправо
      Shifter_Buttons_States >>= 1; // Сдвигаем биты вправо
    }
    */
  }
  return Shifter_Buttons_States; //Shifter_Buttons_Changes;
 }

//################################################################### 
//гасим ЖКИ  
void Gear_LCD_Clear()
{
digitalWrite(LCDGear1_Indicate_Pin, LOW);
digitalWrite(LCDGear2_Indicate_Pin, LOW);
digitalWrite(LCDGear3_Indicate_Pin, LOW);
digitalWrite(LCDGear4_Indicate_Pin, LOW);
digitalWrite(LCDGearD_Indicate_Pin, LOW);
digitalWrite(LCDGearN_Indicate_Pin, LOW);
digitalWrite(LCDGearR_Indicate_Pin, LOW);
digitalWrite(LCDGearP_Indicate_Pin, LOW);
}
 
//################################################################### 
 void Indicate_Gear_On_LCD(byte GearName)
{
Gear_LCD_Clear();  
if (GearName==P_1){digitalWrite(LCDGear1_Indicate_Pin, HIGH);}
if (GearName==P_2){digitalWrite(LCDGear2_Indicate_Pin, HIGH);}
if (GearName==P_3){digitalWrite(LCDGear3_Indicate_Pin, HIGH);}
if (GearName==P_4){digitalWrite(LCDGear4_Indicate_Pin, HIGH);}
if (GearName==P_5){digitalWrite(LCDGearD_Indicate_Pin, HIGH);}
if (GearName==P_R){digitalWrite(LCDGearR_Indicate_Pin, HIGH);}
if (GearName==P_N12){digitalWrite(LCDGearN_Indicate_Pin, HIGH);}
if (GearName==P_N34){digitalWrite(LCDGearN_Indicate_Pin, HIGH);}
if (GearName==P_N5R){digitalWrite(LCDGearN_Indicate_Pin, HIGH);}
}

//###################################################################
void Indicate_Recommended_Gear(float Speed_kmh)
{
  
if (Speed_kmh<=0) {RecommendGear='N';} // реле N
if ((Speed_kmh>0) && (Speed_kmh<=7)) {RecommendGear='1';} // реле   1 
if ((Speed_kmh>10) && (Speed_kmh<=22)) {RecommendGear='2';} // реле   2
if ((Speed_kmh>25) && (Speed_kmh<=40)) {RecommendGear='3';} // реле   3
if ((Speed_kmh>43) && (Speed_kmh<=85)) {RecommendGear='4';} // реле   4
if (Speed_kmh>90) {RecommendGear='D';} // реле   5


if (LastGear!=RecommendGear)
{
if (LastGear=='1'){digitalWrite(LCDGear1_Indicate_Pin, HIGH);}
if (LastGear=='2'){digitalWrite(LCDGear2_Indicate_Pin, HIGH);}
if (LastGear=='3'){digitalWrite(LCDGear3_Indicate_Pin, HIGH);}
if (LastGear=='4'){digitalWrite(LCDGear4_Indicate_Pin, HIGH);}
if (LastGear=='D'){digitalWrite(LCDGearD_Indicate_Pin, HIGH);}
if (LastGear=='N'){digitalWrite(LCDGearN_Indicate_Pin, HIGH);}
if (LastGear=='R'){digitalWrite(LCDGearR_Indicate_Pin, HIGH);}
if (LastGear=='P'){digitalWrite(LCDGearP_Indicate_Pin, HIGH);}

if (RecommendGear=='1'){digitalWrite(LCDGear1_Indicate_Pin, LOW);}
if (RecommendGear=='2'){digitalWrite(LCDGear2_Indicate_Pin, LOW);}
if (RecommendGear=='3'){digitalWrite(LCDGear3_Indicate_Pin, LOW);}
if (RecommendGear=='4'){digitalWrite(LCDGear4_Indicate_Pin, LOW);}
if (RecommendGear=='D'){digitalWrite(LCDGearD_Indicate_Pin, LOW);}
if (RecommendGear=='N'){digitalWrite(LCDGearN_Indicate_Pin, LOW);}
if (RecommendGear=='R'){digitalWrite(LCDGearR_Indicate_Pin, LOW);}
if (RecommendGear=='P'){digitalWrite(LCDGearP_Indicate_Pin, LOW);}

LastGear=RecommendGear;
}  
}



//###################################################################
// Функция привода переключения передач (1ый привод), можно передавать значения только Motor1HallSensor1Pin, Motor1HallSensor2Pin, Motor1HallSensor3Pin
// runaway - шаги для перебега (точное позиционирование после срабатывания датчика холла) 
// holding_time_msec - время (мс) удержания привода после прихода в нужное положение
byte Change_Gear_Motor_On(int steps, int to_Position, int runaway, int holding_time_msec)
{ 
int i_runaway=0;
byte Rezult=0;
int ttime=millis(); 
boolean RelayToDo=true;
int stepped=1; 
int stepcount=abs(steps);
if ((steps>0) && (digitalRead(Motor1HallSensor2Pin)==0)) {RelayToDo=false;} // дальше крутить в эту сторону нельзя - конечное положение
if ((steps<0) && (digitalRead(Motor1HallSensor1Pin)==0)) {RelayToDo=false;} // дальше крутить в эту сторону нельзя - конечное положение
if (digitalRead(to_Position)==0) {RelayToDo=false;} //уже достигли нужного положения по датчику холла

if (RelayToDo) 
    { //1
digitalWrite(Motor1_RelayPin, HIGH); //включаем реле 
if (steps>0) {digitalWrite(Motor1_Rotate_Side_Pin, HIGH);} // задаем сторону вращения
if (steps<0) {digitalWrite(Motor1_Rotate_Side_Pin, LOW);} // задаем сторону вращения
digitalWrite(Motor1_Online_Direct_Pin, HIGH); // прямое управление контроллером шагового двигателя с ардуино
//int TimeBTWNImpulse=3000; //время между импульсами (шагами) - скорость вращения
int TimeBTWNImpulse=1000; //время между импульсами (шагами) - скорость вращения
  
  
while (stepped<=stepcount)
  {
//if (stepped>50) {TimeBTWNImpulse=2000;} //ускорение 1ая ступень
//if (stepped>100) {TimeBTWNImpulse=1500;} //ускорение 2ая ступень
//if (stepped>150) {TimeBTWNImpulse=1000;} //ускорение 3ья ступень
digitalWrite(Motor1_Frequency_Pin, HIGH); //импульс
 delayMicroseconds(TimeBTWNImpulse);
 digitalWrite(Motor1_Frequency_Pin, LOW);
 stepped++; 
if ((steps>0) && (digitalRead(Motor1HallSensor2Pin)==0)) {stepped=stepcount+1;} // дальше крутить в эту сторону нельзя - конечное положение
if ((steps<0) && (digitalRead(Motor1HallSensor1Pin)==0)) {stepped=stepcount+1;} // дальше крутить в эту сторону нельзя - конечное положение
if (digitalRead(to_Position)==0) {i_runaway++; if (i_runaway>=runaway) {stepped=stepcount+1;}} //уже достигли нужного положения по датчику холла
  }
    } //1  
 digitalWrite(Motor1_Frequency_Pin, LOW);
 delay(holding_time_msec); // выдержка (удержание) привода
 digitalWrite(Motor1_RelayPin, LOW); //выключаем реле
//Serial.println( millis()-ttime);  
delay(10); //даем время для адаптации датчикам холла

Rezult=GetCurrentGearPosition();

if (Rezult!=0) {SetSuccessGearPosition_to_EEPROM(Rezult);}

if ((Rezult>=P_1) && (Rezult<=P_5)) {SetFrontGearPosition_to_EEPROM(Rezult);}

return Rezult;
       	  }
       
//###################################################################       
// Функция привода выбора передач (2ой привод), можно передавать значения только Motor2HallSensor4Pin, Motor2HallSensor5Pin, Motor2HallSensor6Pin 
// runaway - шаги для перебега (точное позиционирование после срабатывания датчика холла) 
void Select_Gear_Motor_On(int steps, int to_Position, int runaway)
{ 
boolean NeedToDo=true;   
if ((steps>0) && (digitalRead(Motor2HallSensor5Pin)==0)) {NeedToDo=false;} // дальше крутить в эту сторону нельзя - конечное положение
if ((steps<0) && (digitalRead(Motor2HallSensor6Pin)==0)) {NeedToDo=false;} // дальше крутить в эту сторону нельзя - конечное положение
if (digitalRead(to_Position)==0) {NeedToDo=false;} //уже достигли нужного положения по датчику холла
  
if (NeedToDo) {Motor2.step(steps, to_Position, runaway);}
}  
       

      

//###################################################################
//функция возвращает текущую позицию КПП по датчикам 
//возвращает значения 1,2,3,4,5,R=255,12,34,250
// при неудаче возвращает 0
byte GetCurrentGearPosition()
{
 
byte Rezult=0; //неопределенное положение
int c=0; // количество сработавших датчиков положения (холла)
if ((digitalRead(Motor1HallSensor1Pin)==0) && (digitalRead(Motor2HallSensor6Pin)==0)) {Rezult=P_1;}
if ((digitalRead(Motor1HallSensor2Pin)==0) && (digitalRead(Motor2HallSensor6Pin)==0)) {Rezult=P_2;}
if ((digitalRead(Motor1HallSensor1Pin)==0) && (digitalRead(Motor2HallSensor4Pin)==0)) {Rezult=P_3;}
if ((digitalRead(Motor1HallSensor2Pin)==0) && (digitalRead(Motor2HallSensor4Pin)==0)) {Rezult=P_4;}
if ((digitalRead(Motor1HallSensor1Pin)==0) && (digitalRead(Motor2HallSensor5Pin)==0)) {Rezult=P_5;}
if ((digitalRead(Motor1HallSensor2Pin)==0) && (digitalRead(Motor2HallSensor5Pin)==0)) {Rezult=P_R;} // задняя передача

if ((digitalRead(Motor1HallSensor3Pin)==0) && (digitalRead(Motor2HallSensor6Pin)==0)) {Rezult=P_N12;}
if ((digitalRead(Motor1HallSensor3Pin)==0) && (digitalRead(Motor2HallSensor4Pin)==0)) {Rezult=P_N34;}
if ((digitalRead(Motor1HallSensor3Pin)==0) && (digitalRead(Motor2HallSensor5Pin)==0)) {Rezult=P_N5R;}

if (digitalRead(Motor1HallSensor1Pin)==0) {c++;}
if (digitalRead(Motor1HallSensor2Pin)==0) {c++;}
if (digitalRead(Motor1HallSensor3Pin)==0) {c++;}
if (digitalRead(Motor2HallSensor4Pin)==0) {c++;}
if (digitalRead(Motor2HallSensor5Pin)==0) {c++;}
if (digitalRead(Motor2HallSensor6Pin)==0) {c++;}

if (c!=2) {Rezult=0;} //неопределенное положение
//Serial.println(c); /////////////
return Rezult;  
}


//###################################################################
//функция извлекающая последнюю успешную передачу КПП, последнее определенное положение КПП
//возвращает значения 1,2,3,4,5,R=255,12,34,250
// 0 при отсутствии информации о последнем положении
byte GetLastSuccessGearPosition()
{
byte Rezult=0;
Rezult=EEPROM.read(EEPROMaddrLastSuccessGearPosition);
return Rezult;  
}

byte GetLastFrontGearPosition()
{
byte Rezult=0;
Rezult=EEPROM.read(EEPROMaddrLastFrontGearPosition);
return Rezult;  
}

//процедура записывающая в память включенную передачу
void SetSuccessGearPosition_to_EEPROM(byte Gearvalue)
{
EEPROM.write(EEPROMaddrLastSuccessGearPosition, Gearvalue);
}

void SetFrontGearPosition_to_EEPROM(byte Gearvalue)
{
EEPROM.write(EEPROMaddrLastFrontGearPosition, Gearvalue);
}




//###################################################################  
//функция перевода в нейтральную поперечную линию между 1-3-5 и 2-4-R
//возвращает 0 при неудаче
// 12 при переходе в продольную позицию между 1-2
// 34 при переходе в продольную позицию между 3-4
// 250 при переходе в продольную позицию между 5-R
byte Go_To_Neutral_Line()
{
byte Rezult=0;

byte CurrentGearPosition=GetCurrentGearPosition();
if (CurrentGearPosition==0) {CurrentGearPosition=SearchingGear();}

if ((CurrentGearPosition==P_1) || (CurrentGearPosition==P_3)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10);}
if ((CurrentGearPosition==P_2) || (CurrentGearPosition==P_4)) {Change_Gear_Motor_On(-200, Motor1HallSensor3Pin,14, 10);}
if (CurrentGearPosition==P_5) { if (Gear_Unlock_R_Block_5(false)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10);}}
if (CurrentGearPosition==P_R) { if (Gear_Unlock_R_Block_5(true)) {Change_Gear_Motor_On(-200, Motor1HallSensor3Pin,14, 10); Gear_Unlock_R_Block_5(false);}}

if (CurrentGearPosition==0)
{
byte LastGearPosition=GetLastSuccessGearPosition();
if ((LastGearPosition==P_1) || (LastGearPosition==P_3)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10);}
if ((LastGearPosition==P_2) || (LastGearPosition==P_4)) {Change_Gear_Motor_On(-200, Motor1HallSensor3Pin,14, 10);}
if (LastGearPosition==P_5) { if (Gear_Unlock_R_Block_5(false)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10);}}
if (LastGearPosition==P_R) { if (Gear_Unlock_R_Block_5(true)) {Change_Gear_Motor_On(-200, Motor1HallSensor3Pin,14, 10); Gear_Unlock_R_Block_5(false);}}

}

Rezult=GetCurrentGearPosition();

if (Rezult!=0) {SetSuccessGearPosition_to_EEPROM(Rezult);}
return Rezult;
} 


// функция поиска передач - при неопределенном положении
byte SearchingGear()
{
byte CurrentGearPosition=GetCurrentGearPosition();  
if (CurrentGearPosition!=0)  {return CurrentGearPosition;}


int c=0;
if (digitalRead(Motor1HallSensor1Pin)==0) {c++;}
if (digitalRead(Motor1HallSensor2Pin)==0) {c++;}
if (digitalRead(Motor1HallSensor3Pin)==0) {c++;}
if (digitalRead(Motor2HallSensor4Pin)==0) {c++;}
if (digitalRead(Motor2HallSensor5Pin)==0) {c++;}
if (digitalRead(Motor2HallSensor6Pin)==0) {c++;}
if (c>2) {return 0;} //неопределенное положение из-за залипшего датчика холла - тупиковая ситуация

byte GearLastName=GetLastSuccessGearPosition();

if (c<=0) //*************** самый сложный случай ни один датчик не сработал, положение потеряно полностью
{
if ((GearLastName==P_1) || (GearLastName==P_3) || (GearLastName==P_5)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10); }
if ((GearLastName==P_2) || (GearLastName==P_5) || (GearLastName==P_R)) {Change_Gear_Motor_On(-200, Motor1HallSensor3Pin,14, 10); }
if ((GearLastName==P_N12) || (GearLastName==P_N34) || (GearLastName==P_N5R)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10); }
}

if (digitalRead(Motor1HallSensor1Pin)==0)  
{
Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10); 
if ((GearLastName==P_1) || (GearLastName==P_2) || (GearLastName==P_N12) ) {Select_Gear_Motor_On(-500, Motor2HallSensor6Pin, 30);}
if ((GearLastName==P_3) || (GearLastName==P_4) || (GearLastName==P_N34) ) {Select_Gear_Motor_On(-250, Motor2HallSensor4Pin, 40);}
if ((GearLastName==P_5) || (GearLastName==P_R) || (GearLastName==P_N5R) ) {Select_Gear_Motor_On(500, Motor2HallSensor5Pin, 30);}
return GetCurrentGearPosition();
} 

if (digitalRead(Motor1HallSensor2Pin)==0)  
{
Change_Gear_Motor_On(-200, Motor1HallSensor3Pin,14, 10); 
if ((GearLastName==P_1) || (GearLastName==P_2) || (GearLastName==P_N12) ) {Select_Gear_Motor_On(-500, Motor2HallSensor6Pin, 30);}
if ((GearLastName==P_3) || (GearLastName==P_4) || (GearLastName==P_N34) ) {Select_Gear_Motor_On(-250, Motor2HallSensor4Pin, 40);}
if ((GearLastName==P_5) || (GearLastName==P_R) || (GearLastName==P_N5R) ) {Select_Gear_Motor_On(500, Motor2HallSensor5Pin, 30);}
return GetCurrentGearPosition();
} 

if (digitalRead(Motor1HallSensor3Pin)==0)  
{
if ((GearLastName==P_1) || (GearLastName==P_2) || (GearLastName==P_N12) ) {Select_Gear_Motor_On(-500, Motor2HallSensor6Pin, 30);}
if ((GearLastName==P_3) || (GearLastName==P_4) || (GearLastName==P_N34) ) {Select_Gear_Motor_On(-250, Motor2HallSensor4Pin, 40);}
if ((GearLastName==P_5) || (GearLastName==P_R) || (GearLastName==P_N5R) ) {Select_Gear_Motor_On(500, Motor2HallSensor5Pin, 30);}

return GetCurrentGearPosition();
} 

if ((digitalRead(Motor2HallSensor4Pin)==0) || (digitalRead(Motor2HallSensor5Pin)==0) || (digitalRead(Motor2HallSensor6Pin)==0))  //12 34 5R
{
if ((GearLastName==P_1) || (GearLastName==P_3) || (GearLastName==P_5)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10); }
if ((GearLastName==P_2) || (GearLastName==P_5) || (GearLastName==P_R)) {Change_Gear_Motor_On(-200, Motor1HallSensor3Pin,14, 10); }
if ((GearLastName==P_N12) || (GearLastName==P_N34) || (GearLastName==P_N5R)) {Change_Gear_Motor_On(200, Motor1HallSensor3Pin,18, 10); }
return GetCurrentGearPosition();
}  



}

//###################################################################
//функция выбора передач по линии нейтрали (влево-вправо)
// самостоятельно не вызывать - вызывается из функции Go_To_Gear
byte SelectGear (byte ToNeutralLine)
{
byte Rezult=0;
byte CurrentGearPosition=GetCurrentGearPosition();

if (CurrentGearPosition==0) {CurrentGearPosition=SearchingGear();}

if (CurrentGearPosition==ToNeutralLine) {return CurrentGearPosition;}
if (ToNeutralLine==P_N12)
 {
if (CurrentGearPosition==P_N34) {Select_Gear_Motor_On(-250, Motor2HallSensor6Pin, 30);}
if (CurrentGearPosition==P_N5R) {Select_Gear_Motor_On(-500, Motor2HallSensor6Pin, 30);}

if (CurrentGearPosition==0)
{
byte LastGearPosition=GetLastSuccessGearPosition();
if (LastGearPosition==P_N34) {Select_Gear_Motor_On(-250, Motor2HallSensor6Pin, 30);}
if (LastGearPosition==P_N5R) {Select_Gear_Motor_On(-500, Motor2HallSensor6Pin, 30);}
} 
 }
 
 if (ToNeutralLine==P_N34)
 {
if (CurrentGearPosition==P_N12) {Select_Gear_Motor_On(250, Motor2HallSensor4Pin, 40);}
if (CurrentGearPosition==P_N5R) {Select_Gear_Motor_On(-250, Motor2HallSensor4Pin, 40);}

if (CurrentGearPosition==0)
{
byte LastGearPosition=GetLastSuccessGearPosition();
if (LastGearPosition==P_N12) {Select_Gear_Motor_On(250, Motor2HallSensor4Pin, 40);}
if (LastGearPosition==P_N5R) {Select_Gear_Motor_On(-250, Motor2HallSensor4Pin, 40);}
} 
 }
 
 if (ToNeutralLine==P_N5R)
 {
if (CurrentGearPosition==P_N12) {Select_Gear_Motor_On(500, Motor2HallSensor5Pin, 30);}
if (CurrentGearPosition==P_N34) {Select_Gear_Motor_On(250, Motor2HallSensor5Pin, 30);}

if (CurrentGearPosition==0)
{
byte LastGearPosition=GetLastSuccessGearPosition();
if (LastGearPosition==P_N12) {Select_Gear_Motor_On(500, Motor2HallSensor5Pin, 30);}
if (LastGearPosition==P_N34) {Select_Gear_Motor_On(250, Motor2HallSensor5Pin, 30);}
} 
 }

Rezult=GetCurrentGearPosition();
if (Rezult!=0) {SetSuccessGearPosition_to_EEPROM(Rezult);}
return Rezult;
}

//###################################################################
//функция разблокировки задней передачи (блокировки 5ой)
boolean Gear_Unlock_R_Block_5(boolean Unlock_R_block_5)
{
if (Unlock_R_block_5) {digitalWrite(GearBlock5R_RelayPin, HIGH);}
if (!Unlock_R_block_5) {digitalWrite(GearBlock5R_RelayPin, LOW);}
return true; // встроить сюда проверку при срабатывании актуатора
}

//###################################################################
//функция переключения передачи  
//сначала производится перевод в нейтральную линию
//затем выбор передачи по нейтральной линии
//затем при необходимости разблокировки аередачи (задней или пятой)
//и уже потом перевод в нужное положение
boolean Go_To_Gear(byte GearName)
{
byte CurrentGearPosition=GetCurrentGearPosition();
if (CurrentGearPosition==GearName) {return true;}
if (CurrentGearPosition==0) {CurrentGearPosition=SearchingGear();}
  
byte SetNeutral=Go_To_Neutral_Line(); //переводим в нейтраль
if ((SetNeutral==P_N12) || (SetNeutral==P_N34) || (SetNeutral==P_N5R))
{ //1
if (GearName==P_1) {if (SelectGear(P_N12)==P_N12) {if (Change_Gear_Motor_On(-400, Motor1HallSensor1Pin,0, 100)==GearName){return true;}}}
if (GearName==P_2) {if (SelectGear(P_N12)==P_N12) {if (Change_Gear_Motor_On(400, Motor1HallSensor2Pin,0, 100)==GearName){return true;}}}

if (GearName==P_3) {if (SelectGear(P_N34)==P_N34) {if (Change_Gear_Motor_On(-400, Motor1HallSensor1Pin,0, 100)==GearName){return true;}}}
if (GearName==P_4) {if (SelectGear(P_N34)==P_N34) {if (Change_Gear_Motor_On(400, Motor1HallSensor2Pin,0, 100)==GearName){return true;}}}

if (GearName==P_5) {if (SelectGear(P_N5R)==P_N5R) {if (Gear_Unlock_R_Block_5(false)) {if (Change_Gear_Motor_On(-400, Motor1HallSensor1Pin,0, 100)==GearName){return true;}}}}
if (GearName==P_R) {if (SelectGear(P_N5R)==P_N5R) {if (Gear_Unlock_R_Block_5(true)) {if (Change_Gear_Motor_On(400, Motor1HallSensor2Pin,0, 100)==GearName){Gear_Unlock_R_Block_5(false);return true;}}}}
  
  
}//1
return false;
}  
       
//###################################################################
//###################################################################
// главный цикл
void loop()
{
wdt_reset();
KPP_working();  
}

// процедура работы КПП - самодостаточная
void KPP_working()
{
delay(100);  
uint16_t ShifterButtonsStatus=Read_ShifterButtonsStatus();
ShifterButtonsStatus >>= Shifter_RearGearMode; 
byte Shifter_RearGearModeStatus=ShifterButtonsStatus & 1;
ShifterButtonsStatus=Read_ShifterButtonsStatus();
ShifterButtonsStatus >>= Shifter_PlusMinusMode; 
byte Shifter_PlusMinusModeStatus=ShifterButtonsStatus & 1;  

byte ToGear=GetShifterPosition();
byte GearName=GetCurrentGearPosition();
byte GearNameToIndicate=GearName;

// обычный режим
//*******************
byte GearLastName=GetLastSuccessGearPosition();
if ((GearLastName!=ToGear) && (Shifter_PlusMinusModeStatus==0))
{
if ((ToGear==P_1)&& (Shifter_RearGearModeStatus==0))  {GearNameToIndicate=Go_To_Gear(ToGear);}
if ((ToGear==P_2)&& (Shifter_RearGearModeStatus==0))  {GearNameToIndicate=Go_To_Gear(ToGear);}
if ((ToGear==P_3)&& (Shifter_RearGearModeStatus==0))  {GearNameToIndicate=Go_To_Gear(ToGear);}
if ((ToGear==P_4)&& (Shifter_RearGearModeStatus==0))  {GearNameToIndicate=Go_To_Gear(ToGear);}
if ((ToGear==P_5)&& (Shifter_RearGearModeStatus==0))  {GearNameToIndicate=Go_To_Gear(ToGear);}
if ((ToGear==P_R) && (Shifter_RearGearModeStatus==1)) {GearNameToIndicate=Go_To_Gear(ToGear);}
if ((ToGear==P_N12)||(ToGear==P_N34) ||(ToGear==P_N5R)){GearNameToIndicate=Go_To_Neutral_Line();}
}
//*******************



// спортивный режим +-
//*******************
//byte GearLastName_withoutN=0;
//GearLastName
byte FrontGearLastName=GetLastFrontGearPosition();
if ((FrontGearLastName<P_1) || (FrontGearLastName>P_5)) {FrontGearLastName=P_1;}
if (Shifter_PlusMinusModeStatus==1)
   {
if (ToGear==P_PLUS)
{
if ((GearLastName==P_N5R)&& (FrontGearLastName==P_5)) {GearNameToIndicate=Go_To_Gear(FrontGearLastName);}  
if ((FrontGearLastName>=P_1) && (FrontGearLastName<P_5)) {GearNameToIndicate=Go_To_Gear(FrontGearLastName+1);}
}

if (ToGear==P_MINUS)
{
//if (GearLastName==P_1) {GearName=Go_To_Neutral_Line();}  
if ((GearLastName==P_N12)&& (FrontGearLastName==P_1)) {GearNameToIndicate=Go_To_Gear(FrontGearLastName);}
if ((FrontGearLastName>P_1) && (FrontGearLastName<=P_5))  {GearNameToIndicate=Go_To_Gear(FrontGearLastName-1);}
}

if (Shifter_RearGearModeStatus==1) {GearNameToIndicate=Go_To_Neutral_Line();} 
   }
//*******************

#if DEBUG  
//Serial.println(ToGear);    
//delay(1000);
#endif


Indicate_Gear_On_LCD(GearNameToIndicate);


}





//###################################################################
// обработчик событий тахометра
void  TahometrImpulse_on() //сидит на прерывании 0, срабатывает при возникновении событий на 2 цифровом входе
{ 
//TimeImpulse1=
Tahometr_impulse_count++; //увеличить счетчик импульсов
//Speed=0;
if (Tahometr_impulse_count >=2) //2имп=1 оборот коленвала
  {
Taho_ImpulseTime = micros()-Taho_time;  //время прихода между импульсами
Taho_time = micros(); //обнулить
Taho=((Tahometr_impulse_count*60*1000000)/(2*Taho_ImpulseTime));   // перевод в об/мин, формула универсальна для Тигго, 1 об на 2 ммпульса,1000000 - перевод мкс в сек., 60 - перевод сек в мин.

#if DEBUG
//Serial.println(Taho_ImpulseTime);
//Serial.println(Taho); 
#endif

Tahometr_impulse_count = 0;
  }  
} 

//###################################################################
// обработчик событий датчика скорости
void  SpeedImpulse_on() //сидит на прерывании 1, срабатывает при возникновении событий на 3 цифровом входе
{ 
//TimeImpulse1=
Speed_impulse_count++; //увеличить счетчик импульсов
//Speed=0;
if (Speed_impulse_count >=2) //2имп=0,8м    5имп=2м
  {
Speed_ImpulseTime = micros()-Speed_time;  //время прихода между импульсами
Speed_time = micros(); //обнулить
Speed=((Speed_impulse_count*2*3.6*1000000)/(5*Speed_ImpulseTime));   // перевод в км/ч, формула универсальна для Тигго, 2=2м за 5 ммпульсов, 3.6 - перевод м/с в км/ч, 1000000 - перевод мкс в сек., 5 - 5 импульсов

#if DEBUG
//Serial.println(Speed_ImpulseTime);
//Serial.println(Speed); 
#endif

Speed_impulse_count = 0;
  }  
} 

//###################################################################
// Функция проверки нажатия рулевой кнопки
// Возвращает false если кнопка не была нажата 
// и true если нажата
// ButtonName принимает значения в зависимости от нажатой кнопки +, -, >, R=>>|, L=|<<, S=SRC, X=None
boolean WheelButonPush_IsPushed()    
{    
bool result; 
result=false;
unsigned long buttonVal;
buttonVal=0; 
ButtonName='X';
 res_d = analogRead(WheelButtonsPin);  
  if( res_d < LIMIT) res_d = LIMIT; 
  delay(10);   
  res_dt1 = analogRead(WheelButtonsPin);   
        old_time = millis();    
        math_time = 0;     
        while(math_time < 200)    
          {    
             real_time = millis();                 
             math_time = real_time - old_time;   
            res_dt1 = analogRead(WheelButtonsPin);  
            if(res_dt1 < res_d-LIMIT || res_dt1 > res_d+LIMIT)break; 
          }    
       
    if( math_time > 70)  
      {   
  buttonVal=res_d;
  ButtonName='X';
   //   Serial.println (res_d);
              
        if ((buttonVal>25) && (buttonVal<45))
       {
ButtonName='-'; //35-36
result=true;
        }
    
        if ((buttonVal>60) && (buttonVal<85))
       {
ButtonName='+'; //72-73
result=true;
        }

        if ((buttonVal>110) && (buttonVal<135))
       {
ButtonName='S'; //122
result=true;
        }

        if ((buttonVal>175) && (buttonVal<200))
       {
ButtonName='R'; //187
result=true;
        }

        if ((buttonVal>275) && (buttonVal<295))
       {
ButtonName='L'; //285
result=true;
        }

        if ((buttonVal>415) && (buttonVal<440))
       {
ButtonName='>'; //429
result=true;
        }
        
        if ((buttonVal>645) && (buttonVal<670))
       {
ButtonName='X'; //658-659
result=false;
        }          

 buttonVal=0;    
    }  
       return result;
}  



//###################################################################
 int sensorValue = 0;  // variable to store the value coming from the sensor
 int countvalues = 5;      // how many values must be averaged
 int ZeroLevel = 520;    // Zero level
 float kVolt = 0.0506;      // conversion factor

int Current(int sensorPin) {
  int TMPsensorValue = 0;
  int count = 0;
 
  for (count =0; count < countvalues; count++) {
    // read the value from the sensor:
    TMPsensorValue = analogRead(sensorPin);
    delay(30);
    // make average value
    sensorValue = (sensorValue+TMPsensorValue)/2;
    }
  return sensorValue;
  }

//###################################################################
void Timer2_Timer() //обработка событий в таймере
{

//CurrentSensor1Value = analogRead(CurrentSensor1Pin);       // read analog input pin CurrentSensor1Pin

//int CurrentSensor1Value = Current(CurrentSensor1Pin);
//  Serial.println(kVolt * (CurrentSensor1Value - ZeroLevel));
/*  
#if DEBUG
    //  Serial.println(CurrentSensor1Value);  // prints the value read
 Serial.println((CurrentSensor1Value-512)*1000/20);  // prints the value read
  delay(100);                        // wait 100ms for next reading
#endif
*/   
} 

 

vworld
vworld аватар
Offline
Зарегистрирован: 26.09.2011

раз уж разговор прошел про авто, может кто подскажет чем управляются воздуховодные заслонки климата в авто? не..ну понятно что какой-то двигатель, может кто смотрел?

maks.portnyagin
Offline
Зарегистрирован: 26.08.2012

 Тоже надо переделать управление климатом, сейчас у меня все тросами регулируется. Есть шаговые но пока толком запустить их не удалось.