Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //06.07.25
- //Двустворчатые ворота с засовом.
- //
- //коммандные пины;
- #define IDLEpin 2 //прекратить, что бы ни происходило
- #define OPENingPin 3 //открыть
- #define CLOSingPin 4 //закрыть
- //пины состояния концевиков
- #define LOTpin 5 //левый открыт?
- #define ROTpin 6 //ппавый открыт?
- #define LCTpin 7 //левый закрыт?
- #define RCTpin 8 //правый закрыт?
- #define BOTpin 9 //засов открыт?
- #define BCTpin 10 //засов закрыт?
- //пины состояния реле
- #define LORpin 11 //открыть левый
- #define RORpin 12 //открыть правый
- #define LCRpin 13 //закрыть левый
- #define RCRpin 14 //закрыть правый
- #define BORpin 15 //открыть засов
- #define BCRpin 16 //закрыть засов
- // Флаги состояния концевиков
- bool LOT = 0; // LeftOPENingTerminal
- bool LCT = 0; // LeftCLOSingTerminal
- bool ROT = 0; // RightOPENingTerminal
- bool RCT = 0; // RightCLOSingTerminal
- bool BOT = 0; // BoltOPENingTerminal
- bool BCT = 0; // BoltCLOSingTerminal
- // Флаги состояния реле
- bool LOR = 0; // LeftOPENingRelay
- bool LCR = 0; // LeftCLOSingRelay
- bool ROR = 0; // RightOPENingRelay
- bool RCR = 0; // RightCLOSingRelay
- bool BOR = 0; // BoltOPENingRelay
- bool BCR = 0; // BoltCLOSingRelay
- //Глобальная задача. Новый тип данных, выражается через int.
- enum State {
- IDLE = 0,
- OPEN = 1,
- CLOSE = 2
- };
- State currentState; //Глобальный флаг текущей задачи.
- int PDelay; //Время разбежки между створками.
- /*
- Старт открытия/закрытия створок. Левая внахлест, -- должна начать открываться раньше,
- а закрываться позже. OPENingPlates() и CLOSingPlates() вычислют разницу старта опираясь на moveStarted
- */
- unsigned long moveStarted; //время начала работы, для OPENingPlates() и CLOSingPlates().
- /*Чтобы каждый раз не прогонять OPENingPlates() полностью,
- мы будем в самом ее начале проверять, идет ли движение обеих створок и тут же выходить на новый цикл, если да.
- */
- bool LMove; //левая створка двигается?
- bool RMove; //правая створка двигается?
- /*Переменные антидребезга кнопок и концевиков*/
- int DBDelay = 100; //DeBounce Dalay
- int LBState; //Last Button State, прошлое положение кнопки.
- long LBTime; //Last Button Time. прошлое время срабатывания.
- void setup() {
- PDelay = 4000;
- DBDelay = 100;
- LBState = HIGH;
- currentState = IDLE;
- //Инициализация пинов кнопок.
- pinMode(IDLEpin, INPUT_PULLUP);
- pinMode(OPENingPin, INPUT_PULLUP);
- pinMode(CLOSingPin, INPUT_PULLUP);
- //Инициализация пинов концевиков.
- pinMode(LOTpin, INPUT);
- pinMode(LCTpin, INPUT);
- pinMode(ROTpin, INPUT);
- pinMode(RCTpin, INPUT);
- pinMode(BOTpin, INPUT);
- pinMode(BCTpin, INPUT);
- //Инициализация пинов реле.
- pinMode(LORpin, OUTPUT);
- pinMode(LCRpin, OUTPUT);
- pinMode(RORpin, OUTPUT);
- pinMode(RCRpin, OUTPUT);
- pinMode(BORpin, OUTPUT);
- pinMode(BCRpin, OUTPUT);
- Serial.begin(9600);
- Serial.println("Setup executed");
- }
- int checkErrors() {
- /* Проверяет конфликты состояния датчиков/кнопок.
- В случае конфликта сбрасывает состояние в IDLE
- и сигнализирует об ошибке.
- Например, датчики "открыто" и "закрыто"
- работают одновременно для левой
- или правой половины ворот, или для
- засова:
- */
- if (ROT == RCT || LOT == LCT || BOT == BCT) {
- int ERROR = 1; //пока пример: одновременное срабатывание взаимоислючающих концевиков.
- // blinkError(ERROR); //сигнал характера ошибки.
- Serial.println("ERROR:"+String(ERROR));
- return ERROR;
- }
- return 0;
- }
- void halt() { //остановка всего, по тревоге или штатно
- //работает в простое, вместо подтяжки реле.
- //Кнопки подтянем к земле лапками.
- digitalWrite(LORpin, LOW);
- digitalWrite(LCRpin, LOW);
- digitalWrite(RORpin, LOW);
- digitalWrite(RCRpin, LOW);
- digitalWrite(BORpin, LOW);
- digitalWrite(BCRpin, LOW);
- LOR = 0;
- LCR = 0;
- ROR = 0;
- RCR = 0;
- BOR = 0;
- BCR = 0;
- moveStarted = 0;
- currentState = IDLE;
- }
- bool OPENingBolt() { //открываем засов
- if (!BOT) { //если концевик открытия не замкнут
- BOR = 1; //выставляем флаг открытия
- digitalWrite(BORpin, HIGH); //двигаем реле открытия
- return false; // болт не открыт. Возвращаем ложь в функции движения.
- } else if (BOT == 1) {
- if(BOR){moveStarted = millis();}// запоминаем время старта открытия створок,
- BOR = 0; //чтобы обеспечить разбежку створок.
- digitalWrite(BORpin, LOW);
- return true; // болт открыт. Сигналим об этом.
- }
- }
- bool CLOSingBolt() {
- if (!BCT) {
- BCR = 1;
- digitalWrite(BCRpin, HIGH);
- return false;
- } else if (BCT == 1) {
- digitalWrite(BCRpin, LOW);
- return true;
- }
- }
- void OPENingPlates() {
- /*открывает створки ворот
- левая должна открываться раньше,
- закрываться позже*/
- if (LOT) { //Официальное открытие левой створки свершилось.
- LMove = false;
- digitalWrite(LORpin, LOW);
- }
- if (ROT) { //Официальное откытие правой створки.
- RMove = false; //Левая теперь двиагается одна, через проверку концевика.
- digitalWrite(RORpin, LOW);
- }
- if (LMove && RMove) {
- digitalWrite(LORpin, HIGH);
- digitalWrite(RORpin, HIGH);
- return; //если ворота уже двигаются, продолжаем движение, идем на следующий цикл.
- //выходим из процедуры открытия. Флаги на месте. Cбрасываются они либо
- //концевиками в loop(), либо halt().
- }
- if (!OPENingBolt()) {
- return; //Если засов не открыт, ждем пока откроется
- //идем на следующий цикл.
- } else { //Если засов открыт, доходим до начала движения ворот.
- if ((millis() - moveStarted) > PDelay && !ROT) { //Если после первого цикла функции прошло более 4 сек
- digitalWrite(RORpin, HIGH); //и не открыто полностью, -- начинаем двигать левую створку,
- RMove = true; //о чем выставляем флаг.
- }
- if (!LOT) { //если не замкнут концевик левой створки
- digitalWrite(LORpin, HIGH); //двигаем.
- LMove = true; //о чем выставляем флаг.
- }
- if (LOT && ROT) { //Если обе створки открыты
- currentState = IDLE; //Отдыхаем.
- halt();
- }
- }
- }
- void CLOSingPlates() { //закрываем ворота
- if (!BOT){ //Если засов е открыт
- return; //не пытаемся закрыть ворота.
- }
- if(LCT){
- LMove = false;
- digitalWrite(LCRpin, LOW);
- }
- if(RCT){
- RMove = false;
- digitalWrite(RCRpin, LOW);
- }
- if (LMove && RMove) {
- digitalWrite(LCRpin, HIGH);
- digitalWrite(RCRpin, HIGH);
- return; //если створки уже двигаются, продлжаем цикл.
- }
- if (millis() - moveStarted > PDelay && !LCT) { //начинаем двигать левую створку после паузы.
- digitalWrite(LCRpin, HIGH);
- LMove = true;
- }
- if (!RCT) { //Правая стартует она без задержки
- RMove = true;
- digitalWrite(RCRpin, HIGH);
- }
- if (RCT && LCT) { //Если обе створки закрыты,
- if (!CLOSingBolt()) { //но засов не закрыт
- return; //идем на следующий цикл, где засов продолжает двигаться.
- } else { //Створки закрыты и засов тоже.
- halt(); //Ок. Стоп.
- }
- }
- }
- int dbRead(int PIN) {
- int CBState = digitalRead(PIN);
- if (CBState != LBState) { // Положение кнопки изменилось,
- LBTime = millis(); // запускаем таймер.
- LBState = CBState; // Обновляем глобальный флаг последнего положения.
- } else if (LBState == CBState) { // Это новый цикл. Все еще не изменилось?
- if (millis() - LBTime > DBDelay) { // Замеряем длительность нажатия
- Serial.println("dbRead("+String(PIN)+","+String(CBState)+")");
- return CBState;
- }
- }
- }
- int dtRead(int PIN) { // Антидребезг концевиков. Это не кнопки.
- // Здесь является штатным одновременное состояние многих.
- // поэтому антидребезг каждому.
- static bool LOTlast = LOW;
- static long LOTtime = 0;
- static bool LCTlast = LOW;
- static long LCTtime = 0;
- static bool ROTlast = LOW;
- static long ROTtime = 0;
- static bool RCTlast = LOW;
- static long RCTtime = 0;
- static bool BOTlast = LOW;
- static long BOTtime = 0;
- static bool BCTlast = LOW;
- static long BCTtime = 0;
- switch (PIN) {
- case LOTpin:
- {
- int CTState = digitalRead(LOTpin);
- if (LOTlast != CTState) { // Состояние изменилось
- LOTtime = millis(); // Запускаем таймер
- LOTlast = CTState; // Обновляем состояние
- } else if (millis() - LOTtime > DBDelay) { // Состояние не изменилось. Проверка задержки
- return CTState; // Возвращаем состояние
- }
- break; // Для этого пина завершили. ИИ четко реплицировал остальные кейсы,
- // вежливо проигнорировал просьбу кадрировать switch,
- // и молча добавил инициацию статиков, дав всю функцию целиком.
- //
- }
- case LCTpin:
- {
- int CTState = digitalRead(LCTpin);
- if (LCTlast != CTState) {
- LCTtime = millis();
- LCTlast = CTState;
- } else if (millis() - LCTtime > DBDelay) {
- return CTState;
- }
- break;
- }
- case ROTpin:
- {
- int CTState = digitalRead(ROTpin);
- if (ROTlast != CTState) {
- ROTtime = millis();
- ROTlast = CTState;
- } else if (millis() - ROTtime > DBDelay) {
- return CTState;
- }
- break;
- }
- case RCTpin:
- {
- int CTState = digitalRead(RCTpin);
- if (RCTlast != CTState) {
- RCTtime = millis();
- RCTlast = CTState;
- } else if (millis() - RCTtime > DBDelay) {
- return CTState;
- }
- break;
- }
- case BOTpin:
- {
- int CTState = digitalRead(BOTpin);
- if (BOTlast != CTState) {
- BOTtime = millis();
- BOTlast = CTState;
- } else if (millis() - BOTtime > DBDelay) {
- return CTState;
- }
- break;
- }
- case BCTpin:
- {
- int CTState = digitalRead(BCTpin);
- if (BCTlast != CTState) {
- BCTtime = millis();
- BCTlast = CTState;
- } else if (millis() - BCTtime > DBDelay) {
- return CTState;
- }
- break;
- }
- default:
- return LOW; // Для любых неподдерживаемых пинов
- }
- return LOW; // Возвращаем LOW, если ничего не изменилось
- }
- void checkSensors() {
- if (dbRead(OPENingPin) == HIGH) { //обрабатывая кнопку, мы выставляем флаг,
- //и время нажатия кнопки.
- Serial.println("OPENingPlates:HIGH");
- if (currentState != OPEN) { // это первый цикл вызова функции?
- currentState = OPEN; // время пошло. Обратно флаг будет снят кнопкой либо концевиками.
- OPENingPlates();
- }
- }
- if (dbRead(CLOSingPin) == HIGH) {
- Serial.println("CLOSingPlates:HIGH");
- if(currentState !=CLOSE){ //Это первый вызов функции?
- moveStarted = millis(); //Значит стартуем таймер.
- currentState = CLOSE; //Выставляем глобальную задачу.
- CLOSingPlates();
- }
- }
- if (dbRead(IDLEpin) == HIGH) { //обрабатывая кнопку, мы лишь выставляем флаг.
- currentState = IDLE;
- Serial.println("IDLEpin:HIGH");
- halt();
- }
- /*пробегаемся по концевикам, устанавливаем соответствующие флаги*/
- LOT = dtRead(LOTpin);
- LCT = dtRead(LCTpin);
- ROT = dtRead(ROTpin);
- RCT = dtRead(RCTpin);
- BOT = dtRead(BOTpin);
- BCT = dtRead(BCTpin);
- } //конец checkSensors()
- void loop() { // Генеральная линия Партии.
- checkSensors(); //мацаем кнопки, концевики, возможно другие сигналы
- switch (currentState) {
- case IDLE:
- halt();
- break;
- case OPEN:
- //официальное начало OPENingPlates().
- OPENingPlates();
- if (LOT && ROT) {
- currentState = IDLE; //официальное завершение OPENingPlates().
- }
- break;
- case CLOSE:
- //Официальное начало CLOSingPlates();
- CLOSingPlates(); //ныряем в функцию в цикле
- if (LCT && RCT && BCT) { //пока все гештальты не закрыты.
- currentState = IDLE;
- }
- break;
- default:
- break;
- }
- Serial.println("currentState:" +String(currentState));
- }
Advertisement
Add Comment
Please, Sign In to add comment