Skip to content

ESP32 wifi webserver remote control demo #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions examples/demo-webserver-remote-control/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# arol-alvik-demos

Demos for [Arduino Alvik](https://www.arduino.cc/education/arduino-alvik/) developed by [AROL Closure Systems](https://www.arol.com/).

# Instructions

## 1 - Download IDE

[Download IDE](https://labs.arduino.cc/en/labs/micropython)

Arduino labs for Micropython

Unzip the compressed folder

Run the executable

[Either clone or download this repository as zip](https://github.com/arolgroup/arol-alvik-demos/archive/refs/heads/main.zip)

Unzip this repository

## 2 - Connect to the Alvik

Power on the Alvik with its switch

Connect to the Alvik with a USB C cable

![](/images/1-connect-usb-c.jpg)

## 3 - Transfer demo files to the Alvik

Click on the file icon

Click on the folder path on the right pane and navigate to the folder with the files in this repository

![](/images/3-transfer-files.JPG)

One at a time, select each of the following files and with the left arrow transfer them to the Alvik
- main.py : automatically executed by the robot at startup
- wifi_host.py : demo implementation of a wifi webserver hosted by the Alvik
- page_arrow_control.html : web page to be displayed in the device used to control the Alvik. Can be either a phone or a computer

## 4 - Rename the robot

Double click on "wifi_host.py" on the left pane (inside the robot) and edit the name of the wifi network to the desired name of your robot.

It should be a unique name as not to interfere with other Alvik in the same room or with other networks. I advics calling it "Alvik-myname" for ease

Save the file, it will take a few seconds. On the black console down it should show <OK> repeated a number of times. When it stops, save is complete.

![](/images/4-rename.JPG)

## 5 - run applications - reboot the robot

There is a button near the USB-C port on the alvik. Pressing it will reboot the robot. The robot will always play main.py when rebooted.

You can also run application by using the play button on an opened file in the IDE.

The black console will show the "print" strings when connected to the robot.

You will need to reconnect on the IDE.

## 6 - Connect to the robot via wifi

Wait a few seconds after reboot

In the list of wifi networks now your chosen robot name will show up in the list of networks

Connect to the wifi network, you should get a prompt for a sign in page a after a few seconds, or be redirected to the html page hosted by the robot

Pushing the arrow buttons will now move the robot, this does NOT require the USB-C cable plugged in

![](/images/5-connect-wifi-phone.jpg)

![](/images/5-connect-wifi-pc.JPG)

## 7 Enjoy the wifi remote controls wia webpage hosted by the Alvik!

BUG: Samsung and Apple devices will not redirect automatically. To control the robot, open a web browser with wifi conencted to the Alvik, and go to the web page "192.168.4.1"

https://github.com/user-attachments/assets/10da174e-641d-4e57-8ab0-77a9fef9af31

## 8 - Stop the webserver

Clicking on the red button in the web page will stop the web server and show a disconnection page. The wifi will disconnect.

To restart the application you need to restart the robot, or need to play from the IDE.

This helps you in uploading new code to the robot without needing to reset, as it stops the wifi radio and threads properly.

## Copyright and license

Copyright (C) 2024-2025, [AROL Closure Systems](https://www.arol.com/), all rights reserved.

The source code contained in this repository and the executable distributions are licensed under the terms of the MIT license as detailed in the [LICENSE](LICENSE) file.

<!-- EOF -->
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
10 changes: 10 additions & 0 deletions examples/demo-webserver-remote-control/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#import demo

#import hand_follower.py

#import line_follower.py

#this demo will create a wifi network, and connecting to it with a phone will show on 192.168.4.1 a page with four buttons to move the robot
#you should change the name of the wifi network by editing wifi_host.py line 31 the variable gs_ssid with the name of the robot
#multiple robot with the same wifi network name would interfere with each other
import wifi_host.py
137 changes: 137 additions & 0 deletions examples/demo-webserver-remote-control/page_arrow_control.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>ESP32 Arrow Control Portal</title>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
background: #f5f5f5;
font-family: sans-serif;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#arrowContainer {
display: grid;
grid-template-rows: auto auto auto;
grid-template-columns: auto auto auto;
gap: 10px;
justify-items: center;
align-items: center;
}
/* Hide unused grid cells */
#arrowContainer div.empty {
visibility: hidden;
}
#arrowContainer button {
width: 60px;
height: 60px;
font-size: 24px;
border: none;
border-radius: 10px;
background: #007BFF;
color: #fff;
cursor: pointer;
user-select: none;
}
#debug {
margin-top: 20px;
background: #fff;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
/* Styling for the stop button */
#stopBtn {
margin-top: 20px;
padding: 10px 20px;
font-size: 16px;
background: #d9534f;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
user-select: none;
}
</style>
</head>
<body>
<div id="arrowContainer">
<div class="empty"></div>
<button id="upBtn">&#9650;</button>
<div class="empty"></div>
<button id="leftBtn">&#9664;</button>
<div class="empty"></div>
<button id="rightBtn">&#9654;</button>
<div class="empty"></div>
<button id="downBtn">&#9660;</button>
<div class="empty"></div>
</div>
<div id="debug">Waiting for command...</div>
<button id="stopBtn">Stop Application</button>
<script>
// Function to send the command to the ESP32.
function sendCommand(x, y, evt) {
var debugDiv = document.getElementById('debug');
debugDiv.innerText = "Command: " + evt + " | x: " + x + " y: " + y;
console.log("Sending command:", evt, "x:", x, "y:", y);
var xhr = new XMLHttpRequest();
xhr.open("GET", "/update?x=" + x + "&y=" + y + "&evt=" + evt, true);
xhr.send();
}

// Helper to add continuous push-button functionality.
function addPushButton(buttonID, x, y, label) {
var btn = document.getElementById(buttonID);
var intervalID = null;

function startSending(e) {
e.preventDefault();
if (!intervalID) {
intervalID = setInterval(function() {
sendCommand(x, y, label);
}, 100); // send every 100 ms; adjust as needed
}
}

function stopSending(e) {
e.preventDefault();
if (intervalID) {
clearInterval(intervalID);
intervalID = null;
}
// Send a stop command (0,0).
sendCommand(0, 0, "stop");
}

// For desktop.
btn.addEventListener("mousedown", startSending);
btn.addEventListener("mouseup", stopSending);
btn.addEventListener("mouseleave", stopSending);

// For touch devices.
btn.addEventListener("touchstart", startSending);
btn.addEventListener("touchend", stopSending);
btn.addEventListener("touchcancel", stopSending);
}

// Attach continuous push-button functionality to each arrow.
addPushButton("upBtn", 0, -1, "up");
addPushButton("downBtn", 0, 1, "down");
addPushButton("leftBtn", -1, 0, "left");
addPushButton("rightBtn", 1, 0, "right");

// Event handler for the Stop Application button.
document.getElementById("stopBtn").addEventListener("click", function(e) {
e.preventDefault();
// Redirect to /stop, which triggers the server to stop the application.
window.location.href = "/stop";
});
</script>
</body>
</html>
Loading