HTMAA 25
home about me final projectThis week’s aim was to “design, build, and connect wired or wireless node(s) with network or bus addresses and local input &/or output device(s)”.
I’ll be using a XIAO ESP32C3 board with an attached WiFi/Bluetooth antenna. Since I wasn’t going to have much lab time this week, I simply soldered on the connector pins so that I could use the board with a breadboard (sorry, Neil!).
I then followed this Getting Started guide to set up my Arduino IDE.
To check that everything in my setup was working, I found the code provided by Seeed Studio for scanning wifi networks.
#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);
}
And confirmed that it successfully found the WiFi networks it should have found:
02:52:22.663 -> scan start
02:52:25.263 -> scan done
02:52:25.263 -> 5 networks found
02:52:25.263 -> 1: MIT SECURE (-69)*
02:52:25.263 -> 2: eduroam (-69)*
02:52:25.301 -> 3: MIT GUEST (-69)
02:52:25.301 -> 4: MIT (-69)*
02:52:25.301 -> 5: MITAV (-90)*
Curious about Bluetooth, I tried out that example code too, and used my phone to send messages to the ESP, which would then send the messages through Serial back to my computer.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
delay(2000);
}
This worked, though as is pattern with me, I forgot to document it.
The BLE library stands for Bluetooth Low Energy, which means that unlike typical bluetooth devices, the device is “sleeping” unless data is actively being transferred, and so is much more power efficient. This is suited for short, small bursts of data transfer followed by long periods of no communication. As I was reading up on this, I came across some documentation for the ESP BLE library, which was actually super informative.
I had a bunch of LEDs I could put in with my breadboard and not much else, so I wanted to make a light-based home device. Since the ESP32 had few pins, I recalled the Charlieplexing talked about during the outputs lecture, and decided to try my hand at it.
I sketched up this breadboard schematic that would allow me to charlieplex:
And with the following code:
int cPins[3] = {D3, D4, D5};
void charlie(const int* vals) {
for(int i = 0; i < 3; i++) {
if(vals[i] == -1) {
pinMode(cPins[i], INPUT);
} else {
pinMode(cPins[i], OUTPUT);
digitalWrite(cPins[i], vals[i]);
}
}
}
void setup() {}
const int patterns[6][3] = {
{ 0, 1, -1},
{ 1, 0, -1},
{-1, 1, 0},
{ 0, -1, 1},
{ 1, -1, 0},
{-1, 0, 1},
};
void loop() {
for (int i = 0; i < 6; i++) {
charlie(patterns[i]);
delay(100);
}
}
Achieved this:
The green LEDs going in a loop sparked my actual idea.
Updating my wiring and the order of my charlieplex array, I got:
I combined Bluetooth code and my charlieplex code, making the following alterations and additions:
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "7e13cc6d-ef5f-4213-a005-64f4dfb2523c"
#define CHARACTERISTIC_UUID "b963e6f0-2d8c-4926-9db4-ebb916172f22"
const int num_pins = 3;
const int num_leds = 6;
int cPins[num_pins] = {D3, D4, D5};
const int patterns[num_leds][num_pins] = {
{ 0, 1, -1},
{-1, 1, 0},
{-1, 0, 1},
{ 1, 0, -1},
{ 0, -1, 1},
{ 1, -1, 0},
};
void charlie(int led, int brightness) {
const int* vals = patterns[led];
for(int i = 0; i < num_pins; i++) {
if(vals[i] == -1) {
pinMode(cPins[i], INPUT);
} else {
pinMode(cPins[i], OUTPUT);
analogWrite(cPins[i], vals[i] * brightness);
}
}
}
const int num_modes = 3;
int mode = 0;
int modes[num_modes][6] = {
{0, 1, 2, 3, 4, 5},
{5, 4, 3, 2, 1, 0},
{0, 2, 4, 1, 3, 5},
};
const int time_per_led = 1800;
const int max_brightness = 50;
const int fade_speed = 2;
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String setting = pCharacteristic->getValue();
if (setting.length() > 0) {
int new_mode = setting.toInt();
mode = new_mode % num_modes;
}
}
};
void setup() {
Serial.begin(115200);
BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
for (int i = 0; i < num_leds; i++) {
// fade in
for (int b = 0; b < max_brightness; b += fade_speed) {
charlie(modes[mode][i], b);
delay(time_per_led / (2 * max_brightness / fade_speed));
}
// fade out
for (int b = max_brightness; b > 0; b -= fade_speed) {
charlie(modes[mode][i], b);
delay(time_per_led / (2 * max_brightness / fade_speed));
}
}
}
I’ve long since killed all my real plants, so here’s a demo with a fake plant.
There’s so much to learn about wireless connections that I really just skimmed through to make one of the simplest possible projects - it would be fun to learn about some of the details and protocols more in depth. As for the actual project I made, there are quite a few extensions I’d like to do, e.g: