Skip to content

Commit 0fa28f7

Browse files
Updated content
Added full code snippet Fixed connection errors
1 parent 2fc89b0 commit 0fa28f7

File tree

2 files changed

+187
-28
lines changed

2 files changed

+187
-28
lines changed

content/hardware/08.edu/solution-and-kits/alvik/tutorials/user-manual/user-manual.md

Lines changed: 187 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,6 @@ By following these steps, you can control the LEDs on the Arduino Alvik robot to
10941094

10951095
## Talking With Other Devices!
10961096

1097-
10981097
### WiFi
10991098

11001099
The ESP32 on the Arduino Alvik robot includes built-in Wi-Fi capabilities, enabling it to connect to wireless networks and communicate with other devices over the internet. This can be particularly useful for remote control applications. In this example, we'll set up the Alvik robot to connect to a Wi-Fi network, host a web server, and provide a simple web interface with buttons to control the robot's movements.
@@ -1107,7 +1106,6 @@ The provided code will:
11071106

11081107
### Step By Step Setup
11091108

1110-
11111109
1. Replace `Insert_SSID_Here` and `Password_Here` with your Wi-Fi credentials.
11121110
2. Upload the script to the Arduino Nano ESP32.
11131111
3. Connect to the robot's IP address (printed on the console) using a web browser.
@@ -1124,7 +1122,7 @@ from arduino_alvik import ArduinoAlvik
11241122
from time import sleep_ms
11251123

11261124
# Wi-Fi credentials
1127-
SSID = "InErt_SSID_Here"
1125+
SSID = "Insert_SSID_Here"
11281126
PASSWORD = "Password_Here"
11291127

11301128
# Connect to Wi-Fi
@@ -1186,13 +1184,16 @@ html = """
11861184
We finally set up the web server, note that the selected port should be valid for your network with no conflicts. This can be tuned to the setting that best works for your network configuration.
11871185

11881186
```python
1189-
#EADDRINUSE erroris prompted change port
1190-
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
1187+
# Specify a port
1188+
port = 8080
1189+
addr = socket.getaddrinfo('0.0.0.0', port)[0][-1]
11911190
s = socket.socket()
11921191
s.bind(addr)
11931192
s.listen(5)
11941193

1195-
print('Listening on', addr)
1194+
s.settimeout(5)
1195+
1196+
print(f'Listening on {sta_if.ifconfig()[0]}:{port}')
11961197
```
11971198

11981199
**Handling HTTP Requests**
@@ -1201,26 +1202,47 @@ The following code handles incoming HTTP requests and moves the robot in the spe
12011202

12021203
```python
12031204
def handle_request(conn):
1204-
request = conn.recv(1024)
1205-
request = str(request)
1206-
print("Request:", request)
1207-
1208-
if '/up' in request:
1209-
alvik.set_wheels_speed(30, 30)
1210-
elif '/down' in request:
1211-
alvik.set_wheels_speed(-30, -30)
1212-
elif '/left' in request:
1213-
alvik.set_wheels_speed(-30, 30)
1214-
elif '/right' in request:
1215-
alvik.set_wheels_speed(30, -30)
1216-
else:
1217-
alvik.brake()
1205+
try:
1206+
request = conn.recv(1024).decode('utf-8')
1207+
first_line = request.split('\n')[0] # Get the first line of the request
1208+
path = first_line.split(' ')[1] # Extract the path (e.g., "/up")
1209+
1210+
# Strip query strings (e.g., "/up?")
1211+
if '?' in path:
1212+
path = path.split('?')[0]
1213+
print(f"Request path: {path}")
1214+
1215+
# Ignore favicon requests
1216+
if path == '/favicon.ico':
1217+
conn.send('HTTP/1.1 204 No Content\n')
1218+
conn.send('Connection: close\n\n')
1219+
return
1220+
1221+
# Control the robot based on the request path
1222+
if path == '/up':
1223+
alvik.set_wheels_speed(30, 30)
1224+
elif path == '/down':
1225+
alvik.set_wheels_speed(-30, -30)
1226+
elif path == '/left':
1227+
alvik.set_wheels_speed(-30, 30)
1228+
elif path == '/right':
1229+
alvik.set_wheels_speed(30, -30)
1230+
else:
1231+
alvik.brake()
1232+
1233+
# Send the response for valid paths
1234+
conn.send('HTTP/1.1 200 OK\n')
1235+
conn.send('Content-Type: text/html\n')
1236+
conn.send('Connection: close\n\n')
1237+
conn.sendall(html)
12181238

1219-
conn.send('HTTP/1.1 200 OK\n')
1220-
conn.send('Content-Type: text/html\n')
1221-
conn.send('Connection: close\n\n')
1222-
conn.sendall(html)
1223-
conn.close()
1239+
except OSError as e:
1240+
if e.errno == 104: # ECONNRESET error
1241+
print("Connection reset by client.")
1242+
else:
1243+
print(f"Error: {e}")
1244+
finally:
1245+
conn.close()
12241246
```
12251247

12261248
**Main Loop**
@@ -1231,9 +1253,17 @@ The following code runs the main loop to handle incoming connections and process
12311253
# Main loop to handle incoming connections
12321254
try:
12331255
while True:
1234-
conn, addr = s.accept()
1235-
print('Connection from', addr)
1236-
handle_request(conn)
1256+
try:
1257+
conn, addr = s.accept()
1258+
print('Connection from', addr)
1259+
handle_request(conn)
1260+
except OSError as e:
1261+
if e.errno == 116: # ETIMEDOUT error
1262+
print("Waiting for connection...")
1263+
elif e.errno == 104: # ECONNRESET error
1264+
print("Connection reset by client.")
1265+
else:
1266+
print(f"Accept error: {e}")
12371267
except KeyboardInterrupt:
12381268
print("Server stopped")
12391269
s.close()
@@ -1242,6 +1272,135 @@ except KeyboardInterrupt:
12421272

12431273
This section ensures the server keeps running, accepting incoming connections, and handling requests until the script is interrupted. If an `EADDRINUSE` error occurs, change the port number from 80 to an unused port, like 8080, in the `addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]` line. Also, make sure the device you access the web interface on should be on the same network as the Alvik.
12441274

1275+
1276+
**Full Code**
1277+
```python
1278+
import network
1279+
import socket
1280+
from arduino_alvik import ArduinoAlvik
1281+
from time import sleep_ms
1282+
1283+
# Wi-Fi credentials
1284+
SSID = "Arduino_IoT"
1285+
PASSWORD = "ArduinoIoT2021"
1286+
1287+
# Connect to Wi-Fi
1288+
sta_if = network.WLAN(network.STA_IF)
1289+
sta_if.active(True)
1290+
sta_if.connect(SSID, PASSWORD)
1291+
1292+
# Wait for connection
1293+
while not sta_if.isconnected():
1294+
pass
1295+
1296+
print("Connected to WiFi. IP address:", sta_if.ifconfig()[0])
1297+
1298+
# Initialize the robot
1299+
alvik = ArduinoAlvik()
1300+
alvik.begin()
1301+
sleep_ms(5000)
1302+
1303+
# HTML for the web interface
1304+
html = """
1305+
<!DOCTYPE html>
1306+
<html>
1307+
<head>
1308+
<title>Alvik Robot Control</title>
1309+
</head>
1310+
<body>
1311+
<h1>Control Alvik Robot</h1>
1312+
<form action="/up">
1313+
<button type="submit">Up</button>
1314+
</form>
1315+
<form action="/down">
1316+
<button type="submit">Down</button>
1317+
</form>
1318+
<form action="/left">
1319+
<button type="submit">Left</button>
1320+
</form>
1321+
<form action="/right">
1322+
<button type="submit">Right</button>
1323+
</form>
1324+
</body>
1325+
</html>
1326+
"""
1327+
1328+
# Specify a port
1329+
port = 8080
1330+
addr = socket.getaddrinfo('0.0.0.0', port)[0][-1]
1331+
s = socket.socket()
1332+
s.bind(addr)
1333+
s.listen(5)
1334+
1335+
s.settimeout(5)
1336+
1337+
print(f'Listening on {sta_if.ifconfig()[0]}:{port}')
1338+
1339+
# Function to handle incoming HTTP requests
1340+
def handle_request(conn):
1341+
try:
1342+
request = conn.recv(1024).decode('utf-8')
1343+
first_line = request.split('\n')[0] # Get the first line of the request
1344+
path = first_line.split(' ')[1] # Extract the path (e.g., "/up")
1345+
1346+
# Strip query strings (e.g., "/up?")
1347+
if '?' in path:
1348+
path = path.split('?')[0]
1349+
print(f"Request path: {path}")
1350+
1351+
# Ignore favicon requests
1352+
if path == '/favicon.ico':
1353+
conn.send('HTTP/1.1 204 No Content\n')
1354+
conn.send('Connection: close\n\n')
1355+
return
1356+
1357+
# Control the robot based on the request path
1358+
if path == '/up':
1359+
alvik.set_wheels_speed(30, 30)
1360+
elif path == '/down':
1361+
alvik.set_wheels_speed(-30, -30)
1362+
elif path == '/left':
1363+
alvik.set_wheels_speed(-30, 30)
1364+
elif path == '/right':
1365+
alvik.set_wheels_speed(30, -30)
1366+
else:
1367+
alvik.brake()
1368+
1369+
# Send the response for valid paths
1370+
conn.send('HTTP/1.1 200 OK\n')
1371+
conn.send('Content-Type: text/html\n')
1372+
conn.send('Connection: close\n\n')
1373+
conn.sendall(html)
1374+
1375+
except OSError as e:
1376+
if e.errno == 104: # ECONNRESET error
1377+
print("Connection reset by client.")
1378+
else:
1379+
print(f"Error: {e}")
1380+
finally:
1381+
conn.close()
1382+
1383+
# Main loop to handle incoming connections
1384+
try:
1385+
while True:
1386+
try:
1387+
conn, addr = s.accept()
1388+
print('Connection from', addr)
1389+
handle_request(conn)
1390+
except OSError as e:
1391+
if e.errno == 116: # ETIMEDOUT error
1392+
print("Waiting for connection...")
1393+
elif e.errno == 104: # ECONNRESET error
1394+
print("Connection reset by client.")
1395+
else:
1396+
print(f"Accept error: {e}")
1397+
except KeyboardInterrupt:
1398+
print("Server stopped")
1399+
s.close()
1400+
alvik.stop()
1401+
1402+
```
1403+
12451404
### ESP-NOW
12461405

12471406
The ESP32 on the Arduino Alvik robot also supports ESP-NOW, a fast, connectionless communication protocol that enables direct, quick, and low-power control of smart devices without the need for a router. ESP-NOW can work alongside Wi-Fi and Bluetooth LE, making it versatile for various applications. It supports the ESP8266, ESP32, ESP32-S, and ESP32-C series. In this example, we'll set up the Alvik robot to receive commands via ESP-NOW.

0 commit comments

Comments
 (0)