Skip to content

Networking & Communications

Back to electronics 😔

For this week we have to communicate via wired connections, and wireless connections.

Wired Communication

alt text

Wired connections, (including but not limited to USB, HDMI, and GPIO pins), provide a reliable communication method between a board and external devices or networks. By making tasks like programming, debugging, and interfacing with peripherals much easier, wired connections can help a lot when you’re working on a project.


I2C Communication

For this week, I decided to explore I2C communication, especially because my microcontroller has limited pins, and because all of my components have the I2C option.

What is I2C?

I2C (Inter-Integrated Circuit) is a serial communication protocol commonly used to connect microcontrollers, sensors, and other integrated circuits. It allows multiple devices to communicate with each other using just two wires, a clock line (SCL) for synchronization and a data line (SDA) for transmitting information.

- Google.com

But before I could do anything with my board or components, I needed to understand addresses.

Addresses

In I2C communication, each component on the bus is assigned a unique address, typically 7 bits long, allowing for up to 128 different addresses. Devices may have fixed addresses or configurable ones, usually set through address pins, enabling multiple devices to coexist on the same bus without conflict. To find out the addresses of the components I’m using this week, here’s what I did.

I started off by connecting an SSD1306 OLED Display and an I2C Standard LCD 20x4 to an Arduino board as shown.

alt text!

Then I went online for a code to run, and I came across this really useful website. From there, I found a code that can scan your I2C devices, their addresses, and it doesn’t need any libraries 🎉. This is the code that I ran:

// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// --------------------------------------
// i2c_scanner
//
// Modified from https://playground.arduino.cc/Main/I2cScanner/
// --------------------------------------

#include <Wire.h>

// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE Wire

void setup() {
  WIRE.begin();

  Serial.begin(9600);
  while (!Serial)
     delay(10);
  Serial.println("\nI2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    WIRE.beginTransmission(address);
    error = WIRE.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

After running that code, this is the output that I got on my serial monitor:

alt text

Now we know that my OLED address is 0x3C, and that my LCD address is 0x27.


Wired Display Using I2C

So now that I had my addresses, I could finally start coding!

ChatGPT helped me come up with a basic code to run both devices at once! However, I decided to download some libraries first:

Adafruit_SSD1306.h To program an SSD1306 OLED Display, download the following libraries on your Arduino IDE. alt text alt text

LiquidCrystal_I2C.h To download the LiquidCrystal_I2C.h library, check out this page, and then follow along.

alt text

Once the ZIP file has downloaded, open up your Arduino IDE, and then go to Sketch>Include Library> Add .ZIP Library…

alt text

Then, open your .ZIP file location and then select it!

alt text

Now we’re done with installing all the libraries we need !!! After giving ChatGPT the following prompt:

Please provide a detailed example illustrating the integration of both an LCD display and an OLED display with an Arduino board. Specify the necessary libraries ('Wire.h', 'LiquidCrystal_I2C.h', 'Adafruit_GFX.h', 'Adafruit_SSD1306.h'), define constants for the displays' addresses, sizes, and reset pins. Additionally, explain the usage of functions such as 'lcd.backlight()', 'display.begin()', 'display.clearDisplay()', 'display.setTextSize()', 'display.setTextColor()', 'display.setCursor()', 'display.println()', 'display.display()', 'lcd.clear()', and 'lcd.print()'. The goal is to create a comprehensive guide for utilizing both LCD and OLED displays in an Arduino project.

Here’s the output I got:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// LCD settings
#define LCD_ADDRESS 0x27
#define LCD_COLS 20
#define LCD_ROWS 4
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLS, LCD_ROWS);

// OLED settings
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define OLED_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  // Initialize the LCD
  lcd.backlight();

  // Initialize the OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
    for (;;); // Don't proceed, loop forever
  }
}

void loop() {
  // Display "TWD" on OLED and "wow" on LCD
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("TWD");
  display.display();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("wow");

  delay(2000);

  // Display "wow" on OLED and "TWD" on LCD
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("wow");
  display.display();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("TWD");

  delay(2000);
}

I just wanted to see if the LCD was functional or not, so this code just displays random characters on the screen.

Here’s the result:

Once it worked, I decided to replace the Arduino Uno board with my development board, so I connected the GPIO pins accordingly, and it worked !!!

alt text


Wireless Communication

alt text

Wireless communication refers to the transmission of data between devices without the need for physical cables or wires. It uses electromagnetic waves, such as radio frequencies, infrared, or microwaves, to transmit information over the air, allowing mobility and flexibility in applications such as Wi-Fi, Bluetooth, and cellular networks.

For this week, I decided to use the board I made in week 9 to host a webserver, access that webserver on my computer, and communicate with the development board itself (specifically the LED’s)


XIAO ESP32 C3 Webserver

Before we start off anything, you’re going to need a Bluetooth/WiFi antenna.

alt text

They usually come with your XIAO ESP32 C3, but you can find tonnes of them online incase you don’t have one. Just search up “Bluetooth antenna for XIAO ESP32 C3”.

Once you have your antenna connected, you’re good to go.

I didn’t really know where to start, so I went to the official page for my microcontroller, and they had exactly what I needed for this week!

Scanning for WiFi (Station Mode)

For some practice, I decided to follow along with whatever the website had, and so, I started by connecting my board to a WiFi network.

#include "WiFi.h"

void setup()
{
    Serial.begin(115200);

    // Set WiFi to station mode and disconnect from an AP if it was previously connected
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);

    Serial.println("Setup done");
}

void loop()
{
    Serial.println("scan start");

    // WiFi.scanNetworks will return the number of networks found
    int n = WiFi.scanNetworks();
    Serial.println("scan done");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        for (int i = 0; i < n; ++i) {
            // Print SSID and RSSI for each network found
            Serial.print(i + 1);
            Serial.print(": ");
            Serial.print(WiFi.SSID(i));
            Serial.print(" (");
            Serial.print(WiFi.RSSI(i));
            Serial.print(")");
            Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
            delay(10);
        }
    }
    Serial.println("");

    // Wait a bit before scanning again
    delay(5000);
}

Once you’ve uploaded this code, open your serial monitor to see what connections are nearby!

alt text


Connecting to WiFi

Now, it’s time to connect to a WiFi network! Remember, you need to know the name and password in order to do this !!!

#include <WiFi.h>

const char* ssid     = "your-ssid";
const char* password = "your-password";   

void setup()
{
    Serial.begin(115200);
    delay(10);

    // We start by connecting to a WiFi network

    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}  
void loop()
{
  }

If you’ve connected successfully, the serial monitor should look something like this:

alt text


Webserver

Finally, it’s time to host a webserver. I did some research online and then I consulted ChatGPT for the code. After asking ChatGPT the following:

Could you write acode to create a web server using the Xiao ESP32-C3 microcontroller board. The web server should serve a web page accessible over Wi-Fi, allowing users to control two LEDs connected to the board.

Set up the necessary connections:
1. Connect two LEDs to GPIO pins on the Xiao ESP32-C3 board. Use pin 2 for LED 1 and pin 5 for LED 2.
Connect the Xiao ESP32-C3 board to a Wi-Fi network using the provided SSID and password.
Implement the web server functionality:
Initialize the web server on port 80.
2. Create an HTML page with two sections: one for controlling LED 1 and another for controlling LED 2.
Each section should contain two buttons: one to turn the corresponding LED on and another to turn it off.
Use inline JavaScript (fetch API) to send requests to the server when buttons are clicked.
3. Define routes for handling HTTP requests:
Define a route for the root path ('/') to serve the HTML page.
Implement separate routes for turning each LED on and off ("/on1", "/off1", "/on2", "/off2").
4. When a request is received to turn an LED on, set the corresponding GPIO pin high. When turning it off, set the pin low.
Respond to the client with a success message indicating the state change.
Ensure proper error handling and feedback:
5. Print status messages to the Serial monitor for debugging purposes.
Handle cases where the Wi-Fi connection fails or the server encounters errors gracefully.
Test the functionality:
Upload the code to the Xiao ESP32-C3 board.
6. Verify that the board successfully connects to the Wi-Fi network.
Open a web browser on a device connected to the same network and navigate to the IP address of the Xiao ESP32-C3 board.
Test each button on the web page to ensure that it correctly toggles the corresponding LED on and off.

Note: Make sure to include any necessary library dependencies and ensure compatibility with the Xiao ESP32-C3 board, thanks.

After that, I got the following code:

#include <WiFi.h>
#include <WebServer.h>

const char* ssid = "your-ssid";
const char* password = "your-password";

WebServer server(80);

const int ledPin1 = 2; // GPIO pin for LED 1
const int ledPin2 = 5; // GPIO pin for LED 2

void setup() {
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);

  // Initialize Serial port
  Serial.begin(115200);

  // Connect to Wi-Fi network
  Serial.println();
  Serial.println("Connecting to Wi-Fi");
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // HTML for the web page
  String html = "<html><head><style>";
  html += "body { font-family: Arial, sans-serif; background-color: #957dad; color: #ffffff; margin: 0; padding: 0; }";
  html += "h1 { text-align: center; margin-top: 50px; }";
  html += "h2 { text-align: center; }";
  html += "button { display: block; margin: 20px auto; padding: 10px 20px; font-size: 18px; background-color: #5e5874; border: none; border-radius: 5px; color: #ffffff; cursor: pointer; }";
  html += "button:hover { background-color: #7d75a2; }";
  html += "</style></head><body>";
  html += "<h1>ESP32 Web Server</h1>";
  html += "<h2>HELLO LED</h2>";
  html += "<button onclick=\"fetch('/on1')\">Turn On</button>";
  html += "<button onclick=\"fetch('/off1')\">Turn Off</button>";
  html += "<h2>LED 2</h2>";
  html += "<button onclick=\"fetch('/on2')\">Turn On</button>";
  html += "<button onclick=\"fetch('/off2')\">Turn Off</button>";
  html += "</body></html>";

  // Route for root / web page
  server.on("/", HTTP_GET, [html](){
    server.send(200, "text/html", html);
  });

  // Route to handle turning LED 1 on
  server.on("/on1", HTTP_GET, [](){
    digitalWrite(ledPin1, HIGH);
    server.send(200, "text/plain", "LED 1 turned on");
  });

  // Route to handle turning LED 1 off
  server.on("/off1", HTTP_GET, [](){
    digitalWrite(ledPin1, LOW);
    server.send(200, "text/plain", "LED 1 turned off");
  });

  // Route to handle turning LED 2 on
  server.on("/on2", HTTP_GET, [](){
    digitalWrite(ledPin2, HIGH);
    server.send(200, "text/plain", "LED 2 turned on");
  });

  // Route to handle turning LED 2 off
  server.on("/off2", HTTP_GET, [](){
    digitalWrite(ledPin2, LOW);
    server.send(200, "text/plain", "LED 2 turned off");
  });

  // Start server
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}

Explanation

Here’s a brief explanation of how the code works:

Wi-Fi Connection

The setup function initializes the serial communication for debugging and connects to a Wi-Fi network using the SSID and passwordbthat you give it. It then prints the IP address on your serial monitor once connected.

Web Server Setup

A web server object (server) is created to listen for HTTP requests on port 80. HTML and CSS code is used to create a web page with buttons to control the LEDs.

Routes Definition

There’s a lot of routes that are defined for handling HTTP GET requests:

  • The root route (/) serves the HTML page.
  • Routes /on1 and /off1 control the first LED, turning it on and off respectively.
  • Routes /on2 and /off2 control the second LED in a similar manner.

Handling Requests

In the loop function, server.handleClient() processes incoming HTTP requests and executes the corresponding route handlers, which turn the LEDs on or off and send a plain text response.


Once I uploaded and ran this code, I opened the serial monitor, and pasted the IP in there into google. The webserver worked !!!

Here’s a basic UI of the server, as well as a video that shows how it works: alt text


Problem #1

This week, I had ONE really major issue. No matter what code I had, it wouldn’t upload. Arduino IDE kept returining “error status 2”. I spent about a day being unable to upload anything, and so I decided to troubleshoot this (heh).

After a lot of trial and error, I don’t really know what the physical problem with my board was, but I found a fix. All I had to do was reboot my MC as SOON as I started uploading the code, and then restarting the MC once the code was uploaded.

alt text

To reboot, long click on the B button on the MC, and then click the R button. Then, to restart, just click on R.


note: you can find the design files and design process on my week 9 documentation page.

This website was created using a template provided by Mr. Anith Ghalley and was used with his permission.*


Last update: June 28, 2024