• Как запустить Ladder/FBD/SFC/ST программы на микроконтроллере?

    @SleepyBear09
    Программист, со словарем
    Есть одно ПО которое удовлетворяет твоим запросам - FlProg. На нем можно программировать на языках FBD и LD различные микроконтроллеры. Лично я работал с Arduino. Только скажу сразу, не знаю как со всеми процессорами, но на ардуино - ты просто создаешь проект со всеми переменными и логикой, но потом он просто тебе конвертирует на язык ArduinoIDE. Сколько работал осечек не давал, все четко конвертировал.
    Ниже прикрепил скрин со всеми поддерживаемыми микропроцессорами.
    655b6b0aca621547618496.png
    Ответ написан
    Комментировать
  • Как сделать так, чтобы при нажатии кнопки, на дисплее LCD перестало отображаться время, а заходил в контекстное меню?

    @SleepyBear09 Автор вопроса
    Программист, со словарем
    Закончил, использовал для этого функцию currentState. Получилось не совсем идеально, но свое предназначение исполняет хорошо.

    Итоговый код
    #include <ThreeWire.h>
    #include <RtcDS1302.h>
    #include <LiquidCrystal.h>
    #include <EEPROM.h>
    
    ThreeWire myWire(10, 11, 12); // IO, SCLK, CE
    RtcDS1302<ThreeWire> Rtc(myWire);
    
    LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
    
    RtcDateTime now;
    
    int selectedField = 0; // 0 - часы, 1 - минуты
    
    const int relayPin = 2;
    
    int hour = 11;
    int minute = 33;
    
    #define BTN_UP     1
    #define BTN_DOWN   2
    #define BTN_LEFT   3
    #define BTN_RIGHT  4
    #define BTN_SELECT 5
    #define BTN_NONE   10
    
    // Адреса в EEPROM для хранения времени
    #define ADDR_HOUR   0
    #define ADDR_MINUTE 1
    
    void saveTimeToEEPROM(uint8_t hour, uint8_t minute) {
        EEPROM.write(ADDR_HOUR, hour);
        EEPROM.write(ADDR_MINUTE, minute);
    }
    
    void loadTimeFromEEPROM(uint8_t &hour, uint8_t &minute) {
        hour = EEPROM.read(ADDR_HOUR);
        minute = EEPROM.read(ADDR_MINUTE);
    }
    
    enum State {
        DISPLAY_TIME,
        SET_TIME_MENU,
        SET_HOUR,
        SET_MINUTE
    };
    
    State currentState = DISPLAY_TIME;
    
    void clearLine(int line) {
        lcd.setCursor(0, line);
        lcd.print("                ");
    }
    
    void printDisplay(String message) {
        lcd.setCursor(0, 0);
        lcd.print(message);
        delay(1000);
        clearLine(0);
        clearLine(1);
    }
    
    int detectButton() {
      int keyAnalog =  analogRead(A0);
      if (keyAnalog < 100) {
        // Значение меньше 100 – нажата кнопка right
        return BTN_RIGHT;
      } else if (keyAnalog < 200) {
        // Значение больше 100 (иначе мы бы вошли в предыдущий блок результата сравнения, но меньше 200 – нажата кнопка UP
        return BTN_UP;
      } else if (keyAnalog < 400) {
        // Значение больше 200, но меньше 400 – нажата кнопка DOWN
        return BTN_DOWN;
      } else if (keyAnalog < 600) {
        // Значение больше 400, но меньше 600 – нажата кнопка LEFT
        return BTN_LEFT;
      } else if (keyAnalog < 800) {
        // Значение больше 600, но меньше 800 – нажата кнопка SELECT
        return BTN_SELECT;
      } else {
        // Все остальные значения (до 1023) будут означать, что нажатий не было
        return BTN_NONE;
      }
    }
    
    void updateDisplay() {
        RtcDateTime now = Rtc.GetDateTime();
        char timeString[16]; // формат времени "hh:mm:ss"
    
        // Форматируем строку времени в зависимости от текущего режима
        switch (currentState) {
            case SET_HOUR:
                snprintf_P(timeString, countof(timeString), PSTR("Set Hour: %02u"), hour);
                break;
            case SET_MINUTE:
                snprintf_P(timeString, countof(timeString), PSTR("Set Minute: %02u"), minute);
                break;
            default:
                snprintf_P(timeString, countof(timeString), PSTR("%02u:%02u:%02u"), now.Hour(), now.Minute(), now.Second());
                break;
        }
    
        // Обновляем дисплей
        lcd.setCursor(0, 0);
        lcd.print(timeString);
    }
    
    void handleTimeSetting(int button) {
        switch (currentState) {
            case DISPLAY_TIME:
                if (button == BTN_SELECT) {
                    currentState = SET_TIME_MENU;
                    clearLine(0);
                    clearLine(1);
                    printDisplay("Set Time Menu");
                }
                break;
            case SET_TIME_MENU:
                switch (button) {
                    case BTN_NONE:
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Time Mode");
                    case BTN_UP:
                        currentState = SET_HOUR;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Hour");
                        break;
                    case BTN_DOWN:
                        currentState = SET_MINUTE;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Minute");
                        break;
                    case BTN_RIGHT:
                        currentState = DISPLAY_TIME;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Display Time");
                        clearLine(0);
                        clearLine(1);
                        break;
                    // Добавьте обработку других кнопок при необходимости
                }
                break;
            case SET_HOUR:
            selectedField = 0;
               switch (button) {
                    case BTN_UP:
                        currentState = SET_HOUR;
                        incrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Hour");
                        break;
                    case BTN_DOWN:
                        currentState = SET_HOUR;
                        decrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Hour");
                        break;
                    case BTN_RIGHT:
                        currentState = DISPLAY_TIME;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Display Time");
                        clearLine(0);
                        clearLine(1);
                        break;
                    case BTN_LEFT:
                        currentState = SET_TIME_MENU;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Time Menu");
                        break;
                    // Добавьте обработку других кнопок при необходимости
                }
                break; // Обработка установки часов, аналогично предыдущим примерам
                // Пример: при нажатии кнопки "Select" сохраняем часы и переходим обратно в меню
                if (button == BTN_SELECT) {
                    saveTimeToEEPROM(hour, minute);
                    currentState = SET_TIME_MENU;
                    clearLine(0);
                    clearLine(1);
                    printDisplay("Display Time");
                }
                break;
            case SET_MINUTE:
               selectedField = 1;
               switch (button) {
                    case BTN_UP:
                        currentState = SET_MINUTE;
                        incrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Minute");
                      break;
                    case BTN_DOWN:
                        currentState = SET_MINUTE;
                        decrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Minute");
                    break;
                    case BTN_RIGHT:
                        currentState = DISPLAY_TIME;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Display Time");
                        clearLine(0);
                        clearLine(1);
                      break;
                    case BTN_LEFT:
                        currentState = SET_TIME_MENU;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Time Menu");
                      break;
                    // Добавьте обработку других кнопок при необходимости
                } // Обработка установки минут, аналогично предыдущим примерам
                 // Пример: при нажатии кнопки "Select" сохраняем минуты и переходим обратно в меню
                if (button == BTN_SELECT) {
                    saveTimeToEEPROM(now.Hour(), now.Minute());
                    currentState = DISPLAY_TIME;
                    clearLine(0);
                    printDisplay("Display Time");
                }
                break;
        }
    }
    
    void setup() {
        Serial.begin(9600);
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);
        printDisplay("compiled: ");
        printDisplay(__DATE__);
        pinMode(2, OUTPUT);
    
        Rtc.Begin();
        RtcDateTime compiled = RtcDateTime(__TIME__);
    
        // Загрузим время из EEPROM при старте программы
        uint8_t storedHour, storedMinute;
        loadTimeFromEEPROM(storedHour, storedMinute);
    
        // Выведем время из EEPROM
        lcd.setCursor(0, 0);
        lcd.print("Set time: ");
        char storedTimeString[16];
        snprintf_P(storedTimeString, countof(storedTimeString), PSTR("%02u:%02u"), hour, minute);
        lcd.print(storedTimeString);
        delay(2000);
        clearLine(0);
        clearLine(1);
    }
    
    void loop() {
        RtcDateTime now = Rtc.GetDateTime(); // Объявим переменную now здесь
        handleTimeSetting(detectButton());
        updateDisplay();
    
        if (!now.IsValid()) {
            lcd.print("RTC lost confidence in the DateTime!");
        }
      if (now.Hour() == hour && now.Minute() == minute && now.Second() == 0) {
        // Включаем реле на 3 секунды
        digitalWrite(relayPin, HIGH);
        delay(3000);
        digitalWrite(relayPin, LOW);
      }
    }
    
    #define countof(a) (sizeof(a) / sizeof(a[0]))
    
    void setHour(uint8_t hour) {
        now = Rtc.GetDateTime();
        now = RtcDateTime(now.Year(), now.Month(), now.Day(), hour, now.Minute(), now.Second());
        Rtc.SetDateTime(now);
    }
    
    void setMinute(uint8_t minute) {
        now = Rtc.GetDateTime();
        now = RtcDateTime(now.Year(), now.Month(), now.Day(), now.Hour(), minute, now.Second());
        Rtc.SetDateTime(now);
    }
    
    void incrementSelectedField() {
        switch (selectedField) {
            case 0:
                hour = hour + 1;
                break;
            case 1:
                minute = minute + 1;
                break;
        }
    }
    void decrementSelectedField() {
        switch (selectedField) {
            case 0:
                hour = hour - 1;
                break;
            case 1:
                minute = minute - 1;
                break;
        }
    }
    Ответ написан
    Комментировать
  • Как сделать так, что при нажатии кнопки я мог задать время через LCD дисплей?

    @SleepyBear09 Автор вопроса
    Программист, со словарем
    Закончил, нашел функцию currentState и через нее реализовал меню контекстного меню. Итоговый не является идеальным и еще будет дорабатываться, но он исправно выполняет свою цель.

    Итоговый код:
    #include <ThreeWire.h>
    #include <RtcDS1302.h>
    #include <LiquidCrystal.h>
    #include <EEPROM.h>
    
    ThreeWire myWire(10, 11, 12); // IO, SCLK, CE
    RtcDS1302<ThreeWire> Rtc(myWire);
    
    LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
    
    RtcDateTime now;
    
    int selectedField = 0; // 0 - часы, 1 - минуты
    
    const int relayPin = 2;
    
    int hour = 11;
    int minute = 33;
    
    #define BTN_UP     1
    #define BTN_DOWN   2
    #define BTN_LEFT   3
    #define BTN_RIGHT  4
    #define BTN_SELECT 5
    #define BTN_NONE   10
    
    // Адреса в EEPROM для хранения времени
    #define ADDR_HOUR   0
    #define ADDR_MINUTE 1
    
    void saveTimeToEEPROM(uint8_t hour, uint8_t minute) {
        EEPROM.write(ADDR_HOUR, hour);
        EEPROM.write(ADDR_MINUTE, minute);
    }
    
    void loadTimeFromEEPROM(uint8_t &hour, uint8_t &minute) {
        hour = EEPROM.read(ADDR_HOUR);
        minute = EEPROM.read(ADDR_MINUTE);
    }
    
    enum State {
        DISPLAY_TIME,
        SET_TIME_MENU,
        SET_HOUR,
        SET_MINUTE
    };
    
    State currentState = DISPLAY_TIME;
    
    void clearLine(int line) {
        lcd.setCursor(0, line);
        lcd.print("                ");
    }
    
    void printDisplay(String message) {
        lcd.setCursor(0, 0);
        lcd.print(message);
        delay(1000);
        clearLine(0);
        clearLine(1);
    }
    
    int detectButton() {
      int keyAnalog =  analogRead(A0);
      if (keyAnalog < 100) {
        // Значение меньше 100 – нажата кнопка right
        return BTN_RIGHT;
      } else if (keyAnalog < 200) {
        // Значение больше 100 (иначе мы бы вошли в предыдущий блок результата сравнения, но меньше 200 – нажата кнопка UP
        return BTN_UP;
      } else if (keyAnalog < 400) {
        // Значение больше 200, но меньше 400 – нажата кнопка DOWN
        return BTN_DOWN;
      } else if (keyAnalog < 600) {
        // Значение больше 400, но меньше 600 – нажата кнопка LEFT
        return BTN_LEFT;
      } else if (keyAnalog < 800) {
        // Значение больше 600, но меньше 800 – нажата кнопка SELECT
        return BTN_SELECT;
      } else {
        // Все остальные значения (до 1023) будут означать, что нажатий не было
        return BTN_NONE;
      }
    }
    
    void updateDisplay() {
        RtcDateTime now = Rtc.GetDateTime();
        char timeString[16]; // формат времени "hh:mm:ss"
    
        // Форматируем строку времени в зависимости от текущего режима
        switch (currentState) {
            case SET_HOUR:
                snprintf_P(timeString, countof(timeString), PSTR("Set Hour: %02u"), hour);
                break;
            case SET_MINUTE:
                snprintf_P(timeString, countof(timeString), PSTR("Set Minute: %02u"), minute);
                break;
            default:
                snprintf_P(timeString, countof(timeString), PSTR("%02u:%02u:%02u"), now.Hour(), now.Minute(), now.Second());
                break;
        }
    
        // Обновляем дисплей
        lcd.setCursor(0, 0);
        lcd.print(timeString);
    }
    
    void handleTimeSetting(int button) {
        switch (currentState) {
            case DISPLAY_TIME:
                if (button == BTN_SELECT) {
                    currentState = SET_TIME_MENU;
                    clearLine(0);
                    clearLine(1);
                    printDisplay("Set Time Menu");
                }
                break;
            case SET_TIME_MENU:
                switch (button) {
                    case BTN_NONE:
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Time Mode");
                    case BTN_UP:
                        currentState = SET_HOUR;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Hour");
                        break;
                    case BTN_DOWN:
                        currentState = SET_MINUTE;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Minute");
                        break;
                    case BTN_RIGHT:
                        currentState = DISPLAY_TIME;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Display Time");
                        clearLine(0);
                        clearLine(1);
                        break;
                    // Добавьте обработку других кнопок при необходимости
                }
                break;
            case SET_HOUR:
            selectedField = 0;
               switch (button) {
                    case BTN_UP:
                        currentState = SET_HOUR;
                        incrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Hour");
                        break;
                    case BTN_DOWN:
                        currentState = SET_HOUR;
                        decrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Hour");
                        break;
                    case BTN_RIGHT:
                        currentState = DISPLAY_TIME;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Display Time");
                        clearLine(0);
                        clearLine(1);
                        break;
                    case BTN_LEFT:
                        currentState = SET_TIME_MENU;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Time Menu");
                        break;
                    // Добавьте обработку других кнопок при необходимости
                }
                break; // Обработка установки часов, аналогично предыдущим примерам
                // Пример: при нажатии кнопки "Select" сохраняем часы и переходим обратно в меню
                if (button == BTN_SELECT) {
                    saveTimeToEEPROM(hour, minute);
                    currentState = SET_TIME_MENU;
                    clearLine(0);
                    clearLine(1);
                    printDisplay("Display Time");
                }
                break;
            case SET_MINUTE:
               selectedField = 1;
               switch (button) {
                    case BTN_UP:
                        currentState = SET_MINUTE;
                        incrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Minute");
                      break;
                    case BTN_DOWN:
                        currentState = SET_MINUTE;
                        decrementSelectedField();
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Minute");
                    break;
                    case BTN_RIGHT:
                        currentState = DISPLAY_TIME;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Display Time");
                        clearLine(0);
                        clearLine(1);
                      break;
                    case BTN_LEFT:
                        currentState = SET_TIME_MENU;
                        clearLine(0);
                        clearLine(1);
                        printDisplay("Set Time Menu");
                      break;
                    // Добавьте обработку других кнопок при необходимости
                } // Обработка установки минут, аналогично предыдущим примерам
                 // Пример: при нажатии кнопки "Select" сохраняем минуты и переходим обратно в меню
                if (button == BTN_SELECT) {
                    saveTimeToEEPROM(now.Hour(), now.Minute());
                    currentState = DISPLAY_TIME;
                    clearLine(0);
                    printDisplay("Display Time");
                }
                break;
        }
    }
    
    void setup() {
        Serial.begin(9600);
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);
        printDisplay("compiled: ");
        printDisplay(__DATE__);
        pinMode(2, OUTPUT);
    
        Rtc.Begin();
        RtcDateTime compiled = RtcDateTime(__TIME__);
    
        // Загрузим время из EEPROM при старте программы
        uint8_t storedHour, storedMinute;
        loadTimeFromEEPROM(storedHour, storedMinute);
    
        // Выведем время из EEPROM
        lcd.setCursor(0, 0);
        lcd.print("Set time: ");
        char storedTimeString[16];
        snprintf_P(storedTimeString, countof(storedTimeString), PSTR("%02u:%02u"), hour, minute);
        lcd.print(storedTimeString);
        delay(2000);
        clearLine(0);
        clearLine(1);
    }
    
    void loop() {
        RtcDateTime now = Rtc.GetDateTime(); // Объявим переменную now здесь
        handleTimeSetting(detectButton());
        updateDisplay();
    
        if (!now.IsValid()) {
            lcd.print("RTC lost confidence in the DateTime!");
        }
      if (now.Hour() == hour && now.Minute() == minute && now.Second() == 0) {
        // Включаем реле на 3 секунды
        digitalWrite(relayPin, HIGH);
        delay(3000);
        digitalWrite(relayPin, LOW);
      }
    }
    
    #define countof(a) (sizeof(a) / sizeof(a[0]))
    
    void setHour(uint8_t hour) {
        now = Rtc.GetDateTime();
        now = RtcDateTime(now.Year(), now.Month(), now.Day(), hour, now.Minute(), now.Second());
        Rtc.SetDateTime(now);
    }
    
    void setMinute(uint8_t minute) {
        now = Rtc.GetDateTime();
        now = RtcDateTime(now.Year(), now.Month(), now.Day(), now.Hour(), minute, now.Second());
        Rtc.SetDateTime(now);
    }
    
    void incrementSelectedField() {
        switch (selectedField) {
            case 0:
                hour = hour + 1;
                break;
            case 1:
                minute = minute + 1;
                break;
        }
    }
    void decrementSelectedField() {
        switch (selectedField) {
            case 0:
                hour = hour - 1;
                break;
            case 1:
                minute = minute - 1;
                break;
        }
    }
    Ответ написан
    Комментировать