Skip to content

Interface and application programming

Individual Assignment 2020

Restarting programming

To be clear, I’m not a programmer. Last time I programmed was at university, over 20 years ago. Back then I did learn C and OpenGL to make a bolder-dash type game, but I hardly remember any of it.

This week I planned to write an application that interfaces a user to the ESP32, as that’s what I plan to use in my final project. In order to program for the ESP32 you can use

  • Espressif IDF (IoT Development Framework), as I did last week
  • Arduino IDE
  • Micropython
  • JavaScript
  • LUA
  • … and others

This week I am following a tutorial which recommends using the Arduino IDE, so I set arduino up to be able to interface my ESP32, according to these instructions.

Essentially, I added this URL to the Additional Boards Manager in the Arduino IDE preferences

https://dl.espressif.com/dl/package_esp32_index.json

Then in th Boards Manager, added the ESP32 library, then selected my devboard DOIT ESP32 DEVKIT V1 from the pulldown menu and the port it is connected to (in my case, /dev/cu.SLAB_USBtoUART)

I then opened a simple WiFiScan example program and uploaded it to confirm proper function, pressing the boot button on the board when Arduino starts looking for the board, otherwise the flash will fail. Then I tested the program with the serial monitor, where it printed the available WiFi networks.

Tuning LEDs On and Off over wifi on ESP32

So I ran Rui Santos’ arduino code from the tutorial I followed, and it worked quite well. To be clear it’s not my code, I have no merit at all in this result, but studying the code and explanations in the tutorial I understand how it works and what it does. All I did was change a bit of CSS to change the way the buttons look.

Individual Assignment 2022/2024

This year I followed a Random Nerd tutorial to control a servo motor using a slider in a website hosted on my esp32 development board.

I searched my Micro Servo SG90’s datasheet to figure out which cable’s corresponded to VCC, GND and PWM signal, and looked at the pinout of my Barduino to figure out where to connect those cables to.

! Connection Schematic

I was worried that the 3.3V of my Barduino wasn’t enough to power the servo, but it seems it does work. I then went to the Arduino IDE and installed the SERVOESP32 library from Jarek Paral. Once installed, I opened the simpleServo example, which just rotates the servo’s shaft between 0º and 180º, back and forth. That allowed me to determine that the 3.3V actually was enough for this motor.

I then carried on with the tutorial, that has code that allows my board to connect to my home Wifi Network, host a website with a slider that allows to control the rotation of the servo.

interface

Once uploaded, it worked well

Explanation of the code

The original code from Rui Santos, also known as RandomNerd, is quite well documented in explicit comments throughout the code, so it was easy for me to understand where to put my wifi credentials, and change the servo pin.

Still, I won’t pretend to understand every bit of the code, as it would take me a considerable amount of time to learn so much programming; Nevertheless, it’s important to at least superficially understand the code I reused, especially when I’m presenting it in a weekly assignment.

For this, I asked ChatGPT to explain it to me, which it did, extensively. The following is my curation of what I find most important and interesting.

After the inclusion of the Wifi library and creation of a Servo Object, constants and variables are declared. This is where the Wifi credentials are hard coded into the program, as well as the servo motor GPIO pin.

static const int servoPin = 13; // GPIO pin for the servo

const char* ssid     = "my home network SSID";
const char* password = "my network password";

WiFiServer server(80); // Set web server port number to 80

String header; // Variable to store the HTTP request
String valueString = String(5); // Decode HTTP GET value
int pos1 = 0;
int pos2 = 0;

unsigned long currentTime = millis(); // Current time
unsigned long previousTime = 0; 
const long timeoutTime = 2000; // Define timeout time in milliseconds (2000ms = 2s)
  • servoPin: Specifies the GPIO pin the servo is connected to.
  • ssid and password: Store the network credentials.
  • server: Initializes the web server on port 80.
  • header: Stores the HTTP request header.
  • valueString: Used to decode the HTTP GET value for the servo position.
  • pos1 and pos2: Positions in the header string for parsing.
  • currentTime and previousTime: Track time for managing client connections.
  • timeoutTime: Defines a 2-second timeout for client connections.

The Setup function initializes the serial communication, attaches the servo to the specified pin, connects to the Wi-Fi network and prints the connection status and IP address to serial, in case you’re monitoring it, which is good practice for debugging,and to easily find the IP address the network router assigned the device. Setup also starts the web server.

The Loop function, which does what it says on the label, loops these instructions indefinitely:

  • It listens for incoming client connections from the browsers accessing the server’s IP address.
  • When a client connects, it reads the HTTP request.
  • If the request ends (detected by two newline characters), it sends an HTTP response with an HTML page containing a slider to control the servo.
  • It parses the HTTP GET request to extract the servo position value and rotates the servo accordingly.
  • Finally, it clears the header and closes the client connection, listening for new connections.

How It’s Sent to the Client

So, the program sends the HTML content line-by-line using client.println(). This function sends each line of the HTML code to the client (browser) over the established TCP connection. Very clever, I thought.

The code is sent to the client as part of the HTTP response. WiFiClient client = server.available(); listens for incoming client connections; When a client connects, the server reads the HTTP request and constructs the HTTP response, including the HTML content, which is sent line-by-line as mentioned above.

Web Interface

I was most curious about the html page, as that is what I could most easily customize in the future, and it’s what constitutes the interface a user will see. This is how it’s structured:

HTML Structure and Meta Tags:

  • <!DOCTYPE html><html>: Defines the document type and the start of the HTML document.
  • <head>: Contains meta-information about the HTML document.
  • <meta name="viewport" content="width=device-width, initial-scale=1">: Ensures the page scales correctly on different devices.
  • <link rel="icon" href="data:,">: Sets a favicon for the page (a placeholder in this case).

CSS Styling:

  • <style>: Inline CSS to style the body and the slider.
  • body { text-align: center; font-family: "Trebuchet MS", Arial; margin-left:auto; margin-right:auto;}: Centers the text, sets the font, and centers the body content.

JavaScript Libraries and Script Tags:

  • <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>: Loads the jQuery library to facilitate AJAX requests and other JavaScript functionalities.

Body Content:

  • <body><h1>ESP32 BESTIAL with Servo</h1>: Displays the main heading, which I changed to display the name I wanted it to
  • <p>Position: <span id="servoPos"></span></p>: Displays the current position of the servo using a span element.
  • <input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)" value="5"/>: Creates an input slider ranging from 0 to 180. The onchange event triggers the servo function when the slider value changes.

JavaScript for Interaction:

  • var slider = document.getElementById("servoSlider"); var servoP = document.getElementById("servoPos");: Gets references to the slider and span elements.
  • servoP.innerHTML = slider.value;: Sets the initial slider value in the span.
  • slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }: Updates the span with the current slider value whenever the slider is moved.
  • $.ajaxSetup({timeout:1000}); function servo(pos) { $.get("/?value=" + pos + "&"); }: Sends an AJAX GET request to the server with the current slider value whenever the slider is moved.

Interpretation by the Browser

Receiving the HTTP Response:

  • The client (web browser) receives the HTTP response, including the HTML content, CSS styles, and JavaScript code.

Rendering the Page:

  • The browser parses the HTML and CSS to render the visual elements of the page.
  • The slider and text elements are displayed as specified.

Executing JavaScript:

  • The browser executes the embedded JavaScript code, enabling interactive features like updating the servo position in real-time as the slider is moved.

AJAX Requests:

  • When the slider value changes, the JavaScript code sends an AJAX GET request to the server with the new position value (/value=value). The server processes this request to adjust the servo position accordingly.

This process allows us to control the servo motor via a web interface hosted on the ESP32, providing a way to interact with the hardware through a browser, without third party services, and all embedded in the code on the micro-controller. I find this very liberating.

It’s a long and detailed read, and there’s little I know to customize, in particular the javascript and AJAX completely escape me. But I do know a little html and CSS, so I figure I could edit that to get a more personalized result. In the end, I’m happy I understand the mechanics of the program a little bit more, with the help of ChatGPT.

Files

SimpleServo Arduino Sketch

My final Arduino Sketch

Checklist

Learning outcomes

  • Interpret and implement design and programming protocols to create a Graphic User Interface (GUI).

Have you?

  • Linked to the group assignment page
  • Documented your process
  • Explained the UI that you made and how you did it
  • Outlined problems and how you fixed them
  • Included original code (or a screenshot of the app code if that’s not possible)
  • Included a ‘hero shot/video’ of your application running with your board

Group Assignment

Link to the group assignment part.


Last update: May 25, 2024