Skip to main content
added 510 characters in body
Source Link

2017-03-23 update

I still don't know why it works so well on Yún. Maybe it has a better antenna? Anyway, I've returned Uno WiFi and got a SparkFun ESP32 Thing. Unfortunately, it has the same problem as Uno WiFi. To fix it I've switched from TCP to UDP. It made a world of difference: servos are very responsive now. UDP is OK for my use case: I can send the state of the whole system in each message and lost messages or messages arriving out of order are not a big problem.

Original question

2017-03-23 update

I still don't know why it works so well on Yún. Maybe it has a better antenna? Anyway, I've returned Uno WiFi and got a SparkFun ESP32 Thing. Unfortunately, it has the same problem as Uno WiFi. To fix it I've switched from TCP to UDP. It made a world of difference: servos are very responsive now. UDP is OK for my use case: I can send the state of the whole system in each message and lost messages or messages arriving out of order are not a big problem.

Original question

Tweeted twitter.com/StackArduino/status/841347114554802177
Source Link

How to run TCP socket server on Arduino Uno WiFi?

I want to control servos over WiFi with high precision and low latency. I managed to achieve this using TCP socket communication with Arduino Yún. I want to repeat this with Arduino Uno WiFi, but I can't find example code for socket communication. I connected to the board using telnet but servo output is jerky — as if there was a delay after each servo.write call.

How can I run a TCP socket server on Arduino Uno WiFi in a way that allows for fast low latency communication?

Longer description

I experimented with controlling servos over WiFi using an Arduino Yún board that I borrowed from a friend. I connected a MG92B servo to pin 9, 5V, and GND. I start a TCP socket server on the Arduino and send angle values from a Python script dozens of times per second. It works smoothly.

Encouraged by this experiment I bought my own Arduino. I chose Arduino Uno WiFi (developer edition) because, unlike Yún, it's compatible with shields. Unfortunately I can't find example code for socket communication. I found an example that uses telnet, so I adapted it and used it with my Python script. Sadly, the servo movement is jerky — as if there was a delay after each servo.write call.

Below is a video showing both boards running two sketches: "no network movement" and "network movement".

Video

Code

I attach all code I used.

Arduino oscillation test with no remote control

I use this code to test that the servo is working correctly. It works on both Arduino Yún and Arduino Uno WiFi.

#include <Servo.h>


const int servoPin = 9;
Servo servo;


void setup() {
    servo.attach(servoPin);
}


void loop() {
    // configure movement
    int angleMin = 15;
    int angleMax = 165;
    int interval = 30;

    // oscillate between `angle_min` and `angle_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);
        }
    }
}

Arduino Uno WiFi reading from telnet

This is jerky.

#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 Yún reading from socket

This is smooth.

#include <Bridge.h>
#include <Servo.h>
#include <YunClient.h>
#include <YunServer.h>


// configure
const int port = 5555;
const int servoPin = 9;

// listen on given port
Servo servo;
YunServer server(port);


void setup() {
    // set up servo
    servo.attach(servoPin);

    // start server
    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 writing to socket

This is the network equivalent of the Arduino oscillation test. Works both with Yún (port 5555) and Uno (port 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)