Как считывать показания серводвигателя через последовательную связь?
Я новичок в последовательной связи. Я пытался заставить Arduino общаться с MATLAB, но определенные значения разрешены для приема, например 100 и 101. Я пробовал другие значения, но это не сработало. Проблема в коде ASCII, но я пытался вычесть то, что считывается 48, но не получилось.
Это код Arduino, который я нашел в Google и отредактировал для своей проблемы с серводвигателем:
#include <Servo.h>
const int servoPin = 3;
int recValue; // received value from MATLAB
Servo Servo1;
void setup()
{
Serial.begin(9600);
Servo1.attach(servoPin);
}
void loop()
{
if (Serial.available() > 0)
{
recValue = Serial.read();
if (recValue == 100)
{
Servo1.write(0);
delay(1000);
}
if (recValue == 101)
{
Servo1.write(90);
delay(1000);
}
}
}
И как мне прочитать правильные углы, которые я получил от MATLAB через последовательную связь? Спасибо.
@ezzeddin, 👍1
Обсуждение2 ответа
Лучший ответ:
Крисл совершенно прав. Вам нужно понять, как MATLAB общается с вашим Arduino. Я подозреваю, что он отправляет последовательность символов для каждого угла сервопривода вместо одного символа. В вашем коде вы ждете 100 и 101, которые являются символами ASCII 'd' и 'e', а затем действуете немедленно, как только прочитали один символ. Посмотрите, повернется ли сервопривод, если вы отправите 'd' или 'e'. Если это сработает, то вам нужно прочитать целую строку символов ASCII, например '9' (что равно 57) и '0' (что равно 48), за которыми следует разделитель, например, новая строка (13) В начале строки вы можете установить int angle = 0 и каждый раз, когда вы читаете символ, умножать свой угол на 10 и добавлять новое значение, вычитая из него 48. Достигнув ограничителя, вы можете отправить угол на сервопривод. О, и убедитесь, что MATLAB использует правильную скорость передачи данных.
Спасибо большое. Я попробовал отправить 'd' и 'e', и мотор действительно заработал. Но я все еще не понимаю, как работают последние несколько предложений. Как мне разделить '9' и '0', чтобы получилось 90?, @ezzeddin
Теперь я понимаю, что мы делаем карту между значениями 0-9 и 0-90 градусов, но как это сделать в Arduino? Это делается для переменной recValue в Arduino? или servalue в MATLAB?, @ezzeddin
Если вы хотите отправить 90 на Arduino, он будет отправлен как символ 9 (что равно 57), а затем как символ 0. Вы получите только один символ за раз в каждой итерации вашего цикла. В первый раз, когда Serial.available() равен true, Serial.read() вернет значение 57. Вычтите из него 48, чтобы получить 9 и сохранить в переменной, объявленной как int angle. В следующий раз, когда Serial.available() равен true (что может произойти через несколько циклов()), вы прочитаете 48. Таким образом, angle = angle * 10 + (value - 48) дает вам угол для отправки на ваш сервопривод. Вы можете отправить на сервер, когда получите нецифровой символ из MATLAB, @jksemple
Да, но что такое значение Serial.read()? Это то, что мы получаем из MATLAB через последовательную связь между ним и arduino?, @ezzeddin
Serial.read() соберет следующий доступный символ ASCII, отправленный из MATLAB в Arduino. Он возвращает только один символ за раз, поэтому, если вы отправили число 125 из MATLAB, вам нужно будет вызвать Serial.read() три раза, чтобы получить символы '1', '2' и '5'. Затем вам нужно будет объединить их, как я сказал выше, чтобы получить одно целое число 125 для отправки на сервопривод, @jksemple
Вместо того, чтобы пытаться заставить MATLAB немедленно общаться с Arduino, почему бы вам не попробовать просто использовать последовательное соединение с вашего ПК. Вы можете вводить символы на последовательном мониторе и обрабатывать нажатия клавиш одно за другим с помощью Serial.read(). Затем вы можете вывести отладочную информацию с помощью Serial.write(), чтобы вы могли получить некоторое представление о том, что происходит в коде., @jksemple
Давайте [продолжим это обсуждение в чате](https://chat.stackexchange.com/rooms/79616/discussion-between-ezzeddin-abdullah-and-jksemple)., @ezzeddin
Я предполагаю, что вы отправляете значение угла как 1-байтовое значение, так что никаких закодированных ASCII чисел. Вот как работает код в вашем вопросе, так что он должен быть правильным.
Здесь вам не нужно ничего преобразовывать. Функция Serial.read()
уже возвращает целочисленное значение, и вы сохраняете его в целочисленной переменной. Но в вашем коде вас интересуют только 2 разных состояния (100 и 101) вместо фактического значения угла. Теперь вам нужно только заменить ваши операторы if и записать это значение непосредственно в сервопривод:
Servo1.write(recValue);
РЕДАКТИРОВАТЬ:
Похоже, вы не знаете, как работает последовательная связь (точнее, USART). Поэтому я объясню подробнее:
Данные, которые передаются по последовательному интерфейсу, представляют собой просто поток байтов. Весь передаваемый контент преобразуется в поток байтов. Каждый байт имеет числовое значение. Например, байт с битовым содержимым 00100000
имеет числовое значение 32
. Но в какой-то момент истории возникла необходимость отправлять текст с помощью потока байтов. Поэтому кто-то изобрел ASCII, который назначает символ или команду управления каждому числовому значению от 0 до 127. Так что если вы отправляете байт с числовым значением 32
, вы можете иметь в виду фактическое числовое значение 32
, или вы можете иметь в виду эквивалент ASCII для 32
, который является символом пробела. Это просто интерпретация байтовых данных, которые проходят через последовательный интерфейс.
Поэтому вам нужно выяснить, в каком виде вы кодируете значение угла. Если вы используете fwrite()
в своем коде Matlab, вы, скорее всего, отправляете байтовое значение, которое можно просто использовать, как описано выше. Если вы используете fprintf()
, вы отправляете значение угла в виде строки в кодировке ASCII. Значение 32
из приведенного выше примера будет занимать 2 байта с символами 3
и 2
, которые соответствуют байтовым значениям 51
и 50
. В этом случае вам следует добавить символ-разделитель в конце в fprintf()
(например, символ новой строки "\n") и использовать Serial.parseInt()
, чтобы получить значение угла из строки.
Вы можете прочитать больше об этом во многих руководствах по последовательной связи, которые вы можете найти в Интернете. Также обратитесь к примеру, который идет с Arduino IDE.
Что вы подразумеваете под 1-байтовым значением? Потому что я перепробовал много диапазонов от 0 до 180 градусов, но двигатель все равно не вращается., @ezzeddin
Я также добавил delay(1000)
после Servo1.write(recValue)
, @ezzeddin
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Использовать все контакты как цифровые входы/выходы
- Float печатается только 2 десятичных знака после запятой
- Arduino как USB HID
- Serial1' was not declared in this scope
- Очень простая операция Arduino Uno Serial.readString()
- AT-команда не отвечает на последовательный монитор
Какое именно преимущество вы получаете от Matlab по сравнению с последовательным интерфейсом?, @chrisl
При использовании recValue как 100 двигатель вращается в положение 0, а если 101, двигатель вращается на 90 градусов. Когда я меняю recValue на любое число, я ничего не получаю от MATLAB, и двигатель не вращается ни в какое положение в обоих случаях., @ezzeddin
Я не понимаю, чего именно вы хотите добиться. Ваш комментарий указывает точную функциональность, которая предоставляется вашим кодом. Когда вы хотите управлять углом датчика из Matlab, отправьте фактическое значение в Arduino и используйте его в
Servo1.write()
, @chrislИзвините за неясность. Например, я хочу, чтобы двигатель вращался на 45 градусов. Я должен написать 45 в MATLAB, а затем он может преобразовать значение в 45, чтобы я мог впоследствии использовать
Servo1.write(45)
. Я отредактирую код, но я хочу знать, как преобразовать значение, которое я получаю от MATLAB, чтобы оно было точным значением 45., @ezzeddinSerial.parseInt()?, @Juraj