rc-car and ESP8266-board: which prtocoll to stuck with

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
Post Reply
User avatar
apollodriver
Posts: 34
Joined: Tue Jan 29, 2019 8:54 am

rc-car and ESP8266-board: which prtocoll to stuck with

Post by apollodriver » Tue Jan 29, 2019 9:34 am

good day dear experts,


this is a protocol-discussion for a project: a rc-car that makes use of ESP8266 and the: Websockets, TCP, UDP, RF - which one to take!?

The aim of this project is to build a transmitter and a receiver by using a cheap and easy to use component such as ESP8266,(...or alternatively adafruit-motor-shield-v2, and nRF24L01 transceiver.)

This project should be a good start point for beginners. One of the main questions is the question of the architecture and the protocols to choose: note: I am a beginner in this field and would like some direction - what approach do I take that will allow me to keep the cost low (e.g. no bluetooth modules)? especially the question which protocoll i should use with the ESP8266 is a question: should i us Websockets / TCP or UDP or RF how would you decide?

i want to create an ESP8266 project about a Wi-Fi controlled (ESP8266) RC car using. with a tight budget you can't really buy everything you need at once.

what is needed - which materials do i need:

an ESP8266 / (...or alternatively adafruit-motor-shield-v2, and nRF24L01 transceiver.) well i would say - esp-01 module is difficult and more expensive that choosing a Wemos Mini or a nodeMCU board. advantages; this will be smaller, cheaper and easier to use than e e)
an L298N motor driver - H-bridge
an RC car
also batteries, that meet our needs

regarding the protocolls - not yet every decision is made: the protocols are thinkable: Websockets, TCP, UDP, RF - which protocol should i use!? - Websockets, TCP, UDP, RF - protocoll?

since i am quiet a beginner here - i want to recapitulate the options we have here: There are two types of Internet Protocol (IP) traffic. They are TCP or Transmission Control Protocol and UDP or User Datagram Protocol. TCP is connection oriented - once a connection is established, data can be sent bidirectional. UDP is a simpler, connectionless Internet protocol. Multiple messages are sent as packets in chunks using UDP. The Websocket's require to be frank - systematically an extra overhead for an arduino and esp8266 The issue is that we need to implement (or find a library for) a webserver with HTTP and websocket support.

a side effect; All that overhead is going to be eating up the available memory leaving less for my actual car controlling code to work with. UDP is a protocol without typical connection, but also without delivery control. I guess that the UDP is protocol of choice: - If the packet will be lost-nobody cares. i guess that a simple UDP setup would be best probably. That means that i can just fire off some data packets with commands for the car. With UDP there's a chance some may get lost in transit, if that's a problem then i also might make use TCP instead....i will take into consideration the options ...

conlusio: A simple UDP setup would be best probably. Just fire off some data packets with commands for the car. With UDP there's a chance some may get lost in transit, if that's a problem then use TCP instead. With that i can keep things simple. with the UDP i can make use of the great ESP8266 - choosing a Wemos Mini or a nodeMCU board.

But wait: why should i use remote control over WiFi? There are way that are even easier; why shouldn ´t i take some simpler RF protocol? That would be even faster.

the RF protocol? some recaps: What if i am going to design a remote controlled car and one of the aims is for the controller to be a smartphone. With this i an make use of a transmitter plugged into the headphone jack (that is a Audio-Headphone-signal) which would interpret audio signals that are being sent from a certain controller-app on the mobile phone and then send an appropriate signal to the system of the rc-car.

Some musings about the needed tasks: what has to be controlled on the RC-Car: To sumarize all, that needs to be controlled is the the mode of motion:

forwards/backwards-motion and the steering (i.e. turning left or right):
Ideally it would be able to have speed control - not just forwards and backwards.

Well my initial idea was to make usage of something like this for radio transmission: but then it would mean doing some kind of sinal transformation that looks quite annoying: in fact: i have the signal-processing that goes like this: analog -> digital and sending digital data with some kind of protocol, so then I thought of sending just the analog data but I'm not sure how that would separate the signal fo the two control-cirquits: i.e. forward/backward and right/left.

Some possible solutions: Well the so called "standard" RC protocol is to transmit bursts of AM /(FM) pulses, the relative positions of which are translated by the receiver into a variable-width control pulse-signal. And subsequently this signal is going to be sent to the variouls servos. Well i guess, that it should be pretty straightforward for a (let me say) smartphone app (see for example roboremo -the rc car app :: see https://www.roboremo.com/esp8266-wifi-rc-car.html ) to send pulses out the headphone jack, which are then used to key a simple RF transmitter on a standard RC control frequency.

one of the main advantages: we would be able to use in the car comodity of the shelf things: we 'd use an off-the-shelf RC receiver and servos to control the car.

The servo-side of the game: a basic RC car might have as few as two servos, note a plane might have more each of which needs its independently-controlled pulse-signal.
btw: some musings on the communication between the arduino and the servo (1-2ms 20-50Hz) and its relation to the RF data

- the servo control signals are totally separate from the RF link
- the servo control signals must be continuous
- the RF data only changes the timing of the servo control signals


so based on the above mentioned ideas _ which protocol would you use!

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by kevinkk525 » Tue Jan 29, 2019 1:37 pm

Personally I'd use TCP to make sure the commands arrive at the car because with UDP you might end up losing "left" from a command series of "left, forward" in short succession and the car would go forward instead of left and forward but it depends on your implementation. If you send the signal very often and not only on a change of directions, then UDP would be fine because the loss of the first "left" does not matter as 100ms later the next "left" is being sent.
With TCP however you need a library that keeps the connection stable as it is very possible to lose messages or lose the connection.

Another problem to think about is the wifi connection. I'd use wifi because you could also write an App that directly communicates with the car then. No need for adapters and additional modules.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

User avatar
apollodriver
Posts: 34
Joined: Tue Jan 29, 2019 8:54 am

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by apollodriver » Wed Jan 30, 2019 2:08 pm

hello dear Kevin,

first of all many many thanks for the reply. Glad to hear from you.


many thanks for the quick reply. Great to hear from you.
Personally I'd use TCP to make sure the commands arrive at the car because with UDP you might end up losing "left" from a command series of "left, forward" in short succession and the car would go forward instead of left and forward but it depends on your implementation. If you send the signal very often and not only on a change of directions, then UDP would be fine because the loss of the first "left" does not matter as 100ms later the next "left" is being sent. With TCP however you need a library that keeps the connection
stable as it is very possible to lose messages or lose the connection. Another problem to think about is the wifi connection.
I'd use wifi because you could also write an App that directly communicates with the car then. No need for adapters and additional modules.


very interesting - i guess that youre right regarding the ideas of TCP - we need a library that keeps the connection stable.

the pros and cons - some musings:

Websocket's:
Websocket's require a lot of extra overhead for an arduino. We ´d have to implement (or find a library for) a webserver with HTTP and websocket support. All that overhead is going to be eating up the available memory leaving less for the actual car controlling code to work with. A simple UDP setup would be not bad probably. With that we only and just had to fire off some data packets with commands for the car. With UDP there's a chance some may get lost in transit, if that's a problem then we might use TCP instead.

but what bout RF

RF: well it depends I suppose on what the goal is.

usecase 1: if we want to make use of existing RC stuff and all that stuff is geared to work with an RF based protocol then this might come into consideration.

usecase 2: If we might want to use a smartphone / tablet / PC to control the car then WiFi then it probably would have been a much much better fit as those mentionend devices are likely to already have a WiFi card yet.

Bluethooth:
by the way: what if we have picket all togehter: The car uses several actuators, like servo's, LED's and a DC-motor. Well, imagine all and everything finally is working 100% smoothly, including a Bluetooth connection. Everlything works as it's supposed to. Nothing more, nothing less. However, what do you do if you notice that when you control the speed and you wanna cut the Bluetooth connection (just stop powering the Bluetooth module), your car keeps on driving. What do you do when it keeps doing so - on and on.. ;) That means when your drive the RC car out of range, it keeps going! Then wen need to program a emergency stop for when Bluetooth connection is lost, cutting the cars acceleration and letting it roll out.

We need a solution that cares for this "running out of controll" part...

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by kevinkk525 » Wed Jan 30, 2019 3:55 pm

Websocket's:
Websocket's require a lot of extra overhead for an arduino.
Arduino? I thought this was about having esp8266?
We need a solution that cares for this "running out of controll" part...
This is quite easy, you just have the car expect one command every second. If it does not receive one, it stops.


You can of course use the connection type that fits your existing hardware or use-case best.
Once you have decided that, the search for a good connection library starts.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

User avatar
apollodriver
Posts: 34
Joined: Tue Jan 29, 2019 8:54 am

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by apollodriver » Sun Feb 03, 2019 5:35 pm

hello Kevin

many thanks for the quick reply - thanks for encouraging me to step ahead. You have convinced me in the steps that needs to be done.
This is quite easy, you just have the car expect one command every second. If it does not receive one, it stops.
good idea - i like this idea!
You can of course use the connection type that fits your existing hardware or use-case best. Once you have decided that, the search for a good connection library starts.
well - if i want to go with some web-app or pc controlled thing then i should choose TCP/IP / WIFI or bluetooth ( with ESP 32)

regardingt the hardware:
firstly: I would say that i should not make use of an Uno and an esp-01 module. This makes life much more difficult. i think that i should choose a Wemos Mini D1 or a nodeMCU board. This will be smaller, cheaper and easier to use.

secondly perhaps i should choose a less old-fashioned motor driver than the 298. These will work well with 3.3V circuits, be more efficient and maybe use fewer pins (which may be important when using the Wemos/nodeMCU). What do you think about this idea.

btw regarding the use of MicroPython i have found an interesting approach here:
written by david golak:
https://hackaday.io/project/27444-remot ... r-via-wifi
How to build RC Car with the esp8266.

see the code https://github.com/dgolak/esp8266/blob/master/main.py

Code: Select all


import machine
import time
LED_PIN=15
led=machine.Pin(LED_PIN,machine.Pin.OUT)
led.off()
LIGHT_PIN_L=13
light_l=machine.Pin(LIGHT_PIN_L,machine.Pin.OUT)
light_l.off()
LIGHT_PIN_R=2
light_r=machine.Pin(LIGHT_PIN_R,machine.Pin.OUT)
light_r.off()
class engines:
    def __init__(self, machine):
        self.machine = machine
        self.left_first_pin = 0
        self.left_second_pin = 5
        self.right_first_pin = 14
        self.right_second_pin = 12
    def forward(self, duty=1000):
        self.stop()
        e1=machine.PWM(self.machine.Pin(self.left_first_pin),freq=100,duty=duty)
        e2=machine.PWM(self.machine.Pin(self.right_first_pin),freq=100,duty=duty)
    def backward(self, duty=1000):
        self.stop()
        e1=machine.PWM(self.machine.Pin(self.left_second_pin),freq=100,duty=duty)
        e2=machine.PWM(self.machine.Pin(self.right_second_pin),freq=100,duty=duty)
    def left_up(self):
        self.stop()
        e1=machine.PWM(self.machine.Pin(self.left_first_pin), freq=100, duty=400)
        e2=machine.PWM(machine.Pin(self.right_first_pin), freq=100, duty=1000)
    def right_up(self):
        self.stop()
        e1=machine.PWM(self.machine.Pin(self.left_first_pin),freq=100,duty=1000)
        e2=machine.PWM(self.machine.Pin(self.right_first_pin),freq=100,duty=400)
    def left_down(self):
        self.stop()
        e1=machine.PWM(self.machine.Pin(self.left_second_pin), freq=100, duty=400)
        e2=machine.PWM(machine.Pin(self.right_second_pin), freq=100, duty=1000)
    def right_down(self):
        self.stop()
        e1=machine.PWM(self.machine.Pin(self.left_second_pin),freq=100,duty=1000)
        e2=machine.PWM(self.machine.Pin(self.right_second_pin),freq=100,duty=400)
    def stop(self):
        machine.PWM(self.machine.Pin(self.left_first_pin),freq=0,duty=0)
        machine.PWM(self.machine.Pin(self.right_second_pin),freq=0,duty=0)
        machine.PWM(self.machine.Pin(self.left_second_pin),freq=0,duty=0)
        machine.PWM(self.machine.Pin(self.right_first_pin),freq=0,duty=0)
E=engines(machine)
try:
    import usocket as socket
except:
    import socket
CONTENT = b"""\
HTTP/1.0 200 OK
Hello #%d
"""
CONTENT = b"""\
HTTP/1.0 200 OK
Content-Type: text/html\n\r
<html>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript" charset="utf-8">
  </script>
<head>
<script type="text/javascript">
var DEVICE_URL = 'http://%s'
function iotAction(action){
    if(action=='change_led'){
        if(document.getElementById('led_value').value==1){
            action='led_off'
            document.getElementById('led_value').value=0
            document.getElementById('led_control').style.backgroundImage="url('https://raw.githubusercontent.com/dgolak/esp8266/master/images/alarm_off.jpg')"
        }else if(document.getElementById('led_value').value==0){
            action='led_on'
            document.getElementById('led_value').value=1
            document.getElementById('led_control').style.backgroundImage="url('https://raw.githubusercontent.com/dgolak/esp8266/master/images/alarm_on.jpg')"
        }else{
            action="led_on"
        }
    }
    if(action=='change_light'){
        if(document.getElementById('light_value').value==1){
            action='light_off'
            document.getElementById('light_value').value=0
            document.getElementById('light_control').style.backgroundImage="url('https://raw.githubusercontent.com/dgolak/esp8266/master/images/light_off.jpg')"
        }else if(document.getElementById('light_value').value==0){
            action='light_on'
            document.getElementById('light_value').value=1
            document.getElementById('light_control').style.backgroundImage="url('https://raw.githubusercontent.com/dgolak/esp8266/master/images/light_on.jpg')"
        }else{
            action="light_on"
        }
    }
    var requestURL = DEVICE_URL + "/?action="+action
    $.get (requestURL)
}
</script>
<style>
#container{
    width:800px;
    height:1300px;
    background-image:url("https://raw.githubusercontent.com/dgolak/esp8266/master/images/navi2.png");
    background-position:40px 110px;
    background-size:720px;
    background-repeat: no-repeat;
    -webkit-user-select: none;
    padding-top:100px;
}
button{
    background-color:transparent;
    border-color:transparent;
    border:0px solid red
}
</style>
</head>
<center>
<div id="container">
<table cellpadding="0" cellspacing="0">
<tr>
<td style="padding-left:130px;" colspan="3">
<button style="width:440px;height:150px" ontouchstart="iotAction('forward')" ontouchend="iotAction('stop')"/>
</td>
</tr>
<tr>
<td><button style="width:180px;height:190px" ontouchstart="iotAction('left_up')" ontouchend="iotAction('stop')"/></td>
<td rowspan="2"><button style="width:350px;height:370px" ontouchstart="iotAction('stop')" ontouchend="iotAction('stop')"/></td>
<td><button style="width:180px;height:190px" ontouchstart="iotAction('right_up')" ontouchend="iotAction('stop')"/></td>
</tr>
<tr>
<td><button style="width:180px;height:220px" ontouchstart="iotAction('left_down')" ontouchend="iotAction('stop')"/></td>
<td><button style="width:180px;height:220px" ontouchstart="iotAction('right_down')" ontouchend="iotAction('stop')"/></td>
</tr>
<tr>
<td style="padding-left:130px;" colspan="3">
<button style="width:440px;height:150px" ontouchstart="iotAction('backward')" ontouchend="iotAction('stop')"/>
</td>
</tr>
</table>
<br/><br/>
<table>
<tr>
<td>
<input type="hidden" id="light_value" value="0"/>
<button id="light_control" style="width:200px;height:200px;background-image:url('https://raw.githubusercontent.com/dgolak/esp8266/master/images/light_off.jpg');background-size:200px;"" ontouchstart="iotAction('change_light')"></button>
</td>
<td>
<input type="hidden" id="led_value" value="0"/>
<button id="led_control" style="margin-left:20px;width:200px;height:200px;background-image:url('https://raw.githubusercontent.com/dgolak/esp8266/master/images/%s');background-size:200px;"" ontouchstart="iotAction('change_led')"></button>
</td>
</tr>
</table>
</div>
</center>
</html>
"""

def main(E,micropython_optimize=False):
    s = socket.socket()
    ai = socket.getaddrinfo("172.20.10.10", 80)
    addr = ai[0][-1]
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(addr)
    s.listen(5)
    while True:
        res = s.accept()
        client_sock=res[0]
        if not micropython_optimize:
            client_stream = client_sock.makefile("rwb")
        else:
            client_stream = client_sock
        req = client_stream.readline()
        get = req.split()[1].decode('utf-8')
        if get == '/?action=forward':
            E.forward()
        elif get == '/?action=left_up':
            E.left_up()
        elif get == '/?action=right_up':
            E.right_up()
        elif get == '/?action=left_down':
            E.left_down()
        elif get == '/?action=right_down':
            E.right_down()
        elif get == '/?action=backward':
            E.backward()
        elif get == '/?action=stop':
            E.stop()
        elif get == '/?action=led_on':
            led.on()
        elif get == '/?action=led_off':
            led.off()
        elif get == '/?action=light_on':
            light_l.on()
            light_r.on()
        elif get == '/?action=light_off':
            light_l.off()
            light_r.off()
        else:
            pass
        while True:
            h = client_stream.readline()
            if h == b"" or h == b"\r\n":
                break
        if led.value() == 1:
            led_icon="alarm_on.jpg"
        else:
            led_icon = "alarm_off.jpg"
        client_stream.write(CONTENT % (wlan.ifconfig()[0],led_icon))
        client_stream.close()
        if not micropython_optimize:
            client_sock.close()
main(E)

see https://github.com/dgolak/esp8266/blob/master/main.py


well i guess that this is a straingthforward approach...

cf: david golak:
https://hackaday.io/project/27444-remot ... r-via-wifi
How to build RC Car with the esp8266.

btw: my car has got a option of a steering axle - in other words - i have a slightly different car - than David has.
But that i think does not make a big difference.. I have to change the code at some places to fit.

i will have a closer look at this.

regards
WPGear.org is a compendium of useful developer tools for working with WordPress.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by kevinkk525 » Sun Feb 03, 2019 7:20 pm

I don't know much about different cars and motor drivers in rc cars.

This sounds like a good plan though. Having instructions in micropython is a perfect basis for your project. I'd use wemos mini or NodeMCU too.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

mcoelho
Posts: 2
Joined: Wed Feb 27, 2019 7:34 am

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by mcoelho » Wed Feb 27, 2019 9:10 am

Created an account to interject. #someoneiswrongontheinternet

You don't want TCP, you want UDP. TCP will guarantee the messages get from end to end eventually, but in a live control scenario, a message being delivered 10 seconds late makes control harder, not better. You want messages to either be responded to or ignored. You do NOT want an option where control messages are delivered after a significant delay. See VOIP, video conferencing, online multiplayer games, etc. If you want some sort of confirmation that commands went through, build something on top of UDP. But you do NOT want TCP delivering things like "Full Acceleration" 10 minutes after you sent the command, once it's on the table for repair.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by kevinkk525 » Wed Feb 27, 2019 10:24 am

That is true. It all depends on the application and how you program it.
You might have some commands that you want to have a confirmation and could use TCP for it but for the general command messages it would be better to use UDP and send the command every few ms.
TCP however doesn't have a 10 seconds delay but in recent tests in my local WLAN I experienced ocasional message delays of 1.5 seconds.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

mcoelho
Posts: 2
Joined: Wed Feb 27, 2019 7:34 am

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by mcoelho » Wed Feb 27, 2019 5:09 pm

No, TCP's inherent delay is minuscule. The problem is TCP's default timeout is measured in seconds or minutes depending on the implementation. If there is a problem sending a certain command, TCP will make sure it gets there eventually. For a remote control scenario, you want commands to get there when sent or not at all.

TCP is for when it's important that a specific message gets there, but arrival time is less important. UDP is much preferable for live interaction.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: rc-car and ESP8266-board: which prtocoll to stuck with

Post by kevinkk525 » Wed Feb 27, 2019 6:58 pm

That's what I was saying.. With a normal remote implementation you would use UDP because message loss doesn't matter but latency does.
You don't use a TCP timeout of minutes by the way, you always use at most 2 seconds and these delays are just ocasional.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

Post Reply