Как запустить TCP-сервер сокетов на Arduino Uno WiFi?
Обновление от 23 марта 2017 г.
Я до сих пор не знаю, почему это так хорошо работает на Юне. Может у него антенна получше? В любом случае, я вернул Uno WiFi и получил вещь SparkFun ESP32. К сожалению, у него та же проблема, что и у Uno WiFi. Чтобы это исправить, я переключился с TCP на UDP. Это имело огромное значение: сервоприводы теперь очень отзывчивы. UDP подходит для моего случая использования: я могу отправлять состояние всей системы в каждом сообщении, и потеря сообщений или сообщения, поступающие не по порядку, не являются большой проблемой.
Оригинальный вопрос
Я хочу управлять сервоприводами через Wi-Fi с высокой точностью и низкой задержкой. Мне удалось добиться этого, используя TCP-сокет связи с Arduino Yun. Я хочу повторить это с Arduino Uno WiFi, но не могу найти пример кода для связи через сокет. Я подключился к плате через telnet, но выход сервопривода прерывистый — как будто после каждого вызова servo.write
была задержка
.
Как запустить TCP-сервер сокетов на Arduino Uno WiFi таким образом, чтобы обеспечивает быструю связь с низкой задержкой?
Подробное описание
Я экспериментировал с управлением сервоприводами через Wi-Fi, используя плату Arduino Yun, которую одолжил у друга. Я подключил сервопривод MG92B к контактам 9, 5 В и GND. Я запускаю TCP-сервер сокетов на Arduino и отправляю значения угла из скрипта Python десятки раз в секунду. Работает плавно.
Воодушевленный этим экспериментом, я купил себе Arduino. Я выбрал Arduino Uno WiFi (версия для разработчиков), потому что, в отличие от Yun, он совместим с шилдами. К сожалению, я не могу найти пример кода для связи через сокеты. Я нашел пример, использующий telnet, поэтому я адаптировал его и использовал со своим скриптом Python. К сожалению, движение сервопривода прерывистое — как если бы после каждого вызова servo.write
была задержка
.
Ниже приведено видео, на котором на обеих досках показаны два скетча: «нет движения сети» и «движение сети».
Видео
Код
Я прилагаю весь код, который использовал.
Тест колебаний Arduino без пульта дистанционного управления
Я использую этот код, чтобы проверить правильность работы сервопривода. Он работает как на Arduino Yun, так и на Arduino Uno WiFi.
#include <Servo.h>
const int servoPin = 9;
Servo servo;
void setup() {
servo.attach(servoPin);
}
void loop() {
// настраиваем движение
int angleMin = 15;
int angleMax = 165;
int interval = 30;
// колебаться между angular_min и angular_max
int angle = angleMin;
for (int i = 0; i < 2; i = (i + 1) % 2) {
int sign = pow(-1, i);
for (int j = 0; j < angleMax - angleMin; j += 1) {
angle += sign;
servo.write(angle);
delay(interval);
}
}
}
Чтение Wi-Fi Arduino Uno через telnet
Это ерунда.
#include <Servo.h>
#include <UnoWiFiDevEd.h>
const int servoPin = 9;
Servo servo;
void setup() {
Wifi.begin();
servo.attach(servoPin);
}
void loop() {
while (Wifi.available()) {
servo.write(Wifi.read());
}
}
Arduino Yun читает из сокета
Это нормально.
#include <Bridge.h>
#include <Servo.h>
#include <YunClient.h>
#include <YunServer.h>
// настройка
const int port = 5555;
const int servoPin = 9;
// слушаем данный порт
Servo servo;
YunServer server(port);
void setup() {
// настраиваем сервопривод
servo.attach(servoPin);
// запускаем сервер
Bridge.begin();
server.noListenOnLocalhost();
server.begin();
}
void loop() {
YunClient client = server.accept();
byte angle;
if (client) {
while (client.connected()) {
angle = client.read();
if (angle != 255) {
servo.write(angle);
}
}
client.stop();
}
Serial.println("waiting for client");
delay(1000);
}
Запись Python в сокет
Это сетевой эквивалент теста колебаний Arduino. Работает как с Yun (порт 5555), так и с Uno (порт 23).
import socket
from time import sleep
# connect
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('192.168.240.1', 5555)) # use 5555 for Yun and 23 for Uno
# configure movement
angle_min = 15
angle_max = 165
interval = 30 / 1e3
# oscillate between `angle_min` and `angle_max`
while True:
angle = angle_min
for sign in [1, -1]:
for _ in range(angle_max - angle_min):
angle += sign
client.send(bytearray([angle]))
sleep(interval)
1 ответ
Я подозреваю, что эти задержки вызваны буферизацией TCP.
Чтобы получить некоторую теорию по этому поводу, возможно, прочитайте Алгоритм Нэгла, который охватывает некоторые проблемы с буферизация небольших пакетов. Мне кажется разумным, что платы с меньшим энергопотреблением и/или меньшей скоростью (или даже «просто другие») будут использовать более агрессивную буферизацию.
TCP использует все виды буферизации и проверок, чтобы гарантировать гарантированную доставку данных (или сообщение об ошибке), тогда как UDP этого не делает.
Если у вас работает UDP, возможно, вы захотите включить в протокол связи некоторые собственные функции отслеживания ошибок, если только отсутствие нечетного пакета не является проблемой для вашей системы управления.
- Как подключиться к Arduino с помощью WiFi?
- Как подключить Wi-Fi Shield ESP-12E-ESP8266-UART-WIFI-Wireless-Shield к Arduino
- Как сделать повторитель Wi-Fi на Arduino?
- Как подключить ESP8266 с помощью адаптера ESP-01 к Arduino Uno?
- ESP8266 TCP-соединение WiFiClient проблема
- Как установить связь между веб-камерой и Arduino UNO и получать прямую трансляцию на мобильном телефоне с помощью ESP8266?
- ESP8266 отправляет TCP HEX-пакет из 4 символов
- ESP8266 - Один сервер, отправляющий данные нескольким клиентам