Ардуино не сохраняет данные после получения от последовательной связи

Я новичок в Arduino, и то, что я пытаюсь сделать, это изменить переменную, отправив ее с php на Arduino.

Я добавил задержку, как указано в других вопросах, но это не сработало до сих пор. Вывод 13 ВЕЛ так

Код Arduino

float val;
void setup() {

  Serial.begin(9600);
  
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  val=29.1;

  Serial.println("Start!");
}

void loop() {

  if(Serial.available()){
    String temp = Serial.readStringUntil('\n'); //read string
    val = temp.toFloat(); //convert string to float
  }

  if(val==62.10){
    digitalWrite(13,HIGH);  
  }else{
    digitalWrite(13,LOW);  
  }

  Serial.println(val);
  delay(1000);
  
}

PHP Код

<?php
$port = fopen("COM3", "w");
sleep(2);
fwrite($port, "62.1");
fclose($port);
?>

Любые советы были бы очень признательны. Спасибо, что прочитали.

, 👍1

Обсуждение

Сравнивать поплавки подобным образом никогда не бывает хорошей идеей. Нет такого понятия, как 62.1, как плавающая точка - ближайший-62.0999847412109375. Поплавки всегда являются лишь приближением., @Majenko

Я понимаю. К счастью для меня, сравнение используется только для отладки. @Majenko, @cswannabe

Обычно вы используете abs(val - 62.1) < 0,05, где 0,05-это "точность, которую вы принимаете, поэтому значения между 62,05 и 62,15 приводят к" истинному`, @Michel Keijzers


1 ответ


1

Вы пишете "62.1", но вы пытаетесь прочитать до a \n, который вы никогда не отправляете.

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

fwrite($port, "62.1\n");

Кроме того, стоит отметить, что значения с плавающей запятой являются лишь приблизительным приближением. Они отлично подходят для вычислений, но очень плохо справляются с сравнениями. Ваше тестовое значение 62.1 не может быть точно представлено как значение с плавающей запятой, самое близкое из них-около 62.099. Если вам действительно нужно провести сравнение, то вы должны проверить, что оно находится в пределах небольшого диапазона, а не точного значения.


Ваша "проблема", по-видимому, проистекает из того, что вы открываете последовательный порт с помощью одной программы, посылаете значение, затем закрываете последовательный порт и снова открываете его в чем-то другом и ожидаете увидеть, что это значение будет передано вам эхом.

Такого не может быть на обычном Arduino UNO. Каждый раз, когда вы открываете последовательный порт, линия DTR переключает контакт RESET для входа в загрузчик- вот почему вам нужна 2-секундная задержка после открытия последовательного порта.

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

Существует несколько способов отключить этот сброс, начиная от вырезания трассировки на Arduino и заканчивая добавлением конденсатора большого размера (10 мкФ +) между RESET и GND-и то, и другое будет мешать вашей способности программировать плату. Конденсатор легче реверсировать.

В идеале вы должны использовать другой последовательный канал для связи, чтобы он никогда не мешал сбросу или программированию. Вы можете использовать SoftwareSerial и внешний адаптер USB-UART вместо последовательного подключения или использовать плату с собственным USB-подключением, которое не сбрасывается при открытии последовательного порта, например Leonardo.

,

Я добавил \n в fwrite и применил изменения. Похоже, что Arduino сбрасывается и не может прочитать ранее отправленное значение., @cswannabe

Каждый раз, когда вы открываете последовательный порт, Arduino сбрасывается, да. Вот что он делает. Существует множество статей об этой функциональности и о том, как ее избежать. В основном они связаны с изменениями оборудования., @Majenko