Из string в int, проблема
Я создаю приложения для компьютера, которые будут использоваться для управления манипулятором робота. Я хотел сделать первую попытку запустить приложение не на моторе, а на диоде и проверить, будет ли он менять свою яркость в зависимости от положения ползунка. Я написал приложение на Qt, которое отправляет стринги в Arduino, а Arduino я читаю и преобразовываю в int. Проблема в том, что хотя ползунок установлен на 0, Arduino не показывает это, часто цифры не совпадают слишком часто (часто слишком малы), также когда я внезапно перемещаю ползунок числа, все время считаю вперед, а не назад.
Код Arduino:
String br;
void setup()
{
Serial.begin(9600);
pinMode(9, OUTPUT);
}
void loop()
{
while (Serial.available()>0)
{
br = Serial.readString();
analogWrite(9, br.toInt());
Serial.println(br.toInt());
}
}
Код Qt:
void MainWindow::on_horizontalSliderGrip_sliderMoved(int position)
{
this->sendMessageToDevice(QString::number(position) + "n");
qDebug() << "Grip: " << QString::number(position);
}
void MainWindow::sendMessageToDevice(QString message)
{
if(this->device->isOpen() && this->device->isWritable())
{
//this->addToLogs("Sending information to the device " + message);
this->device->write(message.toStdString().c_str());
}
else
{
this->addToLogs("I can not send a message. The port is not open!");
}
}
@jadvancek, 👍0
Обсуждение1 ответ
Лучший ответ:
Как написал Маженко в своем комментарии, ваша проблема связана с Serial.readString()
. Как правило, это не лучший способ обработки последовательных данных. Он считывает данные из последовательного интерфейса до тех пор, пока не истечет время ожидания (по умолчанию 1 с). Таким образом, он попытается прочитать до 1 секунды после вашего последнего изменения ползунка и вернет все данные в виде одной строки. Затем String.toInt()
начнет считывать строку с первого символа и преобразовывать их в целое число, пока не будет прочитан нецифровой символ (имеется в виду n
, которые вы отправляете). На этом он останавливается и возвращает уже преобразованное значение.
Это означает, что из всех данных, отправленных на Arduino, будет использоваться только первое значение. Остальные выбрасываются.
Лучше использовать неблокирующий код, который правильно обрабатывает сообщения (цифры в вашем случае). Это делается путем чтения входящих последовательных данных байт за байтом, добавления их в буфер, пока не будет получен специальный символ-разделитель. Затем сообщение обрабатывается как единое целое. После этого следующее сообщение может быть прочитано и обработано. Таким образом, вы не пропустите ни одно из отправленных значений.
Специальный символ-разделитель является произвольным; вы можете использовать любой символ, который не встречается в допустимых данных. Поэтому использование символа n
здесь допустимо. Но в основном используется символ новой строки \n
, так что вы также можете отправлять сообщения с буквенно-цифровыми символами. Скорее всего, вы уже хотели использовать \n
.
В качестве примера этого последовательного кода вы можете взять функцию readline()
из Сообщение в блоге Маженко:
char buf[80];
int readline(int readch, char *buffer, int len) {
static int pos = 0;
int rpos;
if (readch > 0) {
switch (readch) {
case '\r': // Игнорировать CR
break;
case '\n': // Возврат на новую строку
rpos = pos;
pos = 0; // Сбросить индекс позиции, готовый к следующему разу
return rpos;
default:
if (pos < len-1) {
buffer[pos++] = readch;
buffer[pos] = 0;
}
}
}
return 0;
}
void setup() {
Serial.begin(115200);
}
void loop() {
if (readline(Serial.read(), buf, 80) > 0) {
Serial.print("You entered: >");
Serial.print(buf);
Serial.println("<");
}
}
Вы можете преобразовать символьный буфер в тип int с помощью atoi()
в операторе if в void loop()
и использовать его для ´analogWrite()`.
- Очень простая операция Arduino Uno Serial.readString()
- AT-команда не отвечает на последовательный монитор
- Как отправить команду AT на sim800l с помощью SoftwareSerial
- Ардуино для чтения с преобразователя RS232 в последовательный модуль TTL
- Чтение SMS с помощью Arduino Uno и SIM800L и печать на LCD (16x2 буквенно-цифровых) с использованием последовательного соединения
- Как связаться с ESP8266 ESP01, отправив данные через программный сериал на Arduino Uno?
- myserial.available() возвращает нулевой байт
- Последовательная связь от Arduino до ESP8266 NodeMCU работает, но от NodeMCU до Arduino не работает
Serial.readString() глубоко ошибочен, и его следует избегать. Прочтите это: https://majenko.co.uk/blog/reading-serial-arduino, @Majenko
И я *уверен*, что вы хотели добавить
\n
к своим исходящим сообщениям, а неn
..., @Majenkoпри отладке такой проблемы, как ваша, поставьте
Serial.println(br);
передanalogWrite()
, чтобы увидеть, что было получено, @jsotola