Помогите подружить ардуино с php

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

В общем хочу попробовать управлять светодиодом через php передавая данные на компорт. Если  открыть  монитор порта в arduino ide тоВозникают следующие ошибки: 

Warning: fopen(COM3) [function.fopen]: failed to open stream: Permission denied in C:\OpenServer\domains\server\index.php on line 10



Warning: fwrite(): supplied argument is not a valid stream resource in C:\OpenServer\domains\server\index.php on line 11



Warning: fclose(): supplied argument is not a valid stream resource in C:\OpenServer\domains\server\index.php on line 12

А если монитор порта закрыт то ничего не происходит. Вот собственно код 

arduino

int ledPin1 = 7;
int ledPin2 = 8;
char tmp;

void setup() {
  Serial.begin(9600);

  pinMode(ledPin2, OUTPUT);

}

void loop() {
  if (Serial.available() > 0) {
    tmp = Serial.read();

    if (tmp == 1) {
      digitalWrite(ledPin2, HIGH);
    }
    else {
      digitalWrite(ledPin2, LOW);
    }
  }


}

 

php

<html>
<head>
<meta charset="utf-8">
<title>Сервер Arduino</title> 
</head>
<body>

	<?
if(isset($_POST['tmp'])){
	$f = fopen("COM3","w");
	fwrite($f,chr(49));
	fclose($f);
}
if(isset($_POST['btn2'])){
	$f = fopen("COM3","w");
	fwrite($f,chr(50));
	fclose($f);
}

?>
	<form action="" method="post">
		<input type="submit" name="tmp" value="ВКЛЮЧИТЬ"/>
		<input type="submit" name="btn2" value="ВЫКЛЮЧИТЬ"/>
	</form>
	


</body>
</html>

 

Araris
Offline
Зарегистрирован: 09.11.2012

Вы посылаете в порт символы 49 и 50, а проверяете получение if (tmp == 1), это выглядит странно, ведь переменная объявлена как char tmp.

Если последовательный порт открыт монитором, то он занят для прочих процессов, поэтому получаете Permission denied. Кто первый порт открыл, тот и хозяин его )))

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

С монитором порта понятно. 

Заменил символы 49 и 50 на 1 и 2, что соответствует написанному в скетче арды. Ничего не изменилось..

Araris
Offline
Зарегистрирован: 09.11.2012

Посылаем в сериал единичку.

Если char tmp - сравниваем с '1', если int tmp - сравниваем с 1.

Вот здесь http://pashkevich.me/article/6.html вроде бы неплохо разжёвано.

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Ничего не изменилось, к сожалению, на долю секунды загорается индикатор tx на плате и все. 

Araris
Offline
Зарегистрирован: 09.11.2012

Выложите-ка ещё разок актуальные коды для Arduino и PHP.

dmitron1036
Offline
Зарегистрирован: 10.01.2016

Дорогой автор,

Если у тебя получится , - прошу мне сообщить.

Я когда то пытался работать с ком-портом через пхп - у меня не получилось.

negavoid
Offline
Зарегистрирован: 09.07.2016

dmitron1036, всё работает, светодиод RX радостно моргает раз в секунду.

<?php
$f = fopen("COM3","w");
while(1) {
	fwrite($f, chr(50));
	sleep(1);
}
// fclose($f);

 

Sanyaba
Sanyaba аватар
Offline
Зарегистрирован: 27.07.2015

Зачем пыхой писать в файл???

GETом не проще?



<html>
<head>
<meta charset="utf-8">
<title>Сервер Arduino</title> 
</head>
<body>

<?php
if(isset($_GET['tmp'])){
	echo trim($_GET['tmp']);
}
?>

<form action="" method="get">
<input type="submit" name="tmp" value="1" />
<input type="submit" name="tmp" value="2" />
</form>
</body>
</html>

 

 

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Раз у вас все работает, подскажите мне что не так? 

int ledPin1 = 7;
int ledPin2 = 8;
int tmp;

void setup() {
  Serial.begin(9600);

  pinMode(ledPin2, OUTPUT);

}

void loop() {
  if (Serial.available()) {
    tmp = Serial.read();

    if (tmp == 'h') {
      digitalWrite(ledPin2, HIGH);
    }
     if (tmp == 'g') {
      digitalWrite(ledPin2, LOW);
    }
  }


}

 

<html>
<head>
<meta charset="utf-8">
<title>Сервер Arduino</title> 
</head>
<body>

<?
if(isset($_POST['tmp'])){
	
	$f = fopen("COM3","w");
	fwrite($f,chr(`1`));
	fclose($f);
}
if(isset($_POST['btn2'])){
	$f = fopen("COM3","w");
	fwrite($f,chr(`2`));
	fclose($f);
}

?>
	<form action="" method="post">
		<input type="submit" name="tmp" value="ВКЛЮЧИТЬ"/>
		<input type="submit" name="btn2" value="ВЫКЛЮЧИТЬ"/>
	</form>
	


</body>
</html>

 

Sanyaba
Sanyaba аватар
Offline
Зарегистрирован: 27.07.2015
if(isset($_POST['tmp'])){ // Если пришел пост и это именно tmp то есть нажата ваша кнопка "ВКЛЮЧИТЬ"
	
	$f = fopen("COM3","w"); // Открываем файл с именем "COM3" в режиме "w"
	// Файл "COM3" находится в той же директории с файле с этим исполняемым кодом
	// Режим "w" = открывает файл только для записи; помещает указатель в начало файла и обрезает файл до нулевой длинны. Если файл не существует - пробует его создать.
	// То есть режим "w" открывает файл, если его нет создает (если есть права в каталоге для создания файлов скриптами) если файл уже был то скрипт его полностью очищает и записывает вашу строку, если файла не было то создает пустой и записывает вашу строку.
	
	fwrite($f,chr("1")); // Пишем в файл "1"
	fclose($f); // Закрываем файл, то есть завершаем работу с ним, если не закрывать файл то он будет постоянно висеть открытым и занимать память...
}

 

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Ничегоо не изменилооось.

Внесу дополнение, с монитора порта ардуино IDE отправляя 1, светодиод загорается...а если через php в баузере то нет

Sanyaba
Sanyaba аватар
Offline
Зарегистрирован: 27.07.2015

Что должно измениться?

Каким образом ардуина понимет что нужно включать светодиод?

Читает из файла значение или как?

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Sanyaba, COM3 в данном случае это не файл, а COM-порт. Т.е. PHP открывает COM-порт COM3 и пишет в него, т.е. отправляет данные.

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Так и должно быть, но этого не происходит...не понятно почемуууу

м.б. проблема в том что я на windows? 

Sanyaba
Sanyaba аватар
Offline
Зарегистрирован: 27.07.2015

Jeka_M пишет:

Sanyaba, COM3 в данном случае это не файл, а COM-порт. Т.е. PHP открывает COM-порт COM3 и пишет в него, т.е. отправляет данные.

Жесть, так как же все таки ардуина понимает что нужно открыть порт, наличием файла или его содержимым?

Он же с PHP создает файл с именем COM3...

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

sava4aev пишет:

м.б. проблема в том что я на windows? 

COM-порты как раз на Windows. На Linux они по-другому обозначаются - /dev/ttyS0,  /dev/ttyUSB0

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Sanyaba пишет:

Jeka_M пишет:

Sanyaba, COM3 в данном случае это не файл, а COM-порт. Т.е. PHP открывает COM-порт COM3 и пишет в него, т.е. отправляет данные.

Жесть, так как же все таки ардуина понимает что нужно открыть порт, наличием файла или его содержимым?

Он же с PHP создает файл с именем COM3...

 

Ардуина слушает порт и ждет когда в него придет что то. 

int ledPin1 = 7;
int ledPin2 = 8;
int tmp;

void setup() {
  Serial.begin(9600);

  pinMode(ledPin2, OUTPUT);

}

void loop() {
  if (Serial.available()) {
    tmp = Serial.read();

    if (tmp == '1') {
      digitalWrite(ledPin1, HIGH);
    }
     if (tmp == '2') {
      digitalWrite(ledPin1,LOW);
    }
  }


}

 

 

Проблема в том что php ниичего в этот com3 не отправляет

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Sanyaba пишет:

Он же с PHP создает файл с именем COM3...

Я не гуру PHP-программирования, но везде пишут что fopen("COM3","w")  должно открывать именно COM-порт, а не файл.

Sanyaba
Sanyaba аватар
Offline
Зарегистрирован: 27.07.2015

Jeka_M пишет:

Sanyaba пишет:

Он же с PHP создает файл с именем COM3...

Я не гуру PHP-программирования, но везде пишут что fopen("COM3","w")  должно открывать именно COM-порт, а не файл.

http://php.net/manual/ru/function.fopen.php

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

sava4aev пишет:

Проблема в том что php ниичего в этот com3 не отправляет

На правах бреда: Вы "COM" точно латиницей написали, а не кириллицей?
sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

смешно и немноооожко обидно) 

negavoid
Offline
Зарегистрирован: 09.07.2016

Не, действительно не работает, я скопипастил повторил, светодиод на ардуине моргает и сразу же выключается при обращениях из php, что с браузера, что с консоли.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014
b707
Offline
Зарегистрирован: 26.05.2017

sava4aev,

А может надо сначала на винде параметры порта выставить? - в вашем скрипте этого не вижу. Это как-то так  (взято из первого попавшегося php-скрипта в гугле)

exec("mode COM3: BAUD=9600 PARITY=n DATA=8 STOP=1 to=off dtr=off rts=off"); 

 

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Этот класс нужно закинуть в папку с index.php или куда ?

b707
Offline
Зарегистрирован: 26.05.2017

sava4aev пишет:
Этот класс нужно закинуть в папку с index.php или куда ?

я не знаю, я в php ни черта не смыслю :) Просто Вы писали, что видели в гугле куча примеров с открытием ком-порта в php, я решил глянуть эти примеры - и почти в каждом есть эта строчка.

Вот, например

https://stackoverflow.com/questions/5920600/open-com-port-in-php

В принципе, логично, что прежде чем что-то посылать в порт, у него надо хотя бы скорость выставить.

Araris
Offline
Зарегистрирован: 09.11.2012

Желаю sava4aev победить PHP и уточняю по скетчу :

// Если
int tmp;
// то
if (tmp == 1) {
//  и
if (tmp == 2) {


// А если
char tmp;
// то
if (tmp == '1') {
//  и
if (tmp == '2') {

// Оба варианта равнозначны и имеют место быть ))
 

 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Всё так, но есть нюанс. В Windows есть зарезервированные имена, которыми нельзя называть файлы. По этой же ссылке приводят цитату с MSDN: "Do not use the following reserved device names for the name of a file: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9." Предполагаю, что при попытке писать в файл с таким именем (например COM1), на самом деле запись будет осуществляться в COM-порт. Походу это реализовано на уровне ОС.

Сейчас вспомнил, что делал подобное на LUA:

os.execute("mode COM3:9600,n,8,1")

wserial=io.open("COM3","w") // this opens the COM
wserial:write("Test") // fills the serial buffer
wserial:flush() // send the serial buffer
wserial:close("COM3") // this closes the COM

И это работало. Хотя по документации это работа с файлами (как и в случае с PHP) - https://www.lua.org/pil/21.2.htmlhttp://www.lua.ru/doc/5.7.html

Вот на Stackoverflow предлагают такой вариант для PHP:

exec("mode COM3 BAUD=9600 PARITY=N data=8 stop=1 xon=off");

$fp = fopen ("COM3", "w");
if (!$fp) {
   echo "Not open";
} else {
   echo "Open";
}

Ещё ссыль - http://radiovibrations.com/php/com-port-access.php

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Jeka_M пишет:

Всё так, но есть нюанс. В Windows есть зарезервированные имена, которыми нельзя называть файлы. По этой же ссылке приводят цитату с MSDN: "Do not use the following reserved device names for the name of a file: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9." Предполагаю, что при попытке писать в файл с таким именем (например COM1), на самом деле запись будет осуществляться в COM-порт. Походу это реализовано на уровне ОС.

Сейчас вспомнил, что делал подобное на LUA:

os.execute("mode COM3:9600,n,8,1")

wserial=io.open("COM3","w") // this opens the COM
wserial:write("Test") // fills the serial buffer
wserial:flush() // send the serial buffer
wserial:close("COM3") // this closes the COM

И это работало. Хотя по документации это работа с файлами (как и в случае с PHP) - https://www.lua.org/pil/21.2.htmlhttp://www.lua.ru/doc/5.7.html

Вот на Stackoverflow предлагают такой вариант для PHP:

exec("mode COM3 BAUD=9600 PARITY=N data=8 stop=1 xon=off");

$fp = fopen ("COM3", "w");
if (!$fp) {
   echo "Not open";
} else {
   echo "Open";
}

Ещё ссыль - http://radiovibrations.com/php/com-port-access.php

Так я уже делал. Порт открывается.

sava4aev
sava4aev аватар
Offline
Зарегистрирован: 12.06.2017

Всем снова привет!)

В конечном итоге решить свой вопрос мне так и не удалось. Пошел другим путем. На C# написал программку, которая (на данный момент) умеет управлять  светодиодами и принимает данные от датчика влаажности и температуры DTH11. Проект планирую развивать на сколько хватит интузиазма. 

Всем спасибо за помощь! Кому интересно могу скинуть исходники на C# и собственно скетч Arduino. 

Vopppier
Vopppier аватар
Offline
Зарегистрирован: 05.03.2018

Привет! Можешь скинуть исходники если остались ? 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
<?php
header("HTTP/1.1 200 OK");
header("Content-Type:text/html; charset=UTF-8");
header("Access-Control-Allow-Origin:*");

//Команда MODE для последовательного порта COM:
//https://ab57.ru/cmdlist/mode.html

$port="com7";//номер com порта
$baud=115200;//скорость передачи для последовательного порта
$bits=8;//биты данных
$stop=1;//стоп биты
exec("mode ".$port.": baud=".$baud."data=".$bits." stop=".$stop." " );



//Отправка данных в порт
function Write($Status){
	global $port;
	$fp = fopen($port, "w+");
	fwrite($fp, $Status);
	//$contents = fread($fp, filesize($port));
    //echo $contents;
	fclose($fp);

}



if (isset($_GET['action'])) {
	$switch1 = $_GET['action'];
		switch ($switch1) {
			case "on":
				Write(chr(97));
				//echo "ON";
			break;

			case "off":
				Write(chr(98));
				//echo "OFF";
			break;
		}//switch
}//if (isset($_GET['action'])) {



?>

Скрипт передаёт данные в порт. Как получить ответ от порта?

sadman41
Offline
Зарегистрирован: 19.10.2016

fread() же написали вон...

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Не работает, ругается на эту строку

sadman41
Offline
Зарегистрирован: 19.10.2016

А... Тут вот пишут, что у php под виндой вообще много проблем с серийными портами: https://forum.arduino.cc/index.php?topic=138335.0

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Ага, проблем нет только на отправку.

нашла другую статью

https://lesson.iarduino.ru/page/upravlyaem-arduino-iz-php-cherez-com-port/

разбираюсь

sadman41
Offline
Зарегистрирован: 19.10.2016

Какой-то троллейбус из булки хлеба.
Цель-то какая преследуется этими манипуляциями?

Под относительно новой виндой имеется нативный PowerShell - достаточно гибкая штука. Практически Сишарп, но скриптовый.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:
Цель-то какая преследуется этими манипуляциями?

Общаться с ардуино из браузера без использования интернет модуля

sadman41
Offline
Зарегистрирован: 19.10.2016

Без посредника - наврядли. Браузеры давно строят так, чтобы пользователь не смог выпрыгнуть в пользовательскую систему. Даже файлы с диска не особо почитаешь.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

В 36 посте ссылка, там как раз таки организована передаче и приём через exe файл приложения. Работает.

KindMan
Offline
Зарегистрирован: 19.12.2018

Irinka пишет:

Общаться с ардуино из браузера без использования интернет модуля

Вам именно PHP нужно? Хром может работать с COM-портом. Но опять же не понятно почему именно браузер? Если у вас Ардуино подключена непосредственно к этому компьютеру, почему не использовать просто программу на Сях/Бэйсиках/Паскалях?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

KindMan пишет:

Irinka пишет:

Общаться с ардуино из браузера без использования интернет модуля

Вам именно PHP нужно? Хром может работать с COM-портом. Но опять же не понятно почему именно браузер? Если у вас Ардуино подключена непосредственно к этому компьютеру, почему не использовать просто программу на Сях/Бэйсиках/Паскалях?

С php html и css знакома, умею работать, легко создать графическую оболочку, так сказать. 

 

KPG
Offline
Зарегистрирован: 09.06.2019

Можно взять проект HTML сервера MiniWeb https://github.com/avih/miniweb (если нужно доработать для работы с СОМ портом, если встроенная-штаттная функциональность работы с СОМ портом не подойдёт)

и "общаться" с ним, например, на JavaScript. :)

Не думали о таком решении?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Меня устраивает обращение к exe файлу, всё прекрасно работает

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Поясните что значит 2>&1 в конце настроек порта

Статья по ссылке

https://lesson.iarduino.ru/page/upravlyaem-arduino-iz-php-cherez-com-port/

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

https://qna.habr.com/q/391038

Не стоит опускаться до уровня "в гугле забаненных". Ранее за тобой такого не замечалось.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Что это такое я прочитала 2>&1 - перенаправление stderr в stdout (который пойдет в /dev/null)

Но для чего не поняла, поэтому попросила пояснить, надо ли (без нее работает)

sadman41
Offline
Зарегистрирован: 19.10.2016

stdout - это куда echo пишет, к примеру, "стандартное устройство вывода". Для исполняемых файлов это может быть консоль. В cmd наберите dir - получите вывод данных в stdout.

sderr - канал вывода сообщений об ошибках. /dev/null - устройство типа "нигде". Не хотите вывод команды dir видеть - отправляете его в null.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Спасибо

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Подскажите люди знающие:

exec("программа.exe  2>&1",$param);

Отправляю запрос-получаю ответ от ардуино.

Но стоит ардуино отключить, получаю зависание php страницы или долгий ответ что порт занят или недоступен, так как программа.exe продолжает ждать ответа от ардуино.

Мне нужно убить процесс программа.exe который я запускаю через exec