Kogotok
Kogotok
1063 просмотров0 комментариев

Управление с помощью Repka PI3 wifi реле через USB - UART PL2303

Еще один вариант с расширенными возможностями по управлению реле:

Комбинация uart свистка и самостоятельно-работающего реле через МК esp32.

Какие плюсы у данной комбинации:

  1. Реле автономно от состояния основного ПК, управляющий компьютер может быть перезагружен, а состояние пинов реле останется неизменным.

  2. Реле может быть подключено к wifi сети и располагать резервным каналом управления.

  3. Одно из четырех реле может следить за состоянием ПК и в случае его зависания, перезагружать основной ПК.

  4. Отсутствует зависимость от GPIO. Вариант годен для установки на любой ПК, с любой операционной системой.

Для подключения нам понадобится:

  1. PL 2303, usb uart

  2. Само реле esp32 4 channel module

  3. 4 проводя для соединения и подачи питания

  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 пины второго реле к пинам репки на перезагрузку. Ну это уж вы как-нибудь сами))


Комментарии (0)

Для участия в обсуждении Вы должны быть авторизованным пользователем
Темы

Навигация

ВойтиРегистрация