Чтение последовательного порта Arduino
-
23-08-2019 - |
Вопрос
Я работаю над марсоходом, управляемым через Интернет, и использую последовательный порт для связи с Ардуино.Я написал PHP, который просто использует fwrite()
и записывает ASCII 1 или ASCII 2 в последовательный порт.Arduino прослушивает этот порт и делает что-то на основе того, что слышит.Я знаю, что мой PHP работает, потому что всякий раз, когда я говорю ему отправить что-то, Arduino его получает.Вот код Ардуино:
//This listens to the serial port (USB) and does stuff based on what it is hearing.
int motor1Pin = 13; //the first motor's port number
int motor2Pin = 12; //the second motor's port number
int usbnumber = 0; //this variable holds what we are currently reading from serial
void setup() { //call this once at the beginning
pinMode(motor1Pin, OUTPUT);
//Tell arduino that the motor pins are going to be outputs
pinMode(motor2Pin, OUTPUT);
Serial.begin(9600); //start up serial port
}
void loop() { //main loop
if (Serial.available() > 0) { //if there is anything on the serial port, read it
usbnumber = Serial.read(); //store it in the usbnumber variable
}
if (usbnumber > 0) { //if we read something
if (usbnumber = 49){
delay(1000);
digitalWrite(motor1Pin, LOW);
digitalWrite(motor2Pin, LOW); //if we read an ASCII 1, stop
}
if (usbnumber = 50){
delay(1000);
digitalWrite(motor1Pin, HIGH);
digitalWrite(motor2Pin, HIGH); //if we read an ASCII 2, drive forward
}
usbnumber = 0; //reset
}
}
Так что это должно быть довольно прямолинейно.Прямо сейчас, когда я отправляю ASCII 1 или ASCII 2, светодиод, который я тестирую (на контакте 13), включается и горит постоянно.Но если я отправлю еще один ASCII 1 или 2, он выключится, а затем снова включится.Цель состоит в том, чтобы он включался только в том случае, если последним отправленным является ASCII 1, и оставался включенным до тех пор, пока последним не будет отправлено 2.
Редактировать:Вот мой PHP:
<?php
$verz="0.0.2";
$comPort = "com3"; /*change to correct com port */
if (isset($_POST["rcmd"])) {
$rcmd = $_POST["rcmd"];
switch ($rcmd) {
case Stop:
$fp =fopen($comPort, "w");
fwrite($fp, chr(1)); /* this is the number that it will write */
fclose($fp);
break;
case Go:
$fp =fopen($comPort, "w");
fwrite($fp, chr(2)); /* this is the number that it will write */
fclose($fp);
break;
default:
die('???');
}
}
?>
<html>
<head><title>Rover Control</title></head>
<body>
<center><h1>Rover Control</h1><b>Version <?php echo $verz; ?></b></center>
<form method="post" action="<?php echo $PHP_SELF;?>">
<table border="0">
<tr>
<td></td>
<td>
</td>
<td></td>
</tr>
<tr>
<td>
<input type="submit" value="Stop" name="rcmd"><br/>
</td>
<td></td>
<td>
<input type="submit" value="Go" name="rcmd"><br />
</td>
</tr>
<tr>
<td></td>
<td><br><br><br><br><br>
</td>
<td></td>
</tr>
</table>
</form>
</body>
</html>
Решение
Если это C, то у вас есть назначение вместо сравнение в обоих тестах, поэтому оба true
, поэтому все записи выполняются каждый раз.Компилировать с высоким уровнем предупреждения (например, -Wall -pedantic
в GCC).Попробуй это:
int a = 0;
if ( a == 1 ) printf( "a is not one: %d\n", a );
if ( a = 1 ) printf( "a is one: %d\n", a );
Из опубликованного вами PHP-кода (я здесь не эксперт) похоже, что вы пишете двоичный код 1 как символ, который не является ASCII 49, а ASCII 1 (так), то же самое и для 2.Попробуйте изменить его на '1'
в PHP-коде (или 1
в коде C.)
Вот ссылка на какую-то статью о Управление последовательным портом с помощью PHP - Я погуглил, понятия не имею о его качестве - но, похоже, недостаточно просто записать целое число в "com1" - это не в моем домене, так что удачи :)
Другие советы
Как упомянул Николай, похоже, что вы выполняете присваивание (=), а не сравнение (==) в своих операторах «if».
Хорошая привычка некоторых программистов на языке C — помещать значения r в левой части сравнения, чтобы компилятор выдавал ошибку, если вы случайно используете оператор присваивания вместо оператора сравнения:
if (50 == usbnumber) { // This is okay. ... } if (50 = usbnumber) { // The compiler will generate an error here. ... }
Это работает независимо от того, какие флаги компилятора или уровень предупреждения вы используете, поскольку присвоение значения r является незаконным.
Должен добавить, что эта «подстраховка» не работает, если вам нужно сравнить два значения lvalue.
Возможно, уже слишком поздно, но я думаю, ваша проблема в том, что серийный.читать() читает только один символ за раз.Если отправить "49" с ПК, при звонке номер USB = серийный.чтение () вы получите «4» в первом цикле и «9» во втором цикле.Ни один из них не удовлетворяет условиям, поэтому ничего не делается, а номер usb сбрасывается на 0.
Чтобы исправить это, вы можете изменить условие Serial.available на
if (Serial.available() == 2)
а затем сделайте что-то вроде следующего, чтобы преобразовать в число:
usbnumber = Serial.read() * 10 + Serial.read();
Другой вариант — использовать библиотеку TextFinder — я написал краткое руководство на своем веб-сайте. http://mechariusprojects.com/thunderbolt/?p=60
Мех
Я нашел ваш ответ в поисках других вещей, в любом случае я только что столкнулся (я думаю) с той же проблемой, что и вы.
Если вы еще не решили эту проблему, я думаю, что проблема не в вашем коде, а в механизме автоматического сброса на плате Arduino.То есть:каждый раз, когда новое соединение устанавливается на последовательном порту, плата Arduino сбрасывается, что позволяет загружать новую прошивку при ее программировании через последовательный порт.
Чтобы убедиться в этом, попробуйте поморгать светодиодом на вашем setup()
функция, если она мигает при каждой загрузке страницы, это подтверждает мой тезис.
Посмотрите здесь: http://www.arduino.cc/playground/Main/DisablingAutoResetOnSerialConnection
Я решил, вставив резистор 120 Ом между +5 В и RESET.Просто не забывайте удалять его каждый раз, когда захотите загрузить на плату новую прошивку.