# 3D Printed Enclosure for Glyph C3/C6
Source: https://learn.pcbcupid.com/documentation/enclosure/3d-printed-enclosure-for-glyph-esp32-boards
Download STL files and print a 3D enclosure designed for Glyph ESP32 development boards, with cutouts for the USB-C port, buttons, and Glink connector.

## Overview
Made from high-quality PLA material, this case offers robust durability while maintaining a sleek, minimalist aesthetic. Its fine 0.2mm layer thickness ensures a smooth, professional finish, complemented by a clean white color that enhances the overall look of your device. The thoughtfully designed 2mm heat inserts and included M2 nut facilitate easy assembly and secure mounting of your GLYPH boards.
**Features**
* Precise cutouts for all GPIO pins, USB, and power connections
* Ventilation slots for heat dissipation
* Snap-fit or screw mounting for secure assembly
* Compatible with standard screws and standoffs
**Dimensions**
* Width: 52 mm
* Length: 57 mm
* Height: 25 mm

### GLYPH Enclosure Assembly Guide
This manual will walk you through the process of securing your PCB into the custom GLYPH enclosure. The design features integrated brass inserts for a secure, professional fit.
**Step 1: Prepare the Bottom Housing**
Place the **bottom half** of the enclosure on a flat surface. You will notice four gold-colored **brass heat-set inserts** in the corners. These are designed to hold the mounting screws for your board.

**Step 2: Align the PCB**
Lower your PCB into the bottom housing. Align the mounting holes on the corners of your PCB with the brass inserts in the enclosure.

> Ensure any ports (like USB or power) are facing the corresponding cutouts on the side of the enclosure wall.
**Step 3: Secure the Board**
Using small Phillips head screws, fasten the PCB to the enclosure.
**Tighten gently:** Turn until you feel resistance. Do not over-tighten, as this could crack the 3D-printed plastic or damage the PCB.
**Step 4: Fit the Top Cover**
Take the **top cover** (the piece featuring the "GLYPH" logo) and align it with the bottom base.
* Check that the **reset button/switch cutout** on the top lid matches the location of the component on your board.
* The lid is designed to snap-fit or sit flush against the bottom rim.
**Step 5: Final Inspection**
Once the lid is pressed into place, your GLYPH device is fully protected. The final dimensions of your assembled unit will be 57mm x 52mm x 25mm.
**Inspired by Practical Design**
* The 3D printed enclosure is designed to securely house your GLYPH ESP32 board while providing easy access to all pins and connectors.
* Cutouts and ventilation slots are positioned for optimal airflow and usability, keeping the board cool and functional.
* Snap-fit or screw-mount options ensure a stable assembly, giving a satisfying hands-on experience when building and using your project.
## Build Guide
Assemble your 3D printed enclosure! Below you'll find a clear, step-by-step guide that walks you through everything from preparing the board and checking pin alignments to securing the board inside the case and completing the final assembly. Follow each step carefully, ensure proper fit for all connectors and standoffs, and take your time with the hardware. By the end of this guide, you'll have a fully assembled, secure, and functional enclosure ready to house your GLYPH ESP32 board.
**Additional Features:**
Convenient Cutouts: Access reset and boot buttons with ease, thanks to strategically placed cutouts for USB-C, slide switch, and QWIIC connector. Free Download and Printing: This enclosure design is freely available for download and printing, empowering you to create a custom case tailored to your specific needs.
[Download Here](https://www.printables.com/model/1018401-enclosure-for-glyph-development-boards)
# Qwiic 2-in-1
Source: https://learn.pcbcupid.com/documentation/modules/breakout-boards/qwiic-2-in-1
Qwiic 2-in-1 Breakout board with dual I2C ports for chaining Qwiic-compatible sensors, displays, and modules to your microcontroller projects.
A [QWIIC 2 IN 1](https://shop.pcbcupid.com/product/gb002/) is an I²C splitter that allows you to connect two Qwiic-compatible devices to a single I²C port. It enables quick, solder-free expansion of sensors and modules using simple plug-and-play connections.
## Pin Configuration
* **GND** : Common ground reference for power and signals
* **SCL** : I²C Serial Clock line used for communication timing
* **SDA** : I²C Serial Data line used for data transfer
* **3V3** : Provides regulated 3.3V power to connected Qwiic devices
## Key Features
* Dual I²C output ports for expanding one I²C bus into two
* Plug-and-play JST-SH connectors (no soldering required)
* 3.3V compatible logic and power
* Compact design for clean prototyping setups
## Applications
* Connecting multiple I²C sensors (IMU, temperature, light, etc.)
* Rapid prototyping with development boards like Glyph C3
* IoT and embedded system projects
* Educational and lab experimentation setups
## Precaution Note
* Ensure all connected devices operate at 3.3V logic (Glyph C3 is not 5V tolerant).
* Avoid connecting too many high-current devices on the 3V3 line.
* Check for duplicate I²C addresses (devices must have unique addresses).
* Keep cable length short to avoid I²C communication issues.
# Qwiic 4-in-1
Source: https://learn.pcbcupid.com/documentation/modules/breakout-boards/qwiic-4-in-1
Qwiic 4-in-1 Breakout board with four I2C ports for chaining multiple Qwiic-compatible sensors and modules from a single microcontroller bus.
A [QWIIC 4 IN 1](https://shop.pcbcupid.com/product/gb005/) expands a single I²C port into four, enabling easy connection of multiple Qwiic devices without soldering.
## Pin Configuration
* **GND** : Common ground reference for power and signals
* **SCL** : I²C Serial Clock line used for communication timing
* **SDA** : I²C Serial Data line used for data transfer
* **3V3** : Provides regulated 3.3V power to connected Qwiic devices
## Key Features
* Four plug-and-play I²C ports
* 3.3V compatible
* Compact and easy integration
## Applications
* Multi-sensor setups
* Rapid prototyping
* IoT and embedded projects
- Ensure all devices use 3.3V logic
- Avoid I²C address conflicts
- Keep cables short for stable communication
# USB 4-in-1
Source: https://learn.pcbcupid.com/documentation/modules/breakout-boards/usb-4-in-1
USB 4-in-1 Breakout board exposing four USB connectors on one board for prototyping multi-port USB devices, hubs, and power distribution circuits.
A [USB 4 in 1 Hub](https://shop.pcbcupid.com/product/gb001/) board designed for signal conversion and development purposes. It breaks out key USB signals—such as VBUS, D+, D-, and GND—into accessible headers, making it ideal for prototyping, testing, debugging, and custom USB interface development.
## Pin Configuration
* **VBUS / 5V** : Provides +5V to the USB device plugged in
* **D-** : USB Data Negative
* **D+** : USB Data Positive
* **GND** : Ground
## Key Features
* Converts one USB interface type to another (e.g., USB to header/pins/terminal).
* Provides easy access to USB signals (VBUS, D+, D-, GND).
* Simple plug-and-play connectivity.
* Compact and lightweight design.
* Ideal for prototyping, testing, and development purposes.
* No active circuitry, purely signal breakout/conversion.
## Applications
* USB signal testing and debugging.
* Prototyping USB-based embedded systems.
* Connecting USB lines to development boards.
* Custom cable development and modification.
* USB power extraction (5V) for small projects.
* Lab testing and hardware validation.
- Avoid connecting multiple devices simultaneously to prevent overload.
- Use a powered USB hub when devices draw higher current.
- Keep cable lengths short to avoid communication delays or voltage drops.
# USB-A Female
Source: https://learn.pcbcupid.com/documentation/modules/breakout-boards/usb-a-breakout-female
USB-A female breakout board exposing VBUS, GND, D+, and D- pins on a PCB to prototype custom USB host ports, hubs, and power delivery circuits.
A [USB-A FEMALE](https://shop.pcbcupid.com/product/gb004/) allows you to plug in USB devices or cables and access power or USB data lines for prototyping, testing, and custom circuit designs.
## Pin Configuration
* **VBUS / 5V** : Provides +5V to the USB device plugged in
* **D-** : USB Data Negative
* **D+** : USB Data Positive
* **GND** : Ground
* **Shield/GND** : Metallic casing connected to ground (optional)
## Key Features
* Exposes standard **USB-A female pins** (VBUS, D+, D-, GND) to **easily solderable headers/pads**.
* Provides access to power (5V) and USB data lines.
* Compatible with any standard USB device or cable.
* Breadboard-friendly and ideal for quick prototyping.
* Durable socket suitable for repeated plug-and-play use
## Applications
* Test benches for USB device validation and diagnostics.
* Production line fixtures requiring repeated USB plug-ins.
* Adding USB access points in control panels or industrial enclosures.
* Firmware flashing or field-updates for embedded industrial devices.
* Used in building IIoT edge devices and gatewaysexperiments.
- Ensure the USB device does not draw more current than the source USB port can supply.
- Avoid shorting 5V and GND — it can damage both the breakout and the host system.
- Keep D+ / D- wires short to prevent signal loss or communication issues.
- Use proper mounting or strain relief to avoid connector damage during repeated insertions.
# USB-A Male
Source: https://learn.pcbcupid.com/documentation/modules/breakout-boards/usb-a-breakout-male
USB-A male breakout board exposing VBUS, GND, D+, and D- pins on a PCB to prototype dongles, macro pads, and USB devices that plug into a host.
A [USB-A MALE](https://shop.pcbcupid.com/product/gb003/) is a small PCB that takes a standard USB-A male plug (like the plug end of a USB cable) and “breaks out” the 4 (or sometimes 5) USB pins — VBUS (5 V), D+, D-, GND (and sometimes shield / shell) — to easily accessible 2.54 mm (0.1″) spaced solder pads or header pins.
## Pin Configuration
* **VBUS / 5V** : +5V power from USB
* **D-** : USB Data Negative
* **D+** : USB Data Positive
* **GND** : Ground
## Key Features
* Exposes standard **USB-A male pins** (VBUS, D+, D-, GND) to **easily solderable headers/pads**.
* Supports **5V power supply** for microcontrollers, sensors, and small electronics.
* Provides access to **USB data lines** for prototyping or debugging USB communication.
* **Compact and breadboard-friendly** design for DIY projects and enclosures.
* Eliminates the need to **cut and splice USB cables**, giving a clean, reliable connection.
* Can be used for **custom USB devices, IoT boards, and power distribution**.
## Applications
* Used in **industrial test benches** to power or interface microcontrollers and diagnostic tools via USB.
* Integrated into **control panels** for providing stable 5V supply to embedded modules or data-logging devices.
* Helps in **firmware flashing, debugging, and maintenance** of industrial controllers through USB access points.
* Utilized in **prototype development** for industrial IoT (IIoT) devices, sensors, and gateways.
* Used in **production line fixtures** where a reliable USB connector is needed for repeated plugging/unplugging.
- Ensure the USB port can safely supply the required 5V to avoid overheating or port damage.
- Never short VBUS (5V) to GND, as this can damage both the breakout and the USB source.
- Handle D+ and D- data lines carefully—long or loose wires can cause noise or communication errors.
- Use proper soldering and strain relief to prevent connector loosening or accidental pull-outs.
# USB-C
Source: https://learn.pcbcupid.com/documentation/modules/breakout-boards/usb-c
USB-C breakout board exposing power and data pins on a PCB to prototype custom USB-C devices, charging circuits, and data transfer projects.
A [USB-C](https://shop.pcbcupid.com/product/gb001/) breakout board provides easy access to the USB-C connector pins for power and data integration in embedded and prototyping projects. It simplifies development without directly soldering to a compact USB-C port.
## Pin Configuration
* **VBUS** : +5V power from USB-C
* **CC1** : Configuration Channel 1 (used for cable orientation and power negotiation)
* **CC2** : Configuration Channel 2 (used for cable orientation and power negotiation)
* **D+** : USB 2.0 Data Positive
* **D-** : USB 2.0 Data Negative
* **GND** : Ground
## Key Features
* Breaks out USB-C pins to standard headers.
* Supports power and data lines.
* Compact and easy-to-integrate design.
* Ideal for rapid prototyping.
## Applications
* Custom PCB development
* USB-powered embedded systems
* Charging and power delivery projects
* Testing USB-C functionality
- Ensure correct voltage and current ratings
- Verify CC pin configuration for proper power negotiation
- Avoid short circuits during prototyping
# SoundBox — DIY MP3 Player
Source: https://learn.pcbcupid.com/documentation/modules/g-kit/soundbox
DIY MP3 player called SoundBox using a Glyph ESP32 board, I2S audio codec, speaker, and SD card.
The G-Kit SoundBox is a standalone MP3 player kit built around the [Glyph Development Board](https://shop.pcbcupid.com/product-category/development-boards/) designed to capture the charm of a vintage boombox while showcasing the power and flexibility of modern modular electronics.

This project combines digital audio, intuitive UI design, and hands-on hardware interaction in one compact build. It's not a music player — it's an educational platform that teaches fundamentals of audio electronics, embedded programming, and system design.
**Learn Embedded Audio Design**
* **Audio Pipeline:** From MP3 decoding → I²S transmission → DAC/amplifier → speaker output.
* **I²S Audio Interface:** Learn how digital sound data flows from ESP32 to a dedicated audio chip.
* **Real-Time Feedback:** Track metadata, elapsed time, and progress sync instantly on OLED display.
* All within Arduino!
**Inspired by the Classics**
The SoundBox replicates the look and feel of a classic boombox, reimagined with modern components. Speaker and button placement mirror traditional stereo layouts.
## Key Features
### Audio Features
* MP3 / WAV Playback from SD card.
* Track Navigation: Next, Previous, Play, Pause.
* Non-blocking Audio Loop — keeps UI and buttons responsive.
* Track Metadata Handling: Displays song title and duration.
### Display & UI Features
* High-contrast OLED UI with U8g2lib.
* Track Info Screen: Title, total time, play/pause state.
* Volume Display (0–100%).
* UI Navigation System (prev/next/select).
### Controls
* 3 Physical Buttons (Prev, Play/Select, Next).
* Debounced Input using OneButton library.
* Volume control Range: 0–100%.
* UI & Player Sync — ensures displayed volume equals actual volume.
## Build Guide
Build your SoundBox! Follow each step in order — wiring, flashing firmware, assembling the case, and first power-on tests.
### Step 1: Hardware Required
#### Get Your Electronics Ready
| S. No. | Image | Component Name | Function |
| ------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------- | ----------------------------------- |
| 1 |  | [GLYPH](https://shop.pcbcupid.com/product/gd002/) | Main Microcontroller (C3 / C6 / S3) |
| 2 |  | GMOD-NAU8325 | I2S CODEC + 3W AMP |
| 3 |  | 1.3inch SH1106 OLED | Visual output |
| 4 |  | GMOD-MicroSD | Audio file storage |
| 5 |  | G-Kit Soundbox | Base board |
| 6 |  | 4Ohm 3W Speaker | Audio output |
| 7 |  | Battery | System power |
| 8 |  | Switch | Power control |
| 9 |  | Buttons | User input |
| 10 |  | Type C USB | USB connectivity |
#### Get Your 3D Printed Parts Ready
| S. No. | Image | Part Name | Function |
| ------ | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------ |
| 1 |  | [Soundbox-shell](https://shop.pcbcupid.com/product/gd002/) | Encloses entire circuit and speaker system |
| 2 |  | Heat-inserts | Added to soundbox shell |
| 3 |  | Custom Button Caps | Engraved functions on caps |
| 4 |  | Speaker-Mount | Speaker holder |
| 5 |  | Back-plate | Covers soundbox shell |
| 6 |  | Handle-holder | Attaches to soundbox shell |
### Step 2: Pin Configuration
Table shows how each module connects to the controller (assuming Glyph C6) internally on the G-Kit base board.
| Component | Function | GlyphC6 Pin (GPIO) |
| ---------------------- | ------------- | ------------------ |
| **SD Card** | CS | 17 |
| | MISO | 23 |
| | MOSI | 22 |
| | SCK | 21 |
| **Audio Codec (I²S)** | MCLK | 16 |
| | BCLK | 15 |
| | WS (LRCK) | 14 |
| | DOUT | 18 |
| **Buttons** | Previous | 3 |
| | Play / Select | 2 |
| | Next | 9 |
| **OLED Display (I²C)** | SDA | 4 |
| | SCL | 5 |
### Step 3: Circuit Diagram
Follow the circuit below to build the SoundBox yourself with a breadboard and jumpers, without needing the PCB.

### Step 4: Assembly
This section walks through complete assembly — from preparing components to final enclosure fitting.
Make sure to follow **Step 5** and **Step 6** for installation first. This ensures Glyph has necessary firmware to run SoundBox features and tests all electronics.
#### Start with the Buttons
Place the 3D printed button cap on top of G-MOD 3x1 Key Array. It won't snap-fit but works great without glue or adhesive.

The enclosure is printed to tight tolerances so components fit snugly. Before proceeding, check all mounting points and openings are clear of print residue.
The button array with the 3D printed cap will snap-fit on the extrusion to hold the button array in place.

Align mounting holes on the button array to snap-fit points on the enclosure. Guide the button so the header faces away from the soundbox.

Apply pressure on one side until mounting holes snap fit, then the other side.
The snap-fit may be very tight and can hold the button array firmly — difficult to remove once in place.

Double-check the button fits well and header pin faces toward you. This is critical as the G-Kit base board will access it.


#### Installing the Speakers
A 3D printed adapter holds the speaker to the enclosure.


Align the speaker adapter to mounting points on the enclosure. Repeat for both speakers.

Use M3 screws from the kit to fasten in place.

Ensure speaker wire connectors face toward the display for easier connection to the G-Kit base board.

#### Installing the OLED
Assemble the OLED with 10mm nylon standoff to hold it firmly to the PCB.
Connect the OLED display to the base board.
Align the OLED so standoffs install correctly. No bolt needed on the other side — the base board and 3D printed parts provide support.
#### Installing the Base Board
Once the display is placed, position the base board into the enclosure.

Ensure the header on top of the base board fits onto the button placed earlier.

Fasten in place using M2.5mm bolts.

Add the toggle button for power on/off.

Connect speaker and toggle switch connectors to the base board.
Apply double-sided tape to the battery to prevent movement inside the soundbox.
Place the battery as shown.

#### Installing the Audio CODEC
Place the audio codec module onto the G-Kit.

#### Installing the SD Card
Place an 8mm nylon spacer on the G-Kit PCB to support the GMOD-microSD.

Place the GMOD-microSD card module and check the SD card is accessible outside the box.

Insert the SD card with pre-loaded music into the SD-Card Module.

#### Installing the USB
Insert the Type C USB from outside.

Ensure it fits snugly in the groove made for the C-port on the 3D model.

Add 2mm bolts and nuts to the Type C USB port to hold it together with the 3D model.

Solder the wires to the GLYPH board (Black → GND, Red → USB).

Add the back panel to finish.

SoundBox after full assembly:

Toggle the switch to start!

After a few seconds the SoundBox boots up.

Navigate and select songs to play.

### Step 5: Code Setup
1. Open Arduino IDE.
2. Make sure to install required libraries.
3. Copy and paste the following code into the Arduino IDE.
The code is broken down into multiple files. Download from our [GitHub Repo](https://github.com/pcbcupid/soundpod/tree/main).
### Step 6: Upload the Code
1. **Connect the Board** — Connect your GLYPH board to your computer.
2. **Select the Board and Port**
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For `Pcbcupid Glyph C6` to appear under `Tools > Board > esp32`, the esp32 board version installed in Arduino IDE should be ≥ 3.1.0.
* `Tools > Port` — select the port connected to your GLYPH.
* `Tools > USB CDC on Boot` — **Enabled**
If `USB CDC on BOOT` is not enabled, you won't see serial data on Arduino IDE.
3. **Upload the Code** — Click the upload button (➡️) or use `CRTL + U` in Arduino IDE.
### Step 7: Observe the Output
**Expected Visual + Audio Behavior:**
* Music playback from SD card over I2S DAC.
* OLED UI with track title, duration, elapsed time, volume.
* Buttons for control (Prev / Play / Next / Vol Up / Vol Down).
* UI updates in sync with audio (progress bar, elapsed time).
# 1-Channel Relay
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/1-ch-relay
Wire a single-channel relay module to a Glyph ESP32 development board and toggle a high-voltage load on and off using an Arduino digital pin.
A **1-channel relay** module provides control for a single independent relay. This makes it ideal for controlling high-power loads using low-power control signals from microcontrollers like Arduino, [GLYPH](https://shop.pcbcupid.com/product-category/development-boards/), or even Raspberry Pi. Here's how it works:
### Components
* Relays: Relay can independently control a high-power (Both AC / DC) device.
* Control Pins: There is one input pin (IN) for controlling the relay.
* Power Supply: A single power source is used for the relays **5V**
* Protection: Has an optocoupler for electrical isolation between the control and relay circuits.
### Pin Configuration
* VCC: Power supply for the module (5V).
* GND: Ground connection.
* IN: Control signal for Relay 1.
* COM, NO, NC: Relay 1 switching terminals.
### Relay Contacts
* COM (Common): The input terminal.
* NO (Normally Open): Open by default, closes when the relay is activated.
* NC (Normally Closed): Closed by default, opens when the relay is activated.
### Working
* Each relay channel works independently, following the same principles as a single-channel relay:
* When Control Signal is LOW (0V):
The associated transistor remains off.
The corresponding relay coil is de-energized.
The relay's Normally Open (NO) contact stays open
* When Control Signal is HIGH (3.3V/5V):
The associated transistor turns on, allowing current to flow through the relay coil.
The coil energizes, creating a magnetic field that pulls the armature.
The relay's NO contact closes, completing the circuit for the connected load.
* Operation Sequence
* IN HIGH: Activates Relay to control the Load.
* IN LOW: Deactivates the relay, disconnecting the load.
### Applications
* Home Automation: Controlling lights and fans independently.
* Industrial Automation: Managing two separate devices or motors.
* DIY Projects: Operating appliances remotely with microcontroller-based projects.
This guide will help you interface a 1 Channel Relay assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview)(but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work)
## Step 1: Hardware Required
1. GLYPH-C3
2. GMOD-Single Channel Relay Module
3. Jumper Wires
4. Power Supply
5. AC Bulb
## Step 2: Circuit Diagram
Connect the relay module as follows:
Relay IN → GPIO8 (Control Pin)
Relay VCC → 3.3V or 5V (Check relay voltage requirement)
Relay GND → GND

## Step 3: Code Setup
```cpp theme={null}
#define RELAY_PIN 8 // GPIO pin connected to the relay's IN pin
void setup() {
pinMode(RELAY_PIN, OUTPUT); // Set the relay pin as an output
digitalWrite(RELAY_PIN, LOW); // Ensure relay is off initially
}
void loop() {
digitalWrite(RELAY_PIN, HIGH); // Turn relay ON (activate)
delay(2500); // Wait for 2.5 seconds
digitalWrite(RELAY_PIN, LOW); // Turn relay OFF (deactivate)
delay(2500); // Wait for 2.5 seconds
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` is not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output

The relay will turn ON for 2.5 seconds, then OFF for 2.5 seconds, and this cycle will repeat.
* Some relay modules are active LOW, meaning they turn ON when LOW and OFF when HIGH. If your relay behaves unexpectedly, try inverting the digitalWrite() logic.
* Ensure the relay's power rating matches the device you want to control.
* You may hear a clicking sound as the relay switches states.

# Audio Codec
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/audio-codec
Interface the NAU8325 digital input Class-D audio amplifier and codec module with a Glyph ESP32 board over I²S to generate sine waves and stream SD card audio.
The **NAU8325** is a highly efficient digital input Class-D audio amplifier designed by Nuvoton Technology Corporation. It is well-suited for compact and battery-powered devices, including portable speakers, IoT devices, tablets, and smart audio systems. It features integrated digital-to-analog conversion, eliminating the need for an external DAC and reducing system complexity.
## How it Works
The NAU8325 receives digital audio via the **I²S (Inter-IC Sound)** protocol, which transfers pulse-code modulated (PCM) data between the MCU and the amplifier.
**I²S Signals:**
* **BCLK (Bit Clock):** Synchronizes each individual bit of audio data.
* **LRCK / WS (Word Select):** Indicates whether the data is for the left or right channel.
* **SD (Serial Data):** The real-time, synchronized audio stream.
* **MCLK (Master Clock):** Optional high-frequency clock for advanced timing (not always required).
## Recommended Audio Format
To ensure compatibility with the NAU8325 and ESP32 hardware, use the following audio settings:
| Feature | Recommended Setting |
| :-------------- | :------------------- |
| **Format** | WAV or MP3 |
| **Sample Rate** | 44,100 Hz (Standard) |
| **Bit Depth** | 16-bit |
| **Channels** | Stereo or Mono |
Tools like [Audacity](https://www.audacityteam.org/) can be used to convert audio files to these formats before playback.
## Key Features & Applications
### Key Features
* **Efficiency**: High-efficiency Class-D output with digital volume control.
* **Simplicity**: Direct I²S input, reducing PCB space and system cost.
* **Streaming**: Supports real-time streaming, sine wave generation, and SD card playback.
* **Versatility**: Ideal for IoT audio, portable speakers, and digital amplifiers.
### Applications
* IoT audio notification and voice prompts
* Portable Bluetooth / Wi-Fi smart speakers
* Embedded audio playback and music players
* Educational kits and sound synthesizers
***
## Example 1: Sine Wave Generation
### Pin Configuration
| Pin (NAU8325) | Glyph Board | Description |
| :------------ | :---------- | :--------------------- |
| **WS** | GPIO 8 | I2S Word Select (LRCK) |
| **BCK** | GPIO 18 | I2S Bit Clock |
| **DATA** | GPIO 7 | I2S Serial Data |
| **MCK** | GPIO 19 | I2S Master Clock |
| **SCL** | GPIO 4 | I2C Clock |
| **SDA** | GPIO 5 | I2C Data |
### Step 1: Hardware Required
1. GLYPH Board
2. NAU8325 Module
3. Speaker
### Step 2: Circuit Diagram

### Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Install the required libraries:**
* Install **[AudioTools](https://github.com/pschatzmann/arduino-audio-tools)**
* Install **[PCBCUPID\_NAU8325](https://github.com/pcbcupid/PCBCUPID-NAU8325)**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
/**
* @file streams-generator-i2s.ino
* @author Phil Schatzmann
* @modified by Karthik E
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-stream/streams-generator-i2s/README.md
* @copyright GPLv3
*/
#include
#include "AudioTools.h"
#include "PCBCUPID_NAU8325.h" // install https://github.com/pcbcupid/PCBCUPID-NAU8325.git
AudioInfo info(44100, 2, 16);
SineWaveGenerator sineWave(32000); // subclass of SoundGenerator with max amplitude of 32000
GeneratedSoundStream sound(sineWave); // Stream generated from sine wave
I2SStream i2s;
StreamCopy copier(i2s, sound); // copies sound into i2s
// Use our NAU8325 codec configuration
TwoWire I2Cbus(0);
PCBCUPID_NAU8325 nau8325(I2Cbus);
void setup(void) {
// Open Serial
Serial.begin(115200);
while(!Serial);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// Initialize I2C for NAU8325
Serial.println("Checking I2C...");
I2Cbus.begin(4, 5);
delay(10);
// Initialize NAU8325 codec
if (!nau8325.begin()) {
Serial.println("NAU8325 init failed");
while (1);
}
nau8325.setVolume(0xFF, 0xFF); // Set max volume
Serial.println("NAU8325 detected and configured!");
// Start I2S
Serial.println("starting I2S...");
auto config = i2s.defaultConfig(TX_MODE);
config.pin_ws = 8;
config.pin_bck = 18;
config.pin_data = 7;
config.pin_mck = 19;
config.is_master = true;
config.use_apll = false;
config.i2s_format = I2S_STD_FORMAT;
config.copyFrom(info);
i2s.begin(config);
// Setup sine wave
sineWave.begin(info, N_B4);
Serial.println("started...");
}
// Arduino loop - copy sound to out
void loop() {
copier.copy();
}
```
### Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer.
2. **Select the Board and Port**
Do the following settings in your Arduino IDE:
* `Tools > Board > esp32 > Pcbcupid GLYPH`
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on Boot` is not enabled, you won't see any serial output in the Serial Monitor.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `Ctrl + U` in Arduino IDE to upload the code to the board.
### Step 5: Observe the Output
* You should hear a continuous sine wave tone from the speaker connected to the NAU8325 module.
***
## Example 2: SD Card Audio Playback
### Pin Configuration
| Peripheral | Signal | ESP32 GPIO Pin | Description |
| :------------ | :----- | :------------- | :--------------- |
| **SD Card** | SCK | GPIO 21 | SPI Clock |
| | MISO | GPIO 23 | SPI MISO |
| | MOSI | GPIO 22 | SPI MOSI |
| | CS | GPIO 19 | SPI Chip Select |
| **NAU8325** | SDA | GPIO 4 | I2C Data |
| | SCL | GPIO 5 | I2C Clock |
| **I2S Audio** | BCK | GPIO 6 | I2S Bit Clock |
| | WS | GPIO 8 | I2S Word Select |
| | DATA | GPIO 7 | I2S Serial Data |
| | MCLK | GPIO 20 | I2S Master Clock |
### Step 1: Hardware Required
1. GLYPH Board
2. NAU8325 Module
3. Speaker
4. SD Card Module
### Step 2: Circuit Diagram

### Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Install the required libraries:**
* Install **[AudioTools](https://github.com/pschatzmann/arduino-audio-tools)**
* Install **[PCBCUPID\_NAU8325](https://github.com/pcbcupid/PCBCUPID-NAU8325)**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include
#include
#include
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "PCBCUPID_NAU8325.h" // install https://github.com/pcbcupid/PCBCUPID-NAU8325.git
/* === Pin configuration === */
// SD Card configuration
#define MY_SCK 11
#define MY_MISO 3
#define MY_MOSI 2
#define MY_CS 1
// I2S (NAU8325) configuration
#define I2S_WS 24
#define I2S_BCK 25
#define I2S_DATA 23
#define I2S_MCLK 22
// === Audio settings ===
const uint32_t sample_rate = 44100; // sample_rate can be changed as per the song frequency (e.g. 48000, 32000, 16000, 8000, 96000, 12000, 64000)
const uint16_t ratio = 256; // ratio supported by NAU8325 (e.g. 256, 400, 500)
const uint8_t bits = 16; // bit depth (e.g. 16, 24, 32)
// === Objects ===
TwoWire I2Cbus(0);
PCBCUPID_NAU8325 nau8325(I2Cbus);
// Audio Stream Configuration
I2SStream i2s;
MP3DecoderHelix decoder;
EncodedAudioStream encodedStream(&i2s, &decoder);
StreamCopy copier;
File audioFile;
void setup() {
Serial.begin(115200);
delay(10);
Serial.println("=== NAU8325 SD EXAMPLE ===");
I2Cbus.begin(4, 5);
if (!nau8325.begin()) {
Serial.println("NAU8325 init failed");
while (1)
;
}
nau8325.setVolume(0xFF, 0xFF); // Setting NAU8325 at maximum volume
Serial.println("NAU8325 Turned ON");
// SD card initialization
SPI.begin(MY_SCK, MY_MISO, MY_MOSI, MY_CS);
if (!SD.begin(MY_CS)) {
Serial.println("SD card init failed");
while (1)
;
}
audioFile = SD.open("/Dwapara.mp3"); // Enter the MP3 song name from your SD card followed by "/" e.g.: "/music.mp3"
if (!audioFile || audioFile.isDirectory()) {
Serial.println("MP3 file not found");
while (1)
;
}
// I2S Config
auto config = i2s.defaultConfig(TX_MODE);
config.sample_rate = sample_rate;
config.bits_per_sample = bits;
config.channels = 2;
config.pin_bck = I2S_BCK;
config.pin_ws = I2S_WS;
config.pin_data = I2S_DATA;
config.pin_mck = I2S_MCLK;
config.i2s_format = I2S_STD_FORMAT;
config.use_apll = false;
i2s.begin(config);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
decoder.begin();
copier.begin(encodedStream, audioFile);
Serial.println("Playback started!");
}
void loop() {
if (!copier.copy()) {
// Sending empty values to auto turn off NAU8325
Serial.println("Playback done. Sending silence...");
int16_t zero = 0;
for (int i = 0; i < 2048 * 2; i++) {
i2s.write((uint8_t *)&zero, sizeof(zero));
}
while (1)
;
}
}
// ========== SD Card File Listing ==========
void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if (!root || !root.isDirectory()) {
Serial.println("Failed to open directory");
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print(" DIR : ");
Serial.println(file.name());
if (levels) listDir(fs, file.path(), levels - 1);
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
```
### Step 4: Upload the Code
1. **Prepare SD Card**
* Format the microSD card (FAT32 recommended).
* Save your MP3 file as `/Dwapara.mp3` on the SD card root directory.
* Insert the SD card into the SD card module.
2. **Connect the Board**
* Connect your GLYPH board to your computer.
3. **Select the Board and Port**
Do the following settings in your Arduino IDE:
* `Tools > Board > esp32 > Pcbcupid GLYPH`
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on Boot` is not enabled, you won't see any serial output in the Serial Monitor.
4. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `Ctrl + U` in Arduino IDE to upload the code to the board.
### Step 5: Observe the Output
* Open the Serial Monitor at **115200 baud**.
* The MP3 file stored on the SD card will play through the speaker connected to the NAU8325 module.
# DC-DC Boost Converter (SX1308)
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/dc-boost-converter
The GMOD SX1308 DC-DC Boost Converter is a high-frequency, high-efficiency step-up module that converts low input voltages (2V–24V) to higher output voltages (2V–28V).
The **GMOD SX1308 DC-DC Boost Converter** is a high-frequency (1.2MHz) step-up power module designed to efficiently convert lower input voltages into stable higher output voltages. Powered by the high-performance **SX1308** IC, this module is perfect for applications requiring compact, high-efficiency power management, such as driving 5V logic from a single 3.7V Li-ion battery or powering sensors in portable electronics.
Its small form factor and 95% peak efficiency make it an ideal choice for robotics, IoT devices, and DIY electronics projects where space and power conservation are critical.
***
## Product Variants
The GMOD Boost Converter is available in two distinct variants to suit different application needs:
1. **Fixed 5V Output**: Pre-configured to provide a steady **5V DC** output, making it a "plug-and-play" solution for powering microcontrollers and standard logic circuits.
2. **Variable Output**: Features an on-board potentiometer allowing you to manually adjust the output voltage anywhere from **2V to 28V**.
***
## Key Features
* **High-Frequency Operation**: Operates at **1.2MHz**, allowing the use of small external components (inductors/capacitors) for a more compact design.
* **High Efficiency**: Advanced synchronous rectification enables up to **95% efficiency**.
* **Stable Performance**: Delivers low ripple and noise for sensitive electronic circuits.
* **Wide Input/Output Range**: Versatile enough for a variety of battery-powered and industrial applications.
* **Integrated Protections**: Includes thermal shutdown and over-current protection.
***
## Technical Specifications
| Parameter | Operating Range |
| :---------------------------- | :-------------- |
| **Input Voltage (V\_IN)** | 2.0V – 24.0V DC |
| **Output Voltage (V\_OUT)** | 2.0V – 28.0V DC |
| **Integrated Switch Current** | 2.0A |
| **Switching Frequency** | 1.2 MHz |
| **Peak Efficiency** | Up to 95% |
| **Internal Resistance** | 100mΩ (Typical) |
***
## Pin Configuration
| Pin Name | Description |
| :-------------- | :---------------------------------------------- |
| **V+ (Input)** | Positive rail of the input supply (2V to 24V) |
| **V- (Input)** | Negative rail (Ground) of the input supply |
| **V+ (Output)** | Boosted positive rail of the output (2V to 28V) |
| **V- (Output)** | Common Ground for the output rail |
***
## Applications
* **Battery Up-Regulation**: Steps up 3.7V Lithium-ion/Li-Polymer battery voltage to 5V to power microcontrollers and sensors.
* **Robotics & IoT**: Provides compact, efficient step-up voltage management in space-constrained layouts.
* **Portable Electronics**: Driving LED arrays, displays, and other modules requiring stable higher voltages from lower battery sources.
***
## Step 1: Hardware Required
1. GMOD Boost Converter (Fixed or Variable)
2. Input Source (e.g., 3.7V Battery or 12V supply)
3. Multimeter (for Variable variant calibration)
4. Load (e.g., LED, Sensor, or Microcontroller)
***
## Step 2: Circuit Connection
Connect the input source to the **V+ (Input)** and **V- (Input)** terminals. For the variable variant, it is recommended to adjust the potentiometer **before** connecting your final load.

***
## Step 3: Observe the Output
Once powered, the module will boost the input voltage.
* **For Fixed 5V**: The output will measure approximately 5V regardless of the input (provided V\_IN \< 5V).
* **For Variable**: Use a multimeter on the output terminals and slowly rotate the potentiometer to set your desired voltage level.

**Boost Ratio Limit**: The SX1308 is a step-up converter; the input voltage should always be **lower** than the desired output voltage for proper operation. Ensure your load does not exceed the 2A internal switch current limit.
* **Potentiometer**: If the output voltage does not change on first use, you may need to rotate the potentiometer **counter-clockwise** for several turns (often 10-20 turns) to begin seeing a reduction or increase.
* **Logic Level Power**: If you are powering a microcontroller from a 3.7V battery, the Fixed 5V variant ensures the logic stays stable even as the battery voltage drops.
# DC-DC Buck Converter (SY81103)
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/dc-buck-converter
The SY81103 DC-DC Buck Converter is a high-efficiency module that steps down input voltage (9V–18V) to a stable 3.3V, 5V, or an adjustable range for electronic devices.
The **SY81103 DC-DC Buck Converter** is a compact, high-efficiency power conversion module designed to reduce a higher input voltage to a stable lower output voltage. Built around the **SY81103** synchronous step-down IC, it ensures minimal power loss and high performance, making it ideal for battery-powered and industrial applications.
***
## Product Variants
To accommodate different system requirements, this module is available in three distinct variants:
1. **Fixed 3.3V Output**: Pre-configured to provide a steady 3.3V DC output.
2. **Fixed 5V Output**: Pre-configured to provide a steady 5V DC output.
3. **Variable Output**: Features an adjustable output range from **1.2V to 5V** using an onboard potentiometer.
***
## Key Features
* **SY81103 High-Efficiency IC**: Synchronous rectification technology for cool operation.
* **Wide Input Range**: Supports input voltages from **9V to 18V**.
* **High Load Capacity**: Delivers up to **3A** output current.
* **Stable 500kHz Frequency**: Ensures low ripple and high efficiency.
* **Protection**: Includes cycle-by-cycle current limit and thermal shutdown.
* **Compact G-Mod Footprint**: Designed to fit seamlessly onto Glyph development boards.
***
## Technical Specifications
| Parameter | Operating Range |
| :-------------------------- | :-------------------------------------------- |
| **Input Voltage (V\_IN)** | 9.0V – 18.0V DC |
| **Output Voltage (V\_OUT)** | 1.2V – 5.0V DC (Variable) / 3.3V & 5V (Fixed) |
| **Output Current** | Up to 3.0A |
| **Switching Frequency** | 500 kHz |
| **Peak Efficiency** | Up to 95% |
| **Integrated IC** | SY81103 |
***
## Pin Configuration
The module features input and output terminal blocks for easy integration:
**Left Side – INPUT**
* **VIN (+)** → DC Input Supply (**9V – 18V**)
* **GND (–)** → DC Input Ground
**Right Side – OUTPUT**
* **VOUT (+)** → Regulated DC Output (**3.3V / 5V / 1.2V–5V**)
* **GND (–)** → Output Ground
***
## Applications
* **IoT & Sensors**: Powers microcontrollers and sensors from 12V batteries.
* **Industrial Automation**: Provides stable control-line power in noisy environments.
* **Automotive Electronics**: Regulates 12V vehicle power for sensitive electronics.
* **Battery Management**: Efficiently steps down Li-ion battery pack voltages (3S/4S).
* **Prototyping**: Ideal for breadboard and custom PCB power distribution.
Please ensure you choose the correct variant (Fixed or Variable) based on your specific application needs.
***
## Step 1: Hardware Required
1. SY81103 DC–DC Buck Converter Module (Variant-specific)
2. DC Power Supply (9V – 18V)
3. Multimeter (for Variable variant calibration)
4. Jumper Wires / Connecting Wires
***
## Step 2: Circuit Connection
Connect the input source to the input terminals. For the variable variant, it is recommended to adjust the potentiometer **before** connecting your final load.
Ensure the input polarity is correct before powering the module. Reverse polarity can permanently damage the SY81103 IC.

***
## Step 3: Observe the Output
1. **Verify Input**: Use a multimeter to confirm your input voltage is within the **9V–18V** range.
2. **Set Output (Variable Variant Only)**: Rotate the onboard potentiometer until the desired voltage (e.g., 3.3V or 5V) is reached.
3. **Confirm Stability**: Check that the output remains stable even when the load is connected.
4. **Thermal Check**: The module is designed for low heat generation, but ensure adequate airflow if drawing the full 3A current for extended periods.
# Key Array
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/key-array
1×3 and 1×6 Push Button Module is a compact board with three independent tactile switches for providing digital input to microcontrollers.
The **1×3 Push Button Module** is a simple input device that combines three tactile switches on a single board. It allows users to give manual digital inputs (ON/OFF signals) to a microcontroller. Each button works independently, making the module suitable for menu navigation, mode selection, or basic control functions in embedded projects.
### Pins Configuration
* VCC – Power supply (3.3V or 5V).
* GND – Ground.
* OUT1 – Digital signal from Button 1.
* OUT2 – Digital signal from Button 2.
* OUT3 – Digital signal from Button 3.
### Key Features
* Three independent push buttons on a single module.
* Designed with clear labeling for Button 1, Button 2, Button 3.
* Each button typically connected with a pull-down/pull-up resistor (depending on design).
* Standard 4-pin/5-pin header for easy interfacing.
### Applications
* Menu navigation (Up/Down/Select).
* Multi-option input control.
* Mode/Function selector in DIY electronics.
* Robotics control panels.
* Educational and prototyping projects.
### Step 1: Hardware Required
1. Glyph Boards
2. 1×3 Push Button Module
### Step 2: Circuit Diagram

### Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
// Define pins (each button shares the same pin as its LED)
int ledButton1 = 6;
int ledButton2 = 10;
int ledButton3 = 7;
void setup() {
Serial.begin(9600);
}
void loop() {
// --- Button 1 ---
pinMode(ledButton1, INPUT);
int state1 = digitalRead(ledButton1);
if (state1 == HIGH) {
Serial.println("Button 1 pressed → LED1 ON");
pinMode(ledButton1, OUTPUT);
digitalWrite(ledButton1, HIGH);
} else {
Serial.println("Button 1 not pressed → LED1 OFF");
pinMode(ledButton1, OUTPUT);
digitalWrite(ledButton1, LOW);
}
// --- Button 2 ---
pinMode(ledButton2, INPUT);
int state2 = digitalRead(ledButton2);
if (state2 == HIGH) {
Serial.println("Button 2 pressed → LED2 ON");
pinMode(ledButton2, OUTPUT);
digitalWrite(ledButton2, HIGH);
} else {
Serial.println("Button 2 not pressed → LED2 OFF");
pinMode(ledButton2, OUTPUT);
digitalWrite(ledButton2, LOW);
}
// --- Button 3 ---
pinMode(ledButton3, INPUT);
int state3 = digitalRead(ledButton3);
if (state3 == HIGH) {
Serial.println("Button 3 pressed → LED3 ON");
pinMode(ledButton3, OUTPUT);
digitalWrite(ledButton3, HIGH);
} else {
Serial.println("Button 3 not pressed → LED3 OFF");
pinMode(ledButton3, OUTPUT);
digitalWrite(ledButton3, LOW);
}
delay(100);
}
```
### Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
### Step 5: Observe the Output
***
The **1×6 Key Array Module** is a compact input device that integrates six tactile switches on a single board. Unlike individual digital buttons, this module uses a resistor network to generate distinct analog voltage levels for each key. When a button is pressed, the microcontroller reads a specific analog value, allowing it to identify which key was selected through a single analog input pin. This makes the module efficient for menu navigation, option selection, and multi-button control in embedded systems while minimizing the number of GPIO pins required.
### Pins Configuration
* VCC - Power supply (3.3V / 5V)
* GND - Ground
* KEY (Analog Output) – Analog signal representing the pressed button
### Key Features
* Six tactile switches on a single board
* Single analog output (KEY pin) for detecting all buttons
* Resistor ladder network design reduces GPIO usage
* Compatible with 3.3V and 5V microcontrollers
* Compact and easy-to-interface module
* Cost-effective solution for multi-button input systems
### Applications
* Menu navigation systems
* Mode selection in embedded devices
* Human–Machine Interface (HMI) controls
* IoT device configuration panels
* DIY electronics and prototyping projects
* Educational learning kits for ADC-based input handling
### Step 1: Hardware Required
1. Glyph Boards
2. 1×6 Push Button Module
### Step 2: Circuit Diagram

### Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#define KEY_PIN A2 // Analog pin
void setup() {
Serial.begin(115200);
}
// Detect button from ADC value
int getButtonFromAnalog(int val) {
if (val > 4000) return -1; // No button pressed
else if (val < 200) return 1; // K1 (around 20)
else if (val < 2700) return 2; // K2 (around 2269)
else if (val < 3200) return 3; // K3 (around 3034)
else if (val < 3600) return 4; // K4 (around 3440)
else if (val < 3800) return 5; // K5 (around 3704)
else return 6; // K6 (around 3880)
}
void loop() {
int analogValue = analogRead(KEY_PIN);
int button = getButtonFromAnalog(analogValue);
if (button != -1) {
Serial.print("Button ");
Serial.print(button);
Serial.println(" pressed");
delay(300); // debounce
}
}
```
### Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
### Step 5: Observe the Output
# Limit Switch Module
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/limit-switch
Use the G-Mod limit switch module to detect mechanical end-of-travel positions and trigger digital inputs on a Glyph ESP32 microcontroller board.
A **limit switch** is an electromechanical device used to detect the presence, absence, or position of an object. It operates by physical contact: when an object moves into a predefined position, it actuates the switch, opening or closing an electrical circuit. Limit switches are widely used in industrial machinery, automation systems, and safety devices to control movement, prevent over-travel, and provide position feedback.
## Pin Configuration
* S - SIGNAL
* G - GND
* V - VCC
## Key Features
* Mechanical or electromechanical operation for detecting position or motion
* Durable and reliable for repeated actuation
* Variety of actuator types: lever, roller, plunger, whisker, etc.
* Normally Open (NO) and Normally Closed (NC) contacts for flexible circuit design
* Wide voltage and current handling depending on model
* Compact and robust design suitable for industrial environments
## Applications
* Industrial Machinery – detects the end of travel of moving parts
* Conveyor Systems – position sensing and item detection
* Robotics & Automation – motion control and position feedback
* Safety Interlocks – prevents machine over-travel or unsafe operation
* Elevators & Lifts – detects door positions and travel limits
* CNC Machines – homing switches for axes
We have 2 variant's of the limit switch, one is GLYPH compatible (in terms of dimension) and the other one is generic. Please choose the variant based on the size and the direction fo the switch! otherwise both of them are electrically same.
## Step 1: Hardware Required
1. Glyph Boards
2. Limit Switch
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#define LIMIT_SWITCH_PIN 2 // Use the GPIO pin you're connecting the limit switch to
void setup() {
Serial.begin(115200);
pinMode(LIMIT_SWITCH_PIN, INPUT_PULLUP); // Enable internal pull-up resistor
}
void loop() {
int switchState = digitalRead(LIMIT_SWITCH_PIN);
// When pressed, switchState will be LOW (0), otherwise HIGH (1)
if (switchState == LOW) {
Serial.println("1"); // Pressed
} else {
Serial.println("0"); // Not pressed
}
delay(100); // Small delay to prevent flooding the serial monitor
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
The Serial Monitor output will be a stream of 1s and 0s depending on the state of the limit switch:
* 1 → Limit switch is pressed/activated (circuit closed, GPIO reads LOW)
* 0 → Limit switch is not pressed (circuit open, GPIO reads HIGH)

# Lithium Charger
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/lithium-charger
The G-Mod Lithium Charger safely charges 1S (3.7V) and 2S (7.4V) lithium-ion batteries with adjustable current settings for portable projects.
A **lithium charger** is a versatile power management module used to safely charge either a single (1S) or double (2S) lithium-ion battery pack. It employs the Constant Current / Constant Voltage (CC/CV) method to ensure maximum battery life and safety. This module is ideal for robotics, portable electronics, and any application requiring reliable battery recharging.
\`
***
## ⚙️ Charging Mode Configuration
The module can be configured for two different battery types by modifying a hardware solder point on the board labeled **2S**.
### 1. Mode Selection
* **1S Mode (3.7V / 4.2V Full)**: Leave the **2S** solder point **OPEN** (default).
* **2S Mode (7.4V / 8.4V Full)**: **SHORT** (solder) the **2S** point to select 2S charging.
### 2. Input Voltage Requirements
To ensure proper charging, your input power supply must meet the following minimums:
* **1S Mode**: 5.0V – 18V DC input.
* **2S Mode**: 10V – 18V DC input (12V recommended).
***
## 🔌 Pin Configuration
* **IN+** – DC Power Input Positive
* **GND** – DC Power Input Ground
* **B+** – Battery Positive Terminal
* **B−** – Battery Negative Terminal
* **G** – Ground
* **NTC** – Temperature sensor input
* **LED+** – LED Positive (for external status)
* **CHR** – Charging status output (Red LED)
* **STB** – Standby / Full status output (Blue/Green LED)
***
## 🚀 Key Features
* **Dual Mode Support**: Charges 1S (3.7V) and 2S (7.4V) packs.
* **High Current Rating**: Supports up to **2A** default charging current.
* **Adjustable Current**: The charging current can be varied by changing the **current limiting resistors** on the board.
* **CC/CV Charging**: Automatic transition from constant current to constant voltage.
* **Status Monitoring**: Dedicated pins for external status LEDs.
* **Safety**: Includes overcharge protection and NTC temperature sensing support.
***
## 🛠️ Step 1: Hardware Required
1. G-MOD Lithium Charger Module (GM014)
2. Lithium-ion Battery:
* **1S**: 3.7V Cell
* **2S**: 7.4V Battery Pack
3. DC Power Supply (5V for 1S, 12V for 2S)
4. Connecting Wires
5. Screwdriver (for terminal connections)
***
## ⚡ Step 2: Circuit Connection
> \[!IMPORTANT]
> Always verify the **2S** solder point configuration before connecting your battery. Connecting a 1S battery while the board is in 2S mode will damage the battery.

***
## 📊 Step 3: Observe the Output
Once connected, the **CHR** pin will pull low to indicate charging is active. Once the battery reaches its target voltage (**4.2V for 1S** or **8.4V for 2S**), the **STB** pin will trigger to signal a full charge.
* **Current Limiting**: If you need to charge smaller batteries, replace the surface-mount current-sensing resistors to lower the 2A output to a safer level for your specific cells.
# MCP79412 RTC
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/mcp79412-rtc
MCP79412 RTC module with I²C, battery backup, alarms, and memory. Ideal for accurate timekeeping in Arduino, Raspberry Pi, and IoT projects.
The **MCP79412** from Microchip Technology is a low-power, I²C-based real-time clock/calendar (RTCC) with integrated EEPROM, SRAM, and a unique ID. It provides highly accurate timekeeping (seconds, minutes, hours, day, date, month, year) and includes alarm functions, power-fail timestamping, and battery backup support, making it ideal for applications that require reliable time and date tracking.
Check the back of the RTC module: modules marked **“M”** use the ***MCP79412***, while those marked **“P”** use the ***PCF8563***.
## Pin Configuration
* VCC → VCC
* GND → GND
* CLK → SCK / Any GPIO
* SDA → SDA
* SCL → SCL
* B → No connection / Internally connected to the 3V battery
Install a 3V Lithium Cell (CR1220) on the RTC module to retain time when the main circuit is powered off. The module can also operate without a battery if the circuit remains powered.
## Key Features
* I²C Interface (400 kHz Fast Mode)
* Timekeeping: seconds, minutes, hours, day, date, month, year with leap year compensation
* Two Alarms with programmable match options
* Battery Backup with automatic switchover
* Power-Fail Timestamp (records time of power loss)
* 64 Bytes SRAM + 1 Kbit EEPROM (non-volatile storage)
* Unique 64-bit ID (factory-programmed)
* Digital Trimming for oscillator accuracy adjustment
* Operating Voltage: 1.8V – 5.5V
* Temperature Range: −40 °C to +85 °C (industrial)
## Applications
* Data loggers and metering systems
* Security and access control devices
* Consumer electronics (appliances, clocks, timers)
* Automotive time-stamping and scheduling
* Embedded systems requiring alarms, scheduling, or backup timekeeping
## Step 1: Hardware Required
1. Glyph Boards
2. GMOD MCP79412 RTC
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
// You can downlaod PCBCUPID_MCP79412 from here https://github.com/pcbcupid/PCBCUPID-MCP79412
#include
#include "PCBCUPID_MCP79412.h"
#include
PCBCUPID_MCP79412RTC rtc;
tmElements_t tm;
// Helper to read an integer cleanly from Serial, flushing leftover chars
int readIntFromSerial() {
while (!Serial.available()) {
delay(10);
}
int val = Serial.parseInt();
while (Serial.available()) Serial.read(); // flush
return val;
}
void setup()
{
Serial.begin(115200);
delay(1000);
Serial.println(F("\r\n=======PCBCUPID_MCP79412 RTC Test Menu ==========\r\n"));
Serial.println(F("0: Wire.begin() default pins\r\n1: Wire.begin(sda,scl,clockFreq)\r\n2: Wire.begin(TwoWire*)"));
Serial.println(F("Type 0-2 to select I2C init mode....."));
uint8_t mode =
readIntFromSerial();
// These are different way's to initialize the I2C of RTC module
switch (mode)
{
case 0:
rtc.begin();
Serial.println(F(">>>Wire.begin() with default pins\r\n"));
break;
case 1:
rtc.begin(4, 5, 400000); // ESP32 based glyph default SDA/SCL
Serial.println(F(">>>Wire.begin(4,5,400kHz)\r\n"));
break;
case 2:
rtc.begin(&Wire);
Serial.println(F(">>>Wire.begin() using custom Twowire instance\r\n"));
break;
default:
Serial.println(F("Invalid Input, using default Wire.begin()\r\n"));
Wire.begin();
}
Serial.println(F("**********RTC Function Modes*************"));
Serial.println(F("3. Set RTC using setTime() + now()"));
Serial.println(F("4. Set RTC using tmElements_t"));
Serial.println(F("5: Set RTC using compile time"));
Serial.println(F("Type 3-5 to select RTC mode..."));
mode = readIntFromSerial();
// below are the different mode to setup the time for the RTC module
switch (mode)
{
case 3:
setTime(3, 43, 45, 20, 5, 2025); // HH, MM, SS, DD, MM, YYYY
rtc.set(now());
Serial.println(F(">> RTC set using setTime() + now()\r\n"));
break;
case 4:
tm.Hour = 23;
tm.Minute = 31;
tm.Second = 30;
tm.Year = 2009 - 1970;
tm.Month = 5;
tm.Day = 20;
tm.Wday = dowTuesday;
rtc.write(tm);
Serial.println(F(">> RTC set using tmElements_t structure\r\n"));
break;
case 5:
setTime(compileTime());
rtc.set(now());
Serial.println(F(">> RTC set using sketch compile time\r\n"));
break;
default:
Serial.println(F("Invalid RTC mode, terminating.\r\n"));
while (true)
;
}
delay(500);
}
void loop()
{
Serial.println(F("\r\n--- Current Time ---"));
printTime(now());
if (rtc.read(tm))
{
Serial.print(F("RTC tmElements_t: "));
Serial.print(tm.Hour); Serial.print(':');
printI00(tm.Minute, ':');
printI00(tm.Second, ' ');
Serial.print(tm.Year + 1970);
Serial.print('/');
Serial.print(tm.Month);
Serial.print('/');
Serial.println(tm.Day);
}
else
{
Serial.println(F("Failed to read RTC time using .read()"));
}
delay(3000);
}
void printTime(time_t t)
{
printI00(hour(t), ':');
printI00(minute(t), ':');
printI00(second(t), ' ');
Serial.print(dayShortStr(weekday(t)));
Serial.print(' ');
printI00(day(t), ' ');
Serial.print(monthShortStr(month(t)));
Serial.print(' ');
Serial.println(year(t));
}
void printI00(int value, char delimiter)
{
if (value < 10)
Serial.print('0');
Serial.print(value);
Serial.print(delimiter);
}
time_t compileTime()
{
const char *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char monthstr[4];
tmElements_t tm;
strncpy(monthstr, __DATE__, 3);
monthstr[3] = '\0';
tm.Month = (strstr(months, monthstr) - months) / 3 + 1;
tm.Day = atoi(__DATE__ + 4);
tm.Year = atoi(__DATE__ + 7) - 1970;
char buf[3];
memcpy(buf, __TIME__, 2);
buf[2] = '\0';
tm.Hour = atoi(buf);
memcpy(buf, __TIME__ + 3, 2);
buf[2] = '\0';
tm.Minute = atoi(buf);
memcpy(buf, __TIME__ + 6, 2);
buf[2] = '\0';
tm.Second = atoi(buf);
return makeTime(tm) + 15; // fudge factor
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
The RTC module tracks time independently. With the onboard 3V Lithium Cell (CR1220), it continues timekeeping even when the GLYPH is powered off.

# Dual Motor Driver
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/motor-driver
The G-Mod TB6612FNG dual motor driver controls two DC motors via an integrated dual H-bridge IC for efficient bidirectional speed and direction control.
The **GMOD TB6612FNG Dual Motor Driver** is a high-efficiency power control module designed to drive up to two DC motors or one bipolar stepper motor. Built around the advanced **TB6612FNG** dual H-bridge IC, it provides superior efficiency and lower heat generation compared to older drivers like the L298N.
This module allows for precise bidirectional control (Forward/Reverse) and speed regulation using PWM signals, making it an essential component for robotics, automated vehicles, and high-performance embedded systems.
***
## Key Features
* **Dual Channel Control**: Independently drives two DC motors or one bipolar stepper motor.
* **High Efficiency**: MOSFET-based H-bridge design for minimal voltage drop and low heat.
* **Built-in Protection**: Includes over-current protection, thermal shutdown, and low-voltage detection.
* **Standard Control Logic**: Compatible with most microcontrollers via PWM and simple direction pins.
* **Compact G-Mod Format**: Plugs directly into Glyph development boards.
***
## Technical Specifications
| Parameter | Operating Range |
| :-------------------------- | :------------------------------ |
| **Motor Supply (VM)** | 2.5V – 13.5V DC |
| **Logic Supply (VCC)** | 2.7V – 5.5V DC |
| **Output Current** | 1.2A (Continuous) / 3.2A (Peak) |
| **Switching Frequency** | Up to 100 kHz (PWM) |
| **Internal MOSFET RDS(on)** | 0.5Ω (Typical) |
***
## Pin Configuration
The module features a standard interface for motor power and control:
| Pin Name | Description |
| :-------------- | :-------------------------------------------------------- |
| **VCC** | Logic Logic Power (3.3V / 5V) |
| **GND** | Ground (Common for Logic and Power) |
| **VM** | External Motor Power Source (2.5V – 13.5V) |
| **STBY** | Standby Control (**HIGH** = Enable, **LOW** = Power Down) |
| **AIN1 / AIN2** | Direction Control inputs for Motor A |
| **PWMA** | PWM input for Speed Control of Motor A |
| **BIN1 / BIN2** | Direction Control inputs for Motor B |
| **PWMB** | PWM input for Speed Control of Motor B |
| **AO1 / AO2** | Output terminals for Motor A |
| **BO1 / BO2** | Output terminals for Motor B |
***
## H-Bridge Control Logic
Both channels (A and B) follow the same truth table for controlling movement:
| STBY | IN1 | IN2 | PWM | Output (O1 / O2) | Motor Mode |
| :------- | :------- | :------- | :------- | :--------------- | :---------------- |
| **LOW** | X | X | X | High-Z | **Standby (OFF)** |
| **HIGH** | **HIGH** | **LOW** | **HIGH** | H / L | **Forward** |
| **HIGH** | **LOW** | **HIGH** | **HIGH** | L / H | **Reverse** |
| **HIGH** | **HIGH** | **HIGH** | X | L / L | **Short Brake** |
| **HIGH** | **LOW** | **LOW** | X | High-Z | **Stop (Coast)** |
***
## Step 1: Hardware Required
1. GMOD TB6612FNG Motor Driver
2. [GLYPH (ESP32-S3 / C3 / C6)](https://shop.pcbcupid.com/product-category/development-boards/)
3. 2x DC Motors
4. External Battery Pack (e.g., 7.4V Li-ion or 12V LiPo)
***
## Step 2: Circuit Connection
Connect the driver to your Glyph board following the GPIO definitions provided in your specific code example.

Always ensure the **VM (Motor Power)** and **VCC (Logic Power)** are not swapped, and that they share a common Ground (GND). Reversing polarity on VM can damage the TB6612FNG IC.
***
## Step 3: Code Setup
* **I2C Conflict**: GPIO 5 is the default **SCL** pin for I2C communication across the entire **GLYPH series (C3, C6, and S3)**. If you are using I2C sensors via the GLINK port, change the `STBY` pin in the code to an alternative digital pin (e.g., GPIO 6 or 14) to avoid communication conflicts.
* **Standby vs. Coast**: Setting `STBY` to `LOW` puts the driver in **Standby** (Power Down). For a true **Coast** stop where the motor spins freely, keep `STBY` HIGH and set both `AIN1` and `AIN2` to `LOW`.
```cpp theme={null}
// Mapping pins for TB6612FNG
const int STBY = 5; // Standby pin
const int AIN1 = 18; // Motor A Direction 1
const int AIN2 = 19; // Motor A Direction 2
const int PWMA = 21; // Motor A Speed (PWM)
void setup() {
pinMode(STBY, OUTPUT);
pinMode(AIN1, OUTPUT);
pinMode(AIN2, OUTPUT);
pinMode(PWMA, OUTPUT);
// Enable the driver
digitalWrite(STBY, HIGH);
}
void loop() {
// Move Forward at half speed
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, LOW);
analogWrite(PWMA, 127); // Range 0-255
delay(2000);
// Stop (Short Brake)
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, HIGH);
delay(1000);
// Reverse at full speed
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
analogWrite(PWMA, 255);
delay(2000);
// Coast Stop
digitalWrite(STBY, LOW); // Disable driver
delay(1000);
digitalWrite(STBY, HIGH); // Re-enable
}
```
***
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer via USB.
2. **Select the Board and Port**
In the Arduino IDE:
* Select `Tools > Board > esp32 > Pcbcupid GLYPH`.
* Select `Tools > Port` and choose the port connected to your board.
* Ensure `Tools > USB CDC on Boot` is set to **Enabled**.
3. **Upload**
* Click the **Upload** button (or press `CTRL + U`) to compile and flash the code.
***
## Step 5: Observe the Output
Once the code is uploaded, the connected motors should rotate forward for 2 seconds, brake briefly, and then reverse for 2 seconds before coasting to a stop.
* **STBY Pin**: Remember that the STBY pin must be pulled **HIGH** for the motor driver to respond to any commands.
* **Common Ground**: Ensure the external motor power supply Ground is connected to the microcontroller Ground.
* **Thermal Check**: While the TB6612FNG is efficient, it may become warm when driving heavy loads. Ensure proper ventilation.
# PCF8563 Real-Time Clock Module
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/pcf8563-rtc
PCF8563 RTC module with I2C interface for precise timekeeping. Ideal for Arduino, ESP32, and low-power embedded projects needing wake-up alarms.
The **PCF8563** is a low-power CMOS real-time clock/calendar (RTC) IC with an I²C-bus interface from NXP. It keeps track of time and date, including seconds, minutes, hours, days, months, years, and has programmable alarms and timers.
Check the back of the RTC module: modules marked **“M”** use the ***MCP79412***, while those marked **“P”** use the ***PCF8563***.
It is widely used in embedded systems, IoT devices, and portable electronics because of its ultra-low power consumption and accuracy.
The PCF8563 RTC is a low-power, I²C-based real-time clock with alarms and timers, ideal for keeping accurate time in embedded systems and low-power applications.
## Pin Configuration
* VCC → VCC
* GND → GND
* CLK → SCK / Any GPIO
* SDA → SDA
* SCL → SCL
* I → Any GPIO / Can be used as interrupt
## Key Features
* I²C (2-wire) communication interface (up to 400 kHz Fast Mode).
* Additional RTC function:
* Seconds, minutes, hours, days, weekdays, months, years.
* Automatic leap year correction (up to year 2099).
* Programmable clock output (32.768 kHz, 1 Hz, etc.).
* Two independent alarms (daily/weekly programmable).
* Countdown timer with interrupt capability.
* Ultra-low operating current (typically \< 1 µA in time-keeping mode).
* Operating voltage: 1.0V – 5.5V (suitable for battery operation)
## Applications
* IoT devices (timestamping sensor data).
* Clocks, watches, and portable devices.
* Data loggers.
* Industrial control and automation.
* Energy meters.
* Battery-powered embedded systems.
## Step 1: Hardware Required
1. Glyph Boards
2. GMOD PCF8563-RTC
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include
PCF8563 pcf;
void setup() {
Serial.begin(9600);
pcf.init();//initialize the clock
pcf.stopClock();//stop the clock
//set time to to 31/3/2018 17:33:0
pcf.setYear(18);//set year
pcf.setMonth(3);//set month
pcf.setDay(31);//set dat
pcf.setHour(17);//set hour
pcf.setMinut(33);//set minut
pcf.setSecond(0);//set second
pcf.startClock();//start the clock
}
void loop() {
Time nowTime = pcf.getTime();//get current time
//print current time
Serial.print(nowTime.day);
Serial.print("/");
Serial.print(nowTime.month);
Serial.print("/");
Serial.print(nowTime.year);
Serial.print(" ");
Serial.print(nowTime.hour);
Serial.print(":");
Serial.print(nowTime.minute);
Serial.print(":");
Serial.println(nowTime.second);
delay(1000);
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
The RTC module tracks time independently. With the onboard 3V Lithium Cell (CR1220), it continues timekeeping even when the GLYPH is powered off.

# 2-Channel Relay
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/relay
Wire the G-Mod 2-channel relay module to a Glyph ESP32 development board and switch two independent high-voltage loads from Arduino digital pins.
A **2-channel relay** for controlling two independent high-power loads simultaneously using low-power control signals from microcontrollers like Arduino, [GLYPH](https://shop.pcbcupid.com/product-category/development-boards/), or even Raspberry Pi. Here's how it works:
### Components
* Two Relays: Each relay can independently control a high-power (Both AC / DC) device.
* Control Pins: There are two input pins (IN1 and IN2) for controlling each relay.
* Power Supply: A single power source is used for both relays **5V**
* Protection : Has 2 Optocoupler to electrical isolation between the control and relay circuits for both channels.
### Pin Configuration
* VCC: Power supply for the module (5V).
* GND: Ground connection.
* IN1: Control signal for Relay 1.
* IN2: Control signal for Relay 2.
* COM1, NO1: Relay 1 switching terminals.
* COM2, NO2: Relay 2 switching terminals.
### Relay Contacts
* COM (Common): The input terminal.
* NO (Normally Open): Open by default, closes when the relay is activated.
### Working
* Each relay channel works independently, following the same principles as a single-channel relay:
* When Control Signal is LOW (0V):
The associated transistor remains off.
The corresponding relay coil is de-energized.
The relay's Normally Open (NO) contact stays open, and the Normally Closed (NC) contact remains closed.
* When Control Signal is HIGH (3.3V/5V):
The associated transistor turns on, allowing current to flow through the relay coil.
The coil energizes, creating a magnetic field that pulls the armature.
The relay's NO contact closes, completing the circuit for the connected load, while the NC contact opens.
* Operation Sequence for Two Relays
* IN1 HIGH: Activates Relay 1 to control Load 1.
* IN2 HIGH: Activates Relay 2 to control Load 2.
* Both IN1 and IN2 HIGH: Activates both relays simultaneously to control both loads.
* Both IN1 and IN2 LOW: Deactivates both relays, disconnecting both loads.
### Applications
* Home Automation: Controlling lights and fans independently.
* Industrial Automation: Managing two separate devices or motors.
* DIY Projects: Operating appliances remotely with microcontroller-based projects.
This guide will help you interface a 2 Channel Relay assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview)(but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work)
## Step 1: Hardware Required
1. Glyph Board
2. GMOD 2 Channel Relay Module
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
// Pin definitions for 2-Channel Relay Module
const int RELAY_1 = 3; // GPIO2 for first relay
const int RELAY_2 = 2; // GPIO3 for second relay
void setup()
{
// Initialize serial communication
Serial.begin(115200);
// Configure relay pins as outputs
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
// Initialize Both Relay Channels to OFF state (relays are typically Active LOW- Means they are OFF when a HIGH Signal is Applied and vice-versa)
digitalWrite(RELAY_1, HIGH);
digitalWrite(RELAY_2, HIGH);
Serial.println("Relay Module Initialized"); //Print that Relay Module is Initialized
}
void loop()
{
// Example control sequence
// Turn ON Relay 1
digitalWrite(RELAY_1, LOW);
Serial.println("Turning on Relay 1");
delay(2000);
// Turn OFF Relay 1
digitalWrite(RELAY_1, HIGH);
Serial.println("Turning off Relay 1");
delay(1000);
// Turn ON Relay 2
digitalWrite(RELAY_2, LOW);
Serial.println("Turning on Relay 2");
delay(2000);
// Turn OFF Relay 2
digitalWrite(RELAY_2, HIGH);
Serial.println("Turning off Relay 2");
delay(1000);
}
// Helper functions for relay control
void turnOnRelay(int relayPin)
{
digitalWrite(relayPin, LOW);
}
void turnOffRelay(int relayPin)
{
digitalWrite(relayPin, HIGH);
}
void toggleRelay(int relayPin)
{
digitalWrite(relayPin, !digitalRead(relayPin));
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` is not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
On Serial Monitor, you should see the output like this:

Along with this you should see the relay ticking and corresponding LED blink.
# Micro SD Card
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/sd-card
Interface the G-Mod micro SD card module with a Glyph ESP32 board over SPI to read and write files, log sensor data, and store project assets.
A **Micro SD Card Module** is a compact circuit designed to interface a microcontroller (e.g., Arduino, ESP32, Raspberry Pi) with a Micro SD card for data storage, retrieval, and management. This module can work both on SPI and SDIO mode, in this particular doc you will understand how to interface SD card with GLYPH in SPI mode.
## Pin Configuration
* 3V3: Power supply for the module (3.3V).
* D1 : data pin, used for data transfer
* SCK: Clock single for SPI communication
* MO : Master out slave in
* MI : Master in Slave out
* CS : chip select
* GND : ground
* D2 : data pin, used for data transfer
## Key Features
* Supports microSD Cards
* SPI & SDIO Interface Compatible
* Plug-and-Play Interface
* Compact and Lightweight Design
* File System Compatibility
* Low Power Consumption
* Push-push type socket
## Application
* Data Logging: Storing sensor data, logs, or measurements in projects like weather monitoring or IoT.
* Media Storage: Saving and retrieving images, videos, or audio files.
* Boot Media: Used in systems like Raspberry Pi for storing operating systems.
* Portable Data Transfer: Enabling easy data transport between devices.
## Step 1: Hardware Required
1. Glyph Boards
2. G-MOD Micro SDCard Module
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include
#include
#define SD_CS 17 // Change this to match your Glyph board's SD card CS pin
//GMOD-- GLYPH
//3v3-- 3v3
//sck-- sck
//MO -- MO
//MI-- MI
//GND-- GND
void listFiles(File dir, int numTabs = 0) {
while (true) {
File entry = dir.openNextFile();
if (!entry) {
break; // No more files
}
for (int i = 0; i < numTabs; i++) {
Serial.print("\t");
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
listFiles(entry, numTabs + 1); // Recursively list directories
} else {
Serial.print("\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println("Initializing SD card...");
if (!SD.begin(SD_CS)) {
Serial.println("SD card not detected!");
return;
}
Serial.println("SD card detected successfully!");
// Print card information
uint32_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.print("Card Size: ");
Serial.print(cardSize);
Serial.println(" MB");
// List files on SD card
File root = SD.open("/");
listFiles(root);
root.close();
}
void loop() {
// Nothing to do in the loop
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe Output on Serial Monitor

# Serial Flash
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/serial-flash
A serial flash module provides reliable non-volatile memory for microcontrollers, allowing for firmware storage, data logging, and configuration management.
A **Serial Flash** Module is a compact memory device designed to interface a microcontroller (e.g., Arduino, ESP32, GLYPH, STM32) for non-volatile data storage, firmware storage, logging, and configuration management. Unlike SD cards, Serial Flash is directly soldered onto the board and communicates typically over SPI (and sometimes QSPI) for high-speed data transfer.
## Pin Configuration
* VCC: Power supply input for the Serial Flash chip (typically 3.3V).
* G (GND): Ground .
* CLK: Serial Clock input for SPI communication
* CS: Chip Select (active LOW). Enables communication with the Serial Flash device.
* MO (MOSI / SI): Master Out Slave In — carries data from the
* MI (MISO / SO): Master In Slave Out — carries data from the Serial Flash to the microcontroller.
* SD2 (IO2): Data line 2. Used in Quad-SPI (QSPI) mode for higher-speed data transfer. In standard SPI mode, this pin is typically unused or acts as a hold function depending on the chip.
* SDI3 (IO3): Data line 3. Used in Quad-SPI (QSPI) mode. In standard SPI mode, this pin may function as Write Protect (WP) or Hold depending on the flash device.
## Key Features
* Non-volatile memory (retains data without power)
* SPI / QSPI communication support
* High-speed data transfer
* Compact and small footprint
* Low power consumption
* High endurance (multiple erase/write cycles)
* Sector and block erase capability
* Supports execute-in-place (XIP) in QSPI
* Wide voltage operating range (typically 3.3V)
* Reliable long-term data storage
## Application
* Firmware Storage: Storing bootloader, application code, or external program memory in embedded systems.
* OTA Updates: Holding firmware files for over-the-air updates in IoT devices.
* Data Logging: Recording sensor readings, event logs, or system data in real-time applications.
* Configuration Storage: Saving device settings, calibration values, or user preferences.
* Buffer Memory: Temporary storage for data processing in communication or control systems.
* Embedded Systems: Expanding memory capacity in microcontroller-based designs.
## Step 1: Hardware Required
1. Glyph Boards
2. G-MOD Serial flash Module
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Copy and paste the following code into the Arduino IDE:**
Here’s your code with detailed comments added so it’s easier to follow and understand:
```cpp theme={null}
#include
// Define the pin connections for the external SPI Flash chip
#define FLASH_CS 5 // Chip Select (CS) pin
#define FLASH_MISO 4 // Master In Slave Out (MISO) pin
#define FLASH_MOSI 7 // Master Out Slave In (MOSI) pin
#define FLASH_CLK 6 // Clock (SCK) pin
// Create an SPI object for FSPI (ESP32-C3 supports FSPI hardware bus)
SPIClass SPI1(FSPI);
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("ESP32-C3 SPI Flash Test");
pinMode(FLASH_CS, OUTPUT);
digitalWrite(FLASH_CS, HIGH);
SPI1.begin(FLASH_CLK, FLASH_MISO, FLASH_MOSI, FLASH_CS);
SPI1.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
// Read JEDEC ID
readJEDEC();
// Write and Read Test Data
writeData(0x000000, "Hello Flash!");
delay(100);
readData(0x000000, 12);
}
void loop() {
// Nothing here
}
// ---------------- JEDEC READ ----------------
void readJEDEC() {
digitalWrite(FLASH_CS, LOW);
SPI1.transfer(0x9F);
byte mfg = SPI1.transfer(0x00);
byte type = SPI1.transfer(0x00);
byte size = SPI1.transfer(0x00);
digitalWrite(FLASH_CS, HIGH);
Serial.print("Manufacturer ID: 0x");
Serial.println(mfg, HEX);
Serial.print("Memory Type: 0x");
Serial.println(type, HEX);
Serial.print("Memory Size: 0x");
Serial.println(size, HEX);
}
// ---------------- WRITE ENABLE ----------------
void writeEnable() {
digitalWrite(FLASH_CS, LOW);
SPI1.transfer(0x06);
digitalWrite(FLASH_CS, HIGH);
}
// ---------------- WRITE DATA ----------------
void writeData(uint32_t address, const char* data) {
writeEnable();
digitalWrite(FLASH_CS, LOW);
SPI1.transfer(0x02); // Page Program
SPI1.transfer((address >> 16) & 0xFF);
SPI1.transfer((address >> 8) & 0xFF);
SPI1.transfer(address & 0xFF);
while (*data) {
SPI1.transfer(*data++);
}
digitalWrite(FLASH_CS, HIGH);
delay(10);
}
// ---------------- READ DATA ----------------
void readData(uint32_t address, int length) {
digitalWrite(FLASH_CS, LOW);
SPI1.transfer(0x03);
SPI1.transfer((address >> 16) & 0xFF);
SPI1.transfer((address >> 8) & 0xFF);
SPI1.transfer(address & 0xFF);
Serial.print("Data Read: ");
for (int i = 0; i < length; i++) {
char c = SPI1.transfer(0x00);
Serial.print(c);
}
digitalWrite(FLASH_CS, HIGH);
Serial.println();
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe Output on Serial Monitor

# WS2812B RGB Ring
Source: https://learn.pcbcupid.com/documentation/modules/g-mod/ws2812b-led
WS2812B RGB LED Ring with individually addressable LEDs, full-color effects, and easy control for Arduino, ESP32, and DIY lighting projects.
The **WS2812B** is a compact, addressable RGB LED module that integrates a control circuit and three discrete red, green, and blue LEDs within a single 5050 SMD package, allowing each pixel’s color and brightness to be set independently via a one-wire digital interface. Internally, it employs an integrated driver and a signal reshaping/amplification circuit, enabling daisy-chaining of virtually unlimited numbers of LEDs from a single microcontroller pin. Control is achieved by sending a 24-bit data packet (8 bits per color channel) per LED, with 256 brightness levels per channel.
**Integrated Design**
1. Chip and LED in one: The WS2812B package embeds both the RGB LEDs and the control IC, simplifying circuit design by eliminating the need for separate driver components
2. 5050 SMD footprint: Common “5050” size (5 mm × 5 mm), compatible with standard LED strip layouts and modules
3. Power and Data- Power: Operates typically at 5 V DC, with a maximum recommended current draw of \~60 mA per LED at full white (all colors at maximum brightness)
4. Data line: A single input (DIN) and output (DOUT) pin carry the high-speed data stream; the protocol embeds timing for “0” and “1” bits directly in signal pulse widths
## Pin configuration
* GND : GND
* VCC : 5V
* DI : (DATA IN) Any GPIO pin
* DO : (DATA OUT) chain to DI of other ring
## Features
1. Individually addressable: Each LED module responds only to its specific 24-bit data, so you can set unique colors for each pixel in a chain
2. High color resolution: 8 bits per channel → 16.7 million possible colors per LED
3. Cascading capability: The DOUT of one LED links to the DIN of the next, allowing long chains (hundreds or thousands of LEDs) from a single microcontroller pin
4. Built-in signal reshaping: Ensures clean, consistent data transmission through long strips without external repeaters
Data is sent as a continuous stream of 24 bits per LED (G7…G0, R7…R0, B7…B0). Timing-sensitive pulses distinguish “0” and “1” bits, typically requiring precise.
## Applications
* LED strips and matrices for decorative lighting, signage, and art installations
* Wearable electronics where flexible, addressable lighting is desired
* Commercial displays and props that require per-pixel animation without bulky wiring
* These modules’ simplicity and rich feature set have made the WS2812B a de facto standard in hobbyist and professional addressable LED applications.
## WS2812B CONCENTRIC CIRCLE RING

The [G-MOD WS2812B](https://shop.pcbcupid.com/product/gm006/) circular LED module is designed with three concentric rings of addressable RGB LEDs. Power (VCC, GND) is distributed across all LEDs in parallel. The data signal (DIN) enters from the solder pads at the bottom, drives the innermost ring first, and then cascades outward ring by ring. The final LED in the outer ring routes its data out to the DO pad, allowing multiple modules to be chained together.

Inside the PCB, three solder jumpers connect the concentric LED rings. These bridges carry power (VCC), ground (GND), and the serial data signal outward from the inner ring to the outer rings. This ensures all LEDs are powered in parallel, while the WS2812B data chain cascades ring-by-ring.
### Step 1: Hardware Required
1. GLYPH
2. WS2812B RGB LED RING
### Step 2: Circuit Diagram

### Step 3: Code Setup
```cpp theme={null}
#include
#define LED_PIN 1 // Pin where NeoPixel strip is connected
#define LED_COUNT 37 // Number of LEDs in strip
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Define 5 colors (R, G, B)
uint32_t colors[5];
void setup() {
strip.begin();
strip.setBrightness(50); // Brightness (0-255)
// Prepare the colors
colors[0] = strip.Color(255, 0, 0); // Red
colors[1] = strip.Color(0, 255, 0); // Green
colors[2] = strip.Color(0, 0, 255); // Blue
colors[3] = strip.Color(255, 255, 0); // Yellow
colors[4] = strip.Color(255, 0, 255); // Magenta
strip.show(); // Initialize all pixels to off
}
void loop() {
for (int i = 0; i < 5; i++) { // Loop through all 5 colors
setAllColor(colors[i]); // Set all LEDs to the current color
delay(1000); // Keep it for 1 second
}
}
// Function to set all LEDs to one color
void setAllColor(uint32_t color) {
for (int j = 0; j < LED_COUNT; j++) {
strip.setPixelColor(j, color);
}
strip.show();
}
```
### Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid Glyph S3`
For the `Pcbcupid Glyph S3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
### Step 5: Observe the Output


## Break Them! to 1, 8, 12 or 16 ring strip
The ring can be broken on and used as a individual ring setup and have the same circuit. Just change the number of led on
the code from 37 to the desired number.



### Code Setup
```cpp theme={null}
#include
#define PIN_WS2812B 7 // The ESP32 pin GPIO16 connected to WS2812B
#define NUM_PIXELS 16 // The number of LEDs (pixels) on WS2812B LED strip
Adafruit_NeoPixel ws2812b(NUM_PIXELS, PIN_WS2812B, NEO_GRB + NEO_KHZ800);
void setup() {
ws2812b.begin(); // initialize WS2812B strip object (REQUIRED)
}
void loop() {
ws2812b.clear(); // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
// turn pixels to green one-by-one with delay between each pixel
for (int pixel = 0; pixel < NUM_PIXELS; pixel++) { // for each pixel
ws2812b.setPixelColor(pixel, ws2812b.Color(0, 255, 0)); // it only takes effect if pixels.show() is called
ws2812b.show(); // update to the WS2812B Led Strip
delay(500); // 500ms pause between each pixel
}
// turn off all pixels for two seconds
ws2812b.clear();
ws2812b.show(); // update to the WS2812B Led Strip
delay(2000); // 2 seconds off time
// turn on all pixels to red at the same time for two seconds
for (int pixel = 0; pixel < NUM_PIXELS; pixel++) { // for each pixel
ws2812b.setPixelColor(pixel, ws2812b.Color(255, 0, 0)); // it only takes effect if pixels.show() is called
}
ws2812b.show(); // update to the WS2812B Led Strip
delay(1000); // 1 second on time
// turn off all pixels for one seconds
ws2812b.clear();
ws2812b.show(); // update to the WS2812B Led Strip
delay(1000); // 1 second off time
}
```
### Observe the Output

# 2-Channel Microphone
Source: https://learn.pcbcupid.com/documentation/modules/g-sense/2-channel-microphone
Dual IM69D130 digital microphones for high-quality stereo audio capture. I2S interface for seamless integration with microcontrollers.
A **dual-channel microphone** is a device that captures audio signals in two independent channels, typically for stereo or two separate audio sources.
The **ICS-43434** digital I2S output bottom port microphone. The complete ICS-43434 solution consists of a MEMS sensor, signal conditioning, an analog-to-digital converter, decimation and antialiasing filters, power management, and an industry standard 24-bit I²S interface. The I²S interface allows the ICS-43434 to connect directly to digital processors, such as DSPs and microcontrollers, without the need for an audio codec in the system.
The ICS-43434 has multiple modes of operation: High Performance, Low Power (AlwaysOn) and Sleep. The ICS-43434 has high SNR and 120 db SPL AOP in all operational modes.
**End of Life (EOL) Notice**: The **ICS43434** sensor has reached its End of Life. For more details and suggested replacements, please refer to the official [TDK InvenSense Product Page](https://invensense.tdk.com/en-us/products/ics-43434).
## Pin Configuration
* **VDD** : Power supply for the microphone (1.62V to 3.63V)
* **GND** : Ground connection
* **WS** : Word Select (Frame Sync) input for I²S interface
* **SCK** : Serial Clock input for I²S interface
* **SD** : Serial Data output
* **L/R** : Left/Right channel select. Determines whether the device outputs data on the left or right channel
## Key Features
* Operating Voltage: 1.62V to 3.63V
* Current Consumption (Typical): 490 µA
* Sleep Current : 12uA
* Acoustic Overload Point: 120 dB SPL
* Signal-to-Noise Ratio (SNR): 65 dB(A)
* Frequency Response: 60 Hz to 20 kHz
* Sensitivity: -26 dBFS ±1 dB
* Interface: I²S (Integrated Interchip Sound)
* Output Format: 24-bit, two’s complement
* Channel Selection: Left/Right selectable via L/R pin
* Application Suitability: Optimized for voice capture and far-field audio
## Applications
* Stereo Recording: Used in music recording, film production, and live performances for spatial sound capture.
* Dual-Source Recording: Captures two separate audio sources simultaneously (e.g., interviews or instruments).
* Podcasting and Streaming: Provides high-quality, independent channels for voice and background sounds.
* Surround Sound: Integrated into systems for 3D sound environments.
## Step 1: Hardware Required
1. Glyph Boards
2. Gsense 2CH Microphone
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the "[Audio Tool](https://github.com/pschatzmann/arduino-audio-tools)" library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include "AudioTools.h"
AudioInfo info(44100, 2, 32);
I2SStream i2sStream; // Access I2S as stream
CsvOutput csvOutput(Serial);
StreamCopy copier(csvOutput, i2sStream); // copy i2sStream to csvOutput
// Arduino Setup
void setup(void)
{
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
auto cfg = i2sStream.defaultConfig(RX_MODE);
cfg.copyFrom(info);
cfg.i2s_format = I2S_STD_FORMAT; // or try with I2S_LSB_FORMAT
cfg.pin_ws = 20;
cfg.pin_bck = 18;
cfg.pin_data_rx = 19;
cfg.is_master = true;
cfg.use_apll = false;
i2sStream.begin(cfg);
// make sure that we have the correct channels set up
csvOutput.begin(info);
}
// Arduino loop - copy data
void loop()
{
copier.copy();
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
The output can be visualized in the plotter of Arduino IDE, Please check the below image for reference
Output on Arduino IDE 1.x
Output on Arduino IDE 2.x
# Capacitive Touch Slider
Source: https://learn.pcbcupid.com/documentation/modules/g-sense/capacitive-touch-slider
CAP1203 3-Channel Capacitive Touch Controller with I²C interface and PWM output. Perfect for touch-sensitive controls and sliders.
The **Capacitive Slider** is a touch-sensitive input module based on the [CAP1203](https://www.microchip.com/en-us/product/cap1203) IC. It provides high-precision touch detection for sliders and buttons, making it perfect for custom user interfaces, control panels, and interactive projects.
This guide provides a step-by-step explanation to help you integrate the [Gsense-Touch Sensor](https://shop.pcbcupid.com/product/gs004/) for touch detection using the G-Sense module on the [GLYPH-H2 board](https://shop.pcbcupid.com/product/gd003/). The system detects left, middle, and right gestures and provides real-time feedback via the Serial Monitor.
## Features
* 3-Channel Capacitive Touch – detects left, middle, and right touch/slide gestures
* Swipe Detection – recognizes directional swipes across the slider
* Digital Output – provides clear HIGH/LOW signals for each touch channel over I2C
* Low Power Consumption – suitable for battery-operated applications
* Integrated Signal Processing – built-in debounce and touch sensing algorithms
* Compact Module – easy integration with boards like GLYPH
## Applications
* Gesture-Control Interfaces – control devices or menus with simple swipes
* Consumer Electronics – touch sliders for volume, brightness, or selection
* Robotics & Automation – simple human-machine interface (HMI) for commands
* IoT Devices – intuitive touch-based input for compact devices
* Gaming & VR Controllers – gesture input for interactive experiences
* Wearable Devices – lightweight, low-power input sensor for compact systems
## Step 1: Hardware Required
1. Glyph Board
2. Gsense Capacitive Touch Slider

## Step 2: Circuit Diagram

## Step 3: Code Setup
```cpp theme={null}
#include
#include "SparkFun_CAP1203.h" // Click here to get the library: http://librarymanager/All#SparkFun_CAP1203
CAP1203 sensor; // Initialize sensor
void setup()
{
Wire.begin(); // Join I2C bus
Serial.begin(9600); // Start serial for output
// Setup sensor
if (sensor.begin() == false)
{
Serial.println("Not connected. Please check connections and read the hookup guide.");
while (1)
;
}
else
{
Serial.println("Connected!");
}
}
void loop()
{
if (sensor.isLeftTouched() == true)
{
Serial.println("Left");
}
if (sensor.isMiddleTouched() == true)
{
Serial.println("Middle");
}
if (sensor.isRightTouched() == true)
{
Serial.println("Right");
}
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
When you touch different sides of the Sensor, you can see the Serial Monitor Output as follows:




# GSI003 Industrial Temp & Humidity Sensor
Source: https://learn.pcbcupid.com/documentation/modules/g-sense/hdc3020-rs485
GSI003 industrial-grade temperature and humidity sensor with RS485 output, powered by TI's MSPM0 microcontroller for harsh environment monitoring.
The **Gsense-HDC3020 (RS485)** is a precision temperature and humidity sensor with an RS485 interface based on the [HDC3020](https://www.ti.com/lit/ds/symlink/hdc3020.pdf) IC. It's designed for industrial environmental monitoring, long-distance data transmission, and smart building applications.
Gsense-GSI003 is a unique sensor module offering from PCBCUPID which uses worlds tiniest micrcontroller **MSCM0C1104** along with **HDC3020** to give high accurate temperature and humidity with RS485 output.
This particular module is a demo kit to show the capability of world tiniest micrcontroller for the presentation [**Zephyr RTOS: Under 1KB of RAM**](https://osseu2025.sched.com/event/25VuG) by [Parthiban N](https://www.linkedin.com/in/parthitce/) and [Karthikeyan Krishnasamy](https://osseu2025.sched.com/speaker/karthikeyan7) happening at Open Source Summit 25th-27th August 2025 - Amsterdam,Netherlands.
## G-Sense GSI003
The G-sense GSI003 is a humidity and temperature sensor with MSPM0 family microcontroller and THVD1406 to produce direct RS485 output from the HDC3020 sensor. These are part of Texas Instruments product series. It is designed for low-cost, low-power, and space-efficient applications.
### Key Features
* Relative humidity (RH) accuracy: ±1.5% (typical)
* Temperature accuracy: ±0.2 °C (typical)
* Operating humidity range: 0% RH to 100% RH
* Operating temperature range: –40 °C to +125 °C
* Supply voltage range: 3.3 V to 5.5 V
* Fully digital output via RS485
* Integrated RS485 Converter
* Integrated WS2812B RGB LED
### Applications
* Industrial monitoring: HVAC systems, industrial control rooms, warehouse monitoring
* Consumer appliances: refrigerators, air conditioners, smart thermostats
* Environmental monitoring: weather stations, portable data loggers
* IoT devices: battery-powered environmental sensing nodes
* Automotive systems: in-cabin climate monitoring
### Components
These are the major components used in G-sense GSI003
* [HDC3020](https://files.pcbcupid.com/Documentation/Boards/g-sense/hdc3020-rs485/hdc3020.pdf)
* [MSMP0C1104](https://files.pcbcupid.com/Documentation/Boards/g-sense/hdc3020-rs485/mspm0c1104.pdf)
* [THVD1406](https://files.pcbcupid.com/Documentation/Boards/g-sense/hdc3020-rs485/thvd1406.pdf)
* [WS2812B](https://files.pcbcupid.com/Documentation/Boards/g-sense/hdc3020-rs485/WS2812B-2020_V10_EN_181106150240761.pdf)
### Schematics
**MSPM0C1104 DBGA PACKAGE WITHOUT RS485**
[Download Schematic in PDF Format](https://files.pcbcupid.com/Documentation/Boards/g-sense/hdc3020-rs485/pcbcupid-mspm0c1104-DBGA-schematics.pdf)
**MSPM0C1104 WSON PACKAGE WITH RS485**
[Download Schematic in PDF Format](https://files.pcbcupid.com/Documentation/Boards/g-sense/hdc3020-rs485/pcbcupid-mspm0c1104-schematics.pdf)
You can checkout the [Git repo](https://github.com/pcbcupid/MSPM0C1104-DEV-KIT) for the kicad schematics/layout files!
### Programming
This sensor has to be programmed to convert the HDC sensor's I2C data to RS485 or to do anything useful. This can be done through the SWD interface provided in the back of the module.
You can use the **PCBCUPID JTAG adapter** along with a **SEGGER EMULATOR PRO** for programming this module along with a JIG
This JIG is designed in such a way that, it can be used for testing/programming both the RS485 and NON-RS485 version. You can use the adapter and change the JIG as needed.
You can download the 3D model [here](https://www.printables.com/model/1394745-g-sense-gsi003-programming-jig)
#### Programming RS485 Version
Make sure the device is powered through USB while programming
#### Programming NON-RS485 Version
Make sure the device is powered through USB while programming
# Single-Channel I2S Microphone
Source: https://learn.pcbcupid.com/documentation/modules/g-sense/microphone
Interface a single-channel ICS43434 I2S MEMS microphone with a Glyph ESP32 development board to capture digital audio for voice and sound projects.
A **single-channel microphone** is a device designed to capture audio and output it as a single-channel signal (mono). This is the most common type of microphone used in applications like speech, music recording, or public addressing systems.
The **ICS-43434** digital I2S output bottom port microphone. The complete ICS-43434 solution consists of a MEMS sensor, signal conditioning, an analog-to-digital converter, decimation and antialiasing filters, power management, and an industry standard 24-bit I²S interface. The I²S interface allows the ICS-43434 to connect directly to digital processors, such as DSPs and microcontrollers, without the need for an audio codec in the system.
The ICS-43434 has multiple modes of operation: High Performance, Low Power (AlwaysOn) and Sleep. The ICS-43434 has high SNR and 120 db SPL AOP in all operational modes.
**End of Life (EOL) Notice**: The **ICS43434** sensor has reached its End of Life. For more details and suggested replacements, please refer to the official [TDK InvenSense Product Page](https://invensense.tdk.com/en-us/products/ics-43434).
## Pin Configuration
* VDD: Power supply for the microphone (1.62V to 3.63V).
* GND: Ground connection.
* WS: Word Select (Frame Sync) input for I²S interface.
* SCK: Serial Clock input for I²S interface.
* SD: Serial Data output.
* L/R: Left/Right channel select. Determines whether the device outputs data on the left or right channel.
## Key Features
* Operating Voltage: 1.62V to 3.63V
* Current Consumption (Typical): 490 µA
* Sleep Current : 12uA
* Acoustic Overload Point: 120 dB SPL
* Signal-to-Noise Ratio (SNR): 65 dB(A)
* Frequency Response: 60 Hz to 20 kHz
* Sensitivity: -26 dBFS ±1 dB
* Interface: I²S (Integrated Interchip Sound)
* Output Format: 24-bit, two’s complement
* Channel Selection: Left/Right selectable via L/R pin
* Application Suitability: Optimized for voice capture and far-field audio
## Application
* Speech Recording: Captures clear voice signals for podcasts, interviews, or telecommunication.
* Music Recording: Records instruments or vocals in studios.
* Public Address Systems: Amplifies a speaker’s voice for large audiences.
* Broadcasting: Used in radio and TV stations for high-quality voice capture.
## Step 1: Hardware Required
1. Glyph Boards
2. Gsense 1CH Microphone
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the "[Audio Tool](https://github.com/pschatzmann/arduino-audio-tools)" library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include "AudioTools.h"
AudioInfo info(44100, 1, 32);
I2SStream i2sStream; // Access I2S as stream
CsvOutput csvOutput(Serial);
StreamCopy copier(csvOutput, i2sStream); // copy i2sStream to csvOutput
// Arduino Setup
void setup(void)
{
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
auto cfg = i2sStream.defaultConfig(RX_MODE);
cfg.copyFrom(info);
cfg.i2s_format = I2S_STD_FORMAT; // or try with I2S_LSB_FORMAT
cfg.pin_ws = 22;
cfg.pin_bck = 20;
cfg.pin_data_rx = 21; //SD Pin
cfg.is_master = true;
cfg.use_apll = false;
i2sStream.begin(cfg);
// make sure that we have the correct channels set up
csvOutput.begin(info);
}
// Arduino loop - copy data
void loop()
{
copier.copy();
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 4: Observe the output
The output can be visualized in the plotter of Arduino IDE, Please check the below image for reference
Output on Arduino IDE 1.x
Output on Arduino IDE 2.x
# QMC6309 Magnetometer
Source: https://learn.pcbcupid.com/documentation/modules/g-sense/qmc6309-magnetometer
QMC6309 3-Axis Electronic Compass with I²C interface, high stability, and built-in self-test. Perfect for drones, robotics, and navigation.
The **QMC6309**, produced by QST Corporation, is a compact and energy-efficient digital magnetometer designed to detect magnetic fields across three axes (X, Y, Z). It integrates both magnetic sensing elements and signal-conditioning circuitry into a single silicon chip.
The QMC6309 stands out as a diminutive, energy-efficient, and accurate 3-axis magnetometer solution, ideal for compact and embedded electronics like VR trackers and flight controllers. With its seamless integration of sensing and signal conditioning, it provides high-precision magnetic field data with minimal PCB footprint.
## Pin Configuration
* **VCC** : Power supply
* **GND** : Ground connection
* **SDA** : SDA of GLYPH board
* **SCL** : SCL of GLYPH board
## Key Features
* 3-axis magnetic field sensing (X, Y, Z)
* I²C digital interface for easy MCU integration
* 16-bit ADC resolution for high-precision measurements
* Wide supply voltage range: 2.5 V – 3.6 V
* Low operating current: \~2 mA (ideal for battery-powered devices)
* Designed for consumer electronics like VR trackers, wearables, and flight controllers
## Applications
* VR / AR Trackers – orientation tracking and drift correction
* Robotics & Drones – navigation, stabilization, and position control
* Consumer Electronics – smartwatches, handheld devices, portable gadgets
* Flight Controllers – magnetic heading reference in UAVs and quadcopters
* Research & Education – low-cost magnetometer for embedded learning projects
## QMC6309 Simple Example
### Step 1: Hardware Required
1. Glyph Boards
2. QMC6309
### Step 2: Circuit Diagram

### Step 3: Code Setup
1. Open Arduino IDE.
2. Make sure to install the library
3. Copy and paste the following code into the Arduino IDE:
### Step 4: Upload the Code
```cpp theme={null}
//You can download the PCBCUPID_QMC6309 library from here : https://github.com/pcbcupid/PCBCUPID-QMC6309
#include
#include "PCBCUPID_QMC6309.h"
#include "ExponentialFilter.h"
PCBCUPID_QMC6309 mag(Wire);
// Calibrated offsets
const float x_offset = 3485.0;
const float y_offset = 1290.0;
const float declination = 0.22;
// Filter object: 0.2 weight (20%)
ExponentialFilter headingFilter(0.2, 0.0);
void setup() {
Serial.begin(115200);
delay(1000);
if (!mag.begin()) {
Serial.println("Magnetometer init failed");
while (1);
}
Serial.println("Heading with Exponential Filter");
}
void loop() {
int16_t x, y, z;
if (mag.readRaw(x, y, z)) {
float x_cal = x - x_offset;
float y_cal = y - y_offset;
float heading = atan2(-x_cal, y_cal) + declination;
if (heading < 0) heading += 2 * PI;
if (heading > 2 * PI) heading -= 2 * PI;
float headingDeg = heading * 180.0 / PI;
// Apply exponential filter
headingFilter.update(headingDeg);
float smoothedHeading = headingFilter.get();
Serial.print("Heading: ");
Serial.print(smoothedHeading, 1);
Serial.print("° (");
Serial.print(mag.headingToDirection(smoothedHeading));
Serial.println(")");
}
delay(200);
}
```
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
### Step 5: Observe the Output
The output shows the smoothed compass heading in degrees (0–360°) along with its cardinal direction (e.g., N, NE, E, SE, etc.).
Might not have accurate reading as this was not the intended purpose, This module is very useful to find strong magnetic field in 3 dimensional space.

## QMC6309 with oled
### Step 1: Hardware Required
1. Glyph Boards
2. QMC6309
3. OLED Display
### Step 2: Circuit Diagram

### Step 3: Code Setup
1. Open Arduino IDE.
2. Make sure to install the "Audio Tool" library
3. Copy and paste the following code into the Arduino IDE:
### Step 4: Upload the Code
```cpp theme={null}
#include
#include "PCBCUPID_QMC6309.h"
#include
// === OLED & Magnetometer ===
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
PCBCUPID_QMC6309 mag(Wire);
// === Graph Box Settings ===
const int graphX = 70;
const int graphY = 8;
const int graphWidth = 54;
const int graphHeight = 48;
const int baselineY = graphY + graphHeight / 2;
const int barHeightMax = graphHeight / 2;
const int barWidth = 5;
const int barSpacing = 18;
const int barStartX = graphX + 9;
const int barRange = 500;
// === Baseline Calibration ===
long avgX = 0, avgY = 0, avgZ = 0;
int samples = 0;
void setup() {
Serial.begin(115200);
Wire.begin();
if (!mag.begin()) {
Serial.println("QMC6309 not found!");
while (1);
}
u8g2.begin();
}
void loop() {
int16_t x, y, z;
if (mag.readRaw(x, y, z)) {
samples++;
avgX = ((avgX * (samples - 1)) + x) / samples;
avgY = ((avgY * (samples - 1)) + y) / samples;
avgZ = ((avgZ * (samples - 1)) + z) / samples;
u8g2.clearBuffer();
// === Serial Debug ===
Serial.print("X: "); Serial.print(x);
Serial.print(" Y: "); Serial.print(y);
Serial.print(" Z: "); Serial.println(z);
// === Left Side Text ===
u8g2.setFont(u8g2_font_5x8_tr);
u8g2.setCursor(4, 10); u8g2.print("X: "); u8g2.print(x);
u8g2.setCursor(4, 20); u8g2.print("Y: "); u8g2.print(y);
u8g2.setCursor(4, 30); u8g2.print("Z: "); u8g2.print(z);
// === G-SENSE Label Box (Left) ===
u8g2.setDrawColor(1);
u8g2.drawBox(2, 38, 52, 12); // G-SENSE Box
u8g2.setDrawColor(0);
u8g2.setCursor(8, 47); u8g2.print("G-SENSE");
u8g2.setDrawColor(1);
// === QMC6309 Label aligned to right end of box ===
u8g2.setFont(u8g2_font_4x6_tr);
u8g2.setCursor(54 - u8g2.getStrWidth("QMC6309"), 59);
u8g2.print("QMC6309");
// === Graph Box ===
u8g2.drawFrame(graphX, graphY, graphWidth, graphHeight);
u8g2.drawHLine(graphX, baselineY, graphWidth); // Midline only
// === Draw Bars (without vertical axis lines) ===
drawBar(barStartX + barSpacing * 0, x - avgX, "X");
drawBar(barStartX + barSpacing * 1, y - avgY, "Y");
drawBar(barStartX + barSpacing * 2, z - avgZ, "Z");
u8g2.sendBuffer();
}
delay(150);
}
void drawBar(int xCenter, int16_t delta, const char* label) {
int percent = map(delta, -barRange, barRange, -100, 100);
percent = constrain(percent, -100, 100);
int barHeight = map(abs(percent), 0, 100, 0, barHeightMax);
int yStart = (percent >= 0) ? (baselineY - barHeight) : baselineY;
// Clip to graph box
if (yStart < graphY) {
barHeight -= (graphY - yStart);
yStart = graphY;
}
if (yStart + barHeight > graphY + graphHeight) {
barHeight = (graphY + graphHeight) - yStart;
}
// Draw the bar
u8g2.drawBox(xCenter - barWidth / 2, yStart, barWidth, barHeight);
// % text outside box
u8g2.setFont(u8g2_font_4x6_tr);
int percentY = (percent >= 0) ? (graphY - 2) : (graphY + graphHeight + 8);
u8g2.setCursor(xCenter - 6, percentY);
u8g2.print(percent); u8g2.print("%");
// Axis label below bar
u8g2.setCursor(xCenter - 2, graphY + graphHeight + 16);
u8g2.print(label);
}
```
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
### Step 5: Observe the Output
outputs real-time X, Y, Z magnetometer readings as both serial text and dynamic bar graphs on an OLED, showing deviation from running average with percentage values.


# SHT35 Temperature and Humidity Sensor
Source: https://learn.pcbcupid.com/documentation/modules/g-sense/sht35
Interfacing G-Sense SHT35 High Accuracy Humidity & Temperature Sensor with Arduino, ESP32, and GLYPH-C3. Includes pinout, circuit diagram, and example code.
The **Gsense-SHT35** is a high-precision temperature and humidity sensor from **Sensirion**. It is part of the SHT3x series and is known for its high accuracy, reliability, and fast response time. It communicates via I²C and provides digital output for temperature and relative humidity readings.
This sensor can be used with the Glyph development board to measure environmental temperature and humidity. The sensor provides high accuracy and stability, making it suitable for precise atmospheric monitoring.
## Pin Configuration
* **VCC (RED)** : 3.3V
* **GND (BLACK)** : Ground
* **SDA (YELLOW)** : GPIO (SDA)
* **SCL (BLUE)** : GPIO (SCL)
## Key Features of SHT35
* Operating Voltage: 2.15\~5.5V
* Operating Current (AVG) : 1.5mA
* Humidity Accuracy: ±1.5%RH
* Humidity Detection Range: 0%RH\~100%RH
* Temperature Accuracy: ±0.2℃
* Temperature Detection Range: -40℃\~125℃
* Interface: I²C (address 0x44 or 0x45)
* Response Time: \~2 seconds (humidity)
* Power Consumption: Low power, ideal for battery-powered applications.
## Application
* HVAC Systems: HVAC systems to monitor and control temperature and humidity, ensuring comfortable indoor environments.
* Weather Stations: These sensors are used in weather stations to measure temperature and humidity for weather forecasting.
* Industrial Monitoring: The SHT35 is used in various industrial settings to monitor temperature and humidity, which can affect production processes and equipment performance.
* Smart Agriculture:The SHT35 can be used in agriculture to monitor soil and air temperature and humidity, optimizing irrigation and crop management.
This guide will help you interface an SHT35 Temperature and Humidity sensor [GLYPH-C6](https://learn.pcbcupid.com/boards/glyph-c6/overview)(but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work)
## Step 1: Hardware Required
1. GLYPH-C6 Board
2. GSense SHT35
3. Breadboard
## Step 2: Circuit Diagram
You can use either the Gsense SHT35 Industrial or Hobby variant. The pinouts for both are shown in the figure along with the circuit connection
* Connect VCC of the sensor to +3.3V of the GLYPH board
* Connect SDA of the sensor to the SDA(GPIO4) of the GLYPH board
* connect SCL of the sensor to the SCL(GPIO5) of the GLYPH board
* Connect GND of the sensor to GROUND of the GLYPH board

## Step 3: Code Setup
1. **Open Arduino IDE**
2. **Install the Necessary Libraries**
Download and install [Adafruit\_SHT31](https://github.com/adafruit/Adafruit_SHT31), this library works for SHT3x Series.
3. **Enter the following code into the Arduino IDE**
```cpp theme={null}
#include // Include the Wire library for I2C communication
#include "Adafruit_SHT31.h" // Include the Adafruit SHT31 library (compatible with SHT35)
// Define I2C pins for GlyphC6
#define SDA_PIN 4 // GPIO4 as SDA (I2C Data)
#define SCL_PIN 5 // GPIO5 as SCL (I2C Clock)
// Create an instance of the SHT31 class (compatible with SHT35)
Adafruit_SHT31 sht35 = Adafruit_SHT31();
void setup() {
Serial.begin(115200); // Start serial communication at 115200 baud rate
// Wait for the serial monitor to open (useful for debugging)
while (!Serial) {
delay(1000);
}
Serial.println("SHT35 Sensor Test with GlyphH2");
// Initialize I2C communication with the defined SDA and SCL pins
Wire.begin(SDA_PIN, SCL_PIN);
// Initialize the SHT35 sensor with its default I2C address (0x45 is the alternate address)
if (!sht35.begin(0x44)) {
Serial.println("Couldn't find SHT35 sensor! Check wiring.");
delay(1000); // Wait before retrying
} else {
Serial.println("SHT35 sensor found!");
}
}
void loop() {
// Read temperature in Celsius
float temp = sht35.readTemperature();
// Read humidity in percentage
float humidity = sht35.readHumidity();
// Check if the readings are valid (not NaN)
if (!isnan(temp) && !isnan(humidity)) {
Serial.print("Temperature: ");
Serial.print(temp);
Serial.println(" *C");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %RH");
} else {
Serial.println("Failed to read from SHT35 sensor!");
}
delay(2000); // Wait 2 seconds before taking the next reading
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For the `Pcbcupid GLYPH C6 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output on the Serial Monitor
The Serial Monitor should start displaying the Humidity, Temperature and Heat Index values of the surrounding air like this:

# SHT45 Temperature and Humidity Sensor
Source: https://learn.pcbcupid.com/documentation/modules/g-sense/sht45
Interfacing G-Sense SHT45 High Accuracy Humidity & Temperature Sensor with Arduino, ESP32, and GLYPH-C3. Includes pinout, circuit diagram, and example code.
The **Gsense-SHT45** is a highly accurate temperature and humidity sensor from Sensirion, designed for precise environmental monitoring in a wide range of applications. It is an upgrade over previous models such as SHT31, offering even better accuracy and lower power consumption.
## Pin Configuration
* **VCC (RED)** : 3.3V
* **GND (BLACK)** : Ground
* **SDA (YELLOW)** : GPIO (SDA)
* **SCL (BLUE)** : GPIO (SCL)
## Key Features of SHT45
* Operating Voltage : 1.08 - 3.6v
* Operating Current (AVG) : 0.4 µA
* Temperature Accuracy: ±0.1°C
* Humidity Accuracy: ±1.0% RH
* Temperature Measurement Range: -40°C to +125°C
* Humidity Measurement Range: 0% to 100% RH
* Interface: I²C (address 0x44 or 0x45)
* Response Time: RH (8s) °C (10s)
* Low Power Consumption: Ideal for battery-powered devices.
## Application
* HVAC Systems: HVAC systems to monitor and control temperature and humidity, ensuring comfortable indoor environments.
* Weather Stations: These sensors are used in weather stations to measure temperature and humidity for weather forecasting.
* Industrial Monitoring: The SHT35 is used in various industrial settings to monitor temperature and humidity, which can affect production processes and equipment performance.
* Smart Agriculture:The SHT35 can be used in agriculture to monitor soil and air temperature and humidity, optimizing irrigation and crop management.
This guide will help you interface an SHT45 Temperature and Humidity sensor [GLYPH-C6](https://learn.pcbcupid.com/boards/glyph-c6/overview)(but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work)
## Step 1: Hardware Required
1. GLYPH-C6 Board
2. Gsense SHT45
3. Breadboard
## Step 2: Circuit Diagram
You can use either the Gsense SHT35 Industrial or Hobby variant. The pinouts for both are shown in the figure along with the circuit connection
* Connect VCC of the sensor to +3.3V of the GLYPH board
* Connect SDA of the sensor to the SDA(GPIO4) of the GLYPH board
* connect SCL of the sensor to the SCL(GPIO5) of the GLYPH board
* Connect GND of the sensor to GROUND of the GLYPH board

## Step 3: Code Setup
1. **Open Arduino IDE**
2. **Install the Necessary Libraries**
We’ll use the [SHT45 library from Adafruit](https://github.com/adafruit/Adafruit_SHT4X)
3. **Enter the following code into the Arduino IDE**
```cpp theme={null}
#include
#include "Adafruit_SHT4x.h"
#define SDA_PIN 4 // Define the SDA pin
#define SCL_PIN 5 // Define the SCL pin
Adafruit_SHT4x sht4 = Adafruit_SHT4x(); // Initialize the sensor object
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(10); // Wait for the serial connection
}
Serial.println("SHT45 Sensor Test");
// Initialize I2C with the custom SDA and SCL pins
Wire.begin(SDA_PIN, SCL_PIN); // Initialize I2C on custom pins
Wire.setClock(100000); // Set I2C clock to 100kHz for communication
// Initialize the SHT45 sensor
if (!sht4.begin()) {
Serial.println("Couldn't find SHT45 sensor!");
while (1); // Halt here if the sensor isn't found
}
Serial.println("SHT45 sensor found");
}
void loop() {
sensors_event_t humidity, temp;
sht4.getEvent(&humidity, &temp); // Get temperature and humidity data
// Check if the sensor is returning valid data
if (isnan(temp.temperature) || isnan(humidity.relative_humidity)) {
Serial.println("Failed to read sensor data!");
} else {
// Print temperature and humidity with extra details
Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" *C");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println(" %");
}
delay(2000); // Wait for 2 seconds before next reading
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For the `Pcbcupid GLYPH C6 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
The Serial Monitor should start displaying the Humidity, Temperature and Heat Index values of the surrounding air like this:

# USB to RS485 Converter
Source: https://learn.pcbcupid.com/documentation/modules/gadgets/usb-to-rs485
The USB to RS485 converter gadget enables seamless serial communication between a computer's USB port and RS485 industrial buses.
The **USB to RS485 Converter** is a compact gadget that lets you connect a computer or SBC (like a Raspberry Pi) directly to an RS485 industrial bus or Modbus device. Using Silicon Labs' high-performance **CP2102N** USB-to-UART bridge controller along with the **MAX485E** differential transceiver, it translates your computer's USB communication into a robust, differential serial signal resistant to electrical noise.
***
## Key Features
* **Plug-and-Play Integration**: Recognized as a standard virtual COM port on Windows, macOS, and Linux.
* **Auto-Direction Flow Control**: Automatic hardware direction-switching handles half-duplex transmission without needing extra GPIO control pins.
* **Robust ESD Protection**: TVS diodes and signal line filtering safeguard your host computer from static discharge and transient voltage spikes.
* **LED Indicators**: Integrated TX and RX status LEDs provide real-time visual feedback on data transmission.
* **Terminal Block Interface**: Screw terminals allow simple, reliable connection to RS485 bus lines (A, B, GND).
***
## Technical Specifications
| Parameter | Operating Range |
| :-------------------------- | :---------------------------------------------------------------- |
| **USB to UART Bridge (U1)** | Silicon Labs CP2102N (CP2102NA02MMD) |
| **RS-485 Transceiver (U2)** | Maxim MAX485E |
| **Input Connection** | USB Type-A / USB Type-C |
| **Output Interface** | 3-pin Screw Terminal (A+, B-, GND) |
| **Maximum Baud Rate** | Up to 3 Mbps (CP2102N capability) / 2.5 Mbps (MAX485E capability) |
| **Transmission Distance** | Up to 1200 meters (at lower baud rates) |
| **Operating Voltage** | 5V DC (bus-powered via USB) |
***
## Pin Configuration
The converter outputs three differential lines on its screw terminal connector:
| Terminal Pin | Signal Name | Description |
| :----------- | :----------- | :------------------------------------------ |
| **A+** | RS485 A (D+) | Non-inverting differential signal line |
| **B-** | RS485 B (D-) | Inverting differential signal line |
| **GND** | Ground | Common reference ground for long cable runs |
***
## Step 1: Driver Installation
The USB to RS485 converter uses the **CP2102N** chip from Silicon Labs. You will need to ensure the Silicon Labs CP210x USB to UART Bridge VCP drivers are installed:
1. Connect the USB to RS485 converter to your computer's USB port.
2. **Windows 10/11**: The driver usually installs automatically via Windows Update. If the device appears as "Unknown Device" in Device Manager, download and install the official **CP210x VCP Drivers** from the [Silicon Labs Website](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers).
3. **macOS**: Modern macOS releases (macOS 10.11+) include a native Apple USB-Serial driver that supports the CP2102N automatically.
4. **Linux**: Built-in support is included in the Linux kernel (via the `cp210x` driver module). The device will automatically enumerate under `/dev/ttyUSB*` (e.g. `/dev/ttyUSB0`).
5. Verify the connection by checking that the COM port is properly recognized in your system.
***
## Step 2: Bus Connections
To interface the USB to RS485 converter with a remote RS485 slave node (like a G-Mod RS485 sensor or Modbus meter), connect the bus lines as follows:
| USB to RS485 Pin | Remote Node / Sensor Pin |
| :--------------- | :----------------------- |
| **A+** | **A (D+)** |
| **B-** | **B (D-)** |
| **GND** | **GND** |
For long-distance cable runs (exceeding 100 meters) or environments with high electrical noise, it is highly recommended to add a **120-ohm terminating resistor** across the A+ and B- lines at both ends of the bus.
***
## Step 3: Software Setup
You can use any serial terminal utility (such as the Arduino IDE Serial Monitor, CoolTerm, or PuTTY) to send and receive commands through the converter:
1. Open your chosen serial monitor software.
2. Select the COM port corresponding to your USB to RS485 converter.
3. Set the communication parameters matching your remote device (commonly **9600** or **115200** baud rate, **8 Data bits, No Parity, 1 Stop bit**).
4. Send commands to poll data from your Modbus or RS485 slaves and view the returned serial bytes.
# Assembly
Source: https://learn.pcbcupid.com/documentation/modules/glyph-mini/glyph-mini-2040/assembly
Assemble the Glyph Mini 2040 by soldering headers to suit your project. Boards ship fully tested without headers attached for maximum configuration flexibility.
We ship Glyphs fully tested but without headers attached - this gives you the most flexibility on choosing how to use and configure your Glyph.
### Header Options!
Before you start soldering, consider the following options for headers:
**Option 1: Plain Male Headers**
This option lets you plug the Glyph into a solderless breadboard.
**Option 2: Socket Female Headers**
This option won't let you plug the Glyph into a breadboard but it will let you attach our upcoming glyph module and sensors boards very easily.
This can be helpful if you want to connect this board to other boards using jumper cables.
**Option 3: Stacking Headers**
This option is sort of the best-of-both-worlds. You get the ability to plug into a solderless breadboard and plug a GlyphWing on top. But it's a little bulky.
# Overview
Source: https://learn.pcbcupid.com/documentation/modules/glyph-mini/glyph-mini-2040/overview
Overview of the Glyph Mini RP2040 development board: a compact and high-performance microcontroller powered by the Raspberry Pi RP2040 chip.
Introducing the Glyph Mini RP2040, a compact and high-performance microcontroller development board powered by the powerful RP2040 chip. Ideal for IoT projects, robotics, sensors, and advanced embedded systems, the Glyph Mini offers flexibility, speed, and modern connectivity—making it a perfect platform for innovation and rapid prototyping.
### Features
* **Dimensions**: Measures 18mm x 23.5mm without headers soldered in
* **Processor**: Raspberry Pi RP2040 32-bit dual-core ARM Cortex-M0+ processor running up to 133 MHz @ 3.3V logic and power
* **RAM**: 264 KB on-chip SRAM
* **Flash Memory**: 8 MB on-board SPI Flash
* **GPIO**: 20 multi-function GPIO pins
All the important peripherals, labeled for easy access.
### Power Management
* **USB Type-C Connector** for power, programming, and serial debugging
* **LDO Regulator** with up to 800mA peak output current
This board lacks on-board battery protection, charging circuitry, or hot-swap logic. Battery connection requires external protection/switching.
### Additional Features
* **On-board Status LED** (Connected to GPIO16)
* **BOOT and RESET buttons** for easy firmware access and programming
### Bootloader and Programming
The Glyph Mini RP2040 comes with a built-in USB UF2 bootloader, making firmware uploads simple and hassle-free. For first-time use, hold down the BOOT button while connecting the board to your computer via USB (or press RESET while holding BOOT). It will appear as a removable mass storage device, allowing you to drag and drop your `.uf2` firmware file.
### Connectivity
The RP2040 is a powerful microcontroller ideal for high-speed local processing and I/O. For wireless applications, it easily supports external modules such as:
* **Bluetooth**: HC-05 / HC-06
* **Wi-Fi**: ESP8266 / ESP32 (AT commands or co-processor)
* **Long Range**: nRF24L01, LoRa, or XBee
With multiple SPI, I2C, and UART interfaces, integrating these modules is straightforward and efficient.
### Development Support
The Glyph Mini RP2040 is supported by a robust ecosystem of development environments:
* **MicroPython** (Official RP2040 support)
* **CircuitPython** (Official Adafruit support)
* **Arduino IDE**
* **C/C++ (Pico SDK)** (Full support via VSCode)
With extensive library support, strong community backing, and rich documentation, getting started with the Glyph Mini RP2040 is simple and efficient for both beginners and advanced developers.
### Memory and Storage
The RP2040 features 264 KB of on-chip SRAM for fast data processing. In addition, it includes 8 MB of on-board SPI Flash shared between code, file storage (LittleFS), and application data.
### RP2040 Chip Features
* **Dual-core ARM Cortex-M0+**: Deterministic and high-performance processing.
* **Up to 133 MHz**: Flexible PLL allows for overclocking if needed.
* **Programmable I/O (PIO)**: Dedicated state machines for custom peripheral protocol handling.
* **Low Power Modes**: Capable of achieving sleep currents around 2 mA.
You can read more about it in [RP2040 DATASHEET](https://files.waveshare.com/upload/f/fd/Rp2040_datasheet.pdf)
# Pinouts
Source: https://learn.pcbcupid.com/documentation/modules/glyph-mini/glyph-mini-2040/pinouts
Tour the Glyph Mini 2040 board: GPIO pin assignments, power rails, communication interfaces, USB-C port, and Glink connector reference pinout.
[CLICK HERE TO DOWNLOAD HD](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/PCBCUPID_GLYPHC3_DEVKIT_Pinout_PNG.png)
[CLICK HERE TO DOWNLOAD PDF](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/PCBCUPID_C3_DEVKIT_Pinout.pdf)
The Glyph-C3 has many pins, ports, and features. This page takes you on a tour on each of the pin on the board!
**Notice to Developers:** The Glyph-C3 Dev Kit features mirrored physical pins for specific GPIOs. The following physical pin pairs are electrically connected to the same internal trace on the RP2040:
| GPIO Label | Left Physical Pin | Right Physical Pin |
| :--------- | :---------------- | :----------------- |
| **GPIO3** | Pin 6 | Pin 20 |
| **GPIO2** | Pin 7 | Pin 19 |
| **GPIO1** | Pin 8 | Pin 18 |
| **GPIO0** | Pin 9 | Pin 17 |
**IMPORTANT:** Do not connect separate electronic components to both pins in a pair simultaneously. Treating these as independent pins will cause signal conflicts and potential hardware damage to the microcontroller. Always choose only one physical pin from each pair for your circuit.
GPIO 8 and GPIO 9 are **Strapping Pins** used during the chip's power-on/reset sequence to determine the boot mode:
* **GPIO 9**: Controls whether the chip boots from internal Flash (Default: High) or enters **Serial Download Mode** (Low). On your Glyph board, this pin is connected to the onboard **BOOT** button.
* **GPIO 8**: Determines the boot behavior and log output. It should ideally be pulled High or left floating during reset for normal operation.
Avoid connecting peripherals to these pins that might pull them to an unexpected state during startup.
### Power Pins and Connections
* **GND**: This is the common ground for all power and logic.
* **BAT**: This is the positive voltage to/from the Battery(+) Positive terminal (This pin is usual at voltage between 2.7v-4.2v)
* **USB**: This is the positive voltage to/from the USB C jack, if USB is connected (This is usual at voltage 5v)
* **EN**: This is the enable pin of esp32, you can pull down this using a external button or other controller to reset the board.
* **3.3V**: These pins are the output from the 3.3V regulator, they can supply 600mA peak current.
* **Lipo Battery PADS**: 2 Pads behind the board to solder Lipo or li-ion batteries to power the Glyph board.
* **MSR PADS**: Short this MSR pad to measure battery capacity using IO0 (Marked as A0 on board).
### Communication Pins
#### I2C, SPI, and UART on RP2040
The RP2040 is capable of handling I2C, SPI, and UART on many pins. However, to simplify things we have assigned few of the IO pins to make things simpler for users.
#### I2C Pins
* I2C SCL: **SCL**, IO5
* I2C SDA: **SDA**, IO4
### Additional Ports / Pins
#### Glyph Glink Port
This is a QWIIC / STEMMA compatible connector which makes it easy for users to connect to 100's of sensors and modules made by Adafruit & Sparkfun.
#### USB Pins
This is used for power and data transfer. Connect to your computer via a USB C cable to update firmware and at the **USB** pin you would receive 5v
#### PWM Pins
The RP2040 supports PWM on all pins. However, it is not capable of PWM on all pins at the same time. There are multiple PWM channels, each with configurable frequency and duty cycle. The important thing to know is that you cannot use the same channel on different pins at the same time. Please refer to [ESP32C3 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/PCBCUPID_ESP32C3_DATASHEET.pdf)
### Analog Pins
The RP2040 has four ADC channels. These pins are the only pins capable of handling analog (12-bit), and they can also do digital.
* **A0/IO0**: ADC1 channel 0
* **A1/IO1**: ADC1 channel 1
* **A2/IO2**: ADC1 channel 2
* **A3/IO3**: ADC1 channel 3
* **SDA/IO4**: ADC1 channel 4
* **SCL/IO5**: ADC2 channel 0
### Digital Pins
These are the digital I/O pins. They all have multiple capabilities but can be used only one at a time.
* **D0/GPIO0**: Digital I/O pin 0( GPIO0, ADC1\_CH0, XTAL\_32K\_P).
* **D1/GPIO1**: Digital I/O pin 1(GPIO1, ADC1\_CH1, XTAL\_32K\_N).
* **D2/GPIO2**: Digital I/O pin 2(GPIO2, ADC1\_CH2, FSPIQ).
* **D3/GPIO3**: Digital I/O pin 3(GPIO3, ADC1\_CH3).
* **SDA/GPIO4**: The main I2C1 data pin(GPIO4, ADC1\_CH4, FSPIHD, MTMS).
* **SCL/GPIO5**: The main I2C1 clock pin(GPIO5, ADC2\_CH0, FSPIWP, MTDI).
* **D8/GPIO8**: Digital I/O pin 8(GPIO8).
* **D9/GPIO9**: Digital I/O pin 9(GPIO9).
* **A0/GPIO0**: Analog I/O pin 0(GPIO0, ADC1\_CH0, XTAL\_32K\_P).
* **A1/GPIO1**: Analog I/O pin 1(GPIO1, ADC1\_CH1, XTAL\_32K\_N).
* **A2/GPIO2**: Analog I/O pin 2(GPIO2, ADC1\_CH2, FSPIQ).
* **A3/GPIO3**: Analog I/O pin 3(GPIO3, ADC1\_CH3).
* **D-/GPIO18**: Digital I/O pin 18(GPIO18, USB\_D).
* **D+/GPIO19**: Digital I/O pin 19(GPIO19, USB\_D+).
* **SCK/GPIO10**: The main SPI0 SCK(GPIO10, FSPICS0).
* **MO/GPIO6**: The main SPI0 MOSI(GPIO6, FSPICLK, MTCK).
* **MI/GPIO7**: The main SPI0 MISO(GPIO7, FSPID, MTDO).
* **RX/GPIO20**: The main UART0 RX pin(GPIO20, U0RXD).
* **TX/GPIO21**: The main UART0 TX pin(GPIO21, U0TXD).
### Schematic Diagram For Glyph-C3
For better view you can download the schematic diagram from [here](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/Glyph-C3-Schematic.pdf)
# Power Management
Source: https://learn.pcbcupid.com/documentation/modules/glyph-mini/glyph-mini-2040/power-management
Power the Glyph Mini 2040 over USB-C or a single-cell lithium battery, monitor charge status, and configure low-power deep sleep modes for IoT projects.
## Power Management for Glyph Mini 2040
### Battery + USB Power
We wanted to make our Glyph boards easy to power both when connected to a computer as well as via battery for portability!
There's two ways to power a Glyph:
1. **USB Power:** You can connect with a USB cable (just plug into the TYPE C Port) and the Glyph will regulate the 5V USB down to 3.3V and power the entire board and peripherals (if any connected).
2. **Battery Power:** You can also connect a 4.2/3.7V Lithium Polymer (LiPo/lipo) or Lithium Ion (LiIon) battery to Battery Pads. This will let the Glyph run on a rechargeable battery.
When the USB power is powered, it will automatically switch over to USB for power, as well as start charging the battery (if attached). This happens 'hot-swap' style so you can always keep the lipo connected as a 'backup' power that will only get used when USB power is lost.
Install the LiPo / Li-ion batteries based on the polarity. Using wrong polarity batteries can destroy your Glyph.
### Power Supplies
The Glyph Mini 2040 offers multiple power supply options:
* **BAT Pin**: Connected to the battery pads (behind the board)
* **USB Pin**: Provides +5V from USB if connected.
* **3V Pin**: Provides output from the 3.3V regulator with a 600mA peak output.
### Measuring Battery Voltage
To monitor battery voltage, short the MSR pads behind the board.
### Alternative Power Options
For powering the Glyph Mini 2040:
* **USB powered**: Use a 5V 1A USB wall adapter to plug in a USB cable for reliable power.
* **Portable Use Without LiPo**: Use a USB battery pack(Power Bank).
* **Higher Voltage Power Supply**: Use a 5V buck converter and wire it to a USB cable's 5V and GND input.
**What You Cannot Do**
* Do not use alkaline or NiMH batteries and connect to the battery port, as it will destroy the LiPo charger.
* Do not use anything >4.2v LiPo batteries on the battery port, as it will destroy the board.
### External Power Supplies
The Glyph ESP32-c3 is not designed for external power supplies. If you must:
* **Connect an external 3.3V power supply** to the 3V and GND pins
* **Connect an external 5V power supply** to the USB and GND pins.
# Assembly
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c3/assembly
Assemble the Glyph C3 by soldering headers to suit your project. Boards ship fully tested without headers attached for maximum configuration flexibility.
We ship Glyphs fully tested but without headers attached - this gives you the most flexibility on choosing how to use and configure your Glyph.
### Header Options!
Before you start soldering, consider the following options for headers:
**Option 1: Plain Male Headers**
This option lets you plug the Glyph into a solderless breadboard.
**Option 2: Socket Female Headers**
This option won't let you plug the Glyph into a breadboard but it will let you attach our upcoming glyph module and sensors boards very easily.
This can be helpful if you want to connect this board to other boards using jumper cables.
**Option 3: Stacking Headers**
This option is sort of the best-of-both-worlds. You get the ability to plug into a solderless breadboard and plug a GlyphWing on top. But it's a little bulky.
# Overview
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c3/overview-glyph-c3
Overview of the Glyph C3 development board: a compact RISC-V microcontroller with Wi-Fi, Bluetooth LE, and Qwiic-compatible Glink connector.
Introducing the Glyph C3, a super efficient microcontroller development board packed with features for your next IoT project! With the robust capabilities of the ESP32-C3 chip, the Glyph-C3 is designed to provide reliable performance and extensive connectivity options in a compact form factor.
* **Dimensions**: Measures 50.8mm x 22.8mm x 1.6mm (without headers soldered)
* **Processor**: C3 32-bit RISC-V single-core processor running at 160 MHz @ 3.3V logic and power
* **RAM**: 400 KB SRAM
* **Flash Memory**: 4 MB SPI FLASH
* **GPIO**: 15 GPIO pins with the following capabilities:
* 12-bit ADCs
* I2C
* SPI
* UART
* USB Serial
All the important peripherals, labeled for easy access.
* **Power Management**:
* USB Type C connector for power, programming, and serial port debugging
* 3.3V regulator with 600mA peak current output
* Built-in lipoly/li-ion charger with charging status indicator LED
* Auto Switch between Battery & USB Power
* Ability to Measure Battery Capacity
* Ability to Turn off the battery with the onboard slide switch
* Reverse Voltage protection with Diode
* **Additional Feature**:
* On-board LED (Connected to GPIO1)
* On-board GLINK connector for easy integration with QWIIC, STEMMA QT compatible sensors & modules.
* High Quality Reset and Bootloader button for easy access
### Native Bootloader and Programming
The Glyph C3 features a built-in USB bootloader that makes programming new firmware easy and keeps the cost of the board down. On first time use, hold down the BOOT button while plugging it into USB, and it will appear as COM PORT in your device Manager. If you face any issue related to hardware not detecting on your system, please check out our troubleshooting guide [here](https://learn.pcbcupid.com/boards/needs/arduino-ide-setup#hardware-not-detecting).
### Connectivity
The Glyph C3 excels in connectivity with its built-in Wi-Fi and Bluetooth support. This makes it ideal for IoT applications, where reliable wireless communication is crucial.
The wireless module on GLYPH board is CE & FCC Certified
### Development Support
The C3 Glyph is supported by a variety of development environments, including:
* **Arduino**
* **MicroPython**
* **ESP-IDF (Espressif IoT Development Framework)**
With extensive library support and a large community, getting started with the Glyph C3 is straightforward.
### Memory and Storage
While the Glyph C3 has 400KB onboard SRAM, it also relies on an external flash chip for program storage. On this board, there is 4 MB of flash memory, which is shared between the code, file storage and OTA.
### C3 Chip Features
* **BluFi**
* **RF Coexistence**
* **ESP-BLE-MESH**
* **ESP-WIFI-MESH**
You can read more about it in [ESP32C3 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/PCBCUPID_ESP32C3_DATASHEET.pdf) and [ESP32C3 OFFICIAL](https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/get-started/index.html) documentation.
***
# Pinouts
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c3/pinouts
Tour the Glyph C3 board: GPIO pin assignments, power rails, communication interfaces, USB-C port, and Glink connector reference pinout.
[CLICK HERE TO DOWNLOAD HD](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/PCBCUPID_GLYPHC3_DEVKIT_Pinout_PNG.png)
[CLICK HERE TO DOWNLOAD PDF](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/PCBCUPID_C3_DEVKIT_Pinout.pdf)
The Glyph-C3 has many pins, ports, and features. This page takes you on a tour on each of the pin on the board!
**Notice to Developers:** The Glyph-C3 Dev Kit features mirrored physical pins for specific GPIOs. The following physical pin pairs are electrically connected to the same internal trace on the ESP32-C3:
| GPIO Label | Left Physical Pin | Right Physical Pin |
| :--------- | :---------------- | :----------------- |
| **GPIO3** | Pin 6 | Pin 20 |
| **GPIO2** | Pin 7 | Pin 19 |
| **GPIO1** | Pin 8 | Pin 18 |
| **GPIO0** | Pin 9 | Pin 17 |
**IMPORTANT:** Do not connect separate electronic components to both pins in a pair simultaneously. Treating these as independent pins will cause signal conflicts and potential hardware damage to the microcontroller. Always choose only one physical pin from each pair for your circuit.
GPIO 8 and GPIO 9 are **Strapping Pins** used during the chip's power-on/reset sequence to determine the boot mode:
* **GPIO 9**: Controls whether the chip boots from internal Flash (Default: High) or enters **Serial Download Mode** (Low). On your Glyph board, this pin is connected to the onboard **BOOT** button.
* **GPIO 8**: Determines the boot behavior and log output. It should ideally be pulled High or left floating during reset for normal operation.
Avoid connecting peripherals to these pins that might pull them to an unexpected state during startup.
### Power Pins and Connections
* **GND**: This is the common ground for all power and logic.
* **BAT**: This is the positive voltage to/from the Battery(+) Positive terminal (This pin is usual at voltage between 2.7v-4.2v)
* **USB**: This is the positive voltage to/from the USB C jack, if USB is connected (This is usual at voltage 5v)
* **EN**: This is the enable pin of esp32, you can pull down this using a external button or other controller to reset the board.
* **3.3V**: These pins are the output from the 3.3V regulator, they can supply 600mA peak current.
* **Lipo Battery PADS**: 2 Pads behind the board to solder Lipo or li-ion batteries to power the Glyph board.
* **MSR PADS**: Short this MSR pad to measure battery capacity using IO0 (Marked as A0 on board).
### Communication Pins
#### I2C, SPI, and UART on ESP32-C3
The ESP32-C3 is capable of handling I2C, SPI, and UART on many pins. However, to simplify things we have assigned few of the IO pins to make things simpler for users.
#### I2C Pins
* I2C SCL: **SCL**, IO5
* I2C SDA: **SDA**, IO4
### Additional Ports / Pins
#### Glyph Glink Port
This is a QWIIC / STEMMA compatible connector which makes it easy for users to connect to 100's of sensors and modules made by Adafruit & Sparkfun.
#### USB Pins
This is used for power and data transfer. Connect to your computer via a USB C cable to update firmware and at the **USB** pin you would receive 5v
#### PWM Pins
The ESP32-C3 supports PWM on all pins. However, it is not capable of PWM on all pins at the same time. There are multiple PWM channels, each with configurable frequency and duty cycle. The important thing to know is that you cannot use the same channel on different pins at the same time. Please refer to [ESP32C3 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/PCBCUPID_ESP32C3_DATASHEET.pdf)
### Analog Pins
The ESP32-C3 has four ADC channels. These pins are the only pins capable of handling analog (12-bit), and they can also do digital.
* **A0/IO0**: ADC1 channel 0
* **A1/IO1**: ADC1 channel 1
* **A2/IO2**: ADC1 channel 2
* **A3/IO3**: ADC1 channel 3
* **SDA/IO4**: ADC1 channel 4
* **SCL/IO5**: ADC2 channel 0
### Digital Pins
These are the digital I/O pins. They all have multiple capabilities but can be used only one at a time.
* **D0/GPIO0**: Digital I/O pin 0( GPIO0, ADC1\_CH0, XTAL\_32K\_P).
* **D1/GPIO1**: Digital I/O pin 1(GPIO1, ADC1\_CH1, XTAL\_32K\_N).
* **D2/GPIO2**: Digital I/O pin 2(GPIO2, ADC1\_CH2, FSPIQ).
* **D3/GPIO3**: Digital I/O pin 3(GPIO3, ADC1\_CH3).
* **SDA/GPIO4**: The main I2C1 data pin(GPIO4, ADC1\_CH4, FSPIHD, MTMS).
* **SCL/GPIO5**: The main I2C1 clock pin(GPIO5, ADC2\_CH0, FSPIWP, MTDI).
* **D8/GPIO8**: Digital I/O pin 8(GPIO8).
* **D9/GPIO9**: Digital I/O pin 9(GPIO9).
* **A0/GPIO0**: Analog I/O pin 0(GPIO0, ADC1\_CH0, XTAL\_32K\_P).
* **A1/GPIO1**: Analog I/O pin 1(GPIO1, ADC1\_CH1, XTAL\_32K\_N).
* **A2/GPIO2**: Analog I/O pin 2(GPIO2, ADC1\_CH2, FSPIQ).
* **A3/GPIO3**: Analog I/O pin 3(GPIO3, ADC1\_CH3).
* **D-/GPIO18**: Digital I/O pin 18(GPIO18, USB\_D).
* **D+/GPIO19**: Digital I/O pin 19(GPIO19, USB\_D+).
* **SCK/GPIO10**: The main SPI0 SCK(GPIO10, FSPICS0).
* **MO/GPIO6**: The main SPI0 MOSI(GPIO6, FSPICLK, MTCK).
* **MI/GPIO7**: The main SPI0 MISO(GPIO7, FSPID, MTDO).
* **RX/GPIO20**: The main UART0 RX pin(GPIO20, U0RXD).
* **TX/GPIO21**: The main UART0 TX pin(GPIO21, U0TXD).
### Schematic Diagram For Glyph-C3
For better view you can download the schematic diagram from [here](https://files.pcbcupid.com/Documentation/Boards/glyph_c3/Glyph-C3-Schematic.pdf)
# Power Management
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c3/power-management
Power the Glyph C3 over USB-C or a single-cell lithium battery, monitor charge status, and configure low-power deep sleep modes for IoT projects.
## Power Management for Glyph C3
### Battery + USB Power
We wanted to make our Glyph boards easy to power both when connected to a computer as well as via battery for portability!
There's two ways to power a Glyph:
1. **USB Power:** You can connect with a USB cable (just plug into the TYPE C Port) and the Glyph will regulate the 5V USB down to 3.3V and power the entire board and peripherals (if any connected).
2. **Battery Power:** You can also connect a 4.2/3.7V Lithium Polymer (LiPo/lipo) or Lithium Ion (LiIon) battery to Battery Pads. This will let the Glyph run on a rechargeable battery.
When the USB power is powered, it will automatically switch over to USB for power, as well as start charging the battery (if attached). This happens 'hot-swap' style so you can always keep the lipo connected as a 'backup' power that will only get used when USB power is lost.
Install the LiPo / Li-ion batteries based on the polarity. Using wrong polarity batteries can destroy your Glyph.
### Power Supplies
The Glyph C3 offers multiple power supply options:
* **BAT Pin**: Connected to the battery pads (behind the board)
* **USB Pin**: Provides +5V from USB if connected.
* **3V Pin**: Provides output from the 3.3V regulator with a 600mA peak output.
### Measuring Battery Voltage
To monitor battery voltage, short the MSR pads behind the board.
### Alternative Power Options
For powering the Glyph C3:
* **USB powered**: Use a 5V 1A USB wall adapter to plug in a USB cable for reliable power.
* **Portable Use Without LiPo**: Use a USB battery pack(Power Bank).
* **Higher Voltage Power Supply**: Use a 5V buck converter and wire it to a USB cable's 5V and GND input.
**What You Cannot Do**
* Do not use alkaline or NiMH batteries and connect to the battery port, as it will destroy the LiPo charger.
* Do not use anything >4.2v LiPo batteries on the battery port, as it will destroy the board.
### External Power Supplies
The Glyph ESP32-c3 is not designed for external power supplies. If you must:
* **Connect an external 3.3V power supply** to the 3V and GND pins
* **Connect an external 5V power supply** to the USB and GND pins.
# Power Management
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c6/glyph-esp32-c6-power-management
Power the Glyph C6 over USB-C or a single-cell lithium battery, monitor charge status, and configure deep sleep modes for low-power IoT projects.
## Power Management for Glyph C6
### Battery + USB Power
We designed the Glyph C6 to be easy to power both when connected to a computer and via a battery. Here are the ways to power your Glyph:
1. **USB Power**: Connect with a USB cable to regulate the 5V USB down to 3.3V.
2. **Battery Power**: Connect a 4.2/3.7V Lithium Polymer (LiPo/LiPo) or Lithium Ion (LiIon) battery to the JST jack for rechargeable battery power.
When USB power is connected, it will automatically switch over to USB for power and start charging the battery (if attached). This hot-swap functionality allows you to keep the LiPo connected as a backup power source that will only be used when USB power is lost.
Install the LiPo / Li-ion batteries based on the polarity. Using wrong polarity batteries can destroy your Glyph.
### Power Supplies
The Glyph C6 offers multiple power supply options:
* **BAT Pin**: Connected to the battery pads (behind the board)
* **USB Pin**: Provides +5V from USB if connected.
* **3V Pin**: Provides output from the 3.3V regulator with a 600mA peak output.
### Measuring Battery Voltage
To monitor battery voltage, short the msr pads behind the board.
### Alternative Power Options
For powering the Glyph C6:
* **USB powered**: Use a 5V 1A USB wall adapter to plug in a USB cable for reliable power.
* **Portable Use Without LiPo**: Use a USB battery pack(Power Bank).
* **Higher Voltage Power Supply**: Use a 5V buck converter and wire it to a USB cable's 5V and GND input.
**What You Cannot Do**
* Do not use alkaline or NiMH batteries and connect to the battery port, as it will destroy the LiPo charger.
* Do not use anything >4.2v LiPo batteries on the battery port, as it will destroy the board.
### External Power Supplies
The Glyph C6 is not designed for external power supplies. If you must:
* **Connect an external 3.3V power supply** to the 3V and GND pins
* **Connect an external 5V power supply** to the USB and GND pins.
# Assembly
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c6/glyphc6-assembly
Assemble the Glyph C6 by soldering headers to suit your project. Boards ship fully tested without headers attached for maximum configuration flexibility.
We ship Glyphs fully tested but without headers attached - this gives you the most flexibility on choosing how to use and configure your Glyph.
### Header Options!
Before you start soldering, consider the following options for headers:
**Option 1: Plain Male Headers**
This option lets you plug the Glyph into a solderless breadboard.
**Option 2: Socket Female Headers**
This option won't let you plug the Glyph into a breadboard but it will let you attach our upcoming glyph module and sensors boards very easily. This can be helpful if you want to connect this board to other boards using jumper cables.
**Option 3: Stacking Headers**
This option is sort of the best-of-both-worlds. You get the ability to plug into a solderless breadboard and plug a GlyphWing on top. But it's a little bulky.
# Pinouts
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c6/glyphc6-pinouts
Tour the Glyph C6 board: GPIO pin assignments, power rails, communication buses, USB-C port, and Glink connector reference pinout diagram.
[CLICK HERE TO DOWNLOAD HD](https://files.pcbcupid.com/Documentation/Boards/glyph_c6/PCBCUPID_GlyphC6_DEVKIT_Pinout_PNG.png)
[CLICK HERE TO DOWNLOAD PDF](https://files.pcbcupid.com/Documentation/Boards/glyph_c6/PCBCUPID_C6_DEVKIT_Pinout.pdf)
The Glyph C6 has many pins, ports, and features. This page takes you on a tour on each of the pin on the board!
GPIO 8 and GPIO 9 are **Strapping Pins** used during the chip's power-on/reset sequence to determine the boot mode:
* **GPIO 9**: Controls whether the chip boots from internal Flash (Default: High) or enters **Serial Download Mode** (Low). On your Glyph board, this pin is connected to the onboard **BOOT** button.
* **GPIO 8**: Determines the boot behavior and log output. It should ideally be pulled High or left floating during reset for normal operation.
Avoid connecting peripherals to these pins that might pull them to an unexpected state during startup.
### Power Pins and Connections
* **GND**: This is the common ground for all power and logic.
* **BAT**: This is the positive voltage to/from the Battery(+) Positive terminal (This pin is usual at voltage between 2.7v-4.2v)
* **USB**: This is the positive voltage to/from the USB C jack, if USB is connected (This is usual at voltage 5v)
* **EN**: This is the enable pin of esp32, you can pull down this using a external button or other controller to reset the board.
* **3.3V**: These pins are the output from the 3.3V regulator, they can supply 600mA peak current.
* **Lipo Battery PADS**: 2 Pads behind the board to solder Lipo or li-ion batteries to power the Glyph board.
* **MSR PADS**: Short this MSR pad to measure battery capacity using IO0 (Marked as A0 on board).
### Communication Pins
#### I2C, SPI, and UART on C6
The C6 is capable of handling I2C, SPI, and UART on many pins. However, to simplify things we have assigned few of the IO pins to make things simpler for users.
#### I2C Pins
* I2C0 SCL: **SCL**, IO5
* I2C0 SDA: **SDA**, IO4
### Additional Ports / Pins
#### Glyph Glink Port
This is a QWIIC / STEMMA compatible connector which makes it easy for users to connect to 100's of sensors and modules made by Adafruit & Sparkfun.
#### USB Pins
This is used for power and data transfer. Connect to your computer via a USB C cable to update firmware and at the USB pin you would receive 5v
#### PWM Pins
The C3 supports PWM on all pins. However, it is not capable of PWM on all pins at the same time. There are multiple PWM channels, each with configurable frequency and duty cycle. The important thing to know is that you cannot use the same channel on different pins at the same time. Please refer to [ESP32C6 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph_c6/PCBCUPID_ESP32C6_DATASHEET.pdf)
### Analog Pins
The C6 has four ADC channels. These pins are the only pins capable of handling analog, and they can also do digital.
* **A0/IO0**: ADC1 channel 0
* **A1/IO1**: ADC1 channel 1
* **A2/IO2**: ADC1 channel 2
* **A3/IO3**: ADC1 channel 3
* **SDA/IO4**: ADC1 channel 4
* **SCL/IO5**: ADC1 channel 5
### Digital Pins
These are the digital I/O pins. They all have multiple capabilities but can be used only one at a time.
* **A0/GPIO0**: Analog I/O pin 0(GPIO0, XTAL\_32K\_P, LP\_GPIO0, LP\_UART\_DTRN, ADC1\_CH0).
* **A1/GPIO1**: Analog I/O pin 1(GPIO1, XTAL\_32K\_N, LP\_GPIO1, LP\_UART\_DSRN, ADC1\_CH1).
* **A2/GPIO2**: Analog I/O pin 2(GPIO2, LP\_GPIO2, LP\_UART\_RTSN, ADC1\_CH2, FSPIQ).
* **A3/GPIO3**: Analog I/O pin 3(GPIO3, LP\_GPIO3, LP\_UART\_CTSN, ADC1\_CH3).
* **SDA/GPIO4**: The main I2C1 data pin(MTMS, GPIO4, LP\_GPIO4, LP\_UART\_RXD, ADC1\_CH4, FSPIHD).
* **SCL/GPIO5**: The main I2C1 clock pin(MTDI, GPIO5, LP\_GPIO5, LP\_UART\_TXD, ADC1\_CH5, FSPIWP).
* **D6/GPIO6**: Digital I/O pin 6(MTCK, GPIO6, LP\_GPIO6, LP\_I2C\_SDA, ADC1\_CH6, FSPICLK).
* **D7/GPIO7**: Digital I/O pin 7(MTDO, GPIO7, LP\_GPIO7, LP\_I2C\_SCL, FSPID).
* **D8/GPIO08**: Digital I/O pin 8(GPIO8).
* **D9/GPIO09**: Digital I/O pin 9(GPIO9).
* **D14/GPIO14**: Digital I/O pin 14(GPIO14).
* **D15/GPIO15**: Digital I/O pin 15(GPIO15).
* **TX/GPIO16**: The main UART0 TX pin(U0TXD, GPIO16, FSPICS0).
* **RX/GPIO17**: The main UART0 RX pin( U0RXD, GPIO17, FSPICS1).
* **D18/GPIO18**: Digital I/O pin 18(GPIO18, SDIO\_CMD, FSPICS2).
* **D19/GPIO19**: Digital I/O pin 19(GPIO19, SDIO\_CLK, FSPICS3).
* **D20/GPIO20**: Digital I/O pin 20(GPIO20, SDIO\_DATA0, FSPICS4).
* **SCK/GPIO21**: The main SPI0 SCK(GPIO21, SDIO\_DATA1, FSPICS5).
* **MO/GPIO22**: The main SPI0 MOSI(GPIO22, SDIO\_DATA2).
* **MI/GPIO23**: The main SPI0 MISO(GPIO23, SDIO\_DATA3).
### Schematic Diagram For Glyph-C6
For better view you can download the schematic diagram from [here](https://files.pcbcupid.com/Documentation/Boards/glyph_c6/Glyph-C6-Schematic.pdf)
# Overview
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32c6/overview-glyph-c6
Overview of the Glyph C6 development board: a RISC-V microcontroller with Wi-Fi 6, Bluetooth LE, Zigbee, Thread, and a Qwiic Glink connector.
Introducing the Glyph C6, a super efficient microcontroller development board packed with features for your next IoT project! With the robust capabilities of the ESP32-C6 chip, the Glyph-C6 is designed to provide reliable performance and extensive connectivity options in a compact form factor.
* **Dimensions**: Measures 50.8mm x 22.8mm x 1.6mm without headers soldered in
* **Processor**: ESP32-C6 32-bit RISC-V single-core processor running at 160 MHz @ 3.3V logic and power
* **RAM**: 512 KB SRAM
* **Flash Memory**: 4 MB SPI FLASH
* **GPIO**: 20 GPIO pins with the following capabilities:
* 12-bit ADCs
* I2C
* SPI
* UART
* USB Serial
All the important peripherals, labeled for easy access.
* **Power Management**:
* USB Type C connector for power, programming, and serial port debugging
* 3.3V regulator with 600mA peak current output
* Built-in lipoly/li-ion charger with charging status indicator LED
* Auto Switch between Battery & USB Power
* Ability to Measure Battery Capacity
* Ability to Turn off the battery with the onboard slide switch
* Reverse Voltage protection with Diode
* **Additional Feature**:
* On-board LED (Connected to GPIO14)
* On-board GLINK connector for easy integration with QWIIC, STEMMA QT compatible sensors & modules.
* High Quality Reset and Bootloader button for easy access
### Bootloader and Programming
The Glyph-C6 features a built-in USB bootloader that makes programming new firmware easy and keeps the cost of the board down. On first time use, hold down the BOOT button while plugging it into USB, and it will appear as COM PORT in your device Manager. If you face any issue related to hardware not detecting on your system, please check out our troubleshooting guide [here](https://learn.pcbcupid.com/boards/needs/arduino-ide-setup#hardware-not-detecting).
### Connectivity
Featuring built-in Bluetooth, Thread, Zigbee and Wi-Fi the ESP32-C6 Glyph excels in connectivity, ideal for IoT applications requiring reliable wireless communication.
The wireless module on GLYPH board is CE & FCC Certified
### Development Support
The Glyph C3 is supported by a variety of development environments, including:
* **Arduino**
* **MicroPython**
* **ESP-IDF (Espressif IoT Development Framework)**
With extensive library support and a large community, getting started with the Glyph-C6 is straightforward.
### Memory and Storage
While the Glyph C6 has 512KB onboard SRAM, it also relies on an external flash chip for program storage. On this board, there is 4 MB of flash memory, which is shared between the code, file storage and OTA.
### C6 Chip Features
* **BluFi**
* **RF Coexistence**
* **ESP-BLE-MESH**
* **ESP-WIFI-MESH**
You can read more about it in [ESP32C6 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph_c6/PCBCUPID_ESP32C6_DATASHEET.pdf) and [ESP32C6 OFFICIAL](https://docs.espressif.com/projects/esp-idf/en/v5.3.1/esp32c6/get-started/index.html) documentation.
# Assembly
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32h2/glyph-assembly
Assemble the Glyph H2 by soldering headers to suit your project. Boards ship fully tested without headers attached for maximum configuration flexibility.
We ship Glyph H2 boards fully tested but without headers attached to give you the most flexibility on how you choose to use and configure your Glyph.
#### Header Options!
Before you start soldering, consider the following options for headers:
**Option 1: Plain Male Headers**
This option lets you plug the Glyph into a solderless breadboard.
**Option 2: Socket Female Headers**
This option won't let you plug the Glyph into a breadboard but it will let you attach Glyph very easily.
**Option 3: Stacking Headers**
This option is sort of the best-of-both-worlds. You get the ability to plug into a solderless breadboard and plug a Glyph on top. But it's a little bulky.
# Overview
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32h2/overview-glyph-h2
Overview of the Glyph H2 development board: a RISC-V microcontroller with Bluetooth LE, Zigbee, and Thread for low-power mesh networking.
Introducing the Glyph H2, a super efficient microcontroller development board packed with features for your next IoT project! With the robust capabilities of the H2 chip, the Glyph H2 is designed to provide reliable performance and extensive connectivity options in a compact form factor.
* **Dimensions**: Measures 50.8mm x 22.8mm x 1.6mm (without headers soldered)
* **Processor**: 32-bit RISC-V single-core processor running at 96 MHz @ 3.3V logic and power
* **RAM**: 320 KB SRAM
* **Flash Memory**: 4 MB SPI FLASH
* **GPIO**: 19 GPIO pins with the following capabilities:
* 12-bit ADCs
* I2C
* SPI
* UART
* USB Serial
All the important peripherals, labeled for easy access.
* **Power Management**:
* USB Type C connector for power, programming, and serial port debugging
* 3.3V regulator with 600mA peak current output
* Built-in lipoly/li-ion charger with charging status indicator LED
* Auto Switch between Battery & USB Power
* Ability to Measure Battery Capacity
* Ability to Turn off the battery with the onboard slide switch
* Reverse Voltage protection with Diode
**Additional Feature**:
* On-board LED (Connected to GPIO0)
* On-board GLINK connector for easy integration with QWIIC, STEMMA QT compatible sensors & modules.
* High Quality Reset and Bootloader button for easy access
### Native Bootloader and Programming
The Glyph H2 features a built-in USB bootloader that makes programming new firmware easy and keeps the cost of the board down. On first time use, hold down the BOOT button while plugging it into USB, and it will appear as COM PORT in your device Manager. If you face any issue related to hardware not detecting on your system, please check out our troubleshooting guide [here](https://learn.pcbcupid.com/boards/needs/arduino-ide-setup#hardware-not-detecting).
### Connectivity
The Glyph H2 excels in connectivity with its built-in Bluetooth, Thread, Zigbee support. This makes it ideal for IoT applications, where reliable wireless communication is crucial.
The wireless module on GLYPH board is CE & FCC Certified
### Development Support
The Glyph H2 is supported by a variety of development environments, including:
* **Arduino**.
* **MicroPython**.
* **ESP-IDF (Espressif IoT Development Framework)**.
With extensive library support and a large community, getting started with the Glyph H2 is straightforward.
### Memory and Storage
While the Glyph H2 has 320KB onboard SRAM, it also relies on an external flash chip for program storage. On this board, there is 4 MB of flash memory, which is shared between the code, file storage and OTA.
### ESP32-H2 Chip Features
* **BluFi**
* **RF Coexistence**
* **ESP-BLE-MESH**
* **ESP-WIFI-MESH**
You can read more about it in [ESP32H2 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph_h2/PCBCUPID_ESP32H2_DATASHEET.pdf) and [ESP32H2 OFFICIAL](https://docs.espressif.com/projects/esp-idf/en/v5.3.1/esp32h2/get-started/index.html) documentation.
# Pinouts
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32h2/pinouts-h2
Tour the Glyph H2 board: GPIO pin assignments, power rails, communication buses, USB-C port, and Glink connector reference pinout diagram.
[CLICK HERE TO DOWNLOAD HD](https://files.pcbcupid.com/Documentation/Boards/glyph_h2/PCBCUPID_GlyphH2_DEVKIT_Pinout_PNG.png)
[CLICK HERE TO DOWNLOAD PDF](https://files.pcbcupid.com/Documentation/Boards/glyph_h2/PCBCUPID_H2_DEVKIT_Pinout.pdf)
The Glyph H2 board is packed with versatile pins and features. This guide will help you navigate the pinout details for efficient use.
GPIO 8 and GPIO 9 are **Strapping Pins** used during the chip's power-on/reset sequence to determine the boot mode:
* **GPIO 9**: Controls whether the chip boots from internal Flash (Default: High) or enters **Serial Download Mode** (Low). On your Glyph board, this pin is connected to the onboard **BOOT** button.
* **GPIO 8**: Determines the boot behavior and log output. It should ideally be pulled High or left floating during reset for normal operation.
Avoid connecting peripherals to these pins that might pull them to an unexpected state during startup.
### Power Pins and Connections
* **GND**: This is the common ground for all power and logic.
* **BAT**: This is the positive voltage to/from the Battery(+) Positive terminal (This pin is usual at voltage between 2.7v-4.2v)
* **USB**: This is the positive voltage to/from the USB C jack, if USB is connected (This is usual at voltage 5v)
* **EN**: This is the enable pin of esp32, you can pull down this using a external button or other controller to reset the board.
* **3.3V**: These pins are the output from the 3.3V regulator, they can supply 600mA peak current.
* **Lipo Battery PADS**: 2 Pads behind the board to solder Lipo or li-ion batteries to power the Glyph board.
* **MSR PADS**: Short this MSR pad to measure battery capacity using IO1 (Marked as A1 on board).
### Communication Pins
#### I2C, SPI, and UART on ESP32-H2
The ESP32-H2 is capable of handling I2C, SPI, and UART on many pins. However, to simplify things we have assigned few of the IO pins to make things simpler for users.
#### I2C Pins
* I2C0 SCL: **SCL**, IO5
* I2C0 SDA: **SDA**, IO4
### Additional Ports / Pins
#### Glyph Glink Port
This is a QWIIC / STEMMA compatible connector which makes it easy for users to connect to 100's of sensors and modules made by Adafruit & Sparkfun.
#### USB Pins
This is used for power and data transfer. Connect to your computer via a USB C cable to update firmware and at the USB pin you would receive 5v
#### PWM Pins
The ESP32-H2 supports PWM on all pins. However, it is not capable of PWM on all pins at the same time. There are multiple PWM channels, each with configurable frequency and duty cycle. The important thing to know is that you cannot use the same channel on different pins at the same time. Please refer to [ESP32H2 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph_h2/PCBCUPID_ESP32H2_DATASHEET.pdf)
### Analog Pins
The ESP32-H2 has four ADC channels. These pins are the only pins capable of handling analog (12-bit), and they can also do digital.
* **A1/IO1**: ADC1 channel 0
* **A2/IO2**: ADC1 channel 1
* **A3/IO3**: ADC1 channel 2
* **SDA/IO4**: ADC1 channel 3
* **SCL/IO5**: ADC2 channel 4
### Digital Pins
These are the digital I/O pins. They all have multiple capabilities but can be used only one at a time.
* **D0/GPIO0**: Digital I/O pin 0(GPIO0, FSPIQ).
* **A1/GPIO1**: Analog I/O pin 1(GPIO1, FSPICS0, ADC1\_CH0).
* **A2/GPIO2**: Analog I/O pin 2(GPIO2, FSPIWP, ADC1\_CH1, MTMS).
* **A3/GPIO3**: Analog I/O pin 3(GPIO3, FSPIHD, ADC1\_CH2, MTDO).
* **SDA/GPIO4**: The main I2C1 data pin(GPIO4, FSPICLK, MTCK,ADC1\_CH3).
* **SCL/GPIO5**: The main I2C1 clock pin(GPIO5, FSPID,ADC1\_CH4,MTDI).
* **D8/GPIO08**: Digital I/O pin 8(GPIO8).
* **D9/GPIO09**: Digital I/O pin 9(GPIO9).
* **D10/GPIO10**: Digital I/O pin 10(GPIO10, ZCD0).
* **SCK/GPIO11**: The main SPI0 SCK(GPIO11, ZCD1).
* **D12/GPIO12**: Digital I/O pin 12(GPIO12).
* **D13/GPIO13**: Digital I/O pin 13(GPIO13, XTAL\_32K\_P).
* **D14/GPIO14**: Digital I/O pin 14(GPIO14, XTAL\_32K\_N).
* **MO/GPIO22**: The main SPI0 MOSI(GPIO22).
* **RX/GPIO23**: The main UART0 RX pin(FSPICS1, U0RXD).
* **TX/GPIO24**: The main UART0 TX pin(GPIO23,FSPICS2, U0TXD).
* **MI/GPIO25**: The main SPI0 MISO(GPIO24,I2C0 SDA, SPI0 CS).
* **D-/GPIO26**: Digital I/O pin 26(GPIO26,FSPICS4,USB\_D-).
* **D+/GPIO27**: Digital I/O pin 27(GPIO27,FSPICS5,USB\_D+).
### Schematic Diagram For Glyph-H2
For better view you can download the schematic diagram from [here](https://files.pcbcupid.com/Documentation/Boards/glyph_h2/Glyph-H2-Schematic.pdf)
# Power Management
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32h2/power-management-glyph
Power the Glyph H2 over USB-C or a single-cell lithium battery, monitor charge status, and configure deep sleep modes for low-power mesh nodes.
## Power Management for Glyph H2
### Battery + USB Power
We designed the Glyph H2 to be easy to power both when connected to a computer and via a battery. Here are the ways to power your Glyph:
1. **USB Power**: Connect with a USB cable to regulate the 5V USB down to 3.3V.
2. **Battery Power**: Connect a 4.2/3.7V Lithium Polymer (LiPo/LiPo) or Lithium Ion (LiIon) battery to the JST jack for rechargeable battery power.
When USB power is connected, it will automatically switch over to USB for power and start charging the battery (if attached). This hot-swap functionality allows you to keep the LiPo connected as a backup power source that will only be used when USB power is lost.
Install the LiPo / Li-ion batteries based on the polarity. Using wrong polarity batteries can destroy your Glyph.
### Power Supplies
The Glyph H2 offers multiple power supply options:
* **BAT Pin**: Connected to the battery pads (behind the board)
* **USB Pin**: Provides +5V from USB if connected.
* **3V Pin**: Provides output from the 3.3V regulator with a 600mA peak output.
### Measuring Battery Voltage
To monitor battery voltage, short the msr pads behind the board.
### Alternative Power Options
For powering the Glyph H2:
* **USB powered**: Use a 5V 1A USB wall adapter to plug in a USB cable for reliable power.
* **Portable Use Without LiPo**: Use a USB battery pack(Power Bank).
* **Higher Voltage Power Supply**: Use a 5V buck converter and wire it to a USB cable's 5V and GND input.
**What You Cannot Do**
* Do not use alkaline or NiMH batteries and connect to the battery port, as it will destroy the LiPo charger.
* Do not use anything >4.2v LiPo batteries on the battery port, as it will destroy the board.
### External Power Supplies
The Glyph H2 is not designed for external power supplies. If you must:
* **Connect an external 3.3V power supply** to the 3V and GND pins
* **Connect an external 5V power supply** to the USB and GND pins.
# Assembly
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32s3/glyph-esp32-s3-assembly
Assemble the Glyph S3 by soldering headers to suit your project. Boards ship fully tested without headers attached for maximum configuration flexibility.
We ship Glyphs fully tested but without headers attached - this gives you the most flexibility on choosing how to use and configure your Glyph.
### Header Options!
Before you start soldering, consider the following options for headers:
**Option 1: Plain Male Headers**
This option lets you plug the Glyph into a solderless breadboard.
**Option 2: Socket Female Headers**
This option won't let you plug the Glyph into a breadboard but it will let you attach our upcoming glyph module and sensors boards very easily.
This can be helpful if you want to connect this board to other boards using jumper cables.
**Option 3: Stacking Headers**
This option is sort of the best-of-both-worlds. You get the ability to plug into a solderless breadboard and plug a GlyphWing on top. But it's a little bulky.
# Pinouts
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32s3/glyph-esp32-s3-pinouts
Tour the Glyph S3 board: GPIO pin assignments, power rails, communication buses, USB-C port, and Glink connector reference pinout diagram.
[CLICK HERE TO DOWNLOAD HD](https://files.pcbcupid.com/Documentation/Boards/glyph-S3/Glyph%20S3%20Pinouts.png)
[CLICK HERE TO DOWNLOAD PDF](https://files.pcbcupid.com/Documentation/Boards/glyph-S3/PCBCUPID_Glyph_S3_Pinouts.pdf)
The Glyph S3 has many pins, ports, and features. This page takes you on a tour on each of the pin on the board!
### Power Pins and Connections
* **GND**: This is the common ground for all power and logic.
* **BAT**: This is the positive voltage to/from the Battery(+) Positive terminal (This pin is usual at voltage between 2.7v-4.2v)
* **USB**: This is the positive voltage to/from the USB C jack, if USB is connected (This is usual at voltage 5v)
* **EN**: This is the enable pin of esp32, you can pull down this using a external button or other controller to reset the board.
* **3.3V**: These pins are the output from the 3.3V regulator, they can supply 900mA peak current.
* **Lipo Battery PADS**: 2 Pads behind the board to solder Lipo or li-ion batteries to power the Glyph board.
* **MSR PADS**: Short this MSR pad to measure battery capacity using IO0 (Marked as A0 on board).
### Communication Pins
#### I2C, SPI, and UART on S3
The S3 is capable of handling I2C, SPI, and UART on many pins. However, to simplify things we have assigned few of the IO pins to make things simpler for users.
#### I2C Pins
* I2C0 SCL: **SCL**, IO5
* I2C0 SDA: **SDA**, IO4
S3 has two I2C controllers. A second I2C bus can be assigned to any available GPIO pair.
#### UART Pins
* UART0 TX: **TX**, IO43
* UART0 RX: **RX**, IO44
* UART1 TX: **IO17**
* UART1 RX: **IO18**
S3 has 3 UART controllers total. UART2 can be assigned to any GPIO via the GPIO matrix.
### Additional Ports / Pins
#### Glyph Glink Port
This is a QWIIC / STEMMA compatible connector which makes it easy for users to connect to 100's of sensors and modules made by Adafruit & Sparkfun.
#### USB Pins
This is used for power and data transfer. Connect to your computer via a USB C cable to update firmware and at the USB pin you would receive 5v
#### PWM Pins
The S3 supports PWM on all pins. However, it is not capable of PWM on all pins at the same time. There are multiple PWM channels, each with configurable frequency and duty cycle. The important thing to know is that you cannot use the same channel on different pins at the same time. Please refer to [ESP32S3 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph-S3/PCBCUPID_esp32-s3_datasheet.pdf)
### Analog Pins
The S3 has two ADC units — ADC1 and ADC2 — with 10 channels each, totalling 20 ADC-capable pins on the chip. On the Glyph-S3 board, 9 ADC1 pins are exposed: IO1, IO2, IO4, IO5, IO6, IO7, IO8, IO9, IO10
* **A1/IO1**: ADC1 channel 1
* **A2/IO2**: ADC1 channel 2
* **IO4**: ADC1 channel 3 (Can also function as ADC1\_CH3 when not used for I2C)
* **IO5**: ADC1 channel 4 (Can also function as ADC1\_CH4 when not used for I2C)
* **A6/IO6**: ADC1 channel 6
* **A7/IO7**: ADC1 channel 7
* **A8/IO8**: ADC1 channel 8
* **A9/IO9**: ADC1 channel 9
* **A10/IO10**: ADC1 channel 10
### Digital Pins
These are the digital I/O pins. They all have multiple capabilities but can be used only one at a time.
* **A1/GPIO1**: ADC1 channel 1
* **A2/GPIO2**: ADC1 channel 2
* **A6/GPIO6**: ADC1 channel 6
* **A7/GPIO7**: ADC1 channel 7
* **A8/GPIO8**: ADC1 channel 8
* **A9/GPIO9**: ADC1 channel 9
* **A10/GPIO10**: ADC1 channel 10
* **SDA/GPIO4**: The main I2C1 data pin(GPIO4).
* **SCL/GPIO5**: The main I2C1 clock pin(GPIO5).
* **D13/GPIO13**: Digital I/O pin 13(GPIO13, FSPIIO7, SUBSPIQ, FSPIQ).
* **D14/GPIO14**: Digital I/O pin 14(GPIO14, FSPIDQS, SUBSPIWP, FSPIWP).
* **D15/GPIO15**: Digital I/O pin 15(GPIO15, U0RTS).
* **D16/GPIO16**: Digital I/O pin 16(GPIO16, U0CTS).
* **D17/GPIO17**: Digital I/O pin 17( GPIO17, U1TXD).
* **D18/GPIO18**: Digital I/O pin 18(GPIO18, U1RXD, CLK\_OUT3).
* **TX/GPIO43**: The main UART0 TX pin(U0TXD, GPIO43, CLK\_OUT1 ).
* **RX/GPIO44**: The main UART0 RX pin(U0RXD, GPIO44, CLK\_OUT2).
* **SCK/GPIO35**: The main SPI0 SCK(GPIO35, SUBSPID, FSPID, SPIIO6).
* **MO/GPIO36**: The main SPI0 MOSI(GPIO36, FSPICLK, SUBSPICLK, SPIIO7).
* **MI/GPIO37**: The main SPI0 MISO(GPIO37, FSPIQ, SUBSPIQ, SPIDQS).
### Schematic Diagram For Glyph S3
For better view you can download the schematic diagram from [here](https://files.pcbcupid.com/Documentation/Boards/glyph-S3/S3%20schematic.pdf)
# Power Management
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32s3/glyph-esp32-s3-power-management
Power the Glyph S3 over USB-C or a single-cell lithium battery, monitor charge status, and configure deep sleep modes for low-power IoT projects.
## Power Management for Glyph S3
### Battery + USB Power
We designed the Glyph S3 to be easy to power both when connected to a computer and via a battery. Here are the ways to power your Glyph:
1. **USB Power**: Connect with a USB cable to regulate the 5V USB down to 3.3V.
2. **Battery Power**: Connect a 4.2/3.7V Lithium Polymer (LiPo/LiPo) or Lithium Ion (LiIon) battery to the JST jack for rechargeable battery power.
When USB power is connected, it will automatically switch over to USB for power and start charging the battery (if attached). This hot-swap functionality allows you to keep the LiPo connected as a backup power source that will only be used when USB power is lost.
Install the LiPo / Li-ion batteries based on the polarity. Using wrong polarity batteries can destroy your Glyph.
### Power Supplies
The Glyph S3 offers multiple power supply options:
* **BAT Pin**: Connected to the battery pads (behind the board)
* **USB Pin**: Provides +5V from USB if connected.
* **3V Pin**: Provides output from the 3.3V regulator with a 600mA peak output.
### Measuring Battery Voltage
To monitor battery voltage, short the msr pads behind the board.
### Alternative Power Options
For powering the Glyph S3:
* **USB powered**: Use a 5V 1A USB wall adapter to plug in a USB cable for reliable power.
* **Portable Use Without LiPo**: Use a USB battery pack(Power Bank).
* **Higher Voltage Power Supply**: Use a 5V buck converter and wire it to a USB cable's 5V and GND input.
**What You Cannot Do**
* Do not use alkaline or NiMH batteries and connect to the battery port, as it will destroy the LiPo charger.
* Do not use anything >4.2v LiPo batteries on the battery port, as it will destroy the board.
### External Power Supplies
The Glyph S3 is not designed for external power supplies. If you must:
* **Connect an external 3.3V power supply** to the 3V and GND pins
* **Connect an external 5V power supply** to the USB and GND pins.
# Overview
Source: https://learn.pcbcupid.com/documentation/modules/glyph/glyph-esp32s3/glyph-s3-overview
Overview of the Glyph S3 development board: a dual-core Xtensa MCU with Wi-Fi, Bluetooth LE, AI acceleration, and a Qwiic Glink connector.
Introducing the Glyph S3, a powerful microcontroller development board based on the ESP32-S3 chip, ideal for AIoT, edge computing, and computer vision applications. With dual-core performance and enhanced peripherals, the Glyph-S3 delivers robust capabilities in a compact footprint.
* **Dimensions**: Measures 50.8mm x 22.8mm x 1.6mm (without headers soldered)
* **Processor**: ESP32-S3 dual-core LX7 microprocessor @ 240 MHz, 3.3V logic and power
* **Memory Options**:
* **SRAM**: 512 KB (Internal)
* **PSRAM**: 2 MB (Only available on PSRAM Variant)
* **Flash Memory**: Up to 8 MB SPI FLASH
* **GPIO**: 20 GPIO pins with the following capabilities:
* 9 GPIO pins support 12-bit ADC (ADC1): IO1, IO2, IO4, IO5, IO6, IO7, IO8, IO9, IO10
* I2C
* SPI
* UART
* USB Serial
All the important peripherals, labeled for easy access.
* **Power Management**:
* USB Type C connector for power, programming, and serial port debugging
* 3.3V regulator with 600mA peak current output
* Built-in lipoly/li-ion charger with charging status indicator LED
* Auto Switch between Battery & USB Power
* Ability to Measure Battery Capacity
* Ability to Turn off the battery with the onboard slide switch
* Reverse Voltage protection with Diode
* **Additional Feature**:
* On-board LED (Connected to GPIO21)
* On-board GLINK connector for easy integration with QWIIC, STEMMA QT compatible sensors & modules.
* High Quality Reset and Bootloader button for easy access
### Native Bootloader and Programming
The Glyph S3 features a built-in USB bootloader that makes programming new firmware easy and keeps the cost of the board down. On first time use, hold down the BOOT button while plugging it into USB, and it will appear as COM PORT in your device Manager. If you face any issue related to hardware not detecting on your system, please check out our troubleshooting guide [here](https://learn.pcbcupid.com/boards/needs/arduino-ide-setup#hardware-not-detecting).
### Connectivity
The Glyph S3 excels in connectivity with its built-in Wi-Fi and Bluetooth support. This makes it ideal for IoT applications, where reliable wireless communication is crucial.
The wireless module on GLYPH board is CE & FCC Certified
### Development Support
The ESP32-S3 Glyph is supported by a variety of development environments, including:
* **Arduino**
* **MicroPython**
* **ESP-IDF (Espressif IoT Development Framework)**
With extensive library support and a large community, getting started with the Glyph S3 is straightforward.
### Memory and Storage
The Glyph-S3 is available with different module configurations to suit your project requirements.
Technical SpecsMemory Architecture
Both variants share the 512KB onboard SRAM for core operations. Depending on your choice:
The Standard Variant offers more storage for code and assets (8MB Flash).
The Performance Variant includes 2MB PSRAM — an essential option if you need extra memory for high-resolution displays or complex data buffers.
### S3 Chip Features
* **BluFi**
* **RF Coexistence**
* **ESP-BLE-MESH**
* **ESP-WIFI-MESH**
You can read more about it in [ESP32S3 DATASHEET](https://files.pcbcupid.com/Documentation/Boards/glyph-S3/PCBCUPID_esp32-s3_datasheet.pdf) and [ESP32S3 OFFICIAL](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/) documentation.
***
# Getting Started
Source: https://learn.pcbcupid.com/documentation/welcome/getting-started
Learn everything you need to be a hardware engineer in a systematic way, which is not behind a paywall! From zero to hero only with pure knowledge.
# Welcome to PCB CUPID! 💘
We understand that Printed Circuit Boards are the currency of the electronic world and as an innovator and a futurist you want to develop the knowledge about that currency, the knowledge that is currently either available and accessible only to few people behind a paywall or remain within the pages of electronic bibles in libraries. Thus, through this platform we are sharing as much as knowledge needed for a hardware engineer without hiding any information behind a paywall.
* **WE CONSTANTLY THRIVE** 🦾to maximize long-term value and build a platform with a hope to lasts forever. We want to be a strong and independent engine, this long term focus guides all of the decisions we make.
* **CONTINUOUSLY LEARN AND ADAPT** 🧗 We value experimentation, metrics-driven decisions, and speed of iteration. All the changes in the platform are decided by YOU!
* **BE DIRECT AND RESPECTFUL** 🎯 We expect and welcome constant feedback and when you are in our forum be straightforward about your question and answer. Also, If you have anything in mind don’t hesitate to contact us.
While on one hand this platform works as an aggregator bridging the gap by bringing in all kinds of knowledge pool (beginners, amateur and experts) to connect with each other within a single frame, on other hand this acts as a learner’s guide by bringing in customized content, videos, graphics and a medium to engage over grilling topics uploaded periodically.
Thus, our effort is to encourage people with different perspectives to sing their tones of PCB so that a symphony is created that benefits all. We value your time and enthusiasm, by coming on board with us we assure you continuous learning experience and a community building that is PCB-philic.
Welcome to PCBCUPID, your ultimate resource for everything related to PCB designs, Hardware engineering and electronics projects! Whether you're a beginner looking to get started or an experienced developer seeking advanced projects, we've got you covered.
## [Pcbcupid](https://pcbcupid.com/)
Place to learn all the latest and greatest tech news and articles related to printed circuit board and hardware engineering.
* **News**: Get updated with all the latest new related to hardware engineering
* **Articles** : Read engaging articles to kick start your journey on Hardware engineering and PCB development.
* **Tips and Tricks**: Pro tips for optimizing PCB designs for performance and manufacturability.
## [Learn](https://learn.pcbcupid.com/)
Explore a diverse range of hardware engineering software & projects
* **KiCad Tutorials**: Comprehensive guides on designing PCBs using KiCad, from schematic capture to PCB layout.
* **EasyEDA Tutorials**: Step-by-step tutorials for designing PCBs with EasyEDA, covering both basic and advanced techniques.
* **IoT Applications**: Build smart home devices, environmental sensors, and more.
* **Automation**: Develop projects for automation and control systems.
## [Forum](https://forum.pcbcupid.com/)
Engage in spirited discussions and share breakthroughs within our vibrant community forum.
It connects users for:
* **Discussions**: Talk about projects, technologies, and ideas.
* **Project Showcases**: Share and get feedback on your work.
* **Technical Support**: Get help with troubleshooting and technical issues.
* **Collaborations**: Find partners and brainstorm new ideas.
* **Support Resources**: Access FAQs, documentation, and customer support for troubleshooting and assistance.
## [Tools](https://tools.pcbcupid.com/)
Find all the tools related to hardware engineering
Access Precision Calculation Tools, it has a range of advanced calculators for:
* **Design Calculations**: Perform complex calculations for PCB design and electronics.
* **Component Sizing**: Accurately determine values for series resistance, series capacitance, energy, admittance.
* **Simulation and Analysis**: Evaluate circuit performance and system behavior.
* **Optimization Tools**: Optimize designs for efficiency and reliability.
## [Github](https://github.com/pcbcupid)
Find all the codes and open source hardware design done by us!

## Social Media
Get in touch with us through the below platforms:
* [Instagram](https://www.instagram.com/pcbcupid/)
* [Youtube](https://www.youtube.com/@pcbcupid)
* [LinkedIn](https://www.linkedin.com/company/pcbcupid)
* [Pinterest](https://in.pinterest.com/pcbcupid/)
* [X](https://x.com/pcbcupid)
# Arduino IDE Setup
Source: https://learn.pcbcupid.com/documentation/welcome/prerequisites/arduino-ide-setup
The Espressif core provides support for ESP32-C3 microcontroller boards. This page covers getting your Arduino IDE set up to include your board.
Glyph Platform is completely built to support new and upcoming innovative creators who love to explore the field of electronics. So, our boards are completely compatible with Arduino IDE. As of 2025, our glyph boards are completely based on the Espressif ESP series of microcontroller. So, in this particular documentation we'll discuss how to setup the Arduino IDE core along with setting up the ESP Core.
This page should covers setup for all the GLYPH Boards that released now and in the coming future.
### Arduino IDE Download
The first thing you will need to do is to download the latest release of the Arduino IDE (preferably **version 2.3** and above), Which you can do by following this link : [Download](https://www.arduino.cc/en/software).
This process can vary based on the operating system you have, currently this documentation assumes you are using Windows 10 and above, In case if you using other operating system please refer to Arduino IDE documentation.

Once you have downloaded and installed the correct variant of the Arduino IDE based on your operating system, open the Arduino IDE.
### Adding the Espressif Board Manager URL
In the Arduino IDE, navigate to the Preferences window.
You can access it through the menubar on the top :
`File > Preferences`

In the Additional Boards Manager URLs field, you'll want to add a new URL. If this is the first time using arduino IDE, this field will most likely be empty. Here you can add the url given below. But if you already have some URL on this field, enter the URLs with comma as a separation. Here you will only have to add each URL once. This URLs point to index files that the Board Manager uses to build the list of available & installed boards.
Copy the following URL:
```
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
```
Click OK to save and close Preferences.
### Add Board Support Package
Now we need to install the board support package which will allow the user to use our glyph board on Arduino IDE platform. Click on `Boards Manager Icon` on the left panel. Here you can search for ESP32 and install the latest version of ESP32 core by Espressif Systems. We recommend you download the latest available version of the ESP32 core or at least above version `3.1.0`.

Installing a new board package can take a 2-5 minutes based on your internet connectivity so don't click on cancel before the installation is complete.
Once the installation is complete, you can close the Boards Manager by clicking on the same `Boards Manager Icon`.
### Choose Your Board
In the `Tools > Boards`, you should now see ESP32.

Navigate to the ESP32 Arduino Boards option and you will see the available boards that you can use with arduino IDE. Here you can Navigate to the ESP32 Arduino Boards menu and choose ESP version based on the glyph board you own:
* **GLYPHC3**
* **GLYPHC6**
* **GLYPHH2**
Alternatively you can also use this :
* **ESP32C3 DEV MODULE**
* **ESP32C6 DEV MODULE**
* **ESP32H2 DEV MODULE**

## Arduino Usage
Now that you've set up the Arduino IDE with the Espressif ESP32 Arduino core, you're ready to start using Arduino with your Glyph Boards!
## Glyph Pinout
Our boards are merged with official Espressif to include our boards on there core platform, So feel free to use the pin names on the top of the board (ex : D1, D2, D3, SDA, SCL, etc...) Alternatively if you are using the DEV MODULE settings, you can use the pin names which is mentioned below the board (ex : GPIO1, GPIO2, etc...) used for Arduino.
To find more detailed pin mapping for you board, check the pinout diagram of respective boards. [Glyph ESP32-C3](https://learn.pcbcupid.com/boards/glyph-c3/pinouts),[Glyph ESP32-C6](https://learn.pcbcupid.com/boards/glyph-c6/pinouts),[Glyph ESP32-H2](https://learn.pcbcupid.com/boards/glyph-h2/pinouts).
## Running Bare Minimum Code
The first and most basic program you can upload to your Board is the Bare Minimum sketch. This sketch doesn't do anything, but it's a great way to make sure everything is working and you're uploading your sketch to the right board and right configuration.
When all else fails, you can always come back to the Bare Minimum sketch!
### Load the Bare Minimum Sketch
Begin by plugging in your board to your computer, and wait a moment for it to be recognized by the OS. It will create a COM/serial port that you can now select from the `Tools > Port` menu dropdown. (In case of ESP Glyph Series you would have the com port along with the name "ESP FAMILY" )
The bare minimum sketch(code) is already present within arduino IDE and you can open by `File > Examples > 01.Basics > Bare Minimum`.
```cpp theme={null}
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
```
This is the absolute bare minimum code required to run on your board. The `setup()` function runs once when the board is powered up or reset, and the `loop()` function runs continuously after `setup()` has completed.
OK now you can click the Verify button to convert the sketch into binary data to be uploaded to the board. On success you will see white text output and the message `Done compiling.` in the message area.

Once the code is verified/compiling cleanly you can upload it to your board. Click the Upload button.
The IDE will try to compile the sketch again for good measure, then it will try to connect to the board and upload the file.

Though it doesn't do anything visible. This is a great starting point for understanding the basics of getting code onto your board and making sure everything is working. If you are confidence enough go crazy with the examples [here](https://learn.pcbcupid.com/boards/examples)
## Hardware Not Detecting!
This is the most common error most beginners face :
Port not detecting on arduino IDE
If you get into a state with the bootloader where you can no longer upload a sketch (*port not found*), or you have uploaded code that crashes and doesn't auto-reboot into the bootloader, you may have to manually enter the bootloader.
To enter the bootloader, hold down the `BOOT` button, and while continuing to hold it (don't let go!), press and release the reset button. Continue to hold the `BOOT` button until the board enters bootloader mode.
Once the board is in bootloader mode, you should see the `COM port` available under tools and your board should be ready accept new code!
### More Problems More Solutions
This is a generalized checklist, some elements may not apply to your hardware. Please use this checklist as a guide based on the Glyph boards you have:
1. Install the very latest Arduino IDE for Desktop (not all boards are supported by the Arduino Web IDE / Arduino IDE version less than 2 so we don't recommend it).
2. Install the board support packages required for your hardware \[in case of GLYPH ESP series, install ESP32 core by Espressif].
3. Get a Data/Sync USB cable for connecting your hardware. This is a problem faced by significant amount of people, so make sure to have cable that's capable of transferring the data.
4. Connect the board to your computer and upload Bare minium or Blink sketch to verify they work!
OK it was a journey but now we're here and you can enjoy having your basic sketch running. This sketch does nothing but provides a solid foundation for you to start building more complex projects. Check out the next section for more codes and examples for you glyph board!
# Code Composer Studio IDE Setup
Source: https://learn.pcbcupid.com/documentation/welcome/prerequisites/cc-studio
Install and configure TI's Code Composer Studio IDE to develop, build, and debug firmware on MSP430 and MSPM0 microcontrollers used with Glyph boards.
# Code Composer Studio (CCS IDE)
To get the complete power of Texas Instruments (TI) microcontrollers Code Composer Studio (CCS) would be the best option out there. This guide provides a step-by-step walkthrough for setting up CCS on your system, ensuring you're ready to develop applications for your Glyph boards.
## Installation Process
### Download
The installation file for Code Composer Studio can be obtained from the below site:
[https://www.ti.com/tool/CCSTUDIO](https://www.ti.com/tool/CCSTUDIO)
**Note:** The download size is approximately 1.0 GB, so ensure you have a stable internet connection.
### System Check
The installer will check the system to see if it meets the requirements for installation. Any issues that need to be addressed will be displayed. Disabling security software is recommended but optional.
Example on Windows host OS:
Example on Ubuntu 22.04 LTS host OS:
Please exit the installer and resolve any missing dependencies before trying again.
### Installation Location
Choose a location to install Code Composer Studio. This location must not already contain a Code Composer Studio installation. If multiple versions of Code Composer Studio or Code Composer Studio will be installed then it is recommended to install them in versioned folders.
### Device Support
Choose the desired device families to install support for.
### Progress
As the installation proceeds the progress screen will show what the installer is doing. Depending on how many device families were selected the installation may take a significant amount of time.
### Completion
The last screen shown during installation is the successful completion screen. This screen provides options to launch Code Composer Studio and create a desktop shortcut.
The dialog will look different on Linux hosts, with an additional message regarding an additional step needed to enable the drivers for the debug probes.
### Post Installation Step (Linux Only)
If Code Composer Studio was installed as user, then it is necessary to run the driver install script after the installation is complete.
Run `/ccs/install_scripts/install_drivers.sh` with sudo as instructed by the installer.
### Ubuntu 24.04
The following steps are not required if the install\_drivers.sh script is successfully executed.
If Ubuntu 24.04 is being used, the following additional steps may be required:
Browse to: `/ccs/theia` and run the following commands:
`sudo chown root chrome-sandbox`
`sudo chmod 4755 chrome-sandbox`
## Resource Explorer
The Resource Explorer helps you find all the latest examples, libraries, demo applications, data sheets, and more for your chosen platform.
The Resource Explorer can be opened by selecting Browse Software and examples under Start exploring in the Getting Started view or from the View → Open Resource Explorer menu item.
Filtering by device, or by TI LaunchPad Kit, the interface enables you to filter the content to only what is relevant to your chosen platform.
Use the Select Board or Device filter field to search and select the device or TI LaunchPad Kit that you are using. For example, if you are using the LP-MSPM0L1306, you can start typing "L1306" in the search field to filter the list to easily find your LaunchPad:
If you have a valid TI kit (such as a LaunchPad Development Kit) connected to your computer, Resource Explorer may be able to autodetect it. If autodetect is successful, you can select the USE MY BOARD option to specify your kit:
Once your device or TI LaunchPad Kit is selected, the filter will be applied and only content relevant to your selection will be displayed. You can now browse through the displayed content to learn more about your device, board, relevant tools, and available software packages. Note the additional filters to display examples based on RTOS and compiler type.
The best way to get going with software development on your target is to start with some existing examples for your target. Many examples are included with the software package which supports your device, and many of these software packages are accessible right from Resource Explorer.
Not all devices are supported via Resource Explorer.
## Creating a New Code Composer Studio Project
Creating a new Code Composer Studio project purely from "scratch" is typically not recommended. Instead, it is strongly recommended to start with an existing SDK example. There is often a very minimal SDK example which often serves as a template for users wishing to start from "scratch".
1. Go to menu File → Create New Project... or open the Getting Started view and select the Create a new project in Code Composer Studio option under the Start developing section of the Getting Started view. This will open the Project Wizard.
2. In Project Wizard, specify the board or device under Select a board or device. Once a board or device is specified, a list of available projects appears.
3. (Optional) Use the Filters and Categories fields to filter the list of available projects.
4. Select the desired project to import. Most SDKs provide some sort of empty type example which serves as a basic template for new projects.
5. (Optional) Under Configure selected project
* Use the Project Name field to change the project name from the default.
* Use the compiler and kernel fields below the project list to specify the compiler type and kernel to use. Note that not all projects have multiple options for these fields.
6. Press Create to import the example project into the Code Composer Studio Explorer
The Project Wizard is based on Resource Explorer and will allow a user to select from a rich variety of device-specific templates from an available online SDK for the device in Resource Explorer. Internet access is required for full access to all the online templates/examples. If internet access is not available, then the user has the option to manually browse for examples from SDKs already installed locally (and detected by Code Composer Studio).
# ESP-IDF Setup for Glyph Boards
Source: https://learn.pcbcupid.com/documentation/welcome/prerequisites/esp-idf
Install Espressif's ESP-IDF toolchain to build C/C++ firmware for Glyph ESP32 boards, including Zigbee examples between the Glyph C6 and Glyph H2.
# Installing ESP-IDF via VS Code Extension
This guide explains how to set up the ESP-IDF (Espressif IoT Development Framework) development environment using Visual Studio Code (VS Code) and the ESP-IDF extension.
## Prerequisites
Before starting, ensure you have the following tools installed:
#### 1. **Visual Studio Code (VS Code)**
* Download from [https://code.visualstudio.com](https://code.visualstudio.com).
#### 2. **Git**
* Install Git from [https://git-scm.com](https://git-scm.com).
#### 3. **Python 3.x**
* ESP-IDF requires Python 3.7 or later. Install it from [https://www.python.org](https://www.python.org).
### Step 1: Install VS Code Extension for ESP-IDF
1. **Open Visual Studio Code.**
2. **Access Extensions Marketplace.**
* In VS Code, click the Extensions icon on the left sidebar, or press `Ctrl+Shift+X` (Windows/Linux) or `Cmd+Shift+X` (macOS).
* Search for `ESP-IDF` in the search bar.
3. **Install ESP-IDF Extension.**
* Find the official ESP-IDF extension by Espressif Systems and click Install.
Make sure you have the latest version of VS Code for compatibility with the ESP-IDF extension.
### Step 2: Set Up ESP-IDF in VS Code
After installing the extension, the ESP-IDF setup wizard will guide you through the installation process.
#### 2.1: **Open ESP-IDF Setup Wizard**

1. **Launch Command Palette:**
* Press `Ctrl+Shift+P` (or `Cmd+Shift+P` on macOS).
2. **Search for ESP-IDF Configuration:**
* Type `ESP-IDF: Configure ESP-IDF extension` and select it.

Make sure your internet connection is stable. An interrupted connection can result in incomplete setup.
#### **2.2: Install ESP-IDF**
1. The wizard will ask if you want to install ESP-IDF. Click Yes to proceed.

#### **2.3 Toolchain Installation:**
* The wizard will also download and configure the required toolchain, including compilers and other essential tools.
* On Windows, it may install MSYS2, a collection of development tools.
* On macOS and Linux, it will configure the necessary packages via the package manager.


Avoid changing system PATH manually. Misconfiguring PATH could interfere with other applications. The ESP-IDF installer handles this automatically.
#### **2.4. Verify Installation:**
* The wizard will verify that the installation was successful by running a series of checks.

### Step 3: Create an ESP-IDF Project
#### **3.1: Start a New Project**
1. **Open Command Palette**(`Ctrl+Shift+P` or `Cmd+Shift+P`).
2. **Create New Project:**
* Type `ESP-IDF: Create New Project` and select it.\


Choose hello\_world or blink template for a quick, functional test of your setup.
3. **Choose Project Template:**
* Pick a template for your project (e.g., `blink`, `hello_world`).
4. **Pick Folder for Project:**
* Choose or create a folder where the project will be created.
#### **3.2: Configure Project**
1. Once the project is created, go to the ESP-IDF menu in the top bar of VS Code.
2. Select ESP-IDF: Set up ESP-IDF tools to configure your project settings.
Avoid moving files within the project folder. ESP-IDF relies on a specific structure, and moving files may break project builds.
3. Inside the project folder, modify the `main` files as needed. You will see a `CMakeLists.txt` file and a `main` directory where your code resides.
### Step 4: Build and Flash the Project
#### **4.1: Build the Project**


1. **Open Command Palette**(`Ctrl+Shift+P` or `Cmd+Shift+P`).
2. **Build Project:**
* Type `ESP-IDF: Build Project` and select it. This will start the build process using the `idf.py build` command.
If the build fails, check your code for syntax errors. Some project templates may require specific ESP-IDF configurations.
#### **4.2: Flash to the Device**
1. **Connect ESP Device:**
* Connect your ESP32 or ESP8266 device to your computer via USB.
2. **Flash the Project:**
* In the Command Palette, type `ESP-IDF: Flash Project` and select it. This will flash your code to the connected device.

3. **Select COM/Serial Port:**
* Ensure the correct COM port (Windows) or serial port (Linux/macOS) is selected in the `menuconfig`.

Be cautious when flashing devices connected to mains power. Always isolate your ESP device from power sources before flashing.
#### **4.3: Monitor the Output**
1. **Open Serial Monitor:**
* In the Command Palette, type `ESP-IDF: Monitor` and select it to view serial output from your device.

### Step 5: Additional Tips
* **Update ESP-IDF**: Periodically run `idf.py update` to keep ESP-IDF up to date.
* **Verify ESP-IDF Version**: Use `idf.py --version` to check the current ESP-IDF version.
* **Multiple ESP-IDF Versions**: You can use specific ESP-IDF versions by setting the path or using version tags (e.g., `v4.4`, `v5.0`).
#### Troubleshooting
* **Python Errors**: If you see Python-related issues, make sure you are using a supported version of Python (3.7 or later).
* **Toolchain Issues**: Ensure that the toolchain has been properly installed and added to the system PATH.
* **Permission Issues**: On Linux or macOS, make sure you have the proper permissions for files and directories. You may need to run some commands with `sudo` on these systems.
Avoid using sudo on commands unless required. Misuse of elevated privileges can compromise your system.
# Glink Connector Overview
Source: https://learn.pcbcupid.com/documentation/welcome/prerequisites/glink
The Glink connector on every Glyph board is electrically and mechanically compatible with Qwiic and STEMMA QT for plug-and-play I2C sensor chaining.

All Glyph Development boards have a GLINK connector which is compatible with QWIIC / STEMMA QT connector.
GLINK offer a solder-free, easy-to-use solution for connecting development boards to various sensors, shields, and accessories. Their polarized connectors eliminate the risk of incorrect wiring, while daisy-chaining capabilities allow multiple devices to be connected efficiently using the I2C bus
GLINK ensure compatibility with a wide range of I2C-based modules and sensors produced by Adafruit & Sparkfun. This standardized approach not only accelerates prototyping but also enhances the overall user experience by eliminating common wiring errors and reducing setup time.

## Feature
GLINK connectors provide several key advantages:
* Solder-free connections for rapid prototyping and experimentation
* Polarized connectors to prevent incorrect wiring
* Daisy-chaining capability for connecting multiple devices efficiently
* Compatibility with the widely-used I2C communication protocol
* Interoperability with QWIIC and STEMMA QT ecosystems
## Standard
GLINK follows [QWIIC](https://www.sparkfun.com/qwiic) standard:
* JST PH (2mm pitch) Connector
* Pinout - GND, VCC, SDA & SCL
* Device connected using GLINK should be 3.3V
* Max current on a GLINK cable is 226mA
* Using 28AWG is good for up to 1.4A (recommended not push more than 1.4A)
* The GLINK cable length can be upto 1M
## Glink Pinout
The GLINK connector follows a standardized pinout, identical to Adafruit's STEMMA QT:
* SCL (Yellow wire)
* SDA (Blue wire)
* 3.3V (Red wire)
* GND (Black wire)
This consistent pinout ensures compatibility across different devices and ecosystems, allowing users to mix and match components from various manufacturers seamlessly.
## Technical Information
### Power Lines
**GND** : Serves as the common ground reference for both power and data.
**3.3V**: Provides power to connected devices. While the standard specifies 3.3V, the system can accommodate voltages between 3-5V DC for flexibility with certain high-current devices.
### Data Lines
**SDA (Serial Data)**: Carries the bidirectional data for I2C communication.
**SCL (Serial Clock)**: Provides the clock signal for synchronizing I2C data transfer.
## Important Considerations
* **Voltage Compatibility**: While GLINK operates at 3.3V, connected devices must be capable of operating within the 3-5V range. Devices requiring lower voltages must incorporate their own voltage regulators.
* **Pull-up Resistors**: I2C devices are expected to include pull-up resistors on the SDA and SCL lines to the positive voltage (3.3V). This is crucial for proper I2C communication.
* **Level Shifting**: Connected devices should implement I2C level shifting if operating at different logic levels.
* **Current Limitations**: It's crucial to stay within the 226mA limit per GLINK cable to ensure safe and reliable operation or you can decrease your wire gauge to handle current up to 1.4A.
* **Daisy-Chaining**: When connecting multiple devices in a daisy-chain configuration, be mindful of the cumulative current draw and potential voltage drop across the chain.
By sticking to these standards and considerations, GLINK provides a robust and flexible connectivity solution for [GLYPH development boards](https://shop.pcbcupid.com/product-category/development-boards/), enabling rapid prototyping and seamless integration with a vast ecosystem of compatible sensors and modules.
# Setting Up MCP
Source: https://learn.pcbcupid.com/documentation/welcome/prerequisites/setting-up-mcp
This guide walks you through setting up the PCB Cupid Model Context Protocol (MCP) server for Claude Code and Codex.
The **Model Context Protocol (MCP)** enables AI assistants to seamlessly connect to external data sources and tools. This guide will walk you through adding the **PCB Cupid Docs MCP server** to your workspace using either **Claude Code** or **Codex**.
***
## Setting Up MCP in Claude Code
For instructions on installing Claude Code, refer to the [Claude Code Installation Guide](https://code-setup.com/index).
Follow these steps to integrate the PCB Cupid Docs MCP server with Claude Code:
### Step 1: Open Your Terminal
Launch your command line interface where Claude Code is configured.

### Step 2: Run the Add Command
Execute the following command to add the server using HTTP transport:
```bash theme={null}
claude mcp add --transport http pcbcupid-docs https://learn.pcbcupid.com/mcp
```
### Step 3: Verify the Connection
Confirm that the server is successfully connected and that Claude has access to the tools.

## 
## Setting Up MCP in Codex
For instructions on installing Codex CLI, refer to the [Codex Installation Guide](https://learn.chatgpt.com/docs/codex/cli).
Follow these steps to integrate the PCB Cupid Docs MCP server with Codex:
### Step 1: Open Your Terminal
Launch your command line interface where Codex is configured.

### Step 2: Run the Add Command
Execute the following command to register the MCP server URL:
```bash theme={null}
codex mcp add pcbcupid-docs --url https://learn.pcbcupid.com/mcp
```
### Step 3: Verify the Connection
Confirm that Codex has successfully loaded the MCP toolset.


# Smowcode IDE Setup
Source: https://learn.pcbcupid.com/documentation/welcome/prerequisites/smowcode-ide-setup
Glyph development board support Smowcode! A low core embedded programming IDE. This page covers getting your Smowcode IDE set up and work with GLYPH Platform.

Smow code IDE is a user-friendly platform designed for creating firmware applications for microcontrollers. It supports the ESP32 microcontroller and other controller like Ti, NXP and Nordic are underdevelopment! Making it ideal for developing smart electronic solutions. The major difference using Smow code over Arudino IDE is the drag and drog user interface, which makes its intuitive for beginners to get started.
## Download and Installation
Smowcode currently available both for offline and online version (demo only), But in this page we'll walk through only about the offline version of smowcode.
Start with [smowcode](https://smowcode.com/) official site and download the smowcode IDE.

Once you have the setup file, install the program just like any regular windows program :
**STEP 1 :** Run the Installer
**STEP 2 :** ESP32 Be the Default Controller
**STEP 3 :** Complete the installation
**STEP 4 :** Restart your computer
To complete the installation, computer restart is required. So make sure to Select `Yes, restart the computer now` and click on `Finish` to complete the installation.
## Setting Up Your First Project
If the setup went through and the smowcode IDE installed successfully, this would be the first screen you would encounter with a login pop up, as soon as you open the smowcode application.

As you finish the login (on a browser and redirect to the application) you should have complete access to the IDE. If you had worked on [node red](https://nodered.org/) before you should be familiar with the user interface and it's should be a breeze to get started.

Start with creating the first project. Click on the hamburger icon on the top right corner and navigate to `Project > New`

On the popup you can select the desired board that you would like to use. If you are using Glyph board choose the following option appropriately based on your board
* Glyph C3 - ESP32C3
* Glyph C6 - ESP32C6
* Glyph H2 - ESP32H2
For this example I'm going with ***ESP32C3*** as I'm using ***[Glyph C3 Board](https://shop.pcbcupid.com/product/gd001/)***

Once the project setup is done click on `Create Project`

## Creating the First Flow
On the left you can see bunch of nodes, These is the key feature, sets Smowcode apart from Arduino IDE. This node based system makes running Microcontroller super easy without even using a single line of code!

Let's try this with a example, just drag and drop the `on Interval` -> `Write` -> `delay` -> `Write` -> `delay` node onto the editor
Here :
* On Interval -> This Node will run the other connected node every one second
* Write -> This Node can write digital High or digital Low to the Microcontroller (In our case GLYPH C3)
* Delay -> This Node will delay set amount of time (in seconds) before executing the next node.

Now connect the nodes one after the other using the **dot** on the node.

Once this setup is ready we can change the property of each node by double clicking on them.
So, let's change the property of **Write Node:**
* Name (Act as a variable name) : LED
* Pin No (Physical Pin no) : 1
* Pin Level (Pin State High\[1] or Low(0)) : 1
Similarly I will change the property of other node to the following :
**Delay Node:**
* Name : delay
* Period (s) : 0.5
**Write Node:**
* Name : LED
* Pin No : 1
* Pin Level : 0
**Delay Node 2:**
* Name : delay
* Period (s) : 0.5

## Uploading to Glyph Board
Once the nodes are setup, connect your board to your computer via USB-C and find the COM port under device manager in Windows.
You can do that by right click on `Windows Start -> Device Manager`
After figuring out the **COM PORT** set the `Device Port` in the smowcode IDE. In our case it's `COM 21`

With the device port setup we can just hit the **upload** button on the top right corner

And within couples of seconds the IDE should verify the code and upload them to GLYPH Board!

## Result
After the flow is uploaded the on-board (GPIO1) LED on [Glyph C3 Board](https://shop.pcbcupid.com/product/gd001/) starts blinking!

If you are not fan of low code, we have dedicate page for setting up [GLYPH BOARD](https://shop.pcbcupid.com/product-category/development-boards/) with [Arduino IDE](https://learn.pcbcupid.com/boards/needs/arduino-ide-setup) and running [Blink Sketch](https://learn.pcbcupid.com/boards/examples/blink-led).
# Edge Impulse Gesture Recognition
Source: https://learn.pcbcupid.com/guides/ai/edge-impulse
Train and deploy a gesture recognition model on ESP32 boards using Edge Impulse, covering data collection, model training, and on-device inference.
# Edge Impulse Gesture Recognition
Build a gesture detection system that runs fully offline on your ESP32. This guide uses Edge Impulse to train a model and export it as a ready-to-use Arduino library.
## How it Works? (The Simple Version)
1. **Data**: You record motion data (gestures) using your smartphone or sensor.
2. **Train**: Edge Impulse uses that data to teach an AI model to recognize those patterns.
3. **Deploy**: You export the model as code and upload it to your ESP32. It then runs locally without needing the internet.
***
## What You Need
Before starting, make sure you have your hardware and software environment ready.
### Hardware Required
* **ESP32 DevKit** (or any ESP32 board).
* **IMU Sensor** (e.g., MPU6050 or LSM6DS3).
* **Smartphone** (To record initial data).
* **USB Cable** (For power and communication).

### Software
* **Arduino IDE**: To upload the code.
* **ESP32 Board Package**: Installed via Arduino Boards Manager.
* **Edge Impulse Account**: To train and export your model.
***
## Software Setup
### Step 1: Create a Project
Go to [edgeimpulse.com](https://edgeimpulse.com), log in, and create a new project named something like **"Gesture Detection"**.

### Step 2: Connect Your Phone
In the **Devices** tab, connect your smartphone by scanning the QR code. Your phone now acts as the motion sensor for data collection.

### Step 3: Collect Data
Go to **Data Acquisition**, type a label like `"up-down"`, hit **Start Sampling**, and perform the gesture. Repeat for each gesture you want to teach. Keep the data balanced and save some as **Test Data**.

### Step 4: Design the Impulse
Go to **Impulse Design**:
1. Set **Window Size** to \~2 seconds.
2. Add **Spectral Analysis** as the processing block.
3. Add **Neural Network** as the learning block.

### Step 5: Check Accuracy
Open **Feature Explorer** and check that your gestures form separate clusters. The more separated they are, the better your accuracy will be.

***
### Step 6: Train the Model
Go to the **Classifier** tab and hit **Start Training**. Expect around 80–90% accuracy.

If accuracy is low, collect more data or be more consistent with your gestures.
### Step 7: Export as Code
Go to **Deployment**, select **Arduino Library**, and download the ZIP file. This is your AI model exported as standard C++ code.

### Step 8: Upload to ESP32
1. Extract the ZIP file.
2. Open Arduino IDE and go to **File → Examples → \[Your Project Name] → ESP32 → ESP32 Fusion**.
3. Install the ESP32 board package, wire up your ESP32 + IMU sensor, select the right board and COM port, then click **Upload**.
Click to see Example Code (C++)
```cpp theme={null}
/* Edge Impulse Arduino examples - Cleaned for Glyph-C6 + ADXL345 */
#include
#include
#include
#include
/* Create the sensor object */
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
/** Struct to link sensor axis name to sensor value function */
typedef struct{
const char *name;
float *value;
uint8_t (*poll_sensor)(void);
bool (*init_sensor)(void);
int8_t status; // -1 not used 0 used(unitialized) 1 used(initalized) 2 data sampled
} eiSensors;
/* Constant defines -------------------------------------------------------- */
#define N_SENSORS 7
/* Forward declarations ------------------------------------------------------- */
float ei_get_sign(float number);
static bool ei_connect_fusion_list(const char *input_list);
bool init_IMU(void);
bool init_ADC(void);
uint8_t poll_IMU(void);
uint8_t poll_ADC(void);
/* Private variables ------------------------------------------------------- */
static const bool debug_nn = false;
static float data[N_SENSORS];
static int8_t fusion_sensors[N_SENSORS];
static int fusion_ix = 0;
/** Used sensors value function connected to label name */
eiSensors sensors[] =
{
"accX", &data[0], &poll_IMU, &init_IMU, -1,
"accY", &data[1], &poll_IMU, &init_IMU, -1,
"accZ", &data[2], &poll_IMU, &init_IMU, -1,
"adc", &data[6], &poll_ADC, &init_ADC, -1,
};
void setup()
{
Serial.begin(115200);
while (!Serial);
/* Connect used sensors */
if(ei_connect_fusion_list(EI_CLASSIFIER_FUSION_AXES_STRING) == false) {
return;
}
/* Init sensors */
for(int i = 0; i < fusion_ix; i++) {
if (sensors[fusion_sensors[i]].status == 0) {
sensors[fusion_sensors[i]].status = sensors[fusion_sensors[i]].init_sensor();
}
}
}
void loop()
{
// Wait between samples
delay(2000);
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME) {
int64_t next_tick = (int64_t)micros() + ((int64_t)EI_CLASSIFIER_INTERVAL_MS * 1000);
for(int i = 0; i < fusion_ix; i++) {
if (sensors[fusion_sensors[i]].status == 1) {
sensors[fusion_sensors[i]].poll_sensor();
sensors[fusion_sensors[i]].status = 2;
}
if (sensors[fusion_sensors[i]].status == 2) {
buffer[ix + i] = *sensors[fusion_sensors[i]].value;
sensors[fusion_sensors[i]].status = 1;
}
}
int64_t wait_time = next_tick - (int64_t)micros();
if(wait_time > 0) {
delayMicroseconds(wait_time);
}
}
signal_t signal;
numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
ei_impulse_result_t result = { 0 };
int err = run_classifier(&signal, &result, debug_nn);
if (err != EI_IMPULSE_OK) return;
// --- CLEAN OUTPUT ONLY ---
bool found = false;
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
// Lowered threshold slightly to 0.70 to help with "Circle" detection
if (result.classification[ix].value > 0.70) {
Serial.print("DETECTED GESTURE: ");
Serial.println(result.classification[ix].label);
found = true;
break;
}
}
if(!found) {
Serial.println("DETECTED GESTURE: Unknown");
}
}
/** IMU and Helper Functions **/
bool init_IMU(void) {
static bool init_status = false;
if (!init_status) {
Wire.begin(4, 5); // SDA Pin 4, SCL Pin 5
if(!accel.begin()) return false;
accel.setRange(ADXL345_RANGE_2_G);
init_status = true;
}
return init_status;
}
uint8_t poll_IMU(void) {
sensors_event_t event;
accel.getEvent(&event);
data[0] = event.acceleration.x;
data[1] = event.acceleration.y;
data[2] = event.acceleration.z;
return 0;
}
static int8_t ei_find_axis(char *axis_name) {
for(int ix = 0; ix < N_SENSORS; ix++) {
if(strstr(axis_name, sensors[ix].name)) return ix;
}
return -1;
}
static bool ei_connect_fusion_list(const char *input_list) {
char *input_string = (char *)ei_malloc(strlen(input_list) + 1);
if (input_string == NULL) return false;
strcpy(input_string, input_list);
memset(fusion_sensors, 0, N_SENSORS);
fusion_ix = 0;
char *buff = strtok(input_string, "+");
while (buff != NULL) {
int8_t found_axis = ei_find_axis(buff);
if(found_axis >= 0 && fusion_ix < N_SENSORS) {
fusion_sensors[fusion_ix++] = found_axis;
sensors[found_axis].status = 0;
}
buff = strtok(NULL, "+ ");
}
ei_free(input_string);
return true;
}
bool init_ADC(void) { return true; }
uint8_t poll_ADC(void) { data[6] = analogRead(A0); return 0; }
float ei_get_sign(float number) { return (number >= 0.0) ? 1.0 : -1.0; }
```

### Step 9: Test Your Gestures
Open the **Serial Monitor** and perform your gestures. You will see real-time predictions like `"Gesture: up-down"`. It runs fully offline on the ESP32!

Have fun with your mini AI Assistant!
# ESP32-C3 Voice Chatbot
Source: https://learn.pcbcupid.com/guides/ai/esp32-c3-voice-chatbot
Build a mini AI voice assistant on the ESP32-C3 using Deepgram for speech recognition, Groq for LLM inference, and n8n for workflow automation.
# ESP32 Voice Chatbot
Think of this as your own **mini Alexa/Google Assistant**, but built by you. You press a button, speak something, and the AI replies back through the speaker.
## How it Works? (The Simple Version)
Even though it’s small, your ESP32 is performing a complex workflow:
1. **ESP32** records your voice when you press the button.
2. That audio is sent to **Deepgram** → converts speech to text.
3. The text is sent to **n8n** → acts like a middleman.
4. **n8n** sends it to **Groq AI** → generates a reply.
5. The reply is sent back to **Deepgram** → converted into audio.
6. **ESP32** receives the audio and plays it through the speaker.
***
## What You Need
Before starting, make sure you have everything ready.
### Hardware Required
* **ESP32-C3 board** (your main device).
* **I2S microphone** (to capture your voice).
* **Small speaker** (to hear responses).
* **USB cable** (for power + uploading code).

Basically: input (mic) → processing (ESP32) → output (speaker)
### Software
* **VS Code** with **PlatformIO** extension.
* **Node.js** (v18 or v20).
* **n8n**: Workflow automation.
* **Deepgram Accounts**: For voice (speech ↔ text).
* **Groq Accounts**: For AI responses.
Keep your API keys safe! Without them, your device won’t “understand” or “talk”.
***
## Software Setup
### Step 1: Install Everything
Take this step slow — this is your foundation.
1. **Install VS Code**: This is where everything will happen.
2. **Install PlatformIO**: Open VS Code → go to Extensions → Search **PlatformIO** and install it.
3. **Install Node.js (v18 or v20)**: Required to run n8n.
4. **Install n8n**: Open your terminal and run:
```bash theme={null}
npm install -g n8n
```
### Step 2: Get API Keys
Now you’re connecting your project to real services.
1. Go to **Deepgram** → create account → copy API key.
2. Go to **Groq** → create account → copy API key.
Think of API keys like passwords that allow your device to use these services.
### Step 3: Setup n8n (The Brain)
n8n is what connects everything together.
1. **Start n8n**: Run this in your terminal:
```bash theme={null}
n8n start
```
Open in browser: `http://localhost:5678`
2. **Import Workflow**:
* Go to **Workflows** → Click **Import**.
* Copy the JSON code below and paste it into the import box.
* Click **Save** and turn it **Active (ON)**.
Click to see n8n Workflow JSON
```json theme={null}
{
"name": "ESP32 Voice Chatbot v12",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "esp32-voice",
"responseMode": "responseNode",
"options": {}
},
"id": "11111111-1111-1111-1111-111111111111",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [180, 300],
"webhookId": "esp32-voice-v11"
},
{
"parameters": {
"jsCode": "const item = $input.first();\nconsole.log('[N8N] received:', JSON.stringify(item.json).substring(0, 300));\nconst body = item.json?.body || item.json || {};\nconst query = body.query || item.json?.query || 'Hello';\nconsole.log('[N8N] query:', query);\nreturn [{ json: { transcript: String(query).trim() } }];"
},
"id": "00000000-0000-0000-0000-000000000001",
"name": "Get Transcript",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [400, 300]
},
{
"parameters": {
"method": "POST",
"url": "https://api.groq.com/openai/v1/chat/completions",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 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"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"llama-3.1-8b-instant\",\n \"temperature\": 0.7,\n \"max_tokens\": 50,\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a voice assistant. You MUST always reply in exactly ONE short sentence of 10 words or less. For jokes give the punchline only. No markdown, no lists, no long answers. Never say you cannot answer.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"{{ $json.transcript }}\"\n }\n ]\n}",
"options": {
"timeout": 10000
}
},
"id": "33333333-3333-3333-3333-333333333333",
"name": "Groq LLM",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [620, 300]
},
{
"parameters": {
"jsCode": "const r = $input.first().json;\nlet reply = '';\ntry {\n reply = r.choices[0].message.content.trim();\n} catch(e) {\n reply = 'I am not sure about that.';\n}\n\n// Hard truncate to 100 chars max to keep TTS fast\nif (reply.length > 100) {\n reply = reply.substring(0, 100).trim();\n // cut at last space to avoid mid-word cut\n const lastSpace = reply.lastIndexOf(' ');\n if (lastSpace > 50) reply = reply.substring(0, lastSpace);\n}\n\nif (!reply) reply = 'I am not sure about that.';\n\nconst transcript = $('Get Transcript').first().json.transcript;\nconsole.log('[Reply] transcript:', transcript);\nconsole.log('[Reply] reply:', reply);\nconsole.log('[Reply] reply length:', reply.length);\nreturn [{ json: { transcript: String(transcript), reply: String(reply) } }];"
},
"id": "44444444-4444-4444-4444-444444444444",
"name": "Get Reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [840, 300]
},
{
"parameters": {
"method": "POST",
"url": "https://api.deepgram.com/v1/speak?model=aura-asteria-en&encoding=linear16&sample_rate=16000&container=wav",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Token 8e7808778ccb81f5b512ec63ff0cc745791a2b08"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"text\": \"{{ $json.reply }}\"\n}",
"options": {
"timeout": 20000,
"response": {
"response": {
"responseFormat": "file",
"outputPropertyName": "audioData"
}
}
}
},
"id": "55555555-5555-5555-5555-555555555555",
"name": "Deepgram TTS",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1060, 300]
},
{
"parameters": {
"jsCode": "const tts = $input.first();\nconst reply = $('Get Reply').first().json.reply;\nconst transcript = $('Get Reply').first().json.transcript;\nconst audio = tts.binary?.audioData;\nif (!audio) {\n console.error('[Build] No audio binary from TTS! TTS response:', JSON.stringify(tts.json).substring(0,200));\n throw new Error('No audio from Deepgram TTS — check API key and reply length');\n}\nconsole.log('[Build] audio mime:', audio.mimeType, 'size:', audio.fileSize);\nreturn [{\n json: { transcript: String(transcript), reply: String(reply) },\n binary: { audioData: audio }\n}];"
},
"id": "66666666-6666-6666-6666-666666666666",
"name": "Build Response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [1280, 300]
},
{
"parameters": {
"respondWith": "binary",
"responseDataSource": "firstIncomingItem",
"options": {
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "audio/wav"
},
{
"name": "X-Transcript",
"value": "={{ $json.transcript }}"
},
{
"name": "X-Reply",
"value": "={{ $json.reply }}"
}
]
}
}
},
"id": "77777777-7777-7777-7777-777777777777",
"name": "Send Audio",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [1500, 300]
}
],
"connections": {
"Webhook": {
"main": [[{ "node": "Get Transcript", "type": "main", "index": 0 }]]
},
"Get Transcript": {
"main": [[{ "node": "Groq LLM", "type": "main", "index": 0 }]]
},
"Groq LLM": {
"main": [[{ "node": "Get Reply", "type": "main", "index": 0 }]]
},
"Get Reply": {
"main": [[{ "node": "Deepgram TTS", "type": "main", "index": 0 }]]
},
"Deepgram TTS": {
"main": [[{ "node": "Build Response", "type": "main", "index": 0 }]]
},
"Build Response": {
"main": [[{ "node": "Send Audio", "type": "main", "index": 0 }]]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true
},
"tags": [],
"triggerCount": 1,
"versionId": "12"
}
```

3. **Add Your API Keys**:
* Open **Groq node** → Replace the existing key with yours.
* Open **Deepgram node** → Replace with your key.
4. **Test It (curl command)**:
Run this command in your terminal:
```bash theme={null}
curl -X POST http://YOUR_IP:5678/webhook/esp32-voice -d '{"query":"Hello"}'
```
* **If you get audio** → everything is working!
### Step 4: Setup ESP32 Code
Now we move to the device itself.
1. **Create Project Structure**:
Your folder should look like this:
```text theme={null}
voice-chatbot/
├── lib/
│ └── PCBCUPID_NAU8325/ <-- Add the library here
├── src/
│ └── main.cpp <-- Your Arduino code
└── platformio.ini <-- Settings file
```
2. **Configure platformio.ini**:
```ini theme={null}
[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
monitor_speed = 115200
```
3. **Add Required Library**:
Download the **NAU8325 library** and place it inside `lib/`. Without this, your speaker won’t work.
4. **Full Arduino Source Code**:
Copy the code below into your `main.cpp` file.
Click to see full Arduino Code (C++)
```cpp theme={null}
/*
* ESP32-C3 Voice Chatbot — PCBCupid Glyph-C3 v25
*
* v25 CHANGES from v24:
* - VOL_BOOST reduced to 6 (cleaner, less distortion)
* - Single speaker: LEFT channel has audio, RIGHT is silent
*/
#include
#include
#include
#include
#include
#include
#include
#include "PCBCUPID_NAU8325.h"
// ─── YOUR SETTINGS ────────────────────────────────────────────
const char* WIFI_SSID = "kbjg";
const char* WIFI_PASSWORD = "33322kbjg";
const char* N8N_HOST = "192.168.0.100";
const int N8N_PORT = 5678;
const char* N8N_PATH = "/webhook/esp32-voice";
const char* DEEPGRAM_API_KEY = "8e7808778ccb81f5b512ec63ff0cc745791a2b08";
const char* DEEPGRAM_STT_HOST = "api.deepgram.com";
// ──────────────────────────────────────────────────────────────
// ─── PIN MAP ──────────────────────────────────────────────────
#define MIC_SCK_GPIO 6
#define MIC_WS_GPIO 7
#define MIC_SD_GPIO 0
#define SPK_BCK_GPIO 10
#define SPK_DAT_GPIO 21
#define SPK_LRCK_GPIO 3
#define SPK_MCLK_GPIO 2
#define I2C_SDA_GPIO 4
#define I2C_SCL_GPIO 5
#define BUTTON_GPIO 9
// ──────────────────────────────────────────────────────────────
// ─── AUDIO ────────────────────────────────────────────────────
static const uint32_t SAMPLE_RATE = 16000;
static const uint32_t MCLK_FREQ = 256 * SAMPLE_RATE;
#define MAX_REC_BYTES 64000
#define WAV_HDR_SIZE 44
#define VOL_BOOST 6
#define STREAM_BUF 4096
#define CHUNK_SIZE 1024
#define FORCE_SHIFT 0
#define TARGET_PEAK_MAX 26000
// ──────────────────────────────────────────────────────────────
i2s_channel_fmt_t micChannel = I2S_CHANNEL_FMT_ONLY_RIGHT;
int micShift = 14;
TwoWire I2Cbus(0);
PCBCUPID_NAU8325 nau(I2Cbus);
bool nauOK = false;
uint8_t* streamBuf = nullptr;
uint8_t* stereoBuf = nullptr;
String serialInput = "";
// ═══════════════════════════════════════════════════════════════
// MONO → SINGLE SPEAKER + BOOST
// LEFT = audio, RIGHT = silent
// (swap if your board drives the other channel)
// ═══════════════════════════════════════════════════════════════
static size_t monoToStereoBoost(const uint8_t* mono, size_t monoBytes,
uint8_t* out) {
const int16_t* src = (const int16_t*)mono;
int16_t* dst = (int16_t*)out;
size_t samples = monoBytes / 2;
for (size_t i = 0; i < samples; i++) {
int32_t v = (int32_t)src[i] * VOL_BOOST;
if (v > 32767) v = 32767;
if (v < -32768) v = -32768;
dst[i*2] = (int16_t)v; // LEFT — audio
dst[i*2+1] = 0; // RIGHT — silent
}
return monoBytes * 2;
}
// ═══════════════════════════════════════════════════════════════
// I2S
// ═══════════════════════════════════════════════════════════════
static void i2sUninstall() {
i2s_zero_dma_buffer(I2S_NUM_0);
i2s_driver_uninstall(I2S_NUM_0);
}
static void i2sInitMic(i2s_channel_fmt_t ch) {
i2s_config_t cfg = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = ch,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pins = {
.mck_io_num = I2S_PIN_NO_CHANGE,
.bck_io_num = MIC_SCK_GPIO,
.ws_io_num = MIC_WS_GPIO,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = MIC_SD_GPIO
};
i2s_driver_install(I2S_NUM_0, &cfg, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pins);
i2s_zero_dma_buffer(I2S_NUM_0);
delay(80);
}
static void i2sInitSpeaker() {
i2s_config_t cfg = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 512,
.use_apll = false,
.tx_desc_auto_clear = true,
.fixed_mclk = (int)MCLK_FREQ
};
i2s_pin_config_t pins = {
.mck_io_num = SPK_MCLK_GPIO,
.bck_io_num = SPK_BCK_GPIO,
.ws_io_num = SPK_LRCK_GPIO,
.data_out_num = SPK_DAT_GPIO,
.data_in_num = I2S_PIN_NO_CHANGE
};
i2s_driver_install(I2S_NUM_0, &cfg, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pins);
i2s_zero_dma_buffer(I2S_NUM_0);
Serial.println("[SPK] I2S speaker ready");
}
static void spkSilence(uint32_t ms) {
int16_t buf[256]; memset(buf, 0, sizeof(buf));
uint32_t end = millis() + ms;
while (millis() < end) {
size_t wr = 0;
i2s_write(I2S_NUM_0, buf, sizeof(buf), &wr, portMAX_DELAY);
}
}
// ═══════════════════════════════════════════════════════════════
// NAU8325
// ═══════════════════════════════════════════════════════════════
static bool nauBegin() {
I2Cbus.end(); delay(20);
I2Cbus.begin(I2C_SDA_GPIO, I2C_SCL_GPIO);
I2Cbus.setClock(100000);
delay(30);
return nau.begin(SAMPLE_RATE, 16, 256);
}
static void nauFullInit() {
for (int attempt = 1; attempt <= 5; attempt++) {
Serial.printf("[NAU] Attempt %d...\n", attempt);
if (nauBegin()) {
nau.powerOn(); delay(300);
nau.setVolume(0xFF, 0xFF); delay(30);
nau.softMute(false); delay(200);
nauOK = true;
Serial.println("[NAU] OK vol=0xFF");
return;
}
delay(200);
}
Serial.println("[NAU] FAILED");
}
static void nauRearm() {
Serial.println("[NAU] Rearming...");
if (nauBegin()) {
nau.powerOn(); delay(300);
nau.setVolume(0xFF, 0xFF); delay(30);
nau.softMute(false); delay(200);
nauOK = true;
Serial.println("[NAU] OK");
} else {
Serial.println("[NAU] Rearm FAILED");
}
}
// ═══════════════════════════════════════════════════════════════
// HELPERS
// ═══════════════════════════════════════════════════════════════
static void buildWavHeader(uint8_t* h, uint32_t pcmBytes) {
uint32_t fileSize = pcmBytes + 36;
uint32_t byteRate = SAMPLE_RATE * 2;
uint16_t align=2, bits=16, ch=1, fmt=1;
uint32_t fmtSz=16;
memcpy(h, "RIFF",4); memcpy(h+4, &fileSize, 4);
memcpy(h+8, "WAVE",4); memcpy(h+12, "fmt ", 4);
memcpy(h+16, &fmtSz,4); memcpy(h+20, &fmt, 2);
memcpy(h+22, &ch, 2); memcpy(h+24, &SAMPLE_RATE, 4);
memcpy(h+28, &byteRate,4); memcpy(h+32,&align, 2);
memcpy(h+34, &bits, 2); memcpy(h+36, "data", 4);
memcpy(h+40, &pcmBytes,4);
}
static uint32_t wavGetRate(const uint8_t* h) {
uint32_t r=0; memcpy(&r, h+24, 4); return r;
}
static void printSummary(uint8_t* pcm, uint32_t bytes,
int32_t maxPeak, int shift, uint32_t ms) {
Serial.println("\n+--------------------------------------+");
Serial.printf( "| Duration : %u ms PCM: %u bytes\n", ms, bytes);
Serial.printf( "| Peak : %d (%.1f%%) shift=%d\n",
maxPeak, (maxPeak/32767.0f)*100.0f, shift);
Serial.print( "| Waveform : |");
const int bars=36;
int spb=max(1,(int)(bytes/2)/bars);
int16_t* p=(int16_t*)pcm;
for (int b=0;bbp) bp=a;
}
Serial.print(" .:;+=xX"[min(7,(int)((bp*8)/32767))]);
}
Serial.println("|");
Serial.println("+--------------------------------------+");
}
// ═══════════════════════════════════════════════════════════════
// MIC CALIBRATION
// ═══════════════════════════════════════════════════════════════
void calibrateMic() {
if (FORCE_SHIFT > 0) {
micShift=FORCE_SHIFT; micChannel=I2S_CHANNEL_FMT_ONLY_RIGHT;
Serial.printf("[MIC] Forced shift=%d\n", micShift); return;
}
int32_t* dma=(int32_t*)malloc(256*4);
if (!dma) { Serial.println("[MIC] malloc failed"); return; }
i2sUninstall();
i2s_channel_fmt_t bestCh=I2S_CHANNEL_FMT_ONLY_RIGHT;
int32_t bestPeak=0;
i2s_channel_fmt_t chs[]={I2S_CHANNEL_FMT_ONLY_LEFT,
I2S_CHANNEL_FMT_ONLY_RIGHT};
const char* chNames[]={"LEFT","RIGHT"};
Serial.println("[MIC] Detecting channel...");
for (int c=0;c<2;c++) {
i2sInitMic(chs[c]);
int32_t peak=0;
for (int r=0;r<10;r++) {
size_t rd=0;
i2s_read(I2S_NUM_0,dma,256*4,&rd,portMAX_DELAY);
for (int i=0;i<(int)(rd/4);i++) {
int32_t a=abs((int32_t)((int16_t)(dma[i]>>11)));
if(a>peak) peak=a;
}
}
Serial.printf("[MIC] %s peak=%d\n",chNames[c],peak);
i2sUninstall(); delay(30);
if (peak>bestPeak) { bestPeak=peak; bestCh=chs[c]; }
}
micChannel=bestCh;
Serial.println("[MIC] >>> SPEAK NOW for gain calibration <<<");
delay(500);
for (int sh=11;sh<=22;sh++) {
i2sInitMic(micChannel);
int32_t peak=0;
for (int r=0;r<30;r++) {
size_t rd=0;
i2s_read(I2S_NUM_0,dma,256*4,&rd,portMAX_DELAY);
for (int i=0;i<(int)(rd/4);i++) {
int32_t a=abs((int32_t)((int16_t)(dma[i]>>sh)));
if(a>peak) peak=a;
}
}
i2sUninstall(); delay(20);
Serial.printf("[MIC] shift=%d peak=%d\n",sh,peak);
if (peak<=TARGET_PEAK_MAX) { micShift=sh; break; }
}
free(dma);
Serial.printf("[MIC] Final: ch=%s shift=%d\n",
micChannel==I2S_CHANNEL_FMT_ONLY_LEFT?"LEFT":"RIGHT",micShift);
i2sInitSpeaker();
nauRearm();
}
// ═══════════════════════════════════════════════════════════════
// TONE TEST
// ═══════════════════════════════════════════════════════════════
void playToneTest() {
spkSilence(50);
int16_t buf[512];
for (int i=0;i<256;i++) {
int16_t s=(int16_t)(28000*sin(2.0*PI*1000.0*i/16000.0));
buf[i*2] = s; // LEFT only
buf[i*2+1] = 0; // RIGHT silent
}
Serial.println("[TEST] Tone...");
uint32_t end=millis()+2000;
while (millis()>> YOU : "+outT);
Serial.println(">>> REPLY: "+outR);
}
// ═══════════════════════════════════════════════════════════════
// PLAY AUDIO FROM WiFiClient
// ═══════════════════════════════════════════════════════════════
void playFromClient(WiFiClient& client) {
uint32_t timeout=millis()+10000;
while (!client.available()&&millis()0&&millis()-t2<15000) {
if (!client.available()) {
if (!client.connected()) goto play_done;
delay(1); yield(); continue;
}
size_t want=min((size_t)rem,(size_t)STREAM_BUF);
size_t rd=client.readBytes((char*)streamBuf,want);
if (!rd) { delay(1); yield(); continue; }
rem-=rd; t2=millis(); timeout=millis()+30000;
if (!headerDone) {
size_t need=WAV_HDR_SIZE-hdrGot;
size_t take=min(need,rd);
memcpy(hdrBuf+hdrGot,streamBuf,take);
hdrGot+=take;
if (hdrGottake) {
size_t sb=monoToStereoBoost(streamBuf+take,rd-take,stereoBuf);
size_t wr=0;
i2s_write(I2S_NUM_0,stereoBuf,sb,&wr,portMAX_DELAY);
totalPCM+=wr;
}
continue;
}
size_t sb=monoToStereoBoost(streamBuf,rd,stereoBuf);
size_t wr=0;
i2s_write(I2S_NUM_0,stereoBuf,sb,&wr,portMAX_DELAY);
totalPCM+=wr;
}
client.readStringUntil('\n');
}
play_done:
spkSilence(80);
i2s_set_sample_rates(I2S_NUM_0,SAMPLE_RATE);
Serial.printf("[PLAY] Done %u bytes\n",totalPCM);
Serial.printf("[MEM] heap=%u\n",ESP.getFreeHeap());
}
// ═══════════════════════════════════════════════════════════════
// DEEPGRAM STT
// ═══════════════════════════════════════════════════════════════
String transcribeAudio(uint8_t* pcmBuf, uint32_t pcmLen) {
if (!pcmLen) return "";
uint8_t hdr[WAV_HDR_SIZE]; buildWavHeader(hdr,pcmLen);
uint32_t wavLen=WAV_HDR_SIZE+pcmLen;
WiFiClientSecure ssl; ssl.setInsecure(); ssl.setTimeout(30);
if (!ssl.connect(DEEPGRAM_STT_HOST,443)) {
Serial.println("[STT] Connect FAILED"); return "";
}
ssl.printf(
"POST /v1/listen?model=nova-2&language=en&punctuate=true HTTP/1.1\r\n"
"Host: %s\r\nAuthorization: Token %s\r\n"
"Content-Type: audio/wav\r\nContent-Length: %u\r\nConnection: close\r\n\r\n",
DEEPGRAM_STT_HOST,DEEPGRAM_API_KEY,wavLen);
ssl.write(hdr,WAV_HDR_SIZE);
for (uint32_t s=0;s=0) chunked=true;
if (lo.startsWith("content-length:")) clen=lo.substring(15).toInt();
}
String body=""; body.reserve(2048);
if (chunked) {
uint32_t tout=millis()+20000;
while (millis()0;) {
while (!ssl.available()) { delay(1); yield(); }
uint8_t tmp[256];
size_t rd=ssl.readBytes((char*)tmp,min((uint32_t)256,rem));
for (size_t i=0;i0&&(int)body.length()>=clen) goto stt_done;
}
if (!ssl.connected()&&!ssl.available()) break;
delay(5); yield();
}
}
stt_done:
ssl.stop();
Serial.println("[STT] "+body.substring(0,120));
const String key="\"transcript\":\"";
int idx=body.indexOf(key); if (idx<0) return "";
idx+=key.length();
String tr="";
for (int i=idx;i<(int)body.length();i++) {
char c=body[i];
if (c=='\\'&&i+1<(int)body.length()) {
char n=body[++i];
if (n=='"') tr+='"'; else if (n=='n') tr+=' '; else tr+=n;
continue;
}
if (c=='"') break; tr+=c;
}
tr.trim();
Serial.println("[STT] >> "+tr);
return tr;
}
// ═══════════════════════════════════════════════════════════════
// WiFi
// ═══════════════════════════════════════════════════════════════
bool ensureWiFi() {
if (WiFi.status()==WL_CONNECTED) return true;
WiFi.disconnect(); delay(100);
WiFi.begin(WIFI_SSID,WIFI_PASSWORD);
for (int i=0;i<40;i++) {
if (WiFi.status()==WL_CONNECTED) return true;
delay(500); Serial.print(".");
}
Serial.println(); return false;
}
void connectWiFi() {
Serial.printf("[WiFi] Connecting to %s",WIFI_SSID);
WiFi.begin(WIFI_SSID,WIFI_PASSWORD);
for (int t=0;WiFi.status()!=WL_CONNECTED&&t<30;t++) {
delay(500); Serial.print(".");
}
if (WiFi.status()==WL_CONNECTED)
Serial.printf("\n[WiFi] IP: %s\n",WiFi.localIP().toString().c_str());
else Serial.println("\n[WiFi] FAILED");
}
// ═══════════════════════════════════════════════════════════════
// SEND → n8n → PLAY
// ═══════════════════════════════════════════════════════════════
bool sendTextToN8N(const String& text) {
if (!ensureWiFi()) return false;
WiFiClient client; client.setTimeout(30);
if (!client.connect(N8N_HOST,N8N_PORT)) {
Serial.println("[N8N] Connect failed"); return false;
}
String safe=text; safe.replace("\"","\\\"");
String body="{\"query\":\""+safe+"\"}";
client.printf(
"POST %s HTTP/1.1\r\nHost: %s:%d\r\n"
"Content-Type: application/json\r\nContent-Length: %u\r\nConnection: close\r\n\r\n",
N8N_PATH,N8N_HOST,N8N_PORT,body.length());
client.print(body);
Serial.printf("[N8N] >> %s\n",text.c_str());
uint32_t t=millis()+20000;
while (!client.available()&&millis()>micShift);
memcpy(pcmBuf+written,&s,2); written+=2;
int32_t a=abs((int32_t)s); if(a>maxPeak) maxPeak=a;
}
if (++dots%4==0) Serial.print('.');
yield();
}
Serial.println(" [done]");
free(dma);
uint32_t dur=millis()-recStart;
// Restore speaker + rearm NAU immediately
// (~530ms settles during STT network call below)
i2sUninstall();
i2sInitSpeaker();
nauRearm();
if (written<3200) {
Serial.println("[REC] Too short");
free(pcmBuf); return false;
}
printSummary(pcmBuf,written,maxPeak,micShift,dur);
Serial.printf("[MEM] heap=%u\n",ESP.getFreeHeap());
String transcript=transcribeAudio(pcmBuf,written);
free(pcmBuf);
if (!transcript.length()) {
Serial.println("[STT] Empty"); return false;
}
Serial.println(">> YOU: "+transcript);
return sendTextToN8N(transcript);
}
// ═══════════════════════════════════════════════════════════════
// SETUP
// ═══════════════════════════════════════════════════════════════
void setup() {
Serial.begin(115200);
delay(300);
Serial.println("\n=== ESP32-C3 Voice Chatbot v25 ===");
Serial.printf("[MEM] heap=%u\n",ESP.getFreeHeap());
streamBuf=(uint8_t*)malloc(STREAM_BUF);
stereoBuf=(uint8_t*)malloc(STREAM_BUF*2);
if (!streamBuf||!stereoBuf) {
Serial.println("[ERR] Buffer alloc failed"); while(1);
}
Serial.printf("[MEM] Buffers OK heap=%u\n",ESP.getFreeHeap());
pinMode(BUTTON_GPIO,INPUT_PULLUP);
i2sInitSpeaker();
nauFullInit();
Serial.println("[MIC] >>> SPEAK for calibration <<<");
delay(800);
calibrateMic();
connectWiFi();
Serial.println("[TEST] Tone...");
playToneTest();
Serial.println("\n[READY] Hold BOOT to speak\n");
}
// ═══════════════════════════════════════════════════════════════
// LOOP
// ═══════════════════════════════════════════════════════════════
void loop() {
while (Serial.available()) {
char c=Serial.read();
if (c=='\n'||c=='\r') {
serialInput.trim();
if (serialInput.length()) {
sendTextToN8N(serialInput);
serialInput="";
Serial.println("[READY]");
}
} else serialInput+=c;
}
if (digitalRead(BUTTON_GPIO)==LOW) {
delay(30);
if (digitalRead(BUTTON_GPIO)==LOW) {
recordTranscribeAndPlay();
while (digitalRead(BUTTON_GPIO)==LOW) delay(10);
Serial.println("[READY]");
}
}
if (WiFi.status()!=WL_CONNECTED) connectWiFi();
delay(10);
}
```
4. **Update Your Settings**:
Inside `main.cpp`, update:
```cpp theme={null}
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASSWORD = "YOUR_PASSWORD";
const char* N8N_HOST = "YOUR_SERVER_IP";
const int N8N_PORT = 5678;
const char* DEEPGRAM_API_KEY = "YOUR_KEY";
```
### Step 5: Upload Code to ESP32
Now bring your device to life.
1. Connect ESP32 using USB.
2. Open project in VS Code.
3. Click **Upload** (or run `pio run --target upload`).
### Step 6: First Boot & Monitor
Open the **Serial Monitor** (115200 baud). You should see:
`[READY] Hold BOOT to speak`
👉 **This means WiFi is connected and the AI is ready to listen!**
### Step 7: How to Use
#### Voice Mode (Main Feature)
1. **Hold** the BOOT button.
2. **Speak** clearly into the microphone.
3. **Release** the button.
4. **Wait** a second for the AI response.
Keep your voice commands short (1–2 seconds) for the fastest response!
#### Text Mode (Testing)
Type your message in the **Serial Monitor** and press **Enter**.


***
## ❗ Common Issues (Quick Fixes)
| Issue | Check |
| :--------------------- | :-------------------------------------------------------- |
| **No Sound** | Check speaker wiring & amplifier logs. |
| **No Response** | Ensure n8n is running & WiFi is connected. |
| **Not Understanding** | Speak louder, hold button longer, check Deepgram API key. |
| **Server Not Opening** | Check `http://YOUR_IP:5678` - fix server first. |
***
## Customization (Make It Yours)
### Change AI Personality
Inside n8n, update the prompt:
`"You are a smart assistant. Reply in one short sentence."`
### Adjust Volume
Inside your code, locate and change:
```cpp theme={null}
#define VOL_BOOST 6
```
Have fun with your mini AI Assistant!
# Z-Claw AI
Source: https://learn.pcbcupid.com/guides/ai/z-claw
Build the Z-Claw robotic gripper that uses on-device AI and computer vision on ESP32 to detect, classify, and pick up objects autonomously.
# Z-Claw AI Assistant
Z-Claw is the smallest AI personal assistant you can build. It runs on the **GLYPH-C3** board and lets you talk to an AI to control your home, set reminders, and more.
## How it Works? (The Simple Version)
Even though it's tiny, your **GLYPH-C3** board is doing some smart work:
1. **Connection**: It connects to your WiFi and listens for your messages (via Telegram or a Serial monitor).
2. **The Brain**: It sends your question to an **AI Brain** (either running on your computer with **Ollama** or in the cloud).
3. **Actions**: The AI doesn't just talk—it understands "tools." For example, if you say "Turn on the light," the AI tells the board to flick a switch (GPIO pin).
4. **No Lag**: Because the code is written in **C**, it's extremely fast and uses very little power.
***
## What You Need
Before starting, make sure you have your hardware and software environment ready.
### Hardware Required
* **GLYPH-C3 board** (The main AI device).
* **LED** (For testing).
* **220 ohm resistor** (For testing).
* **Breadboard** (For testing).
* **Jumper wires** (For testing).
### Circuit diagram

### Software
* **ESP-IDF v5.x**: The core development tools from Espressif.
* **Git**: Required to download the project files.
* **Python**: Required for the build system and provisioning scripts.
***
## Software Setup
You have two ways to give your assistant a "brain":
1. **Ollama (Local)**: No cost, runs on your own computer (Recommended).
2. **API Key (Cloud)**: Uses a paid service like OpenRouter.
### Step 1: Get the Code
First, we need to download the Z-Claw project files from GitHub to your computer. Go to the [Z-Claw GitHub Repository](https://github.com/tnm/zclaw) and copy the clone URL.

Open your terminal and run:
```bash theme={null}
git clone --recursive https://github.com/zclaw-org/zclaw.git %userprofile%\ZClaw
```

***
### Step 2: Setup YOUR ESP-IDF Environment
To compile and upload the code, you need the ESP-IDF tools. You have two ways to do this:
#### Option A: ESP-IDF Terminal
If you installed the standalone ESP-IDF 5.x tools, open the **ESP-IDF 5.x PowerShell** (or CMD) from your Windows Start Menu.
Once open, navigate to your project folder:
```bash theme={null}
cd %userprofile%\ZClaw
```
#### Option B: VS Code Extension
You can also use the official ESP-IDF extension for VS Code. This makes it easier to build and flash using the VS Code interface.
For a full guide on setting up the extension, see our [ESP-IDF Setup Guide](/boards/needs/esp-idf).
***
### Step 3: Set the Target Board
Every ESP32 chip is slightly different. We need to tell the project that we are using the **esp32c3** chip (the one inside your **GLYPH-C3**).

```bash theme={null}
cd ZClaw
idf.py set-target esp32c3
```
***
### Step 4: Configure Your AI Brain
Before connecting your board, you need to decide which AI **"Brain"** to use. You will need these details for both the configuration menu below and the provisioning script in **Step 7**.
#### Prepare Your AI Details
* **Option A: Ollama (Local AI)**: Install [Ollama](https://ollama.com/) on your computer. Make sure it's running and keep your computer's IP address ready (e.g., `http://192.168.1.50:11434`).
* **Local Device URL**: After getting the IP address, you should also have a local device URL ready that you will need to enter in the terminal manually.
* **Option B: OpenRouter (Cloud AI)**/**OpenAI** and keep it ready.
**Need an API Key?**
Get one from [OpenRouter](https://openrouter.ai/settings/keys) or [OpenAI](https://openai.com/) by creating a new key named "zclaw".

Gathering these details now will make the next steps much smoother! You'll need them again in **Step 7**.
#### Run the Configuration Menu
Now, open the "Settings" menu to tell your board which AI to talk to:
```bash theme={null}
idf.py menuconfig
```
Select **zclaw Configuration --->**.
***
### Step 5: Add Telegram Bot
This allows you to message your assistant from your phone using the Telegram app.
Save your **Bot Token** and **Chat ID**; you'll need them for the provisioning script in **Step 7**.
### 1. Message [@BotFather](https://t.me/botfather) and use `/newbot` to get a **Token**.
### 2. Message [@userinfobot](https://t.me/userinfobot) to get your **Chat ID**.
***
### Step 6: Build and Flash the Firmware
This command compiles your C code and "burns" the logic onto the ESP32. Run this in your ESP-IDF terminal:
```bash theme={null}
idf.py build flash
```
Wait for the process to hit 100% and show "Done."

***
### Step 7: Provision Your Credentials
Now, save your WiFi, Telegram, and LLM details into the board's memory. Run this command in the same terminal:
```bash theme={null}
"C:\Program Files\Git\bin\bash.exe" scripts/provision.sh --port YOUR_PORT_HERE
```
*(Replace `YOUR_PORT_HERE` with your actual port number, e.g., `COM145`).*
Follow the prompts to enter:
* **WiFi SSID & Password**
* **LLM Provider**: (e.g., `openai` or `ollama`)
* **LLM Model**: (e.g., `qwen2.5:0.5b`)
* **Local Device URL**: (e.g., `http://192.168.1.50:11434`)
* **Telegram Bot Token & Chat ID**
***
### Step 8: Start the Assistant (Monitor)
Finally, run this to start the assistant and see the output in real-time:
```bash theme={null}
idf.py -p YOUR_PORT_HERE monitor
```

***
## What can I say?
Try talking to your assistant:
* "Remind me to water the plants at 8am daily."
* "What is the temperature?"
* "Turn off the lights (GPIO 2)."
Have fun with your mini AI Assistant!
# Blink LED
Source: https://learn.pcbcupid.com/guides/arduino-ide-blink-led
Run your first Arduino sketch on a Glyph board: wire an LED, install the ESP32 core, and upload the classic Blink example from the Arduino IDE.
## Blinking of On-Board LED
Click here to know how to do the [initial setup](https://learn.pcbcupid.com/boards/needs/arduino-ide-setup) for Arduino IDE.

The **"Hello World!"** program of hardware world, the Blink Sketch! You can upload this sketch and it's a great way to make sure your board is working and you're uploading your sketch to the right glyph board and right configuration (after the Bare minimum sketch).
You can either open the inbuilt example from arduino IDE by clicking through `File > Examples > 01.Basics > Blink` and modify based on your GLYPH Board.
These are the inbuilt LED pin based on the type of GLYPH board you have :
* GLYPH C3 On board LED is on GPIO1(A1)
* GLYPH H2 On board LED is on GPIO0(D0)
* GLYPH C6 On board LED is on GPIO14(D14)
If not you can copy the below code and comment/uncomment the **led** initialization.
```cpp theme={null}
//Use this line if you are using GLYPH C3
int led = 1;
//uncomment this line for GLYPH H2
// int led = 0;
//uncomment this line for GLYPH C6
//int led = 14;
void setup()
{
pinMode(led, OUTPUT); // set LED to be an output pin
}
void loop()
{
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a one second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a one second
}
```
Next begin by plugging in your board to your computer, and wait a moment for it to be recognized by the OS. It will create a COM/serial port that you can now select from the `Tools > Port` menu dropdown and upload the sketch.
The LED should start blinking!

## Blinking of External LED
A similar process can be followed to blink an external LED, but do remember to change the led LED number in the code to the pin number where an external led is connected.
Below you can see an example code which should help
```cpp theme={null}
int led = A2; // LED is connected to A2 pin
void setup()
{
pinMode(led, OUTPUT); // set LED to be an output pin
}
void loop()
{
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a one second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a one second
}
```
Next begin by plugging in your board to your computer, and wait a moment for it to be recognized by the OS. It will create a COM/serial port that you can now select from the `Tools > Port` menu dropdown and upload the sketch.

Once complete, the LED on the glyph board will begin blinking once every second! Try changing up the `delay()` timing on the code to change the rate at which the LED blinks.

# Flame Sensor Test
Source: https://learn.pcbcupid.com/guides/basic-sensors/flame-sensor
Wire a flame sensor to a Glyph ESP32 board and read analog input values to detect open flames or infrared light sources for fire safety projects.
# Flame Sensor Test using GLYPH-C6
An IR (Infrared) sensor is an electronic device that detects infrared radiation (IR light) emitted by objects.
It typically consists of an IR emitter (like an IR LED) and an IR receiver (like a photodiode or phototransistor).
IR sensors are commonly used for detecting motion, measuring distance, or sensing heat and flames, depending on the design and wavelength sensitivity.
This example demonstrates how to use a **flame sensor** with a **GLYPH-C6 (ESP32-C6)** board to detect fire or flame by reading analog values and
comparing them with a threshold.
**How it Works**
The flame sensor outputs an analog voltage proportional to the intensity of detected IR radiation (from fire). When the analog value drops below a preset threshold, we assume a flame is detected.
**Flame Emits IR Radiation**
1. All flames release heat and IR light, usually in the range of 760–1100 nanometers (nm).
2. IR Sensor Detects This Radiation
The IR receiver in the sensor is tuned to pick up IR waves in that flame-specific range.
When a flame is nearby, this IR light hits the sensor.
3. Sensor Processes the Signal
The sensor checks the intensity of the incoming IR light.
If it’s strong enough, it decides a flame is present.
4. Output Changes
The sensor gives a signal:
Digital Output (D0) becomes LOW (0V) when flame is detected.
Analog Output (A0) gives a low value (0–300) when flame is nearby.
Make sure your flame sensor outputs analog voltage (some have digital-only pins). GPIO 4 on GLYPH supports analog read.
## Step 1: Hardware Required
* GLYPH Board
* Flame Sensor Module (Analog output type)
* Jumper Wires
* Breadboard
* Flame or lighter for testing
## Step 2: Circuit Diagram
Flame Sensor Pinout:
* **D0 / A0** → Analog output
* **VCC** → 3.3V or 5V (based on your sensor)
* **GND** → Ground
Wiring with GLYPH-C6:
* **Sensor D0/A0** → GPIO 4
* **Sensor VCC** → 3.3V
* **Sensor GND** → GND

## Step 3: Code Setup
```cpp theme={null}
#define FLAME_SENSOR_D0 4 // D0 from sensor to GPIO4 on GLYPH-C6
#define FLAME_THRESHOLD 400 // Adjust based on environment
void setup() {
Serial.begin(115200);
}
void loop() {
int analogValue = analogRead(FLAME_SENSOR_D0);
Serial.print("Analog Value: ");
Serial.println(analogValue);
if (analogValue < FLAME_THRESHOLD) {
Serial.println(" Flame Detected!");
} else {
Serial.println("No flame.");
}
delay(500);
}
```
## Step 4: Upload the Code
1. **Connect the Board**
Connect your GLYPH-C6 board to your PC using a USB cable.
2. **Select the Board and Port**
Tools > Board > esp32 > Pcbcupid GLYPH C6
Tools > Port → Select the correct COM port
Tools > USB CDC on Boot → Enabled
Ensure USB CDC on BOOT is enabled. Otherwise, you won’t see serial output.
3. **Upload the Code**
Click the ➡️ Upload button or press CTRL + U to upload the sketch.
## Step 5: Observe the Output on Serial Monitor
Open the Serial Monitor at 115200 baud.
Without a flame nearby, the sensor shows higher analog values (e.g., \~800–1000).
When you bring a flame source close to the sensor, the analog value will drop below the threshold, and the Serial Monitor will display "Flame Detected!".

# IR Sensor
Source: https://learn.pcbcupid.com/guides/basic-sensors/infrared-sensor
Connect an infrared proximity sensor to the Glyph ESP32-C6, read digital output, and detect nearby objects for line-following or obstacle avoidance.
# Interfacing an IR Sensor with GLYPH
## Introduction
An **IR sensor** is an electronic device that emits Infrared (IR) light to sense objects in its surroundings. The IR sensor can measure the heat of an object and detect motion. Usually, in the infrared spectrum, all objects radiate some form of thermal radiation. This radiation is invisible to our eyes, but the IR sensor can detect it.
The emitter is an IR LED (Light Emitting Diode) and the detector is an IR photodiode. A **photodiode** is sensitive to IR light of the same wavelength emitted by the IR LED. When IR light falls on the photodiode, its resistance and output voltage change in proportion to the magnitude of the IR light received.
There are five basic elements used in a typical infrared detection system:
1. An infrared source - Infrared lasers and Infrared LED’s of specific wavelength used as infrared sources.
2. A transmission medium
3. An optical component
4. Infrared detectors or receivers
5. Signal processing
The three main types of media used for infrared transmission are vacuum, atmosphere and optical fibers. Optical components are used to focus the infrared radiation or to limit the spectral response.
There are different types of infrared transmitters depending on their wavelengths, output power and response time. An IR sensor consists of an IR LED and an IR Photodiode. Together, they form an optical pair often used for object detection.
**IR Transmitter or IR LED**
**Infrared Transmitter** is a light emitting diode (LED) which emits infrared radiation. Even though an IR LED looks like a normal LED, the radiation emitted by it is invisible to the human eye. The image below shows an IR receiver/photodiode:
**IR Receiver or Photodiode**
**Infrared Receivers** or infrared sensors detect the radiation from an IR transmitter. IR receivers come in the form of photodiodes and phototransistors. Infrared Photodiodes are different from normal photo diodes as they detect only infrared radiation. Below image shows the picture of an IR receiver,
Different types of IR receivers exist based on the wavelength, voltage, package, etc. When used in an infrared transmitter – receiver combination, the wavelength of the receiver should match with that of the transmitter.
The emitter is an IR LED and the detector is an IR photodiode. The IR photodiode is sensitive to the IR light emitted by an IR LED. The photo-diode’s resistance and output voltage change in proportion to the IR light received. This is the underlying working principle of the IR sensor.
When the IR transmitter emits radiation, it reaches the object, and some of it reflects back to the IR receiver. Based on the intensity of the reflection, the sensor's output is defined.
**IR Sensor Circuit**
An IR Sensor's circuit can be built with a photodiode, IR LED, an Op-Amp, LED & a potentiometer, The main function of an infrared LED is to emit IR light and the photodiode is used to sense the IR light. In this circuit, an operational amplifier is used as a voltage comparator and the output of the sensor can be adjusted by the potentiometer based on the requirement.
Once the light generated from the infrared LED can be dropped on the photodiode once striking an object, then the photodiode’s resistance will be dropped.
Here, op-amp’s one of the input at threshold value can be set through the potentiometer whereas other inputs can be set by using the series resistor of the photodiode. Once the radiation on the photodiode is more, then the voltage drop will be more across the series resistor. In the operational amplifier, both the voltages are evaluated.
If the series resistor’s voltage is higher than the threshold voltage then the IC output is high. When the IC output is given to an LED then it will blink. So using a potentiometer, the threshold voltage can be adjusted based on the conditions of surroundings.
In this circuit, the arrangement of the IR receiver and the IR LED is a very essential factor. Once the infrared LED is placed directly ahead of the infrared receiver, then this arrangement can be known as Direct Incidence.
So in this case, nearly the whole radiation from the infrared LED will drop on the infrared receiver. Therefore there is a row of view contact among the IR Tx & Rx. If a target drops in this row, it blocks the emission while approaching the receiver by reproducing or absorbing the radiation.
**Advantages**
* Low power consumption
* Noise immunity is strong
* Detects motion when the light is present or absent
* They do not need to get in touch with objects for detection.
* No data leakage because of the directionality infrared radiation of ray
* It responds very quickly as compared to thermocouples.
**Disadvantages**
* Line of sight is necessary
* It can be affected based on the conditions of the environment like fog, rain, pollution, dust, etc
* These sensors can be blocked with common objects.
* The data rate transmission is not fast
* Range is limited
* High force IR signals can harm human eyes
**Applications of IR Sensor**
IR sensors are used in various robotic projects, most commonly for path tracing in line follower robots and in various electronic devices. Some of its applications are:
1. **Night Vision Devices**- An Infrared technology implemented in night vision equipment if there is not enough visible light available to see unaided. Night vision devices convert ambient photons of light into electrons and then amplify them using a chemical and electrical process before finally converting them back into visible light.
2. **Radiation Thermometers**- IR sensors are used in radiation thermometers to measure the temperature depend upon the temperature and the material of the object and these thermometers have some of the following features
* Measurement without direct contact with the object
* Faster response
* Easy pattern measurements
3. **Infrared Tracking**-IR Sensor also finds use in tracking of Robots, Drones & Unmanned Aerial Vehicles and Missile technology. Infrared Tracking or Infrared Homing, is a missile guidance system which operates using the infrared electromagnetic radiation emitted from a target to track it.
4. **IR Imaging Devices**
## Step 1: Hardware Required
1. GLYPH Board
2. IR Sensor
## Step 2: Circuit Diagram
## Step 3: Code Setup
```cpp theme={null}
/*
* This ESP32 code is created by esp32io.com
*
* This ESP32 code is released in the public domain
*
* For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-infrared-obstacle-avoidance-sensor
*/
#define SENSOR_PIN 7 // ESP32-C6 pin GPIO 7 connected to OUT pin of IR sensor
void setup()
{
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// initialize the Arduino's pin as an input
pinMode(SENSOR_PIN, INPUT);
}
void loop()
{
// read the state of the the input pin:
int state = digitalRead(SENSOR_PIN);
if (state == LOW)
Serial.println("The obstacle is present");
else
Serial.println("The obstacle is NOT present");
delay(100);
}
```
## Step 4: Upload the Code
1. **Connect the Board**
Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* Tools > Board > esp32 > Pcbcupid GLYPH C6
For the `Pcbcupid Glyph` to appear under Tools > Board > esp32, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* Tools > Port and select the port connected to your GLYPH.
* Tools > USB CDC on Boot > **Enabled**
If USB CDC on BOOT is not enabled, you won't see any serial data in the Arduino IDE.
3. **Upload the Code**
Upload the corresponding code for your board to the GLYPH board using the Arduino IDE.
* Click the upload button (➡ icon) or use the shortcut CTRL + U in Arduino IDE to upload the code to the board.
## Step 5: Observe the Serial Monitor Output
Place your hand in front of the IR Sensor Transmitter LED and you will see the IR Sensor Module's LED light up and the Serial Monitor showing that the Obstacle is detected

# LDR Light Sensor
Source: https://learn.pcbcupid.com/guides/basic-sensors/ldr
Wire a light-dependent resistor (LDR) to the Glyph ESP32-C6 board and read analog values to measure ambient light levels in your IoT projects.
# Interfacing an LDR with GLYPH board
An LDR (Light Dependent Resistor), also known as a photoresistor, is a variable resistor that changes its resistance based on the intensity of light falling on it.
**How an LDR Works**:
Light Intensity vs. Resistance:
In darkness, the resistance of an LDR is very high (in the range of megaohms, MΩ).
In bright light, the resistance drops significantly (to a few hundred ohms, Ω).
**Material Composition**:
LDRs are made of semiconductor materials like cadmium sulfide (CdS), which have high resistance in darkness but become more conductive when exposed to light (due to photon energy freeing electrons).
**LDR in a Circuit**:
Voltage Divider Circuit:
An LDR is often used in a voltage divider with a fixed resistor to convert changes in light intensity into voltage variations.
The voltage across the LDR can be measured using a microcontroller (e.g., ESP32, Arduino).
**Controlling Devices**:
LDRs are used in automatic streetlights, light meters, and solar tracking systems to control relays, LEDs, or other devices based on ambient light levels.
## Step 1: Hardware Required
1. GLYPH Board
2. Light Dependent Resistor (LDR)
## Step 2: Circuit Diagram
## Step 3: Code Setup
```cpp theme={null}
#define LIGHT_SENSOR_PIN 3 // GLYPH-C6 pin GPIO 3 (ADC channel)
void setup()
{
// initialize serial communication at 115200 bits per second:
Serial.begin(115200);
// set the ADC attenuation to 11 dB (up to ~3.3V input)
analogSetAttenuation(ADC_11db);
}
void loop()
{
// reads the input on analog pin (value between 0 and 4095)
int analogValue = analogRead(LIGHT_SENSOR_PIN);
Serial.print("Analog Value = ");
Serial.print(analogValue); // the raw analog reading
// We'll have a few thresholds, qualitatively determined
if (analogValue < 40)
{
Serial.println(" => Dark");
}
else if (analogValue < 800)
{
Serial.println(" => Dim");
}
else if (analogValue < 2000)
{
Serial.println(" => Light");
}
else if (analogValue < 3200)
{
Serial.println(" => Bright");
}
else
{
Serial.println(" => Very bright");
}
delay(100);
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* Tools > Board > esp32 > Pcbcupid GLYPH C6
For the `Pcbcupid GLYPH C6` to appear under Tools > Board > esp32, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* Tools > Port and select the port connected to your GLYPH.
* Tools > USB CDC on Boot > **Enabled**
If USB CDC on BOOT is not enabled, you won't see any serial data in the Arduino IDE.
3. **Upload the Code**
Upload the corresponding code for your board to the GLYPH board using the Arduino IDE.
* Click the upload button (➡ icon) or use the shortcut CTRL + U in Arduino IDE to upload the code to the board.
## Step 5: Observe the Serial Monitor Output
Try covering and uncovering the LDR with your hand to block and pass light, and observe the output on the Serial Monitor.

# MQ2 Gas Sensor
Source: https://learn.pcbcupid.com/guides/basic-sensors/mq2-sensor
Interface the MQ2 gas sensor with the Glyph ESP32-C6 board to detect LPG, smoke, methane, and other combustible gases for safety projects.
# Using MQ2 Gas Sensor with GLYPH-C6 Board
The MQ2 gas sensor is widely used for detecting LPG, methane, hydrogen, carbon monoxide, alcohol, smoke, and propane. It provides an analog voltage output that varies depending on the concentration of detected gases.
The MQ2 sensor consists of a heating element and a gas-sensitive material (usually SnO₂ – Tin Dioxide).
* Wide Gas Detection Range – Detects multiple gases, including LPG, CO, CH4, and H2.
* High Sensitivity & Fast Response – Quickly reacts to gas concentration changes.
* Analog & Digital Output – Provides proportional voltage output and a digital HIGH/LOW threshold output.
* Low Power Consumption – Ideal for battery-powered devices.
**Working Principle:**
* The heating element maintains a high temperature (\~200-300°C) to activate the sensor.
* When target gases are present, the surface of SnO₂ reacts with the gas molecules.
* This changes the resistance (Rs) of the sensor based on gas concentration.
* The sensor outputs a voltage signal, which can be read using an ESP32-C6 ADC pin.
## Step 1: Hardware Required
1. GLYPH Board
2. MQ2 Gas Sensor Module
3. Jumper Wires
4. Breadboard
## Step 2: Circuit Diagram
Connect the MQ2 sensor to the GLYPH-C6 as follows:
* **VCC** → 5V (Recommended for the internal heater)
* **A0** → GPIO 4 (Analog Output)
* **D0** → GPIO 5 (Digital Threshold Output)
* **GND** → Ground

## Step 3: Code Setup
```cpp theme={null}
#define MQ2_PIN 4 // ADC1 channel (GPIO 4 on GLYPH-C6)
float Ro = 10.0; // Ro value (calibrated in clean air, update if needed)
const float RL = 3.3; // Load resistance in kilo ohms
// LPG: y = -0.45*log10(x) + 1.3
float getPPM_LPG(float rs_ro) {
return pow(10, ((log10(rs_ro) - 1.3) / -0.45));
}
// CO: y = -0.38*log10(x) + 1.55
float getPPM_CO(float rs_ro) {
return pow(10, ((log10(rs_ro) - 1.55) / -0.38));
}
// SMOKE: y = -0.42*log10(x) + 0.93
float getPPM_Smoke(float rs_ro) {
return pow(10, ((log10(rs_ro) - 0.93) / -0.42));
}
void setup() {
Serial.begin(115200);
analogReadResolution(12); // 12-bit ADC for ESP32
}
void loop() {
int adcValue = analogRead(MQ2_PIN);
float voltage = adcValue * 3.3 / 4095.0;
float Rs = ((3.3 - voltage) * RL) / voltage; // Sensor resistance
float rs_ro = Rs / Ro;
float ppmLPG = getPPM_LPG(rs_ro);
float ppmCO = getPPM_CO(rs_ro);
float ppmSmoke = getPPM_Smoke(rs_ro);
Serial.print("ADC: "); Serial.print(adcValue);
Serial.print(" | V: "); Serial.print(voltage, 2);
Serial.print(" V | Rs/Ro: "); Serial.print(rs_ro, 2);
Serial.print(" | LPG: "); Serial.print(ppmLPG, 0); Serial.print(" ppm");
Serial.print(" | CO: "); Serial.print(ppmCO, 0); Serial.print(" ppm");
Serial.print(" | Smoke: "); Serial.print(ppmSmoke, 0); Serial.println(" ppm");
delay(2000);
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Plug the GLYPH board into your computer using a USB cable.
2. **Select the Board and Port**
Tools > Board > esp32 > Pcbcupid GLYPH C6
Tools > Port and select the connected port.
Tools > USB CDC on Boot > Enabled
For the `Pcbcupid GLYPH C6` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` is not enabled, you won't see any serial data in the Arduino IDE.
3. **Upload the Code**
Click the upload button (➡️ icon) or press CTRL + U to upload the code.
## Step 5: Observe the Output on the Serial Monitor
When you open Serial Monitor, you can see the Carbon Monoxide & Smoke Concentration displayed in parts per million(ppm) along with the ADC readings and corresponding voltage levels.

The sensor's response changes based on the surrounding gas concentration.
# HC-SR04 Ultrasonic Sensor
Source: https://learn.pcbcupid.com/guides/basic-sensors/ultrasonic-sensor
Connect the HC-SR04 ultrasonic distance sensor to the Glyph ESP32-C6 board, send a trigger pulse, and measure distance using the echo response.
# Interfacing an Ultrasonic Sensor with GLYPH-C6
## Introduction
Ultrasonic sensors are electronic devices that calculate the target’s distance by emission of ultrasonic sound waves and convert those waves into electrical signals. The speed of emitted ultrasonic waves is faster than the audible sound.
**Working Principle of Ultrasonic sensor**
Ultrasonic sensor working principle is either similar to SONAR or RADAR which evaluates the target/object attributes by understanding the received echoes from sound/radio waves correspondingly.
This guide will help you interface an **HC-SR04** Ultrasonic Sensor with a GLYPH-C6 board.
The **HC-SR04** has mainly two essential elements- the transmitter and receiver. Using the piezoelectric crystals, the transmitter generates sound, and from there it travels to the target and gets back to the receiver component. The **HC-SR04** Sensor emits ultrasonic waves at a frequency of around 40,000 Hz (though the actual frequency may vary slightly). These waves travel through the air until they encounter an object in their path. Upon hitting the object, the waves bounce back to the sensor.
By measuring the time, it takes for the ultrasonic pulse to travel to the object and return, and knowing the speed of sound in air (approximately 340 meters per second at room temperature), you can accurately calculate the distance between the sensor and the object.
To initiate the ultrasound emission, we set the Trig pin to a High state for 10 microseconds. This action triggers the transmission of an 8-cycle ultrasonic burst, traveling at the speed of sound. Immediately after sending this burst, the Echo pin goes high, indicating its readiness to receive the reflected wave from any objects in the vicinity.
If there’s no object or reflected pulse detected, the Echo pin will return to a low state after 38 milliseconds due to a timeout. If there is a reflected pulse, causes the Echo pin to transition to a low state before the 38-millisecond timeout. By measuring the duration for which the Echo pin remains HIGH, we can ascertain the distance traveled by the sound wave, and consequently, the distance from the sensor to the object.
The formula for calculating distance using the HC-SR04 sensor is:
Distance = (Time taken by the wave to return(T) x Speed of sound(S) ) / 2
S corresponds to Sound speed = 343 measured in m/sec
This formula divides the time by 2 because the wave travels from the sensor to the object and back again, so the total distance traveled is twice the distance between the sensor and the object.
Here is a concise summary of its characteristics:
* **Power Supply**: +5V DC
* **Quiescent Current**: \< 2mA
* **Working Current**: 15mA
* **Effectual Angle**: \< 15
* **Ranging Distance**: 2cm – 400 cm
* **Resolution**: 0.3 cm
* **Measuring Angle**: 30 degrees
* **Trigger Input Pulse width**: 10uS TTL pulse
* **Echo Output Signal**: TTL pulse proportional to the distance range
* **Dimensions**: 45mm x 20mm x 15mm
You can interface the HC-SR04 sensor with microcontrollers like Arduino, Raspberry Pi, or any other microcontroller that supports GPIO (General Purpose Input Output). By reading the signal from the Echo pin, you can measure the time taken for the ultrasonic pulse to return, and hence calculate the distance using the formula mentioned above. The HC-SR04 ultrasonic sensor is widely used in applications owing to its precision in distance measurement using sound waves.
Here’s a breakdown of some prevalent uses:
-**Robotics**: Within robotics, it serves purposes such as obstacle detection, evasion, pathfinding, and environment mapping.
-**Speed and Direction Measurement**: The sensor is adept at determining speed and direction between two entities.
-**Medical Appliances**: It finds application in medical ultrasonography, offering a non-invasive means to examine the body.
-**Burglar Alarms**: Integrating the sensor into security setups enables intruder detection.
-**Sonar Systems**: Underwater, it aids sonar equipment in object detection.
-**Humidifiers**: In the realm of humidifiers, it aids in gauging water levels.
-**Wireless Charging**: The sensor plays a role in aligning devices for efficient wireless charging.
-**Non-Destructive Testing**: Its utilization in inspecting materials and structures without causing harm proves invaluable.
These applications capitalize on the sensor’s non-contact detection capabilities, delivering both safety and convenience across diverse domains. While the HC-SR04 Ultrasonic Sensor is a versatile and widely used component for distance measurement in various projects, it does have some limitations.
Here are the constraints or limitations on its usage:
-**Limited Range**: The HC-SR04 sensor has a maximum range typically around 2 meters, beyond which accuracy decreases.
-**Blind Spots**: The sensor may struggle to detect objects with irregular shapes or surfaces that absorb sound waves, leading to blind spots in detection.
-**Angle Dependency**: Accuracy may vary based on the angle of incidence of the sound waves, affecting the reliability of distance measurements.
-**Interference**: Environmental factors such as noise and other ultrasonic sources can interfere with sensor readings, potentially leading to inaccuracies.
-**Temperature Sensitivity**: The speed of sound in air, which the sensor relies on for distance calculation, can vary with temperature, affecting measurement accuracy.
-**Resolution**: The sensor’s resolution may not be fine enough for applications requiring precise distance measurements, as it typically provides distance readings in centimeters.
-**Limited Functionality in Certain Conditions**: HC-SR04 may encounter challenges in highly reflective or absorbent environments, affecting its performance.
## Step 1: Hardware Required
* Glyph Boards
* HC-SR04 Ultrasonic Sensor
* Jumper wires
* Breadboard (optional)
## Step 2: Circuit Diagram
Connect the **HC-SR04** sensor to the GLYPH-C6 board using the following pin configurations:
* **VCC** to 5V (Standard HC-SR04 requires 5V)
* **GND** to GND
* **TRIG** to GPIO 18
* **ECHO** to GPIO 15

## Step 3: Code Setup
1. **Open Arduino IDE**
2. **Enter the following code into the Arduino IDE**
```cpp theme={null}
const int trigPin = 18;
const int echoPin = 15;
//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701
long duration;
float distanceCm;
float distanceInch;
void setup()
{
Serial.begin(115200); // Starts the serial communication
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
}
void loop()
{
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculate the distance
distanceCm = duration * SOUND_SPEED/2;
// Convert to inches
distanceInch = distanceCm * CM_TO_INCH;
// Prints the distance in the Serial Monitor
Serial.print("Distance (cm): ");
Serial.println(distanceCm);
Serial.print("Distance (inch): ");
Serial.println(distanceInch);
delay(1000);
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For the `Pcbcupid GLYPH C6` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` is not enabled, you won't see any serial data in the Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Check the Output on Serial Monitor
The Serial Monitor will display the distance to the detected object in cm as well as inches

# Battery Voltage Measurement
Source: https://learn.pcbcupid.com/guides/battery-measurement
Read battery voltage on a Glyph ESP32 board using the onboard voltage divider, scale the ADC reading, and report state of charge to the serial monitor.
## Overview

This guide will walk you through configuring the [GLYPH-C3 board](https://shop.pcbcupid.com/product/gd001/) to measure the voltage and charge percentage of a Li-ion or Li-Polymer(LiPo) battery. You will learn how to set up the board, connect the battery, and display the voltage readings on the Serial Monitor.
# Voltage Measurement
Battery voltage measurement is the process of determining the electrical potential difference between the positive and negative terminals of a battery. It provides a quantitative value in volts (V), which indicates the charge level and health of the battery. The voltage range of a battery depends on its chemistry (Li-ion, LiPo, NiMH, Lead-Acid, etc.). The correct minimum (empty) and maximum (full) voltage values must be set to measure the charge percentage accurately. You need to update the Battery object with the correct min and max voltages.
Monitor Battery Health – Helps determine if the battery is functioning properly and whether it needs replacement. Prevent Overcharging & Deep Discharging – Ensures the battery is used within safe voltage limits to prolong its lifespan. Estimate Remaining Charge – Provides an approximate percentage of battery capacity remaining. Optimize Performance – Ensures the battery supplies the correct voltage for efficient device operation. Safety – Prevents excessive discharge or overvoltage conditions that may cause damage or overheating.
## Step 1: Hardware Required
1. Glyph Board
2. Li-ion or Li-Polymer(LiPo) battery
## Step 2: Circuit Diagram
#### Circuit Diagram with Lithium Ion Battery:

#### Circuit Diagram with Lithium Polymer Battery:

## Step 3: Connect the Battery
* First Short the MSR Pin at the back of the Glyph C3 board
* Solder the Positive and Negative leads of the battery to the leads on the back of Glyph C3 which says BAT+ and BAT-
* Connect the positive terminal of the battery to the analog input pin on the board.
* Connect the negative terminal of the battery to the ground pin on the board.
## Step 4: Code Setup
1. **Open Arduino IDE.**
2. Install the **Battery Sense** library by going to `Sketch > Include Library > Manage Libraries` and searching for Battery Sense
3. Copy and paste the following code into the Arduino IDE:
```cpp theme={null}
#include
Battery battery(3400, 4200, A0,12); //(Battery voltage varies between 3.4V (empty) and 4.2V (full charge) in Li-ion/LiPo batteries.
//To convert raw ADC readings into actual battery percentage, the system needs a reference range (3400–4200 mV).
//The analog pin (A0) reads a voltage between 0V and 3.3V (scaled using a voltage divider).
//ADC resolution determines measurement accuracy (12-bit means values range from 0–4095).12 indicates the ADC Resolution bits for Glyph )
/**
* 1 cell li-ion/li-poly battery wired to A0 before voltage booster, on demand sensing on pin 3, linear mapping function
* https://github.com/rlogiacco/BatterySense#lesser-than-5v-with-voltage-booster
**/
void setup()
{
Serial.begin(115200);
while (!Serial);
battery.begin(3300,1.585); //(voltage divider A voltage divider is a simple electrical circuit that reduces a higher voltage to a lower voltage. It is commonly used in battery voltage measurement to ensure that the ESP32 (or any microcontroller) receives a safe voltage within its ADC (Analog-to-Digital Converter range).
//1.585 → Voltage Divider Ratio
//Since batteries typically output voltages higher than ESP32’s ADC limit (3.3V max), a voltage divider is used to scale it down.
//If your board has a different resistor divider, this value must be changed.
//How to Change for Different Batteries?
//If you have a higher voltage battery (e.g., 7.4V or 12V), you need:
//Larger R1 to drop more voltage.
//A new voltage divider ratio in the battery.begin() function.)
}
void loop()
{
//Blinks the Onboard LED to indicate that the battery is connected and being measured.
digitalWrite(1, HIGH);
delay(500);
digitalWrite(1, LOW);
delay(500);
Serial.print("Battery voltage is ");
Serial.print(battery.voltage());
Serial.print(" (");
Serial.print(battery.level());
Serial.println("%)");
}
```
### ADC Calibration and Real-World Accuracy
One important thing to understand is that ESP32 ADC readings are not always perfectly accurate.
In real hardware, ADC readings can vary slightly due to:
* ADC non-linearity
* Resistor tolerances
* Board variations
* Noise
Because of this, a calibration factor is often used to fine tune the measured voltage.
Example:
```cpp theme={null}
const float CALIBRATION_FACTOR = 1.14;
```
This calibration factor compensates for ADC measurement error and helps produce more accurate battery readings.
This is a very common practice in embedded systems and battery-powered devices.
***
### Why Future Revisions May Use Dedicated Fuel Gauge ICs
While ADC-based battery measurement works well, it still depends on calibration and voltage estimation.
Future revisions of the GLYPH boards may use dedicated LiPo fuel gauge ICs over I2C for:
* Improved Accuracy
* Better Battery Estimation
* More Stable Readings
These dedicated chips are specifically designed for battery monitoring applications.
Here is the sample code with ADC Calibration
```cpp theme={null}
// ADC configuration
#define BATTERY_PIN A0
const float VOLTAGE_DIVIDER_RATIO = 2.0; // 200k:200k divider
const float ADC_REF_VOLTAGE = 3.3; // ESP32 ADC reference
const float CALIBRATION_FACTOR = 1.14;
const float MIN_VOLTAGE = 3.2; // Battery empty
const float MAX_VOLTAGE = 4.2; // Battery full
// Read battery voltage and A0
float readBatteryVoltage(int& rawADC, float& v_adc) {
rawADC = analogRead(BATTERY_PIN);
v_adc = (rawADC / 4095.0) * ADC_REF_VOLTAGE * CALIBRATION_FACTOR;
float batteryVoltage = v_adc * VOLTAGE_DIVIDER_RATIO;
return batteryVoltage;
}
// Map float
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
// Battery percentage
int calculateBatteryPercentage(float voltage) {
voltage = constrain(voltage, MIN_VOLTAGE, MAX_VOLTAGE);
float percent = mapFloat(voltage, MIN_VOLTAGE, MAX_VOLTAGE, 0, 100);
return (int)percent;
}
void setup() {
Serial.begin(115200);
analogReadResolution(12); // 12-bit ADC
analogSetAttenuation(ADC_11db); // Full-scale input ~3.3V
pinMode(BATTERY_PIN, INPUT);
}
void loop() {
int rawADC;
float v_adc;
float batteryVoltage = readBatteryVoltage(rawADC, v_adc);
int batteryPercent = calculateBatteryPercentage(batteryVoltage);
Serial.println("=== Battery Monitor ===");
Serial.printf("Raw ADC Value: %d\n", rawADC);
Serial.printf("Voltage at A0: %.3f V\n", v_adc);
Serial.printf("Battery Voltage: %.3f V\n", batteryVoltage);
Serial.printf("Battery Percentage: %d%%\n", batteryPercent);
Serial.println();
delay(2000); // Update every 2 seconds
}
```
## Step 5: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port** Do the following settings in your Arduino IDE, Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board. **Note:** Ensure that the voltage applied to the analog pin does not exceed the maximum allowable voltage (usually 3.3V for the ESP32).
## Step 6: Observe the Output
1. **See the LED Light up** - After soldering the battery leads to the BAT+ & BAT- terminals and connecting your Glyph board to your PC, you can see the onboard led of your Glyph board light up like this:


2. **Open Serial Monitor**
* In Arduino IDE, go to`Tools > Serial Monitor` or press`Ctrl+Shift+M` to open the Serial Monitor.
3. **View Battery Readings**
* You should see the current battery voltage & battery charge percentage every second on the Serial Monitor.

# BH1750 Adafruit Sensor
Source: https://learn.pcbcupid.com/guides/bh1750adafruit-compatibility
Connect the BH1750 Adafruit light sensor to a Glyph development board over I2C using the Glink/Qwiic connector and read ambient lux values.
# Integrating Adafruit with GLYPH Boards

This guide helps you integrate the BH1750 light sensor with GLYPH Boards assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview) (but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work). Along with that it should prove to be a good example for using [G-LINK](https://learn.pcbcupid.com/boards/needs/glink) that comes as a part of GLYPH board and also shows cross compatibility between [G-LINK](https://learn.pcbcupid.com/boards/needs/glink) and [QWIIC](https://www.sparkfun.com/qwiic) Connector. The provided code in this example should reads light levels and prints them to the Serial Monitor. We'll walk you through setting up the sensor and modifying the code.
## Step 1: Hardware Required
* Glyph Boards
* BH1750 light sensor
* GLINK / QWIIC connector
* Breadboard (optional)
## Step 2: Circuit Diagram
Connect the BH1750 sensor to the Glyph boards using the following pin configurations:
* **VCC to 3.3V** (on the Adafruit board)
* **GND to GND**
* **SCL to SCL**
* **SDA to SDA**
## Step 3: Code setup
1. **Open Arduino IDE.**
2. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include
#include
BH1750 lightMeter;
void setup()
{
Serial.begin(9600);
// Initialize the I2C bus (BH1750 library doesn't do this automatically)
Wire.begin();
lightMeter.begin();
Serial.println(F("BH1750 begin"));
}
void loop()
{
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
delay(1000);
}
```
### Explanation
* **Wire.begin():** On the GLYPH boards, you can use the default `Wire.begin()` to initialize the I2C bus, or specify the SDA and SCL pins manually if needed.
* **Sensor Setup:** The `lightMeter.begin()` function initializes the BH1750 sensor.
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Check the Output on Serial Monitor
1. **Open the Serial Monitor**
* After uploading the code, open the Serial Monitor by clicking on the magnifying glass icon in the top right corner of Arduino IDE or by going to `Tools > Serial Monitor`.
2. **Set the Baud Rate**
* Ensure the baud rate is set to `9600`.
3. **Read the Light Levels**
* The Serial Monitor will display light levels in lux measured by the BH1750 sensor. The output should look something like this:

# BLE Server Demo
Source: https://learn.pcbcupid.com/guides/bluetooth/bluetoothglyph
Set up a Bluetooth Low Energy server on a Glyph ESP32 board, advertise a custom service, and exchange data with a phone or BLE central device.
# GLYPH BLE SERVER

This guide will help you configure the GLYPH board as a Bluetooth server and send data to your GLYPH board through a Smart Phone, assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview) (but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work)
## Step 1: Code Setup
1. **Open Arduino IDE**
2. **Enter the following code into the Arduino IDE**
```cpp theme={null}
// ESP32 Series BLE Library
#include
#include
#include
//UUIDs for the Bluetooth service and characteristic
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
//Class to handle when a data is received from smart phone
class onReceive: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
// Retrieve the value written to the characteristic and Convert to Arduino String
String value = pCharacteristic->getValue().c_str();
// If the value length is greater than 0, print it to the Serial Monitor
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]); // Print each character of the received value
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200); // Initialize the Serial Monitor
// Initialize BLE device with the name "GLYPHC3"
BLEDevice::init("GLYPHC3");
// Create a BLE server
BLEServer *pServer = BLEDevice::createServer();
// Create a BLE service with the defined UUID
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE characteristic with the defined UUID
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
// Set the function that as to be called when data is received
pCharacteristic->setCallbacks(new onReceive());
// Set an initial value for the characteristic
pCharacteristic->setValue("Hello World");
pService->start(); // Start the service
// Start advertising the BLE service
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
// Print message indicating that the server has started
Serial.println("BLE Server started, advertising...");
}
void loop() {
//The main loop doesn't do anything until the data is received by the BLE
delay(2000); // Wait for 2 seconds
}
```
This code is derived and modified from `SeeedStudio Xiao ESP32C3`
If your Arduino ESP32 Core is not upgraded to version 3.0.0 or above, make sure to update the code:
* Change `String value = pCharacteristic->getValue();` to `std::string value = pCharacteristic->getValue();`
## Step 2: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following setting in your Arduino IDE,
* `Tools > Board` and select the appropriate board.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot` and select ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 3: Download & Install LightBlue App
1. **Install the App**
* [Download LightBlue App for Android](https://play.google.com/store/apps/details?id=com.punchthrough.lightblueexplorer\&hl=en_US\&gl=US)
* [Download LightBlue App for Apple](https://apps.apple.com/us/app/lightblue/id557428110)
## Step 4: Connect to the Bluetooth Device
1. **Open Bluetooth on Your Phone**
* Ensure Bluetooth is enabled on your smartphone.
2. **Scan for Devices**
* Bring your phone close to the GLYPH board.
* Scan for devices and locate the **GLYPHC3** device.
## Step 5: Open LightBlue App and Connect
1. **Open the LightBlue App**
* Launch the LightBlue app on your smartphone.
2. **Scan Tab**
* Click on the **scan** tab.
3. **Connect to Device**
* Click **CONNECT** next to **GLYPHC3**.
4. **Select Readable, Writable Section**
* Click on the section at the very bottom which says **Readable, Writable**.
5. **Set Data Format**
* Under the **Data format** drop-down menu, select **UTF-8 String**.
6. **Send a Message**
* Type any text that you like to send to your GLYPH Board, In this case let's try **"PCBCUPID-GLYPHC3"** under `WRITTEN VALUES` and click `WRITE`.
## Step 6: View the Output
1. **Check the Serial Monitor**
* You will see the text string "Hello" output on the Serial Monitor of Arduino IDE.
# DHT Sensor One-Wire Communication
Source: https://learn.pcbcupid.com/guides/dht-onewire-communication
Read temperature and humidity from a DHT11 or DHT22 sensor on Glyph ESP32 boards using the One-Wire protocol with example Arduino code.
# One Wire Communication using DHT22 & GLYPH
One-wire communication is a serial communication protocol that enables data transfer between devices using a single data wire (along with ground). It allows bidirectional data exchange without requiring additional clock or synchronization lines, making it highly efficient for low-speed, low-power applications such as sensor interfacing.
How One-Wire Communication Works:
The communication follows a sequence of steps between a master (e.g., microcontroller) and slave (e.g., sensor).
1. Initialization Phase
The master device pulls the data line LOW for a specific duration (e.g., 480µs in DHT22).
This signals the slave device to get ready for communication.
2. Presence Response
The slave device detects the start signal.
It responds by pulling the data line LOW for a short time (e.g., 80µs) and then releases it back to HIGH.
This indicates that the slave is ready to communicate.
3. Data Transmission (Bit Encoding)
Data is sent bit by bit using pulse width modulation (PWM):
Bit ‘0’ → A long LOW pulse (\~80µs)
Bit ‘1’ → A short LOW pulse (\~26µs)
4. The receiver measures the duration of the LOW pulse to determine whether the bit is 0 or 1.
The receiver reads the incoming bits, assembles them into bytes, and then processes the data accordingly.
5. End of Communication
Once all data is transmitted, the line is released to HIGH (idle state).

This guide will help you interface a DHT22 Sensor Module with a GLYPH board to read and display Humidity, Temperature and Heat Index of the surrounding air, assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview/) (but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work)
The DHT22 sensor is a Digital sensor that measures Humidity values in Percentage in **Relative Humidity(20 to 90%)** and **Temperature values in degree Celsius(0 to 50°C)**.
**Relative humidity** is the ratio of water vapor in the air to the maximum amount of water vapor the air can hold.
**Heat Index** is a calculated value that combines Air Temperature and Relative Humidity to estimate how hot it actually feels in a given location.
DHT11/DHT22 uses a Capacitive Humidity sensor and a Thermistor to measure the air around it and outputs a Digital signal on the Data pin. It requires a power supply of 3 to 5.5 Volts DC.
DHT22 is overall better in terms of performance & accuracy compared to DHT11
## Step 1: Hardware Required
1. GLYPH-C3 Board
2. DHT22 Sensor
3. 4.7k / 10k Ohm Resistor(Optional)
4. Breadboard
5. Jumper Wires
## Step 2: Circuit Diagram
You can use either the DHT22 Sensor or it’s Module.In the present example, we use the DHT22 Sensor.The Circuit diagram with DHT22 Sensor is given below:
As shown in the figure, If you are using just the DHT22 Sensor, then it will have 4 pins, unlike the modules which expose only 3-pin.
* Connect pin 1 (on the left) of the sensor to +3.3V of the GLYPH board
* Connect pin 2 of the sensor to the DHTPIN D0 of the GLYPH board
* Pin 3 is a No-Connect (NC) Pin. So, no need to use that pin. This pin is not present in the DHT11 Sensor Module
* Connect pin 4 (on the right) of the sensor to GROUND of the GLYPH board (This is Pin 3 of the Module)
* (Optional) Connect a 10K or a 4.7K Ohm **pull-up resistor** from pin 2 (data) to pin 1 (VCC or power pin) of the sensor - You require a pull-up resistor between the data wire and VCC because the DHT11 uses a **Bidirectional Communication system on a Single Wire**. When neither end is communicating, both ends of the link will be in **high impedance** mode - i.e., **input mode**. In that case, the signal will be **floating** and needs the pull-up to keep it in a **known state**. This is not needed if you are using a Sensor Module, as the Module already has an in-built pull-up resistor.
## Step 3: Code Setup
1. **Open Arduino IDE**
2. **Install the Necessary Libraries**
To read from the DHT sensor, we’ll use the [DHT library from Adafruit](https://github.com/adafruit/DHT-sensor-library). To use this library you also need to install the [Adafruit Unified Sensor library](https://github.com/adafruit/Adafruit_Sensor). Follow these steps to install those libraries:
* Open your Arduino IDE and go to `Sketch > Include Library > Manage Libraries`. The Library Manager should open.
* Search for **Adafruit DHT** on the Search box and install the **DHT sensor library** by **Adafruit**.
* After installing the Adafruit DHT library, search for **Adafruit Unified Sensor** library and install it.
* After installing the libraries, restart your Arduino IDE.
3. **Enter the following code into the Arduino IDE**
```cpp theme={null}
// Importing the DHT Library of Adafruit
#include "DHT.h"
// ‘#define’ is a preprocessor directive and is a useful C++ component that allows the programmer to give a name to a constant value before the program is compiled. The compiler will replace references to these constants with the defined value at compile time and they don’t take up any program memory on the chip, unlike constants defined through variables (ie. const int variable_name = value)
#define DHTPIN 9 // Defines the Digital pin that the DHT Sensor Data Pin is connected to. Here, it is connected to GPIO9, which is the Digital Pin D9. So, all instances of ‘DHTPIN’ are replaced by the value 9. If it doesn't work on D9, please try other GPIO Pins also
#define DHTTYPE DHT22 // Defines DHT22 as the type of the DHT Sensor you are using and replaces all instances of ‘DHTTYPE’ with DHT22
// #define DHTTYPE DHT11 // Defines DHT11 as the type of the DHT Sensor you are using and replaces all instances of ‘DHTTYPE’ with DHT11.If you are using a DHT11 Sensor, uncomment this line and replace this with the above line.
DHT dht(DHTPIN, DHTTYPE); // Creates a DHT Object using the defined DHTPIN and DHTTYPE
void setup()
{
// Initialize the Serial Monitor Baud Rate as 9600 (you can also set it to 115200 if you need more number of serial printings per second)
Serial.begin(9600);
// Initializing the DHT sensor
dht.begin(); // Initializing the defined DHT Object. This function is executed when the GLYPH C3 starts
}
void loop()
{
// Wait a few seconds between measurements
delay(2000);
// Reading temperature or humidity with DHT11 takes about 250 milliseconds.
// Sensor readings may also be up to 2 seconds 'old', as DHT11 has a slow Sampling Rate
float h = dht.readHumidity(); // Calling the function readHumidity() via the created DHT Object to read the Relative Humidity. This function returns a float value that represents the Relative Humidity as a percentage.
// Read the Temperature as Celsius (the default)
float t = dht.readTemperature();
//The function readTemperature() reads the Temperature and returns temperature in Celsius by default, but the parameter ‘true’ is passed as an argument to get the corresponding temperature in Fahrenheit also.
float f = dht.readTemperature(true);
// The function isnan(x) is used to check if the value obtained from the DHT11 sensor is a NaN (Not a Number) value or not. The NaN values are used to identify undefined or non-representable values for floating-point elements, such as the square root of negative numbers or the result of 0/0.
// The parameter x for this function is always a floating-point value. isnan(x) returns a non-zero value (true) if x is a NaN value; and zero (false) otherwise. If the DHT11 sensor gives a NaN value, it can cause your code to malfunction.So, the condition if (isnan(h) || isnan(t) || isnan(f)) checks if any of the h, t or f values are a NaN(Meaning any of the reads Failed), then quickly exit and try the reads again.
if (isnan(h) || isnan(t) || isnan(f))
{
// F() is a macro that instructs the compiler to store the String that is passed as a parameter to the GLYPH C3’s Flash Memory, instead of the SRAM.This is a method for minimizing the amount of RAM that a sketch needs.Remember that GLYPH C3 has a Flash Memory of 4 MB, but only 320 KB of SRAM.
Serial.println(F("Failed to read from DHT sensor!")); // Printing that the read Failed to the Serial Monitor
return; // return statement is used to exit the loop() function and return back to the hidden main() function that called it. The main() function then calls loop() again- so round and round it goes.
}
// Computes the Heat Index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// Computes Heat Index in Celsius by passing the parameter ‘false’ as an argument
float hic = dht.computeHeatIndex(t, h, false);
// Printing the Humidity, Temperature and Heat Index values onto the Serial Monitor
Serial.print(F("Humidity: "));
Serial.print(h);
Serial.print(F("% Temperature: "));
Serial.print(t);
Serial.print(F("°C "));
Serial.print(f);
Serial.print(F("°F Heat index: "));
Serial.print(hic);
Serial.print(F("°C "));
Serial.print(hif);
Serial.println(F("°F"));
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output on the Serial Monitor
The Serial Monitor should start displaying the Humidity, Temperature and Heat Index values of the surrounding air like this:

If you place your finger on the DHT11 sensor or blow some air onto the sensor (or even light a Flame Lighter and hold it near the DHT11 sensor), then you will see the readings change appropriately.
# OLED Display Test
Source: https://learn.pcbcupid.com/guides/display-test
Run a built-in OLED display test on Glyph ESP32 boards over I2C using the Adafruit SSD1306 library to verify wiring and screen functionality.
# OLED Display Test for Glyph using SH1106 & SSD1306
## 1. Using SH1106 OLED Display

The SH1106 is an OLED driver IC commonly used in 128x64 pixel monochrome OLED displays. It can communicate with microcontrollers via I2C, SPI, or parallel interfaces. While similar to the SSD1306, it has some differences, particularly in memory mapping and buffer size.
It's made by Sino Wealth and is often found in 0.96", 1.3", and similar small OLED modules used in electronics projects.
## 2. Using SSD1306 OLED Display

This guide demonstrates how to use an OLED display with the GLYPH Boards,initializing the display, drawing shapes, and displaying text like PCB Cupid and Generating PCB Cupid's Logo on the display,assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview) (but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work).
The SSD1306 is a display driver IC made by Solomon Systech. It’s used to control monochrome OLED displays — most commonly the 0.96-inch 128x64 pixel modules used in electronics projects.
The SSD1306 isn’t the screen itself — it’s the chip inside the display module that handles communication and controls the screen.
1. How SSD1306 & SH1106 Work – Step-by-Step
Both SSD1306 and SH1106 operate in similar ways, with just a few internal differences. Let’s explain the general process first:
1) Microcontroller Sends Data
Your microcontroller (like ESP32, Arduino, GLYPH board) sends commands and pixel data to the display through I2C or SPI interface.
There are two types of data:
Commands – for things like turning the display on/off, setting contrast, clearing the screen, etc.
Display data – tells the display which pixels to light up (image, text, graphics).
2) Driver IC Stores the Data in Display RAM
Each chip (SSD1306 or SH1106) has internal Display RAM (called GDDRAM):
SSD1306 → 128 x 64 bits = 1024 bytes
SH1106 → 132 x 64 bits = 1056 bytes
Each bit in the memory = 1 pixel (since the displays are monochrome: black or white)
So when you send data like display.print("Hello"), it gets translated into pixel positions and stored in this internal RAM.
3) Data is Transferred to OLED Panel
The driver IC then continuously refreshes the screen using the data in its RAM.
It lights up each pixel based on the bit value stored (1 = ON, 0 = OFF).
It scans through the rows and columns using multiplexing.
Think of it like a movie projector: the driver IC shows what’s in its memory onto the screen over and over.
4) Refresh Cycle Happens Rapidly
The display is refreshed dozens of times per second (usually 60–100 Hz), which keeps the image stable and flicker-free.
You don’t have to manage this refresh manually — the driver chip does it automatically.
Differences in How They Work Internally:
Feature SSD1306 SH1106
Display RAM Size 128 x 64 = 1024 bytes 132 x 64 = 1056 bytes (extra columns!)
Column Mapping Direct: column 0 = pixel 0 Offset: pixel starts at column 2
Library Handling Works easily with Adafruit\_SSD1306 Needs manual offset in some libraries
Visible Pixels 128 x 64 128 x 64 (but extra 4 columns unused)
In SH1106, since it has 132 columns but only 128 visible, the pixel data needs to be offset by 2 columns — that’s why SSD1306 libraries don’t work perfectly on it.
Key Differences :
Screen Size: SSD1306 is usually in 0.96-inch displays; SH1106 is in 1.3-inch displays.
Internal Memory: SSD1306 has 128 columns; SH1106 has 132 columns (with a 2-column shift).
Compatibility: SSD1306 works great with Adafruit libraries; SH1106 needs different libraries like U8g2.
Issues: If you try to use an SSD1306 library on an SH1106 screen, the output might be offset or wrong.
Usage: Both display text, graphics, sensor data, etc., but you must use the right library for each.
## Step 1: Hardware Required
1. Glyph Board
2. Either SH1106 or SSD1306 OLED Display
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Install the U8g2 library by going to `Sketch > Include Library > Manage Libraries` and search for **U8g2** library by olikraus**
3. **Copy and paste the following code into the Arduino IDE:**
### Code for SH1106 OLED Display
```cpp theme={null}
#include
#include
#include
//Initialize OLED (SH1106 128x64)
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
// PCBCupid Logo (Replace with actual generated XBM data)- This bitmap is generated by uploading the Logo directly to the lopaka.app website, where you can edit the image features, add text to it etc.
static const unsigned char image_PCB_Cupid_logo_Design_logo_JPG_300722_V1_bits[] = {
0xfc,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xc3,0xff,0x0f,0x00,0x7f,0x00,0xfe,0x0f,0x00,0x3e,0x00,0xfc,
0x0f,0x00,0x1c,0x00,0xf8,0x0f,0x3f,0x1c,0x7e,0xf8,0x0f,0x7f,0x08,0xff,0xf0,
0x0f,0x7f,0x08,0xff,0xff,0x0f,0x7f,0x88,0xff,0xff,0x0f,0x3f,0x8c,0xff,0xf9,
0x0f,0x00,0x8c,0x7f,0xe0,0x0f,0x00,0x0e,0x3f,0xe7,0x0f,0x00,0x0f,0x3f,0xcf,
0x0f,0xff,0x1f,0x3e,0xcf,0x0f,0xff,0x1f,0x10,0xe6,0x0f,0xff,0x3f,0x00,0xe0,
0x0f,0xff,0x7f,0x00,0xf8,0xff,0xff,0xff,0x83,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0xfc,
0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0xe0,
0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x80
};
void setup() {
u8g2.begin();
}
void loop()
{
u8g2.clearBuffer();
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
u8g2.drawXBM(42, 6, 40, 38, image_PCB_Cupid_logo_Design_logo_JPG_300722_V1_bits);
u8g2.setDrawColor(2);
u8g2.setFont(u8g2_font_timR10_tr);
u8g2.drawStr(30, 56, "PCB Cupid");
u8g2.sendBuffer();
}
```
3. Go to the website named [Lopaka](https://lopaka.app/sandbox). Then do as in these Images:
Step 1: Under the **Library** drop down box, select **u8g2** and set **display** to **128x64**
*
Step 2: Now, Click on **Add Image** as shown by the arrow in the image below
*
Step 3: Next, click on **Browse Files** and Select your Picture/Logo to Upload
*
Step 4: Now, adjust your Width & Height Sizes, enable Grayscale & set appropriate Brightness and Contrast Levels till your uploaded image in Lopaka becomes Clear
*
Step 5: Now, select your uploaded image from **Current Projects**.Then click on the Icon named **Aa(String)** and type any text that you want to display along with your image
* 
Step 6: Under the Code tab, you can see the code generated corresponding to the uploaded picture's bitmap.Copy that code
*
Step 7: Paste the Code in your Arduino IDE as shown below
*
### Code for SSD1306 OLED Display
1. **Install the **Adafruit SD1306** & **Adafruit GFX** Libraries by Adafruit by going to `Sketch > Include Library > Manage Libraries` and searching for these libraries**
2. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include
#include
#include
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup()
{
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 10);
display.print("PCBCUPID");
// Set brightness level (0x00 = dim, 0xFF = bright)
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(0xFF); // Adjust this value (0x00 - 0xFF)
display.display();
}
void loop()
{
// Nothing needed here
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe Output on your OLED Display
After uploading the code for SH1106 OLED Display to the GlyphC3 board, the SH1106 OLED displays the Logo of PCB CUPID along with the text **PCBCUPID**, both centrally aligned, like this:

After uploading the code for SSD1306 OLED Display to the GlyphC3 board, the SSD1306 OLED displays the text **PCBCUPID**.

# I2C Scanner
Source: https://learn.pcbcupid.com/guides/i2c-scan-test
Run an I2C scanner sketch on a Glyph ESP32 development board to discover the 7-bit addresses of connected I2C sensors, displays, and modules.
# GLYPH I2C Scan

This guide will walk you through performing an I2C Scan with a GLYPH board, assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview) (but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/) from the ESP32 Series should work).
The **I2C (Inter-Integrated Circuit)** protocol is a popular communication method for connecting various sensors and modules to Microcontrollers.
Developed by Philips Semiconductor (now NXP Semiconductors) in 1982, I2C was designed to provide a simple and efficient way for chips to communicate within electronic devices.
**I2C** uses just two bidirectional open-drain lines: **SCL (Serial Clock Line) and SDA (Serial Data Line)**, making it a space-efficient and cost-effective solution for short-distance communication. Its multi-master capability and addressable nature allow multiple devices to share the same bus, which has contributed to its widespread adoption in various applications, from consumer electronics to automotive systems and IoT devices. In the I2C protocol, each device on the bus is identified by a **unique 7-bit address**, allowing multiple devices to share the same SCL and SDA lines as long as each device has a different/distinct address. This way, the microcontroller can communicate with each device individually by addressing them with their specific I2C addresses.
There are **4 methods** how you can connect your GLYPH board via I2C:
## 1. Pre-Assigned pin on board (SDA,SCL)
This method is perfect if you are using GLYPH board settings on Arduino IDA as it's officially supported by Arduino Core.

## 2. Through Terminal Blocks
You can use this method if you using one of our industrial sensor like **SHT 35 & SHT 45**

## 3. Through a GLINK
This method is the most convenient if you are using modules that are Glink / stemmaQT / QWIIC compatible.

## 4. Connect to any GPIO pin!
ESP32 boards support GPIO multiplexing, so you can use any pin as SDA, SCL but need to change this manually in the code.

## Step 1: Hardware Required
1. GLYPH-C3 Board.
2. Any I2C Compatible Sensor / Modules
## Step 2: Code Setup
1. **Open Arduino IDE**
2. **Enter the following code into the Arduino IDE**
```cpp theme={null}
// Wire.h is part of the core Arduino libraries and comes pre-installed with the Arduino IDE.
#include // Include the Wire library for I2C communication
void setup()
{
Serial.begin(115200); // Initialize serial communication at a baud rate of 115200
Wire.begin(); // Start the I2C bus
//Wire.begin(4,5); //Use this if you have custom pins for I2C SDA,SCL
Serial.println("\nI2C Scanner"); // Print a header message in Serial Monitor indicating the scanner's start
}
void loop()
{
byte error, address; // Variable 'error' stores the status of I2C transmission; 'address' is the I2C address of the device
int nDevices = 0; // Variable to count the number of detected I2C devices
Serial.println("Scanning..."); // Print message indicating that scanning has started
// Loop through all possible I2C addresses (1 to 126)
for (address = 1; address < 127; address++)
{
Wire.beginTransmission(address); // Start communication with the device at the specified I2C address
error = Wire.endTransmission(); // Send I2C message to the device, see whether it responds and check for errors in the response
// If no error, an I2C device responded at this address
if (error == 0)
{
Serial.print("I2C device found at address 0x"); // Print message indicating a device is found
// If address is a single-digit hex (0x00 to 0x0F), print a leading zero for formatting
if (address < 16)
{
Serial.print("0"); // Print a leading zero for single-digit hexadecimal addresses
}
Serial.print(address, HEX); // Print the device address in hexadecimal format
Serial.println(" !"); // Indicate a successful connection with an exclamation mark at the end for emphasis
nDevices++; // Increment the device count
}
// If an error code 4 is returned, it indicates an unknown error
else if (error == 4)
{
Serial.print("Unknown error at address 0x"); // Print message indicating unknown error at a specific address
// Print leading zero for single-digit hexadecimal addresses
if (address < 16)
{
Serial.print("0");
}
Serial.println(address, HEX); // Print the address with the unknown error in hexadecimal
}
}
// If no devices were detected, print a message; otherwise, print "Done."
if (nDevices == 0)
{
Serial.println("No I2C devices found\n"); // Print a message indicating no devices were found
}
else
{
Serial.println("Done.\n"); // Scanning completed with at least one device found
}
delay(5000); // Wait 5 seconds before starting the next scan
}
```
## Step 3: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 4: Check Serial Monitor
The Serial Monitor should display the I2C Addresses if a device connected on the I2C bus:
**GSense Capacitive Touch Slider Sensor I2C Address**

**SHT 35 I2C Address**

**SHT 45 I2C Address**

**BH1750 Adafruit Light Sensor I2C Address**

The DS1307 Module has an Onboard AT24C32 EEPROM so you would likely see 2 different I2C address.
**DS1307 Real Time Clock (RTC) module I2C Address**

# Parallel LCD Display
Source: https://learn.pcbcupid.com/guides/lcd
Wire a 16x2 parallel LCD to a Glyph ESP32 board and print text using the LiquidCrystal library, covering pin connections and example code.
# LCD

## Introduction
A 16×2 LCD is a character-based display capable of showing 16 characters per line on 2 lines, widely used in microcontroller projects for displaying text, numbers, or simple symbols.
When connected directly to a microcontroller, the LCD uses parallel communication, requiring multiple GPIO pins for control and data transfer.
## Pin Configuration
| LCD Pin | Function | Glyph-C3 |
| ------- | --------------- | ------------------- |
| RS | Register Select | GPIO 8 |
| RW | GND | GND |
| EN | Enable | GPIO 9 |
| D4 | Data 4 | GPIO 10 |
| D5 | Data 5 | GPIO 2 |
| D6 | Data 6 | GPIO 3 |
| D7 | Data 7 | GPIO 4 |
| VCC | Power | 5V |
| VSS | GROUND | GND |
| V0 | Contrast | Potentiometer wiper |
| LED+ | Backlight + | 5V |
| LED- | Backlight - | GND |
## Features
* Character Display: 16 columns × 2 rows.
* Controller: HD44780 or compatible.
* Parallel Communication: Direct pin-to-pin interface.
* Backlight: Built-in LED for better visibility.
* Custom Characters: Supports user-defined symbols via CGRAM.
* Contrast Control: Adjustable using a potentiometer.
* Voltage: Typically operates at 5V (some modules support 3.3V).
* Low Cost & Widely Available: Easy integration for embedded projects.
## Typical Applications
* Embedded system displays – show status or messages.
* Sensor data monitoring – temperature, voltage, humidity.
* Industrial control panels – parameter display.
* IoT projects – display device or network status.
* Educational and prototyping projects – learn microcontroller interfacing.
* Home automation devices – show time, modes, or device status.
* DIY electronics – simple, low-cost display solution.
## Step 1: Hardware Required
1. GLYPH
2. LCD Display
3. Potentiometer
## Step 2: Circuit Diagram
## Step 3: Code Setup
1. Open Arduino IDE.
2. Make sure to install the library
3. Copy and paste the following code into the Arduino IDE
```cpp theme={null}
#include //https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
// Initialize LCD with pin configuration: RS, EN, D4, D5, D6, D7
LiquidCrystal lcd(8, 9, 10, 2, 3, 4);
void setup() {
// Initialize LCD with 16 columns and 2 rows
lcd.begin(16, 2);
// Print to LCD
lcd.print("Hello ESP32!");
lcd.setCursor(0, 1);
lcd.print("LiquidCrystal");
}
void loop() {
// Static display - nothing needed
delay(1000);
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid Glyph S3`
For the `Pcbcupid Glyph S3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe Output on Serial Monitor


# I2C LCD Display
Source: https://learn.pcbcupid.com/guides/lcd-i2c
Connect a 16x2 LCD with I2C backpack to a Glyph ESP32 board over two wires and print messages using the LiquidCrystal_I2C Arduino library.
# LCD I2C

## Introduction
The 16×2 LCD (Liquid Crystal Display) is a widely used alphanumeric display module capable of showing 16 characters per line on 2 lines. It is based on the Hitachi HD44780 controller, which provides a simple command-based interface for displaying characters, symbols, and custom graphics.
To reduce the number of GPIO pins required for communication, the LCD is often connected through an I²C I/O expander, typically the PCF8574 chip. This configuration allows the LCD to communicate with the microcontroller using only two wires — SDA (Serial Data) and SCL (Serial Clock) — instead of the usual 6 to 8 parallel data and control lines.
The PCF8574 acts as a bridge between the microcontroller’s I²C bus and the LCD’s parallel interface, providing:
* Pin saving
* Simpler wiring
* Easy software control
* Without it, you would need many more GPIO pins and complex wiring to operate the LCD.
## Pin Configuration
| LCD Pin | Glyph-C3 |
| ------- | ------------ |
| VCC | Power Supply |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
## Features
* Uses I²C communication — only two wires (SDA and SCL) are required.
* Saves microcontroller pins — reduces pin usage from 8 (parallel) to 2.
* Compatible with the HD44780 LCD controller.
* Based on PCF8574 I/O expander for serial-to-parallel data conversion.
* Built-in LED backlight for better visibility.
* Adjustable contrast using the onboard potentiometer.
* Operates on 3.3V or 5V, suitable for most microcontrollers (Arduino, ESP32, ESP8266, Raspberry Pi).
* Displays 16 characters × 2 lines (total 32 characters).
## Typical Applications
* Embedded system displays — show system status or information.
* Sensor data monitoring — display temperature, humidity, voltage, etc.
* Industrial control panels — parameter and status display.
* IoT devices — display device data or connection status.
* Educational and training projects — for learning I²C and LCD interfacing.
* Digital meters — voltage, current, and frequency measurement displays.
* Home automation systems — display time, mode, or device state.
## Step 1: Hardware Required
1. GLYPH
2. LCD Display
3. PCF-8574
## Step 2: Circuit Diagram
## Step 3: Code Setup
1. Open Arduino IDE.
2. Make sure to install the library
3. Copy and paste the following code into the Arduino IDE
```cpp theme={null}
#include
#include // https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
// Initialize LCD: I2C address 0x27, 16 columns, 2 rows
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
lcd.init(); // Initialize the LCD
lcd.backlight(); // Turn ON backlight
// Print text
lcd.setCursor(0, 0);
lcd.print("Hello");
lcd.setCursor(0, 1);
lcd.print("PCBCUPID");
}
void loop() {
// Static display - nothing needed
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid Glyph S3`
For the `Pcbcupid Glyph S3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe Output on Serial Monitor

# Analog Input and Output
Source: https://learn.pcbcupid.com/guides/reading-analoginput
Read analog values from a potentiometer and drive PWM outputs on the Glyph ESP32 development board using analogRead and analogWrite in Arduino.
# Reading Analog Input / Output with GLYPH

This guide will help you read Analog input using a Potentiometer and write it to an LED to control it's brightness, assuming you are using [GLYPH-C3](https://learn.pcbcupid.com/boards/glyph-c3/overview/) (but any [GLYPH development board](https://shop.pcbcupid.com/product-category/development-boards/))
A **potentiometer** is a variable resistor with three terminals that adjusts voltage by sliding a wiper across a resistive track. It works as a voltage divider(A voltage divider is a simple circuit that reduces voltage using two resistors in series. It’s commonly used to step down voltages for sensors, ADC inputs, or interfacing components with different voltage levels), where the output voltage varies based on the wiper's position.
When you move the wiper of a potentiometer (variable resistor), it changes the resistance between the wiper and the two end terminals, which in turn varies the output voltage according to the voltage divider rule.
A potentiometer works as a variable voltage divider with three terminals:
1. Two outer terminals connect to a fixed resistance.
2. The middle terminal (wiper) moves along the resistive track, changing the resistance ratio.
3. As the wiper moves, the output voltage varies proportionally between the input voltage and ground.
When a potentiometer is connected to a Glyph board, it acts as a variable voltage divider, generating an analog voltage that controls the LED brightness using PWM (Pulse Width Modulation) or DAC (Digital-to-Analog Converter).
This is achieved through 2 techniques:
* **Analog to Digital Conversion (ADC)** - This is a peripheral on the GLYPH board which is used to convert Analog signals like Voltage to Digital values. This allows GLYPH to read and process the analog signals. The Resolution on the GLYPH series boards is 12-bit (0 - 4095)
* **Pulse Width Modulation (PWM)** - This peripheral on the GLYPH is used to output an Analog-like signal from digital signal. This is done by modifying the Pulse-Width/Duty cycle of the digital signals generated by the GLYPH. Alternatively you can use DAC on the GLYPH but it would be complicated for beginners.
## Step 1: Hardware Required
1. GLYPH-C3 Board
2. LED
3. 220 Ohm Resistor
4. Potentiometer - 47k
5. Breadboard
6. Male to Male Jumper Wires
## Step 2: Circuit Diagram
Connect the circuit as per the following Circuit Diagram:

## Step 3: Code Setup
In this program, the Configuring and Writing of LED PWM Value can be done in 2 Ways:
* **Method 1** - Using **ledcWrite()** function for ESP32 based GLYPH Boards
* **Method 2** - Using **analogWrite()** function for Arduino Compatible GLYPH Boards
(Both functions are included in the latest ESP32 Documentation here- [ESP32 LED Library Functions](https://docs.espressif.com/projects/arduino-esp32/en/latest/api/ledc.html#))
1. **Open Arduino IDE**
2. **Enter the following code into the Arduino IDE**
* **Method 1** : Using **ledcWrite()** function
```cpp theme={null}
// Pin number of the LED
const int led = 1; // which is Digital pin D0 in GLYPH-C3
// Pin number of the Potentiometer
const int pot = 2; //, which is Analog pin A1 in GLYPH-C3
// Setting PWM Properties like Frequency and Resolution
const int freq = 5000; // LEDC PWM channel’s Frequency Range is 10 Hz - 40 MHz.So, set a Frequency value in this range
const int resolution = 8; // The Default Resolution for LEDC PWM is 8 bits
void setup()
{
// Initialize the Serial Monitor Baud Rate as 115200 (you can also set it to 9600)
Serial.begin(115200);
pinMode(led, OUTPUT); // Set LED to be an output pin
pinMode(pot, INPUT); // Set Potentiometer to be an input pin
// Setting up the LEDC pin with the PWM Properties and Attaching this pin to ADC Channel 0, where the Potentiometer is connected
ledcAttachChannel(led,freq,resolution,0);
}
void loop()
{
// Read the Analog input voltage between 0 V and 3.3 V from the Potentiometer and map it into corresponding integer values between 0 and 4095 using C3's 12-bit ADC8
int potvalue = analogRead(pot);
// Changing the Potentiometer's ADC range from 0 - 4095 to the LED PWM duty cycle range 0 - 255 (As we are using 8-bit resolution for PWM) using the equation (255.0/4095.0)*potvalue
int brightness = (255.0/4095.0)*potvalue;
ledcWrite(led, brightness); // Changing the LED brightness by setting the above PWM Duty cycle
// Print the LED brightness value onto Serial Monitor
Serial.print("Led Brightness is:");
Serial.println(brightness);
}
```
* **Method 2** : Using **analogWrite()** function
```cpp theme={null}
// Pin number of the LED
const int led = A1; // which is Digital pin A1 in GLYPH-C3
// Pin number of the Potentiometer
const int pot = A0; //, which is Analog pin A1 in GLYPH-C3
void setup()
{
// Initialize the Serial Monitor Baud Rate as 9600 (you can also set it to 115200 if you need more number of serial printings per second)
Serial.begin(9600);
pinMode(led, OUTPUT); // Set LED to be an output pin
pinMode(pot, INPUT); // Set Potentiometer to be an input pin
}
void loop()
{
// Read the Analog input voltage between 0 V and 3.3 V from the Potentiometer and map it into corresponding integer values between 0 and 4095 using the 12-bit ADC of Glyph Boards
int potvalue = analogRead(pot);
// Converting the Potentiometer's ADC range from 0 - 4095 to the LED PWM duty cycle range 0 - 255 using the equation (255.0/4095.0)*potvalue
int brightness = (255.0/4095.0)*potvalue;
analogWrite(led, brightness); // Set the LED brightness using PWM with the calculated duty cycle
// Print the LED brightness value onto Serial Monitor
Serial.print("Led Brightness is:");
Serial.println(brightness);
}
```
If you are using Method 2, it is not mandatory to set the PWM Resolution and Frequency, as the function **analogWrite()** by default, generates an 8-bit PWM by setting the Duty cycle values in the range 0 - 255 (255 is the maximum possible duty cycle value that **analogWrite()** can accept). However, if you wish to set a custom PWM frequency and resolution on a selected pin, you can do so by using the functions **analogWriteResolution()** and
**analogWriteFrequency()**.
The syntax for the **analogWriteResolution** function in Arduino IDE is :
**void analogWriteResolution(uint8\_t pin, uint32\_t resolution bits)**
The syntax for the **analogWriteFrequency** function in Arduino IDE is :
**void analogWriteFrequency(uint8\_t pin, uint32\_t freq)**.
The freq parameter is the new PWM frequency in hertz (Hz) units, and the range is 0 to (2^32 - 1) Hz.
Both **analogWriteResolution** and **analogWriteFrequency** functions must be called before **analogWrite()** to apply these settings.
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
Depending on the Initial Position of the Potentiometer Knob, few cases are possible:
* **Case 1 - The LED is in OFF state**
In this Case, the Serial Monitor should display the Led Brightness as **0**(LOW):


**To Turn ON the LED and increase its brightness**, slowly turn the Potentiometer Knob in the **Clockwise direction**. At the Maximum Possible Limit of the Clockwise Rotation, the LED will glow the Brightest.The Serial Monitor should now display the Brightness value which is the Maximum PWM Duty Cycle value as **255**(HIGH) or a value in the range 200-255 due to the knob-turning limitations of the potentiometer that we use.
* **Case 2 - The LED is in ON state**
In this Case, the Serial Monitor should display the Maximum LED Brightness value of **255**. Sometimes, It may show a value slightly less than the Max. Brightness value 255(like **216** in our case) due to the knob-turning limitations of the potentiometer that we use.


**To Turn OFF the LED and decrease its brightness**, slowly turn the Potentiometer knob in the **Anti-Clockwise direction**. At the Maximum Possible Limit of the Anti-Clockwise Rotation, the LED will not glow at all and its brightness value will again become **0**.
* **Case 3 - The LED is in ON state with a Brightness value of 22**(or numbers **close** to 22, in the range of **20-30**, as an exact value of 22 may be difficult to get by manually turning your potentiometer knob).
The Serial Monitor should now display the value of **22** or values in the range of **20-30** like this:


* **Case 4 - The LED is in ON state with a Brightness value of 170**(or numbers close to 170)
The Serial Monitor should now display the value of 170 or values close to 170:


# Rotary Encoder with Glyph ESP32-C6
Source: https://learn.pcbcupid.com/guides/rotor-encoder-with-glyph-c6
Read direction, position, and button presses from a rotary encoder on the Glyph ESP32-C6 board using interrupts and example Arduino code.
# Rotary Encoder with Push Button on GLYPH Boards

A rotary encoder is a mechanical device that converts rotational movement into digital signals. The encoder outputs two signals, typically labeled CLK (Clock) and DT (Data), which provide information about the direction and amount of rotation
A rotary encoder is a device that converts rotational motion into electrical signals. It is commonly used for position sensing, volume control, and menu navigation in electronics.
Inside a mechanical rotary encoder, the movement of the shaft generates electrical signals based on physical contact with a conductive disk. Let's break it down step by step.
Rotary Shaft: The part you rotate.
Slotted or Conductive Disk: A circular disk with evenly spaced openings or conductive areas.
Two Contact Brushes (A & B Terminals): These touch the disk to detect movement.
Spring Mechanism: Provides the "clicky" feel and holds the shaft in place.
Push Button Mechanism: (Optional) Detects when the knob is pressed.

This guide demonstrates how to use a rotary encoder with a push-button switch to track the position and direction of rotation, and detect button presses with a GLYPH board. This example is also compatible with [GLYPH-C3](https://shop.pcbcupid.com/product/gd001/) and [GLYPH-H2](https://shop.pcbcupid.com/product/gd003/) boards
The push-button switch on the encoder can be used to trigger specific actions when pressed.
## Step 1: Hardware Required
1. GLYPH-C6
2. Rotor encoder module
3. Jumper Wires
4. Breadboard
## Step 2: Circuit Diagram
Rotary Encoder Pinout:
CLK (Clock): The main pin that outputs the clock signal used for determining rotation direction.
DT (Data): The data pin that works with the clock signal to calculate the rotation direction.
SW (Switch): The button pin used for detecting button presses.
Connect the encoder as follows:
CLK Pin → GPIO4 (or any available digital pin)
DT Pin → GPIO5 (or any available digital pin)
SW Pin → GPIO6 (or any available digital pin)
VCC → 3.3V or 5V (depending on your encoder module)
GND → Ground

## Step 3: Code Setup
```cpp theme={null}
#define ENCODER_CLK 4
#define ENCODER_DT 5
#define ENCODER_SW 6 // Button Pin
volatile int position = 0;
volatile int direction = 0;
bool buttonPressed = false;
void IRAM_ATTR readEncoder() {
if (digitalRead(ENCODER_CLK) == digitalRead(ENCODER_DT))
{
position--; // Counter-clockwise
direction = -1;
} else
{
position++; // Clockwise
direction = 1;
}
}
void IRAM_ATTR buttonISR() {
buttonPressed = true; // Set flag when button is pressed
}
void setup() {
Serial.begin(115200);
pinMode(ENCODER_CLK, INPUT_PULLUP);
pinMode(ENCODER_DT, INPUT_PULLUP);
pinMode(ENCODER_SW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCODER_SW), buttonISR, FALLING);
}
void loop() {
static int lastPosition = 0;
// Print position update
if (lastPosition != position) {
Serial.print("Position: ");
Serial.print(position);
Serial.print(" | Direction: ");
Serial.println(direction == 1 ? "Increasing" : "Decreasing");
lastPosition = position;
}
// Print button press message
if (buttonPressed) {
Serial.println("Button Pressed!");
buttonPressed = false; // Reset flag
}
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For the `Pcbcupid GLYPH C6 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
The Serial Monitor will display updates to the encoder's position and direction as it rotates. When the button is pressed, the message "Button Pressed!" will be printed to indicate that the button was activated.

# Servo Motor Control with Glyph C6
Source: https://learn.pcbcupid.com/guides/servo-motor-with-glyph-c6
Control a hobby servo motor's angle using PWM on the Glyph ESP32-C6 development board with the ESP32Servo Arduino library and wiring diagram.
# Drive Servo Motor using PWM on GLYPH-C6

## Introduction
**What is a Servo Motor and its Working Priciple**
A **Servo Motor** is a rotary or linear actuator designed for precise control of angular or linear position, velocity, and acceleration. It consists of a DC or AC motor, a position sensor (usually a potentiometer or encoder), and a control circuit.The motor’s position is controlled by varying the width of a Pulse Width Modulated (PWM) signal.
A Servo Motor consists of a Motor (DC or AC), a potentiometer, gear assembly, and a controlling circuit. First of all, we use gear assembly to reduce RPM(Revolutions Per Minute) and to increase torque of the motor. Say at initial position of servo motor shaft, the position of the potentiometer knob is such that there is no electrical signal generated at the output port of the potentiometer. Now an electrical signal is given to another input terminal of the error detector amplifier. Now the difference between these two signals, one comes from the potentiometer and another comes from other sources, will be processed in a feedback mechanism and output will be provided in terms of error signal. This error signal acts as the input for motor and motor starts rotating. Now motor shaft is connected with the potentiometer and as the motor rotates so the potentiometer and it will generate a signal. So as the potentiometer’s angular position changes, its output feedback signal changes. After sometime the position of potentiometer reaches at a position that the output of potentiometer is same as external signal provided. At this condition, there will be no output signal from the amplifier to the motor input as there is no difference between external applied signal and the signal generated at potentiometer, and in this situation motor stops rotating.
This guide will help you interface a Servo Motor with [GLYPH-C6](https://shop.pcbcupid.com/product/gd002/) board using PWM to control its angular position.
**Key Features of Servo Motors:**
* Closed-loop Control: Uses feedback from the position sensor to adjust movement for high accuracy.
* High Torque & Precision: Can maintain a set position accurately.
* Controlled via PWM: Typically controlled using a Pulse Width Modulation (PWM) signal in hobby applications.
* Gearing System: Often includes a gearbox to reduce speed and increase torque.
**Types of Servo Motors:**
* AC Servo Motors: Used in industrial automation, robotics, and CNC machines. High efficiency and accuracy.
* DC Servo Motors: Common in robotics, RC cars, and consumer electronics. Cheaper but require more maintenance.
* Stepper-based Servo Motors: Combine stepper motor principles with closed-loop feedback.
* Linear Servo Motors: Provide linear motion rather than rotational.
**Applications of Servo Motors:**
✅Robotics – Used for arm movement, humanoid robots, and industrial automation.
✅CNC Machines – Provide precise positioning for cutting, milling, and machining.
✅Drones & RC Vehicles – Control steering, flaps, and other movable parts.
✅Medical Equipment – Used in surgical robots and precision medical devices.
## Step 1: Hardware Required
1. GLYPH C6
2. Servo Motor (e.g., SG90 or MG995)
3. External Power Source (if required by the servo)
4. Male-to-Male Jumper Wires
5. Breadboard (optional)
6. Male to Male Jumper Wires (If you use just the servo motor)
## Step 2: Circuit Diagram
Connect the servo motor to the GLYPH-C6 as follows
* **VCC (Red wire)** → Connect to 3.3V or 5V of the GLYPH-C6 (depending on servo power requirements).
* **GND (Black/Brown wire)** → Connect to GND of the GLYPH-C6.
* **Signal (Yellow/Orange wire)** → Connect to GPIO6 (or any PWM-capable pin on GLYPH-C6).

## Step 3: Code Setup
1. **Open Arduino IDE**
2. **Install the Necessary Libraries**
Open Arduino IDE and navigate to `Sketch > Include Library > Manage Libraries`. Search for `ESP32Servo` and install the library by Kevin Harrington.
3. **Enter the following code into the Arduino IDE**
```cpp theme={null}
#include // Include the ESP32 Servo library
Servo myServo; // Create a Servo object
#define SERVO_PIN 6 // Use any PWM-capable GPIO on GLYPH-C6
void setup() {
Serial.begin(115200); // Start serial communication
myServo.attach(SERVO_PIN); // Attach the servo to the defined pin
}
void loop() {
// Move servo from 0° to 180°
for (int pos = 0; pos <= 180; pos += 5) {
myServo.write(pos);
Serial.print("Servo Position: ");
Serial.println(pos);
delay(15); // Adjust delay for smoother motion
}
// Move servo from 180° back to 0°
for (int pos = 180; pos >= 0; pos -= 5) {
myServo.write(pos);
Serial.print("Servo Position: ");
Serial.println(pos);
delay(15);
}
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For the `Pcbcupid GLYPH C6 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
After uploading the code, open the Serial Monitor (Tools > Serial Monitor) and set the baud rate to 115200.
You should see the servo motor moving back and forth from 0° to 180° and back, with the position being printed on the Serial Monitor.(If your servo does not move, check the wiring and ensure your power supply is sufficient for the servo's requirements).



# Stepper Motor
Source: https://learn.pcbcupid.com/guides/stepper-motor-with-drv8833
Drive a bipolar stepper motor at variable speeds using the DRV8833 motor driver and a Glyph ESP32 board with example Arduino code and wiring.
# Stepper Motor
## Overview
Stepper motors allow precise control of angular position, speed, and acceleration. The DRV8825 stepper driver module provides an easy interface to control bipolar stepper motors via simple digital signals (STEP and DIR).
Stepper Motor
A stepper motor is a type of electric motor that moves in precise, small steps instead of spinning continuously like a regular motor.
* Each step rotates the motor by a fixed angle (called step angle).
* You can control position, speed, and direction very accurately.
* No need for feedback sensors (in most basic systems).
How does it work:
A stepper motor has:
* Multiple electromagnets (coils) arranged around a central rotor.
* When you energize coils in a specific sequence, the magnetic field causes the rotor to move one "step" at a time.
DRV8825 Driver:
The DRV8825 is a microstepping driver for controlling bipolar stepper motors. It can handle up to 2.5A per coil (with proper cooling) and supports up to 1/32 microstepping, allowing smooth and quiet motor operation.
Key Signals:
* STEP: Each pulse advances motor by one microstep.
* DIR: Sets direction of rotation (HIGH = one direction, LOW = opposite).
* ENABLE: Enables or disables motor coils (LOW = enable, HIGH = disable).
* Microstep Pins (MS1, MS2, MS3): Select microstepping resolution.
* VMOT & GND: Power supply for the motor.
## Pin Configuration
* STEP: GPIO 18
* DIR : GPIO 15
* ENABLE : GPIO 20 (OPTIONAL)
* VMOT: External Motor Power
* GND : External Motor Power
* GND (Logic) : GND (GLYPH BOARD)
* SLP : 5V SUPPLY (GLYPH BOARD)
* RST : 5V SUPPLY(GLYPH BOARD)
connect SLP and RST together, then tie to 5v supply in GLYPH BOARD :
* Common approach in DRV8825 modules.
* Keeps both active together.
## Key Features
* Accurate Stepper Motor Control
* Adjustable Speed via DelayMicroseconds
* Direction Control
* Enable/Disable Motor Driver
* Compatible with GLYPH-C6 (ESP32-C6)
## Application
* Precision motion control systems
* Positioning and alignment mechanisms
* Robotics and automation projects
* CNC machines and engraving systems
* 3D printers and fabrication devices
* Smart home motorized appliances
Conveyor and material handling systems
Camera sliders and pan-tilt systems
Automatic feeders and dispensing units
Valve and actuator control systems
Industrial control applications
IoT-based remote motor control projects
## Step 1: Hardware Required
1. GLYPH-C6 Board (ESP32-C6)
2. DRV8825 Stepper Motor Driver Module
3. Bipolar Stepper Motor (e.g., NEMA 17)
4. External Motor Power Supply (12V recommended)
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Make sure to install the library**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
// For GLYPH-C6
// Define GPIO pins
#define STEP_PIN 18
#define DIR_PIN 15
#define ENABLE_PIN 20 // Optional (LOW = enabled)
// Define number of steps per revolution (depends on microstepping)
const int stepsPerRevolution = 19200; // Example for high microstepping
void setup() {
pinMode(STEP_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
pinMode(ENABLE_PIN, OUTPUT);
digitalWrite(ENABLE_PIN, LOW); // Enable driver
Serial.begin(115200);
Serial.println("Starting Stepper Test...");
}
void loop() {
Serial.println("Rotating Clockwise...");
rotateStepper(true, stepsPerRevolution);
delay(1000);
Serial.println("Rotating Counter-Clockwise...");
rotateStepper(false, stepsPerRevolution);
delay(1000);
}
void rotateStepper(bool dir, int steps) {
digitalWrite(DIR_PIN, dir ? HIGH : LOW);
for (int i = 0; i < steps; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500); // Pulse HIGH
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(1000); // Pulse LOW (adjust speed here)
}
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C6`
For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output
* The stepper motor rotates clockwise and counterclockwise.
* Serial Monitor will display rotation direction and steps.
* Adjust delayMicroseconds() for speed tuning.
* Modify stepsPerRevolution to match your motor & microstepping settings.
# OpenWeatherMap REST API
Source: https://learn.pcbcupid.com/guides/temperature-monitoring-using-glyph
Call the OpenWeatherMap REST API from a Glyph ESP32 board over Wi-Fi, parse JSON responses, and log temperature and humidity to the serial monitor.
# Temperature monitoring using OpenWeatherMap & GLYPH
This guide will help you to set up a Temperature Monitoring system with a [GLYPH-C3](https://shop.pcbcupid.com/product/gd001/) that fetches Weather data and retrieve the Current Temperature data for a specified location using the OpenWeatherMap API and display it on the Arduino IDE Serial Monitor. We are doing this using the [WiFiManager Library](https://github.com/tzapu/WiFiManager), which provides an easy way to connect the device to a WiFi network without hardcoding credentials or constantly re-uploading new firmware when WiFi settings change.
Note that the WiFiManager Library, as stated in its [GitHub Page](https://github.com/tzapu/WiFiManager), only supports certain ESP32 Devices. Currently it only supports GLYPH-C3. Hence, you cannot use other GLYPH boards for this project.
**OpenWeatherMap** is a popular weather data service that provides a variety of weather information, including current weather, forecasts, historical data, and climate information. It offers APIs that developers can integrate into their applications to retrieve weather data for specific locations. There are some key points to be remembered, they are:
* **API (Application Programming Interface)**: An API allows different software applications to communicate with each other. In the context of OpenWeatherMap, it lets developers access weather data programmatically.
* **API Key**: It is a unique identifier assigned to each user when they sign up for OpenWeatherMap's services. It acts as a password to authenticate requests to the API, ensuring that the user has permission to access the data.
* **Endpoint**: An endpoint is a specific URL within the API that corresponds to a particular function or resource.
Let us consider the example of detecting the Temperature of Bangalore city. The API key inserted in the code below will be different for each user. This API key is also present in OpenWeatherMap. The specific location for which we want to detect the temperature is also selected in OpenWeatherMap.
## Step 1: Code Setup
1. **Open Arduino IDE**
2. **Install the Necessary Libraries:**
Open Arduino IDE and go to `Sketch > Include Library > Manage Libraries`. Search for and Install the following libraries:
* **WiFiManager by tzapu** - You can also install this Library via [WiFiManager Library-tzapu-GitHub](https://github.com/tzapu/WiFiManager) and then go to `Sketch > Include Library > Add .ZIP Library`
* **ArduinoJson by Blanchon** [ArduinoJson-GitHub](https://github.com/bblanchon/ArduinoJson)
* **HTTPClient by McEwen** [HTTPClient-GitHub](https://github.com/amcewen/HttpClient)
3. **GetOpenWeatherMap API Key**:
* Signup at OpenWeatherMap.
* After registering, go to the API section and get your API Key.
* You will use this key to make Authenticated requests to fetch weather data.
4. **Enter the following code into the Arduino IDE**
```cpp theme={null}
#include // WiFiManager library
#include // HTTP client to make requests. HTTPClient is a class provided by libraries such as HTTPClient.h on the GLYPH board, allowing you to make HTTP requests (such as GET and POST) to web servers over the internet. It is commonly used to interact with APIs, send data to servers, or retrieve information from the web (e.g., weather data, sensor logs, etc.).
#include // ArduinoJson to parse JSON. It provides a simple and efficient way to parse (read) and serialize (write) JSON data in memory-constrained environments.
// OpenWeatherMap API endpoint and API key
const char* apiKey = "871cd481558344e66f35315c8d1b2f65"; // enter the API key which we can get from the openweathermap
const char* cityName = "Bangalore";//enter the city name which want to be detected.
const char* apiUrl = “http://api.openweathermap.org/data/2.5/weather?q=Bangalore&appid=871cd481558344e66f35315c8d1b2f65&units=metric”; // This URL is taken from OpenWeatherMap to replace the API key
// Create an instance of the WiFiManager class. his instance (wm) will be used to manage Wi-Fi connections for the GLYPH board. WiFiManager simplifies connecting to Wi-Fi networks, allowing for easy handling of saved credentials and configuration options when no saved credentials are found.
WiFiManager wm; // Declare a WiFiManager object named 'wm'.
void setup()
{
Serial.begin(115200); // Initialize the serial communication at a baud rate of 115200
// Automatically connect using saved credentials
if(!wm.autoConnect("WeatherAP_AccessPoint")) // wm.autoConnect("WeatherAP_AccessPoint"): This function attempts to connect to to the last known WiFi network using previously saved credentials (SSID and Password) from EEPROM/flash. If the device has connected to a WiFi network before, the credentials are stored, and autoConnect will attempt to reconnect to that network automatically. If GLYPH-C3 cannot connect to a saved WiFi network (either because the credentials are not stored or the network is unavailable), it will create an Access Point (AP) with the SSID "WeatherAP_AccessPoint". This allows the user to connect to GLYPH-C3 from another device (e.g., a phone or laptop), access the captive portal, and provide WiFi credentials through a web interface.The GLYPH C3 now reattempts to connect with the new saved credentials. If the connection is successful, the function returns true as the result and the if block will not be executed due to ! operator used with the result. If the connection attempt fails, the function returns false and the if block is executed.
{
Serial.println("Failed to connect"); // Print a message that the Connection has Failed
// Restart the GLYPH to attempt connecting again - This is useful if you want to reinitialize the WiFi stack and try to connect afresh.
ESP.restart();
}
// After Successfully Connecting to the saved WiFi Network
Serial.println("Connected to WiFi!");
void fetchWeatherData()
{
// HTTP is the foundational protocol used by the web to transfer data between a Client (e.g., a web browser or the GLYPH board) and a Server. HTTPClient is a library often used in IoT devices (like ESP32 and GLYPH boards) for making HTTP Requests. It simplifies sending HTTP requests, handling responses, and even deals with security for HTTPS.
HTTPClient http; // Create an HTTPClient object to handle the HTTP requests
// Initiate HTTP GET request
http.begin(apiUrl); // Begin the HTTP request by providing the API URL
int httpCode = http.GET(); // Send the GET request and store the HTTP response code
// Check if the HTTP request was successful (i.e., response code > 0)
if (httpCode > 0)
{
// Check if the response is HTTP OK
if (httpCode == HTTP_CODE_OK)
{
// Retrieve the server’s response data (e.g., weather data in JSON format) as a string. This data will typically include the actual weather information you're fetching from the API. 'Payload' typically refers to the actual data being transmitted or processed within a system, particularly in the context of networking, APIs, or messaging.
String payload = http.getString();
// Print a message indicating that the weather data has been successfully received
Serial.println("Weather data received:");
// Print the raw weather data (in JSON or text format) to the Serial Monitor for debugging
Serial.println(payload);
// Create a JSON document object to hold the parsed data. The number 1024 specifies the size of the memory buffer in bytes that will be used to store the JSON data. JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is often used to send and receive data from web services in a structured format. JSON represents data in key-value pairs and arrays. A DynamicJsonDocument is used to store the parsed JSON. Parsing is typically done when you need to extract meaningful information from raw data such as text, numbers, or special tokens in a string. When you parse JSON, you take the raw JSON string and transform it into a format you can work with programmatically, like reading specific values or modifying them.
DynamicJsonDocument doc(1024); // DynamicJsonDocument adjusts this size according to the size of the expected JSON response.
// Parse the JSON payload (the raw data from the server response) and store the result in the `doc` object. `deserializeJson` function parses the payload string and fills the `doc` with the corresponding JSON structure. It returns a `DeserializationError` which will indicate if the parsing was successful or if there was an error
DeserializationError error = deserializeJson(doc, payload);// Check if the deserialization (JSON parsing) process was successful
if (!error)
{
// Parsing was successful, and the `doc` object now contains the parsed JSON structure. Now you can access individual elements of the JSON data as needed, e.g., temperature, weather description, etc. Example: Access and print the value of the "temp" field inside the "main" object
float temperature = doc["main"]["temp"];
// Example: Access and print the "description" field from the first object in the "weather" array. Index [0] specifies that we want to access the first object in the "weather" array. Since arrays are zero-indexed, the first element is accessed with index 0. This accesses the "description" property of the first object in the "weather" array. The expected value is typically a string that describes the current weather conditions, such as "clear sky" or "light rain". The retrieved description is stored in a const char* variable called description.
const char* description = doc["weather"][0]["description"];
// Display data on Serial Monitor. Print the label "Temperature in " followed by the city name
Serial.print("Temperature in ");// Prints a string message "Temperature in " without moving to the next line
// Print the name of the city (stored in `cityName` variable). This assumes `cityName` contains the city name as a string (e.g., "New York")
Serial.print(cityName); // Prints the value of `cityName` (the name of the city)
// Print the colon ":" and a space after the city name to format the output nicely
Serial.print(": ");// Prints ": " to separate the city name and temperature
// Print the temperature value (assumed to be stored in the `temperature` variable). The value of `temperature` is expected to be a float that contains the temperature in degrees Celsius
Serial.print(temperature); // Prints the temperature value (e.g., 25.3)
// Print the degree symbol and "C" to indicate Celsius
Serial.println(" °C");// Prints " °C" to indicate the temperature unit and moves to the next line
// Print the label "Weather description: " to introduce the weather description
Serial.print("Weather description: ");// Prints "Weather description: " without moving to the next line
// Print the actual weather description (assumed to be stored in the `description` variable). The `description` variable holds a string that describes the current weather (e.g., "clear sky")
Serial.println(description); // Prints the weather description and moves to the next line
}
else
{
// If JSON parsing failed (i.e., there was an error), print an error message to the Serial Monitor
Serial.println("Failed to parse JSON");// Prints an error message indicating that the JSON parsing failed
}
}
}
// else block: This block is executed if the if (httpCode > 0) check fails, meaning the HTTP request did not return a successful response or there was an error in deserializing the JSON data.
else
{
// If there was an error during JSON deserialization or the HTTP request failed, print an error message to the Serial Monitor for debugging purposes.
Serial.print("Error on HTTP request: ");
// `Serial.println(httpCode);` prints the actual HTTP status code that was returned by the server,
Serial.println(httpCode);
}
// This function call ensures that the HTTP connection is properly closed and all resources allocated for the request are released. Not calling http.end() could lead to memory leaks or other resource-related issues, which could eventually cause the program to behave incorrectly.
http.end();
}
void loop()
{
// Fetch weather data every 30seconds(30000 milliseconds =30seconds)
fetchWeatherData(); // Call the function to get the latest weather data . This function is called to retrieve the latest weather information from the OpenWeatherMap API.
delay(30000); // Wait for 30 seconds(30000 milliseconds) before fetching. This delay between each request is to avoid exceeding the API rate limits and making unnecessary requests. You can adjust the delay time based on how frequently you want to update the weather data.
}
```
## Step 2: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 3: Observe the Output on the Serial Monitor
The Serial Monitor should start displaying the Weather Description and Temperature of the Location which has been set in OpenWeatherMap.

# REST API Weather on SH1106 OLED
Source: https://learn.pcbcupid.com/guides/temperaturemonitoring-glyph+sh1106oled
Fetch live temperature data from the OpenWeatherMap REST API on a Glyph ESP32 board and display readings on an SH1106 OLED screen over I2C.
# Temperature monitoring using OpenWeatherMap & GLYPH
This guide will help you to set up a Temperature Monitoring system with a [GLYPH-C3](https://shop.pcbcupid.com/product/gd001/) that fetches Weather data and retrieve the Current Temperature data for a specified location using the OpenWeatherMap API and display it on the SH1106-OLED-Display.
**OpenWeatherMap** is a popular weather data service that provides a variety of weather information, including current weather, forecasts, historical data, and climate information. It offers APIs that developers can integrate into their applications to retrieve weather data for specific locations. There are some key points to be remembered, they are:
* **API (Application Programming Interface)**: An API allows different software applications to communicate with each other. In the context of OpenWeatherMap, it lets developers access weather data programmatically.
* **API Key**: It is a unique identifier assigned to each user when they sign up for OpenWeatherMap's services. It acts as a password to authenticate requests to the API, ensuring that the user has permission to access the data.
* **Endpoint**: An endpoint is a specific URL within the API that corresponds to a particular function or resource.
Let us consider the example of detecting the Temperature of Bangalore city. The API key inserted in the code below will be different for each user. This API key is also present in OpenWeatherMap. The specific location for which we want to detect the temperature is also selected in OpenWeatherMap.
SH1106 OLED Display:
The SH1106 is also a driver used in OLED displays, mostly in larger 1.3-inch OLED screens. Like the SSD1306, it also supports 128x64 pixels of visible screen space and works over I2C or SPI.
However, the SH1106 has a slightly different memory setup — it actually has 132 columns in its internal memory instead of 128. That means there's a small mismatch between its memory and the visible screen. Because of this, if you use the same SSD1306 libraries with an SH1106 screen, the image might appear shifted, cut off, or not show at all.
To fix this, you should use libraries like U8g2 or SH1106Wire, which are made to handle this offset and map the pixels correctly.
1\)Microcontroller Sends Commands & Data
You connect the display to a microcontroller like an ESP32, Arduino, or GLYPH board using I2C or SPI.
You write code like display.print("Hello").
That gets converted into commands and image data.
The microcontroller sends this over I2C or SPI to the SH1106 chip.
2️) SH1106 Stores Data in Internal RAM
Inside the SH1106 chip is display memory (called GDDRAM) — a kind of pixel buffer.
It stores 132 columns × 64 rows of pixel data (even though only 128 columns are visible).
Each pixel on the display is controlled by a single bit in this memory:
1 means the pixel is ON (white)
0 means the pixel is OFF (black)
So when you send an image or text, the SH1106 stores that information in its memory.
3️) Pixel Data is Mapped to the Display
Here’s where SH1106 is a bit different from SSD1306:
The first 2 columns of memory (column 0 and 1) are not visible on screen.
Display starts from column 2 to column 129 — these 128 columns are what you see.
So any image you send must be shifted by 2 columns to be centered properly.
4️) SH1106 Continuously Refreshes the Screen
The chip refreshes the OLED pixels many times per second using the data in memory.
You don’t need to manage the refresh — the SH1106 does it automatically.
It uses electrical signals to light up the pixels row by row, column by column (like scanning).
5️) Screen Shows Your Image or Text
Finally, the OLED pixels light up based on the data in memory, and you see your message, graphics, or sensor values on screen.
## Step 1: Hardware Required
1. Glyph Board
2. SH1106 OLED Display
## Step 2: Circuit Diagram

## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Install the U8g2 library by going to `Sketch > Include Library > Manage Libraries` and search for **U8g2** library by olikraus**
3. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include
#include
#include
#include
#define SDA_PIN 4
#define SCL_PIN 5
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, SCL_PIN, SDA_PIN);
const char* ssid = "1111";
const char* password = "keerti1234";
String APIKEY = "871cd481558344e66f35315c8d1b2f65";
String CityID = "1277333"; // Replace with your city ID
WiFiClient client;
const char* servername = "api.openweathermap.org";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
u8g2.begin();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_5x8_tr); // Use an even smaller font
u8g2.drawStr(0, 10, "Connecting...");
u8g2.sendBuffer();
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected!");
}
void loop()
{
if (WiFi.status() != WL_CONNECTED)
{
Serial.println("WiFi Disconnected. Reconnecting...");
WiFi.begin(ssid, password);
return;
}
if (client.connect(servername, 80))
{
client.println("GET /data/2.5/weather?id=" + CityID + "&units=metric&appid=" + APIKEY + " HTTP/1.1");
client.println("Host: api.openweathermap.org");
client.println("Connection: close");
client.println();
} else
{
Serial.println("Connection failed");
return;
}
// Read response
String result;
bool jsonStarted = false;
while (client.connected() || client.available())
{
char c = client.read();
if (c == '{') jsonStarted = true; // Start when JSON begins
if (jsonStarted) result += c;
}
client.stop();
Serial.println("Received JSON:");
Serial.println(result); // Print the JSON response
// Parse JSON
StaticJsonDocument<512> doc;
DeserializationError error = deserializeJson(doc, result);
if (error)
{
Serial.print("JSON Parsing Failed: ");
Serial.println(error.c_str());
return;
}
// Extract temperature, humidity, latitude, longitude, and pressure
int temperature = doc["main"]["temp"];
int humidity = doc["main"]["humidity"];
float latitude = doc["coord"]["lat"];
float longitude = doc["coord"]["lon"];
float pressure = doc["main"]["pressure"]; // Pressure in hPa
// Print to Serial Monitor
Serial.printf("Temperature: %d°C\n", temperature);
Serial.printf("Humidity: %d%%\n", humidity);
Serial.printf("Latitude: %.2f\n", latitude);
Serial.printf("Longitude: %.2f\n", longitude);
Serial.printf("Pressure: %.2f hPa\n", pressure);
// Display temperature, humidity, latitude, longitude, and pressure on OLED
u8g2.clearBuffer();
// Use even smaller font size for display
u8g2.setFont(u8g2_font_5x8_tr); // Smaller font
u8g2.setCursor(0, 10);
u8g2.printf("Temp: %d°C", temperature);
u8g2.setCursor(0, 20);
u8g2.printf("Humidity: %d%%", humidity);
u8g2.setCursor(0, 30);
u8g2.printf("Lat: %.2f", latitude);
u8g2.setCursor(0, 40);
u8g2.printf("Lon: %.2f", longitude);
u8g2.setCursor(0, 50);
u8g2.printf("Pressure: %.2f hPa", pressure); // Display pressure
u8g2.sendBuffer();
delay(60000); // Update every minute
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output on the SH1106 OLED Display
The SH1106 OLED Display should now show the entire Weather Details from OpenWeatherMap like Temperature, Latitude etc.

# Control a Dual Relay over Wi-Fi
Source: https://learn.pcbcupid.com/guides/wifi/local-webserver-to-control-relay
Host a local web server on a Glyph ESP32 board to switch a two-channel relay on and off from a browser for remote control of lights or appliances.
# Dual-Channel Relay To Switch Via WiFi
A dual-channel relay is an electromagnetic switch module with two independent relays, allowing control of two electrical devices separately using a microcontroller like GLYPH boards.
How Relay Works: You can check this [link](https://learn.pcbcupid.com/boards/g-mod/2-ch-relay) to see how the GMOD-2-CH-Relay Works!
Unlike other relay module GMOD 2-ch-Relay is HIGH level logic module, i.e :
* LOW (0V) → Relay OFF (bulb turns OFF)
* HIGH (3.3V) → Relay ON (bulb turns ON)
**How relay works with on/off bulbs**
1. The glyph board sets up a WiFi Access Point (AP) or connects to an existing WiFi network.
2. A web server runs on the glyphc3, providing buttons to toggle the relay.
3. When a user clicks a button, the glyphc3 activates or deactivates the relays, switching the bulbs ON or OFF.

The [GLYPH-C3 board](https://shop.pcbcupid.com/product/gd001/) is configured as a WiFi server, allowing users to access a web-based interface from any connected device. The 2-channel relay acts as an electrically isolated switch to turn the bulbs on and off according to user inputs received over WiFi.
## Step 1: Hardware Required
* GLYPH-C3 board (other glyph development boards too)
* GMOD Double Channel Relay Module
* 2 AC Bulbs
* Jumper Wires
## Step 2: Circuit Diagram
GMOD Wiring:

* Relay 1 IN → A2 (GLYPH)
* Relay 2 IN → A1 (GLYPH)
* VCC → 5V (GLYPH)
* GND → GND (GLYPH)
* Bulbs: Connected to relay outputs with an AC power source.
## Step 3: Code Setup
1. **Open Arduino IDE.**
2. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
#include // Include the WiFi library for ESP32
// WiFi Credentials (Replace with your actual SSID and Password)
const char* ssid = "your_ssid"; // Your WiFi network name
const char* password = "your_password"; // Your WiFi password
WiFiServer server(80); // Create a web server on port 80 (HTTP)
// Define Relay Control Pins (Ensure GPIOs are compatible with your relay module)
#define RELAY1 A2 // connected to Relay 1 (Bulb 1)
#define RELAY2 A3 // connected to Relay 2 (Bulb 2)
void setup() {
Serial.begin(115200); // Start serial communication for debugging
delay(1000); // Short delay for stability
pinMode(RELAY1, OUTPUT); // Set relay 1 pin as output
pinMode(RELAY2, OUTPUT); // Set relay 2 pin as output
// Set relays to LOW (OFF) initially
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, LOW);
// Connect to WiFi
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
// Wait until WiFi is connected
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print IP address assigned to ESP32
Serial.println("\nWiFi Connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
server.begin(); // Start the web server
}
void loop() {
WiFiClient client = server.available(); // Check if a client has connected
if (client) { // If a client is connected
Serial.println("\nClient Connected");
String request = client.readStringUntil('\r'); // Read the HTTP request
Serial.print("Received Request: ");
Serial.println(request);
client.flush(); // Clear the request buffer
// Control Relays Based on the Request URL
if (request.indexOf("/bulb1on") != -1) {
digitalWrite(RELAY1, HIGH); // Turn ON Relay 1 (Bulb 1)
Serial.println("Bulb 1 TURNED ON");
}
else if (request.indexOf("/bulb1off") != -1) {
digitalWrite(RELAY1, LOW); // Turn OFF Relay 1 (Bulb 1)
Serial.println("Bulb 1 TURNED OFF");
}
else if (request.indexOf("/bulb2on") != -1) {
digitalWrite(RELAY2, HIGH); // Turn ON Relay 2 (Bulb 2)
Serial.println("Bulb 2 TURNED ON");
}
else if (request.indexOf("/bulb2off") != -1) {
digitalWrite(RELAY2, LOW); // Turn OFF Relay 2 (Bulb 2)
Serial.println("Bulb 2 TURNED OFF");
}
else if (request.indexOf("/bothon") != -1) {
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH); // Turn ON both bulbs
Serial.println("BOTH BULBS TURNED ON");
}
else if (request.indexOf("/bothoff") != -1) {
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, LOW); // Turn OFF both bulbs
Serial.println("BOTH BULBS TURNED OFF");
}
else if (request.indexOf("/bulb1on2off") != -1) {
digitalWrite(RELAY1, HIGH); // Bulb 1 ON
digitalWrite(RELAY2, LOW); // Bulb 2 OFF
Serial.println("Bulb 1 TURNED ON, Bulb 2 TURNED OFF");
}
else if (request.indexOf("/bulb2on1off") != -1) {
digitalWrite(RELAY1, LOW); // Bulb 1 OFF
digitalWrite(RELAY2, HIGH); // Bulb 2 ON
Serial.println("Bulb 2 TURNED ON, Bulb 1 TURNED OFF");
}
// Respond to Client with Web Interface
client.println("HTTP/1.1 200 OK"); // Send HTTP response header
client.println("Content-Type: text/html"); // Specify HTML content
client.println();
// Start HTML Content
client.println("");
client.println("WiFi Bulb Control");
// Basic CSS for button styling
client.println("");
client.println("");
client.println("
WiFi Bulb Control
");
// Buttons for controlling Bulb 1
client.println("Bulb 1 ON");
client.println("Bulb 1 OFF");
client.println(" ");
// Buttons for controlling Bulb 2
client.println("Bulb 2 ON");
client.println("Bulb 2 OFF");
client.println(" ");
// Buttons for controlling both bulbs at the same time
client.println("Both ON");
client.println("Both OFF");
client.println(" ");
// Buttons for alternate ON/OFF configurations
client.println("Bulb 1 ON, Bulb 2 OFF");
client.println("Bulb 2 ON, Bulb 1 OFF");
client.println(""); // Close HTML content
client.stop(); // Disconnect client
}
}
```
## Step 4: Upload the Code
1. **Connect the Board**
* Connect your GLYPH board to your computer
2. **Select the Board and Port**
Do the following settings in your Arduino IDE,
Do the following settings in your Arduino IDE,
* `Tools > Board > esp32 > Pcbcupid GLYPH C3`
For the `Pcbcupid GLYPH C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater than or equal to 3.1.0.
* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***
If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
3. **Upload the Code**
* Click the upload button (➡️ icon) or use the shortcut `CTRL + U` in Arduino IDE to upload the code to the board.
## Step 5: Observe the Output on the Serial
After uploading, open the Serial Monitor:
* See WiFi setting up for communication
* Find the IP Address.
* Enter the IP Address in a web browser.
* A Web interface with Graphical Buttons for controlling bulbs will appear
* Click the buttons to turn bulbs ON/OFF.These buttons work by handling HTTP requests to toggle relays, thus controlling the bulbs in the process.
You can see along with the serial monitor, the AC light bulb turn on and turn off accordingly


* Ensure WiFi credentials are correct.
* Some relay modules are active LOW (LOW = ON, HIGH = OFF).
* Ensure the relay power rating matches your bulb requirements.
# Create a Wi-Fi Access Point on Glyph
Source: https://learn.pcbcupid.com/guides/wifi/wifiaccess-point
Configure a Glyph ESP32 board as a standalone Wi-Fi access point so other devices can connect directly without an external router or internet.
# Create a WiFi Access Point and Control LED with the Glyph C3
## Introduction
This guide will help you set up a WiFi access point using the [GLYPH-C3 board](https://shop.pcbcupid.com/product/gd001/), generate an IP address, and control switches via a web interface. Follow these steps carefully to ensure a smooth setup process.
Glyph C3 as a **Soft Access Point**: A **Soft Access Point (SoftAP)** is a mode in which a Wi-Fi-enabled device, like the Glyph C3, creates its own wireless network, allowing other devices to connect directly to it without needing a router or external access point. This is different from the typical "station" mode, where the Glyph C3 connects to an existing network as a "client".
Key Features of SoftAP are:
1. **Direct Network Creation**: The device generates its own Wi-Fi network (SSID) and can assign IP addresses to connected devices, creating a small, standalone network.
2. **Local Communication**: Devices that connect to the SoftAP can communicate directly with it and with each other, enabling a range of applications without internet connectivity.
3. **Limited Range and Clients**: SoftAPs are usually designed for local, small-scale connections and typically support fewer devices and have shorter ranges than traditional access points.
SoftAP is useful for Applications like:
* **Configuration Portals**: Allowing users to configure **IoT devices** over Wi-Fi.
* **Local Data Exchange**: For **Smart Home** setups or sensor data exchanges without internet.
* **Mobile Hotspots**: Enabling one device to share its network connection with others.
For example, when using the Glyph C3 as a SoftAP, other devices like smartphones can connect to it, and you can access a web server running on the Glyph C3 to serve pages, collect data, or adjust settings locally.
## Step 1: Hardware Required
1. GLYPH-C3 Board
2. External LED (Optional, as in this documentation we control only the GLYPH-C3 Onboard LED)
## Step 2: Set Up the WiFi Access Point
### Copy the Code
1. **Open Arduino IDE.**
2. **Copy and paste the following code into the Arduino IDE:**
```cpp theme={null}
// Load Wi-Fi library
#include
// Replace with your network credentials
const char* ssid = "your_ssid"; // Replace with your WiFi SSID
const char* password = "your_password"; // Replace with your WiFi password
// Set web server port number to 80
WiFiServer server(80); // This initializes a server object using the WiFiServer class and sets it to listen on port 80, which is the default port for HTTP. This means your Glyph C3 will host a Web Server that can handle HTTP requests on that port.
// Variable to store the HTTP request
String header; // This declares a String variable named header, which is often used in web server code to store the HTTP request header data sent by a client.
// Auxiliary variables to store the current output state
String output1State = "off";
String output2State = "off";
// Assign output variables to GPIO pins 1 & 2 (Pins A1 & A2)
const int output1 = 1;
const int output2 = 2;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup()
{
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output1, OUTPUT);
pinMode(output2, OUTPUT);
// Set outputs to LOW
digitalWrite(output1, LOW);
digitalWrite(output2, LOW);
if (!WiFi.softAP(ssid, password)) {
log_e("Soft AP creation failed.");
while (1);
}
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
}
void loop()
{
WiFiClient client = server.available(); // Listen for incoming clients. This is used to check for any incoming client connections to your WiFi server
if (client) // // If a new client connects,
{
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // Print a message out in the serial port
String currentLine = ""; // Make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime)
{ // Loop while the client's connected
currentTime = millis();
if (client.available())
{ // If there's bytes to read from the client,
char c = client.read(); // Read a byte, then
Serial.write(c); // Print it out the serial monitor
header += c;
if (c == '\n')
{ // If the byte is a newline character
// If the current line is blank, you got two newline characters in a row.
// That's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0)
{
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Turn the GPIOs on and off
if (header.indexOf("GET /1/on") >= 0) // The header.indexOf("GET /1/on") function searches the header string for the substring "GET /1/on". If this substring is found, indexOf returns the position (index) of the first occurrence. If it is not found, it returns -1.
{
Serial.println("A1 on"); // sends the message "A1 on" to the Serial Monitor. This line is useful for debugging, as it confirms that the code segment responsible for turning on device A1 (connected to output1) has been executed.
output1State = "on"; // sets a variable output1State (which should be declared earlier in your code, likely as a String type) to the value "on"
digitalWrite(output1, HIGH); // Turns on the 1st LED - A1
}
else if (header.indexOf("GET /1/off") >= 0)
{
Serial.println("A1 off"); // Print to Serial Monitor for debugging
output1State = "off";
digitalWrite(output1, LOW); // Turns off the 1st LED - A1
}
else if (header.indexOf("GET /2/on") >= 0) // "GET /2/on" is found in the header. It indicates that a client has requested to turn on a device associated with the identifier /2.
{
Serial.println("A2 on"); // ");// Prints a message to the Serial Monitor for debugging
output2State = "on"; // Updates the state variable to indicate that 2nd LED - A2 is on.
digitalWrite(output2, HIGH); // Turns on the 2nd LED - A2
}
else if (header.indexOf("GET /2/off") >= 0) // Checks if the command to turn on 2nd LED - A2 was received.
{
Serial.println("A2 off"); // Prints a message indicating that device 2 has been turned off.
output2State = "off"; // Updates the state variable to indicate that 2nd LED - A2 is off.
digitalWrite(output2, LOW); // Turns off the 2nd LED - A2.
}
// Display the HTML web page
client.println(""); // This line indicates that the document is HTML5. It helps the browser understand how to render the page correctly.
client.println(""); // This line includes a tag that sets the viewport to make the page responsive on mobile devices. The width=device-width ensures that the page scales appropriately to the device's screen size.
client.println(""); // This line sets a blank favicon for the webpage. A favicon is the small icon shown in browser tabs. Here, an empty data URL is used, which means no icon will be displayed.
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println(""); // background-color: #555555;: Sets a darker gray background color for a secondary button style, which is often used for actions like "Off" or "Cancel".
// Web Page Heading
client.println("
GLYPH C3
"); // used to add content to the HTML document being served by your Glyph C3 web server.
// Display current state, and ON/OFF buttons for A1
client.println("
ON BOARD LED
"); //
- This tag creates a subheading. Using
indicates that it's a lower-level heading compared to
, which is used for the main title. This helps organize the information visually and hierarchically. ON BOARD LED - The text displayed in the subheading, indicating the section related to the on-board LED.
client.println("
A1 - State " + output1State + "
"); //
- This tag defines a paragraph of text. A1 - State + output1State: This line concatenates a string to indicate the state of the LED connected to output1. The variable output1State contains the current state ("on" or "off"). This allows the web page to show whether the LED is currently on or off.
// If the output1State is off, it displays the ON button
if (output1State=="off")
{
client.println("
");
}
else
{
client.println("
");
}
// Display current state, and ON/OFF buttons for A2
client.println("
EXTERNAL LED
"); // used to generate a subheading in the HTML document that your Glyph C3 web server is serving to the client (typically a web browser)
client.println("
A2 - State " + output2State + "
");
// If the output2State is off, it displays the ON button
if (output2State=="off") // This condition checks if the 2nd LED - A2 is currently off.
{
client.println("
## 1. Go to **[LionCircuits.com](https://www.lioncircuits.com/)**

## 2. Create an Account

Click on **Sign Up** if you are a first-time user and enter your First Name, Last Name, Email and Password to sign up.If you have already signed-up, then click on **Login** and enter your Email id and Password to login. Or Alternatively you can directly sign in via your Google Account with the option **Sign in With Google**
## 3. Creating a Project
\
Once logged in, click on **My Projects** as shown in the image above

Next, Click on **New Project**

* In the **Project Name** field, enter the Name of your project
* In the **Description** field, give a description for your project(if any)
* In the **Layers** field, specify the number of layers your PCB has

* In the **Gerber File Upload** field, click on **Choose From Files/Drag And Drop**

* Upload your Gerber zip file and Click on **Proceed**
This will create a New Project that displays the Project Name along with a unique Project ID (given as PID). You can use this PID to communicate your queries to the Lion circuits Sales & Support team.
## 4. Specifying What You Want
* Next, you will see 4 Steps that you must go through before Placing your Order :
1. **Fabrication**
2. **Assembly**
3. **Procurement**
4. **Summary**
### Step 1: **Fabrication**
In the **Fabrication** step , The Default settings should look like this:

* **Layers** - set to **2**
* **PCB Qty** - set to **5**
* **Board Dimension** - Calculated from your Gerber
* **Discrete Design** - **1**
* **Board Type** - **Single PCB**
* **PCB Thickness - 1.6mm**
* **Copper Thickness - 1 oz(35 um)**
* **PCB Finish - HASL Finish**
* **Mask Color - Green**
You can vary these parameters based on your specific needs and you can see the price on the right update live!
Once you are done with your requirement you can click on **Add & Proceed** which will add the fabrication to the project and move on assembly. In case if you just need assembly without needing for fabrication you can just skip this process with **Skip Fabrication** button.
### Step 2: **Assembly**
Next for the assembly make sure you prepare your BOM file as per the [EXAMPLE BOM](https://order-lioncircuits.s3-us-west-1.amazonaws.com/resources/public/BOM/sample_bom.xlsx) given by Lion Circuits.

* To upload the bom file click on **BOM File Upload** and upload your BOM File

* Once the BOM file is uploaded, a drop-down menu called **Map your BOM Fields** will appear. Map your file's BOM Fields to the correct Assembly BOM Fields and click on **Next**

* In the **Units** Field, specify how much Units you need
* In the **Assembly Type** Field, specify what type of Assembly you want - **Manual or Automatic Assembly**
* If you want to do **Automatic Assembly**, Another field called **XY File** will appear

* In the **XY File** Field, Upload the respective XY File generated from your CAD program which can be **Top, Bottom or Combined**

* In the **Stencil Field**, select either **Frameless** or **Framed** as per your requirements
* In the **Solder Field**, select either **Leaded** or **LeadFree** as per your requirements
With these setup you can see the cost and build time on the right pane. Just as the previous step you can skip this process by clicking on the **Skip Assembly** or clicking on **Add & Proceed** to include this process.
### Step 3: **Procurement**
Here in this step you can procure the parts that you need for your PCB project.

Here based on the requirement you can select the **Mode Of Procurement**
* **Procure by LC :** All the components are procured by LionCircuit with the price shown on the BOM Table.
* **Procure by Me :** Where you can purchase all the parts by yourself and ship it to LionCircuit warehouse.
* **Partial Procure :** With this method you can procure and send few parts by yourself and the rest can be purchased by LC.
Next select the **Total Number of Boards** that you want to assemble
* In the table, you can see the list of your BOM components that are available or in stock, along with their Quantity, Price per unit change as you change the total number of boards.

With these setup you can see the cost and procurement time on the right pane. Just as the previous step you can skip this process by clicking on the **Skip Procurement** or by clicking on **Add & Proceed** to include this process.
### Step 4: **Checkout**

Under the **Shipping Method**, select your desired shipping mode- **Standard 2-3 Working Days** or **Premium 1-2 Working Days**
and finally, add your **Billing and Shipping Addresses** and click on **Pay Now** under **Charge Details**.

You will be redirected to the LionCircuits Razorpay Payment portal where you can select the mode of your payment. As simple as that you can finish complete electronic manufacturing from Fabrication to Final Product in a single project!
If you like to place order for your PCB check out this [link](https://www.lioncircuits.com/) and to learn more about product building you can check this [youtube playlist](https://www.youtube.com/watch?v=e1ifblb0CRQ\&list=PLn6004q9oeqH1Y86fvJ5knaRUbPwJEcSj).