Skip to content

Embed


📚 AMBA Project - Complete Technical Documentation

🎯 Project Overview

AMBA (Adaptive Musical Box with AI) คือระบบเครื่องดนตรีอัจฉริยะที่ผสานระหว่าง ESP32 (Embedded System) และ Raspberry Pi (AI Server) เพื่อสร้างดนตรีแบบ real-time ด้วย AI

📋 Table of Contents

🏗️ Architecture Overview

System Architecture

┌─────────────────────────────────────────────────────────────┐
│ AMBA SYSTEM ARCHITECTURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ HTTPS/TLS ┌───────────┐ │
│ │ ESP32 │◄────────────────────────────┤ Cloudflare│ │
│ │ (Client) │ Secure Tunnel │ CDN │ │
│ │ │ └─────┬─────┘ │
│ │ - Keypad │ │ │
│ │ - I2S Audio │ │ │
│ │ - FreeRTOS │ Encrypted Tunnel │ │
│ │ - Watchdog │ │ │
│ └──────────────┘ ┌─────┴─────┐ │
│ │Raspberry │ │
│ │ Pi │ │
│ │ │ │
│ │ - FastAPI │ │
│ │ - Markov │ │
│ │ - PyTorch │ │
│ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘


Component Breakdown

ESP32 (Client Side)

Hardware Interface: 4x4 Keypad input, I2S audio output
Processing: Dual-core FreeRTOS multi-threading
Communication: HTTPS over WiFi with TLS/SSL
Safety: Watchdog timer, mutex protection

Raspberry Pi (Server Side)

AI Engine: 4th-order Markov Chain with PyTorch
API: FastAPI RESTful web service
Storage: User session management, harmonic memory
Deployment: Systemd service auto-start

Cloud Infrastructure

CDN: Cloudflare global edge network
Security: SSL/TLS encryption, DDoS protection
Tunnel: Cloudflare Tunnel (no port forwarding needed)
DNS: Custom domain routing

🎮 ESP32 Embedded System

1. Hardware Configuration

I2S Audio Output

#define BCLK_PIN 26 // Bit Clock
#define LRC_PIN 25 // Left/Right Clock (Word Select)
#define DIN_PIN 16 // Data In
#define SAMPLE_RATE 16000
#define BUFFER_SIZE 128


การทำงานของ I2S (Inter-IC Sound):
I2S คือ protocol สำหรับส่งสัญญาณเสียงดิจิทัลแบบ serial

Pin Configuration:
┌─────────────────────────────────────────┐
│ ESP32 → MAX98357A │
├─────────────────────────────────────────┤
│ GPIO 26 (BCLK) → BCLK (Bit Clock) │
│ GPIO 25 (LRC) → LRC (Word Select) │
│ GPIO 16 (DIN) → DIN (Data) │
│ GND → GND │
│ 5V/3.3V → VIN │
└─────────────────────────────────────────┘

Timing Diagram:
BCLK: _‾_‾_‾_‾_‾_‾_‾_‾_‾_‾_‾_‾_‾_‾_‾_‾
LRC: ___________‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
DIN: [16-bit L][16-bit R][16-bit L]...

Sample Rate: 16000 Hz
Bit Depth: 16-bit
Channels: 2 (Left/Right)
Bitrate: 16000 × 16 × 2 = 512 kbps


I2S Configuration Code:
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
// ↑ ESP32 เป็น master (สร้าง clock), TX = ส่งข้อมูล

.sample_rate = 16000,
// ↑ ส่ง sample 16000 ตัวต่อวินาที

.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
// ↑ แต่ละ sample ใช้ 16 bits

.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
// ↑ สลับส่ง Left แล้ว Right

.communication_format = I2S_COMM_FORMAT_STAND_I2S,
// ↑ ใช้ standard I2S protocol

.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
// ↑ Interrupt priority level 1

.dma_buf_count = 8,
// ↑ ใช้ 8 DMA buffers

.dma_buf_len = 128,
// ↑ แต่ละ buffer เก็บได้ 128 samples

.use_apll = false,
// ↑ ไม่ใช้ APLL (Audio PLL) ใช้ clock ปกติ

.tx_desc_auto_clear = true
// ↑ ล้าง descriptor อัตโนมัติหลังส่งเสร็จ
};


DMA (Direct Memory Access) Explained:
DMA = การถ่ายโอนข้อมูลโดยไม่ผ่าน CPU

Without DMA:
CPU: Read data → Write to I2S → Repeat
↑ CPU blocked, can't do other work

With DMA:
CPU: Setup DMA → Do other work
DMA: Automatically transfer data to I2S
↑ CPU free to do other tasks!

Buffer Chain:
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│Buf 0│→│Buf 1│→│Buf 2│→│... │
└─────┘ └─────┘ └─────┘ └─────┘
↓ Sending ↑ CPU fills

Ping-Pong Buffering:
- DMA ส่ง buffer 0 → CPU เติม buffer 1
- DMA ส่ง buffer 1 → CPU เติม buffer 0


4x4 Matrix Keypad

const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};

byte rowPins[ROWS] = { 14, 27, 19, 18 }; // Output pins
byte colPins[COLS] = { 4, 13, 32, 33 }; // Input pins (pull-up)


Matrix Keypad Scanning:
Physical Connection:
Col0 Col1 Col2 Col3
↓ ↓ ↓ ↓
Row0 → [1] [2] [3] [A]
Row1 → [4] [5] [6] [B]
Row2 → [7] [8] [9] [C]
Row3 → [*] [0] [#] [D]

Scanning Algorithm:
1. Set all rows to HIGH
2. Set all columns to INPUT_PULLUP (HIGH)

3. For each row i:
- Set row[i] to LOW
- For each column j:
- If column[j] reads LOW:
→ Button at (i, j) is pressed!
- Set row[i] back to HIGH

Example: Press '5'
Row1 = LOW, Col1 = LOW detected
→ keys[1][1] = '5'

Debouncing:
- Library handles automatic debouncing
- Prevents multiple reads from single press


2. Audio Generation

Sine Wave Synthesis

void generateAndPlayTone() {
unsigned long elapsed = millis() - noteStartTime;
float envelope = 1.0;
Want to print your doc?
This is not the way.
Try clicking the ··· in the right corner or using a keyboard shortcut (
CtrlP
) instead.