Еще один вариант с расширенными возможностями по управлению реле:
Комбинация uart свистка и самостоятельно-работающего реле через МК esp32.
Какие плюсы у данной комбинации:
-
Реле автономно от состояния основного ПК, управляющий компьютер может быть перезагружен, а состояние пинов реле останется неизменным.
-
Реле может быть подключено к wifi сети и располагать резервным каналом управления.
-
Одно из четырех реле может следить за состоянием ПК и в случае его зависания, перезагружать основной ПК.
-
Отсутствует зависимость от GPIO. Вариант годен для установки на любой ПК, с любой операционной системой.
Для подключения нам понадобится:
-
PL 2303, usb uart
-
Само реле esp32 4 channel module
-
4 проводя для соединения и подачи питания
-
Repka pi3
Приступаем к сборке:
Вот так выглядит свисток usb-uart Pl2303. Данная модель выбрана по причине отличающегося идентификатора от привычных нам ch340 и его можно легко отличить через скрипты подключения.
Осторожно, в разных версиях, распиновка может отличаться.
Общий вид и описание реле
Подключаем реле к usb-uart. Этот вариант нам будет выполнять две функции: прошивку и использование.
Далее скачиваем arduino Ide https://www.arduino.cc/en/software/
После установки Файл → Настройки → Дополнительные ссылки для менеджера плат
В открывшееся модальное окно вставляем ссылку, жмем ОК
https://dl.espressif.com/dl/package_esp32_index.json
Снова в меню выбираем Инструменты → Плата → Менеджер плат
Находим в поиске по аббревиатуре esp
esp32 by espressif systems, выбираем актуальную версию и нажимаем установку
Далее подключаем реле и свисток к компьютеру.
В среде arduino ide выбираем lolin32. Также выберите порт, к которому подключился usb-uart. В данном примере COM1, у вас название может отличаться… com4, com21 и т д
Создаем скетч Файл→Новый. Перед программированием в плату сохраните его на диск.
Теперь смотрим на рисунок подключения usb-uart, там обозначены две кнопки. Необходимо зажать 1 и далее нажать вторую - далее вместе их отпустить. Контроллер перейдет в режим программирования.
Вставляем в скетч данный код и жмем Инструменты → Загрузка
//Определяем GPIO
//========================Relay
#define pin_RELAY_1 32
#define pin_RELAY_2 33
#define pin_RELAY_3 25
#define pin_RELAY_4 26
//GPIO23 Status LED
//==================================================================SETUP=====================================================================================================
void setup() {
pinMode(pin_RELAY_1, OUTPUT); //Relay 1 используется для управления чем-нибудь, свет, насос...
pinMode(pin_RELAY_2, OUTPUT); //Relay 2 используется для управления питанием репки, поддержание в активном состоянии
pinMode(pin_RELAY_3, OUTPUT); //Relay 3 в примере не используем
pinMode(pin_RELAY_4, OUTPUT); //Relay 4 в примере не используем
digitalWrite(pin_RELAY_1, LOW);
digitalWrite(pin_RELAY_2, LOW);
digitalWrite(pin_RELAY_3, LOW);
digitalWrite(pin_RELAY_4, LOW);
Serial.begin(9600);//подключение Serial
}
//=============определяем переменные для watchdog таймера
unsigned long watchdog_timer; // переменная для хранения текущего времени watchdog таймера
unsigned long watchdog_timeout_sec=180; // таймаут на срабатывание перезагрузки
//==================================================================START LOOP================================================================================================
void loop() {
while(Serial.available()) //Чтение из Serial команд по управлению реле
{
String serial_string=Serial.readString();
String result="";
if (serial_string=="relay1open")
{
result = relay_change(1,1);
}
else if (serial_string=="relay1close")
{
result = relay_change(1,0);
}
else if (serial_string=="relay1openclose")
{
result = relay_change(1,1);
delay(5000);
result = relay_change(1,0);
}
else if (serial_string=="watchdog_reset")
{
watchdog_timer = millis();
result="reset timer complete";
watchdog_timeout_sec=180; //возвращаем таймер к стандартному значению, на случае если оно было ранее изменено при активации watchdog
}
Serial.println(String(millis())+": [SERIAL] RESULT:"+result);
}
//===================================второе реле служит для отслеживания состояния ПК. Если отсутствует сигнал 120 сек, то перезагружаем через пин Репки
//watchdog
check_watchdog();
} //main loop ends
//----------------------------------------------------------------------------
int relay_change(int relay_num, int signal_level) //1 high open, 0 - low close
{
if (relay_num==1)
{
digitalWrite(pin_RELAY_1, signal_level);
return digitalRead(pin_RELAY_1);
}
else if (relay_num==2)
{
digitalWrite(pin_RELAY_2, signal_level);
return digitalRead(pin_RELAY_2);
} else if (relay_num==3)
{
digitalWrite(pin_RELAY_3, signal_level);
return digitalRead(pin_RELAY_3);
} else if (relay_num==4)
{
digitalWrite(pin_RELAY_4, signal_level);
return digitalRead(pin_RELAY_4);
}
}
//----------------------------------------------------------------------------
int relay_state(int relay_num)
{
if (relay_num==1)
{
return digitalRead(pin_RELAY_1);
}
else if (relay_num==2)
{
return digitalRead(pin_RELAY_2);
} else if (relay_num==3)
{
return digitalRead(pin_RELAY_3);
} else if (relay_num==4)
{
return digitalRead(pin_RELAY_4);
}
return -1;
}
void check_watchdog()
{
if (millis() - watchdog_timer > (long)watchdog_timeout_sec*1000 )
{
Serial.println(String(millis())+": [WATCHDOG] reset run relay2");
relay_change(2,1);
delay(5000);
relay_change(2,0);
watchdog_timer = millis();
Serial.println(String(millis())+": [WATCHDOG] reset complete");
watchdog_timeout_sec=600;//увеличиваем время повторной активации реле, даем репке загрузиться.
}
}
Теперь подключаемся к репке через ssh или работаем через обычный терминал репки
# Добавляем репозиторий в систему
sudo add-apt-repository ppa:ondrej/php
# Обновляем список пакетов
sudo apt-get update
#Ставим apache
sudo apt install apache2
sudo service apache2 start
sudo systemctl enable apache2
#Дополняем конфигурацию, чтобы php обрабатывалось как надо.
#Добавляем в файл две строки
sudo nano /etc/apache2/sites-available/000-default.conf
RemoveHandler .html .htm
AddType application/x-httpd-php .php .htm .html
#Жмем ctrl+x и далее отвечаем Y … Enter (сохранить)
sudo service apache2 reload
#Устанавливаем php
sudo apt-get install -y php libapache2-mod-php php-curl php-json php-cgi php-xml
#некоторые этого советуют не делать, тем не менее для обучающего процесса избавляемся от блокирующих сообщений
sudo chmod 777 -R /var/www/html
Теперь мы готовы создать скрипт для управления реле через PHP
sudo nano /var/www/html/read_usb_relay_repka.php
<?php
$start_time=time();
/*Лог создания службы
sudo nano /etc/systemd/system/read_usb_relay_repka.service
[Unit]
Description=USB RELAY read com data
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=1
AmbientCapabilities=CAP_SYS_RAWIO
User=root
ExecStart=/usr/bin/php /var/www/html/read_usb_relay_repka.php
[Install]
WantedBy=multi-user.target
//----------------------------------------------
Вот и все. Теперь мы можем запустить сервис:
sudo systemctl start read_usb_relay_repka
И автоматически запускаться при загрузке:
sudo systemctl enable read_usb_relay_repka
-----------------------------------------------------
Управляющие команды следующие:
этот скрипт упакован в службу сназванием read_usb_relay_repka
sudo systemctl start read_usb_relay_repka
sudo systemctl restart read_usb_relay_repka
sudo systemctl stop read_usb_relay_repka
Все что касается управления службой
sudo systemctl enable read_usb_relay_repka
sudo systemctl disable read_usb_relay_repka
sudo systemctl status read_usb_relay_repka
*/
ini_set('max_execution_time', 0);
//$eol=chr(10).chr(13);
$eol=""; //для реле не нужно
//=======================
$dev = '';
$port='';
$sstr="";
$terminal=shell_exec('lsusb');
$tline=explode("\n",$terminal);
$i=0;
foreach ($tline as $fdev)
{
$terminal=shell_exec('udevadm info -a -n /dev/ttyUSB'.$i);
foreach (explode("\n",$terminal) as $t2)
{
if (strpos(strtolower($t2),'pl2303')!==false)
{
$dev = '/dev/ttyUSB'.$i;
echo $dev."\n";
break;
}
}
$i=$i+1;
}
echo "DEV=".$dev."\n";
//=======================================================================================
if(strlen($dev)==0)
{
sleep(30); //ждем 30 сек и перезагружаем
}
else
{
exec("stty -F $dev 9600 raw -echo");
if ($handle = fopen($dev, "r+")){
read_usb_relay_repka_add_log("-------------------------\r\n");
while(1==1)
{
// set stream into non-blocking mode
stream_set_timeout($handle, 20);
stream_set_read_buffer($handle, 0);
stream_set_blocking($handle, false);
$rx = fread($handle,1); //ждем чтения одного символа из терминалки
usleep(100000); //10000 = 10ms
//================================================================STATE
//сделать опрос через 30 сек
if(time()-$start_time>30)
{
$start_time=time();
fwrite($handle, "watchdog_reset".$eol); //обновление wtd внутри wifi relay
}
//================================================================
if(file_exists(__DIR__."/relay1open.txt"))//relay
{
fwrite($handle, "relay1open".$eol);
unlink(__DIR__."/relay1open.txt");
}else if(file_exists(__DIR__."/relay1close.txt"))//relay
{
fwrite($handle, "relay1close".$eol);
unlink(__DIR__."/relay1close.txt");
}
//================================================================
if (ord($rx)==13 && $prev_ord==1)
{
read_usb_relay_repka_add_log("TRACE:".$sstr);
$sstr="";
}
else
{
$sstr=$sstr.$rx;
if(ord($rx)==10 || $rx=="\n")
{
read_usb_relay_repka_add_log($sstr);
$sstr="";
}
}
//================================================================
if (ord($rx)==10){$prev_ord=1;} else {$prev_ord=0;}
}
fclose($handle);
echo $rx;
}
else //если устройство извлечено или потеряло соединение
{
echo "exit";
sleep(10);
}
}
//=============================================================================
function read_usb_relay_repka_add_log($str)
{
$f=fopen(__DIR__."/usb_relay_log.txt", "a");
fwrite($f,date("Y-m-d H:i:s",time())." - ".$str."\r\n");
fclose($f);
}
?>
Далее создаем службу, чтобы скрипт работал постоянно.
sudo nano /etc/systemd/system/read_usb_relay_repka.service
[Unit]
Description=USB RELAY read com data
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=1
AmbientCapabilities=CAP_SYS_RAWIO
User=root
ExecStart=/usr/bin/php /var/www/html/read_usb_relay_repka.php
[Install]
WantedBy=multi-user.target
ставим задачу на исполнение (в терминале пишем)
sudo systemctl start read_usb_relay_repka
sudo systemctl enable read_usb_relay_repka
#смотрим статус
sudo systemctl status read_usb_relay_repka
Что мы получили. Мы получили связь репки и реле через uart, скрипт каждые 30 секунд отправляет сброс таймера. Если репка зависнет, то через 3 минуты сработает реле перезагрузки и репка снова восстановится в работе.
чтобы управлять включением реле, можно отправить следующую команду в терминал
root@Repka-Pi:/var/www/html# > /var/www/html/relay1open.txt
потом так
root@Repka-Pi:/var/www/html# > /var/www/html/relay1close.txt
Ну да, мы забыли подключить 1 и 2 пины второго реле к пинам репки на перезагрузку. Ну это уж вы как-нибудь сами))