#define pPulse 2 //Пульс таходатчика
#define pOpenESP 12 //Команда открытия ворот от ESPхи
#define pCloseESP 11 //Команда закрытия ворот от ESPхи
#define pOpenMan 9 //Кнопка открытия ворот, инвертированная!
#define pCloseMan 10 //Кнопка закрытия ворот, инвертированная!
#define pPowerRelay 13 //Силовое общее реле, размыкает оба полюса
#define pReverceRelay 4 //Реле реверса, переключает обмотки двгателя
#define pPower 3 //Выход для тиристорного ключа
#define aBorder 1 //Аналоговый вход для уовня напряжения с герконов
#define pSensZero 5 //Датчик 0
#define FullPower 60 //Максимальная мощность мотора
#include
unsigned int CntPulse = 0;
bool bPulseHigh = false;
unsigned int TimePulse = 0;
long PercentPower = 0;
void setup()
{
pinMode(pPowerRelay, OUTPUT);
pinMode(pReverceRelay, OUTPUT);
pinMode(pPower, OUTPUT);
pinMode(pPulse, INPUT);
pinMode(pOpenESP, INPUT);
pinMode(pCloseESP, INPUT);
pinMode(pOpenMan, INPUT);
pinMode(pCloseMan, INPUT);
pinMode(pSensZero, INPUT);
Serial.begin(9600);
Serial.println("Init ok");
Serial.println(analogRead(aBorder));
if (GateState() == 0)
Serial.println("State - ERROR!!!");
if (GateState() == 1)
Serial.println("State - Open");
if (GateState() == 2)
Serial.println("State - Close");
if (GateState() == 3)
Serial.println("State - Neytral");
}
void loop()
{
//Обработка открытия
if (ComfirmCommand(pOpenESP, true) || (digitalRead(pCloseMan) && ComfirmCommand(pOpenMan, false))) //Нажали кнопку открытия
{
Serial.println("Command Open");
if (CntPulse == 0) //Режим ожидания
{
if (GateState() == 2 || GateState() == 3) //Закрыто или середина
{
Serial.println("Start Open");
digitalWrite(pReverceRelay, HIGH);
pStart();
}
else //И так открыто. Ничего делать и не надо
{
Serial.println("Command ignore");
delay(500);
}
}
else
{
if (IsClosing()) //Сейчас закрываем - останавливаем процесс
{
Serial.println("Manual stop");
pStop(false);
}
}
}
//Обработка закрытия
if (ComfirmCommand(pCloseESP, true) || (digitalRead(pOpenMan) && ComfirmCommand(pCloseMan, false))) //Нажали кнопку открытия
{
Serial.println("Command Close");
if (CntPulse == 0) //Режим ожидания
{
if (GateState() == 1 || GateState() == 3) //Открыто или середина
{
Serial.println("Start Close");
pStart();
}
else //И так закрыто. Ничего делать и не надо
{
Serial.println("Command ignore");
delay(500);
}
}
else
{
if (!IsClosing()) //Сейчас открываем - останавливаем процесс
{
Serial.println("Manual stop");
pStop(false);
}
}
}
if (CntPulse > 0) //Если счётчик стронулся - считаем что пошёл процесс открывания/закрывания
{
pRun();
}
else
{
//ну... шобы наверняка. Тушим свет, сливаем воду.
digitalWrite(pPower, LOW);
digitalWrite(pPowerRelay, LOW);
digitalWrite(pReverceRelay, LOW);
}
}
//Вернёт состояние ворот.
byte GateState()
{
if (analogRead(aBorder) > 400 && analogRead(aBorder) < 500)
return 1; //Открыто
if (analogRead(aBorder) > 550 && analogRead(aBorder) < 650)
return 2; //Закрыто
if (analogRead(aBorder) > 750 && analogRead(aBorder) < 850)
return 3; //Серединнное положение
return 0; //Ошибка!
}
//Вернёт, закрываем ли мы сейчас ворота?
bool IsClosing()
{
return !digitalRead(pReverceRelay);
}
//Разгон мотора
void pStart()
{
digitalWrite(pPowerRelay, HIGH);
delay(100);
Serial.println("Servo Start");
for (long i = 0; i < 15000; i++)
{
PercentPower = FullPower * (i / 150) / 100;
SetPower();
}
Serial.println("...Started");
CntPulse = 1;
}
//Рабочий ход мотора
void pRun()
{
PercentPower = FullPower;
SetPower();
TimePulse ++;
if (bPulseHigh != digitalRead(pPulse))
{
bPulseHigh = !bPulseHigh;
TimePulse = 0;
CntPulse ++;
}
if (TimePulse > 300)
{
pStop(true);
Serial.println("No pulse!");
return;
}
//Аварийная остановка по времени работы
if (CntPulse == 4000)
{
Serial.println("Max CntPulse!");
pStop(true);
}
if (CntPulse == 150)
{
//Аварийные остановки по неразмыканию герконов после запуска
if (IsClosing() && GateState() == 1)
{
Serial.println("Closing failed!");
pStop(true);
}
if (!IsClosing() && GateState() == 2)
{
Serial.println("Opening failed!");
pStop(true);
}
}
if (IsClosing() && GateState() == 2)
pStop(false);
if (!IsClosing() && GateState() == 1)
pStop(false);
}
//Остановка мотора. Флаг - резкая остановка, или плавная
void pStop(bool bForced)
{
if (bForced)
Serial.println("Servo Stop Forced");
else
Serial.println("Servo Stop");
if (!bForced)
{
for (long i = 0; i < 30000; i = i + 15)
{
PercentPower = FullPower - FullPower * (i / 300) / 100;
SetPower();
}
}
PercentPower = 0;
MsTimer2::stop();
digitalWrite(pPower, LOW);
delay(50);
digitalWrite(pPowerRelay, LOW);
digitalWrite(pReverceRelay, LOW);
Serial.print("CntPulse = ");
Serial.println(CntPulse);
CntPulse = 0;
}
// Установка мощности мотора.
void SetPower()
{
if (digitalRead(pSensZero) == HIGH) //Всё взводится только если сейчас 0!
{
MsTimer2::stop();
digitalWrite(pPower, LOW);
//Serial.println(PercentPower);
if (PercentPower <= 0 || PercentPower > 100)
return;
unsigned long ms = 6 - (PercentPower * 6 / 100); //А 6мс потому, что датчик 0 не идеален и уже проходит некоторое время до того, как напряжение будет достаточно большое для загорания светодиода в оптоаре.
MsTimer2::set(ms, PowerControl);
MsTimer2::start();
}
}
//Функция избавления от дребезга контактов и импульсных помех
bool ComfirmCommand(int button, bool ActiveHigh)
{
for (byte i = 0; i < 150; i++)
{
if (digitalRead(button) == (ActiveHigh? LOW : HIGH))
{
delayMicroseconds(500);
return false;
}
}
return true;
}
//Метод вызывается из перывания по таймеру и тупо активирует тиристорный ключ.
void PowerControl()
{
digitalWrite(pPower, HIGH);
}