Skip to content

yrjo/meeting-room-tablet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Meeting Room Display

E-Paper meeting room dashboard firmware for the LaskaKit ESPink board with a Good Display GDEY075T7 7.5" 800×480 BW display.

Shows the room's daily schedule (fetched directly from Microsoft 365 Graph API), current time indicator, temperature/humidity (SHT40 sensor), and battery level. Refreshes every 5 minutes using deep sleep.


Hardware

Component Details
Board LaskaKit ESPink v2.7 (ESP32) or v3.5 (ESP32-S3)
Display Good Display GDEY075T7 – 7.5" 800×480, BW, connected via 24-pin FPC
Sensor SHT40 temperature & humidity, connected via μŠup I2C
Battery LiPo single-cell (3.7 V nominal), connected to JST-PH connector on ESPink

Pin Mapping (auto-selected at build time)

Function ESPink v2.7 (ESP32) ESPink v3.5 (ESP32-S3)
EPD MOSI 23 11
EPD SCK 18 12
EPD CS 5 10
EPD DC 17 48
EPD RST 16 45
EPD BUSY 4 38
I2C SDA 21 42
I2C SCL 22 2
Power Gate 2 47
VBAT ADC 34 9

Software Architecture

src/
├── config.h          – All configurable parameters (WiFi, Azure, pins, etc.)
├── main.cpp          – Setup-only loop: power on → read sensors → fetch calendar → draw → deep sleep
├── ms_graph.h/cpp    – OAuth2 client-credentials flow + MS Graph calendarView API
├── display_ui.h/cpp  – Full-screen e-Paper rendering (portrait 480×800 layout)

Firmware Flow (each wake cycle)

  1. Power on peripherals (GPIO drives MOSFET gate for display + I2C bus)
  2. Read battery voltage via ADC + voltage divider
  3. Read SHT40 temperature & humidity over I2C
  4. Connect to WiFi
  5. Sync time via NTP (pool.ntp.org)
  6. Acquire OAuth2 access token from Azure Entra ID
  7. Fetch today's calendar events from MS Graph (/users/{room}/calendarView)
  8. Disconnect WiFi
  9. Render dashboard on e-Paper display
  10. Enter deep sleep for 5 minutes

Prerequisites — Setting Up Your System

macOS

# Install Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install Python 3 and PlatformIO CLI
brew install python3
pip3 install platformio

# Install USB-to-serial driver (CH340) if not auto-detected
# Most modern macOS versions include the driver. If not:
brew install --cask wch-ch34x-usb-serial-driver

Windows

  1. Python 3 — Download and install from python.org. Check "Add Python to PATH" during install.
  2. PlatformIO CLI:
    pip install platformio
  3. USB driver — Install the CH340 driver (ESPink uses CH340 USB-to-serial chip).
  4. Plug in the board and note the COM port in Device Manager (e.g., COM3).

Linux (Ubuntu/Debian)

sudo apt update && sudo apt install python3 python3-pip
pip3 install platformio

# Add your user to the dialout group for serial port access
sudo usermod -a -G dialout $USER
# Log out and back in for the group change to take effect

# The CH340 driver is included in the kernel. Verify with:
ls /dev/ttyUSB*

All Platforms — Verify PlatformIO

pio --version
# Should print something like: PlatformIO Core, version 6.x.x

Onboarding a New Device

Follow these steps for each new meeting room display you deploy.

1. Azure Entra ID — App Registration (one-time)

If you already have an app registration, skip to the per-room steps.

  1. Go to Azure Portal → Entra ID → App registrations
  2. Click New registration
    • Name: Meeting Room Display
    • Supported account types: Single tenant
    • Redirect URI: leave blank
  3. Go to Certificates & secrets → New client secret
    • Copy the Value (this is AZURE_CLIENT_SECRET). It is only shown once!
  4. Note down from the Overview page:
    • Application (client) IDAZURE_CLIENT_ID
    • Directory (tenant) IDAZURE_TENANT_ID

2. Room Mailbox — Get the Email Address

Each meeting room in Microsoft 365 has a room resource mailbox. Ask your Exchange/M365 admin for the room's email address, e.g., meeting-room-lobby@yourcompany.com.

3. Setup RBAC for particular calendars

  1. Get the correct Service Principal Object ID
Connect-MgGraph -Scopes "Application.Read.All"
$sp = Get-MgServicePrincipal -Filter "appId eq 'AZURE_CLIENT_ID'"
$sp.Id
  1. Connect to Exchange Online PowerShell
Install-Module ExchangeOnlineManagement -Scope CurrentUser -Force
Connect-ExchangeOnline
  1. Define variables
$AppId = "xxx"
$SpObjectId = "<PASTE_ENTERPRISE_APP_SERVICE_PRINCIPAL_OBJECT_ID_HERE>"
$AdminUnitId = "xxx"
  1. Create the Exchange “pointer” to the Entra service principal
New-ServicePrincipal -AppId $AppId -ObjectId $SpObjectId -DisplayName "ADD NAME HERE"
  1. Assign the scoped role Application Calendars.Read to the AU
New-ManagementRoleAssignment -Name "ADD NAME HERE" `
  -App $SpObjectId `
  -Role "Application Calendars.Read" `
  -RecipientAdministrativeUnitScope $AdminUnitId
  1. Test Scope
Test-ServicePrincipalAuthorization -Identity $SpObjectId -Resource "meeting-room-half-life@noibit.com"

4. (Recommended) Fix Room Calendar Subject Display

By default, Exchange replaces the meeting subject with the organizer's name for room mailboxes. To show actual meeting titles, an Exchange admin should run:

# Connect to Exchange Online
Connect-ExchangeOnline

# Check current settings
Get-CalendarProcessing -Identity "room-email@yourcompany.com" | FL DeleteSubject, AddOrganizerToSubject

# Fix it
Set-CalendarProcessing -Identity "room-email@yourcompany.com" -DeleteSubject $false -AddOrganizerToSubject $false

Note: The firmware handles the duplicate gracefully — if subject equals organizer name, it shows the name only once. But running the PowerShell fix above will show actual meeting titles.

4. Configure the Firmware

Edit src/config.h:

// WiFi credentials for the room's network
#define WIFI_SSID           "YourWiFiSSID"
#define WIFI_PASSWORD       "YourWiFiPassword"

// Azure credentials (from step 1)
#define AZURE_TENANT_ID     "your-tenant-id"
#define AZURE_CLIENT_ID     "your-client-id"
#define AZURE_CLIENT_SECRET "your-client-secret"

// This room's mailbox
#define ROOM_EMAIL          "room-email@yourcompany.com"
#define ROOM_DISPLAY_NAME   "Room Name"

Other settings you may want to adjust:

Setting Default Description
CALENDAR_START_HOUR 7 First hour shown on the calendar grid
CALENDAR_END_HOUR 20 Last hour shown on the calendar grid
SLEEP_MINUTES 5 Minutes between display refreshes
DISPLAY_ROTATION 3 0=landscape, 1=portrait, 2=landscape flipped, 3=portrait flipped
TZ_INFO CET-1CEST,M3.5.0,M10.5.0/3 POSIX timezone string (default: Europe/Prague)

5. Build and Flash

cd meeting-room-display

# For ESPink v2.7 (ESP32):
pio run -e espink-v2 -t upload

# For ESPink v3.5 (ESP32-S3):
pio run -e espink-v3 -t upload

If auto-detection fails, specify the port explicitly:

# macOS
pio run -e espink-v2 -t upload --upload-port /dev/cu.usbserial-XXXX

# Linux
pio run -e espink-v2 -t upload --upload-port /dev/ttyUSB0

# Windows
pio run -e espink-v2 -t upload --upload-port COM3

6. Monitor Serial Output (optional)

pio device monitor -e espink-v2

You should see output like:

====== Meeting Room Display ======
[PWR]  peripherals ON
[BAT]  4.12 V  (93%)
[SHT40] 23.1 °C   45 %RH
[WiFi] connecting to YourSSID . OK  IP=10.0.0.42  RSSI=-45 dBm
[NTP]  syncing  OK
[NTP]  2026-02-27 09:15:22 CET
[Graph] token obtained (1942 chars)
[Graph] fetched 5 calendar events
[WiFi] disconnected
[PWR]  peripherals OFF
[SLEEP] deep sleep for 5 min

Troubleshooting

Problem Solution
Upload fails with "Wrong chip" error You selected the wrong environment. Use -e espink-v2 for ESP32 boards, -e espink-v3 for ESP32-S3.
"No serial port detected" Install the CH340 driver. On Linux, ensure your user is in the dialout group.
WiFi connection fails Check SSID/password in config.h. The ESP32 only supports 2.4 GHz WiFi.
[Graph] token request HTTP 401 Verify AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET. The secret may have expired.
[Graph] token request HTTP 403 Admin consent for Calendars.Read has not been granted. Go to Azure Portal → App registrations → API permissions → Grant admin consent.
No events showing on display Verify ROOM_EMAIL matches the room mailbox. Check that the room has events in the calendar window (CALENDAR_START_HOURCALENDAR_END_HOUR).
Display shows garbled image Check DISPLAY_ROTATION in config.h. Try values 0–3 to match your mounting orientation.
Sensor shows "N/A" Ensure the SHT40 module is connected via the μŠup I2C connector. Check that the I2C address is 0x44 (default for SHT40).
Battery reads 0% while on USB Normal — the ADC reading can be inaccurate when USB power is connected. Battery percentage is accurate on battery power.

Libraries & Dependencies

All dependencies are managed by PlatformIO and downloaded automatically on first build.

Library Version Purpose
GxEPD2 ^1.6.2 E-Paper display driver
Adafruit SHT4x ^1.0.5 Temperature/humidity sensor
Adafruit GFX ^1.12.4 Graphics primitives & fonts
ArduinoJson ^7.4.2 JSON parsing for MS Graph API responses

Power Consumption & Battery Life

The board uses deep sleep between refreshes. Approximate power draw:

State Current
Active (WiFi + display refresh) ~120–180 mA for ~5s
Deep sleep ~10 μA

With a 5000 mAh battery and 5-minute refresh interval, expect several months of battery life.


License

Server Side Public License

About

E-INK Tablet/display for Meeting Room Calendar

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors