#include <Arduino.h>
#include <string>
#include <vector>
// Номер пина лампочки
#define LED_PIN 39
// Номер пина кнопки
#define BUTTON_PIN 18
// Периодичность вывода истории команд
#define PRINT_HISTORY_INTERVAL 20
// Размер истории команд
#define HISTORY_SIZE 4
// Массив для хранения истории команд
std::vector<int> history;
// мощность свечения
int power = 4096;
// признак того что лампочка должна включиться
bool light_on = false;
// Время запуска таймера для отсчета
// времени, которое осталось до
// вывода истории команд
unsigned long timer_start = 0;
/// @brief Функция для ротации истории (сдвиг влево на одну позицию и удаление последнего элемента)
void rotate_history() {
for (int idx=0;idx<history.size()-1;idx+=1) {
history[idx] = history[idx+1];
}
history.pop_back();
}
/// @brief Выводит содержимое истории команд
///
void print_history() {
for (int item : history) {
Serial.println(item);
}
}
/// @brief Проверяет, является ли строка числом
/// @param s Входящая строка
/// @return bool true если строка содержит только цифры и false иначе
bool is_number(const std::string& s) {
for (char ch : s)
{
if (!isdigit(ch) && ch != 13)
{
return false;
}
}
return true;
}
/// @brief Считывает строку из серийного порта,конвертирует ее в число и сохраняет
/// в истории полученных команд
/// @return int Число или -1 если не удалось конвертировать
int read_value()
{
// буфер для приема сообщений
std::string message = "";
// считываем все из серийного порта
while(Serial.available() > 0)
{
message += std::string(1, char(Serial.read()));
delay(500);
};
if (message[message.size()-1] == '\n') {
message.erase(message.size()-1);
}
// Если это не число, то выходим с ошибкой
if (!is_number(message))
{
return -1;
}
// Конвертируем в число
int power = std::stoi(message);
// Если массив принятых значений заполнен
if (history.size() == HISTORY_SIZE)
{
// удаляем первый элемент и сдвигаем все остальные
// на одну позицию влево
rotate_history();
}
// Добавляем значение в массив
history.push_back(power);
return power;
}
void setup() {
// Устанавливаем пин лампочки в режим записи
pinMode(LED_PIN, OUTPUT);
// Устанавливаем пин кнопки в режим чтения
pinMode(BUTTON_PIN, INPUT);
// Устанавливаем скорость серийного порта
Serial.begin(115200);
// Устанавливаем время отсчета в колличество миллисекунд
// с момента старта контроллера
timer_start = millis();
}
void loop() {
// читаем данные из серийного порта
if (Serial.available() > 0)
{
// Считываем число из серийного порта
int tmp_power = read_value();
// и если принятый ввод корректен
if (tmp_power != -1) {
// устанавливаем значение яркости в это число
power = tmp_power;
Serial.print("Recieved: power = ");
Serial.println(power);
} else {
Serial.println("Incorrect input");
}
}
// Каждые PRINT_HISTORY_INTERVAL секунд выводим список последних команд
// переданных на серийный порт
if (millis() - timer_start >= PRINT_HISTORY_INTERVAL * 1000) {
print_history();
// сбрасываем таймер
timer_start = millis();
}
// Если кнопка нажата, то включаем признак
// того что нужно включить лампочку
if(digitalRead(18) == HIGH)
{
light_on = true;
}
// включаем лампочку
if(light_on == true)
{
light_on = false;
// используя последнее значение яркости
analogWrite(LED_PIN, power);
delay(1000);
}
else{
analogWrite(LED_PIN, 0);
}
}