minerva/hardware/maixduino/maix_test_simple.py
pyr0ball 173f7f37d4 feat: import mycroft-precise work as Minerva foundation
Ports prior voice assistant research and prototypes from devl/Devops
into the Minerva repo. Includes:

- docs/: architecture, wake word guides, ESP32-S3 spec, hardware buying guide
- scripts/: voice_server.py, voice_server_enhanced.py, setup scripts
- hardware/maixduino/: edge device scripts with WiFi credentials scrubbed
  (replaced hardcoded password with secrets.py pattern)
- config/.env.example: server config template
- .gitignore: excludes .env, secrets.py, model blobs, ELF firmware
- CLAUDE.md: Minerva product context and connection to cf-voice roadmap
2026-04-06 22:21:12 -07:00

252 lines
7.4 KiB
Python

# Maix Duino - Simple Test Script
# Copy/paste this into MaixPy IDE and click RUN
#
# This script tests:
# 1. LCD display
# 2. WiFi connectivity
# 3. Network connection to Heimdall server
# 4. I2S audio initialization (without recording yet)
import time
import lcd
from Maix import GPIO, I2S
from fpioa_manager import fm
# Import the correct network module
try:
import network
# Create ESP32_SPI instance (for Maix Duino with ESP32)
nic = None # Will be initialized in test_wifi
except Exception as e:
print("Network module import error: " + str(e))
nic = None
# ===== CONFIGURATION - EDIT THESE =====
# Load credentials from secrets.py (gitignored)
try:
from secrets import SECRETS
except ImportError:
SECRETS = {}
WIFI_SSID = "Tell My WiFi Love Her" # <<< CHANGE THIS
WIFI_PASSWORD = SECRETS.get("wifi_password", "") # set in secrets.py # <<< CHANGE THIS
SERVER_URL = "http://10.1.10.71:3006" # Heimdall voice server
# =======================================
# Colors (as tuples for easy reference)
COLOR_BLACK = (0, 0, 0)
COLOR_WHITE = (255, 255, 255)
COLOR_RED = (255, 0, 0)
COLOR_GREEN = (0, 255, 0)
COLOR_BLUE = (0, 0, 255)
COLOR_YELLOW = (255, 255, 0)
def display_msg(msg, color=COLOR_WHITE, y=50):
"""Display message on LCD"""
# lcd.draw_string needs RGB as separate ints: lcd.draw_string(x, y, text, color_int, bg_color_int)
# Convert RGB tuple to single integer: (R << 16) | (G << 8) | B
color_int = (color[0] << 16) | (color[1] << 8) | color[2]
bg_int = 0 # Black background
lcd.draw_string(10, y, msg, color_int, bg_int)
print(msg)
def test_lcd():
"""Test LCD display"""
lcd.init()
lcd.clear(COLOR_BLACK)
display_msg("MaixDuino Test", COLOR_YELLOW, 10)
display_msg("Initializing...", COLOR_WHITE, 30)
time.sleep(1)
return True
def test_wifi():
"""Test WiFi connection"""
global nic
display_msg("Connecting WiFi...", COLOR_BLUE, 50)
try:
# Initialize ESP32_SPI network interface
print("Initializing ESP32_SPI...")
# Create network interface instance with Maix Duino pins
# Maix Duino ESP32 default pins:
# CS=25, RST=8, RDY=9, MOSI=28, MISO=26, SCLK=27
from network import ESP32_SPI
from fpioa_manager import fm
from Maix import GPIO
# Register pins for ESP32 SPI communication
fm.register(25, fm.fpioa.GPIOHS10, force=True) # CS
fm.register(8, fm.fpioa.GPIOHS11, force=True) # RST
fm.register(9, fm.fpioa.GPIOHS12, force=True) # RDY
fm.register(28, fm.fpioa.GPIOHS13, force=True) # MOSI
fm.register(26, fm.fpioa.GPIOHS14, force=True) # MISO
fm.register(27, fm.fpioa.GPIOHS15, force=True) # SCLK
nic = ESP32_SPI(
cs=fm.fpioa.GPIOHS10,
rst=fm.fpioa.GPIOHS11,
rdy=fm.fpioa.GPIOHS12,
mosi=fm.fpioa.GPIOHS13,
miso=fm.fpioa.GPIOHS14,
sclk=fm.fpioa.GPIOHS15
)
print("Connecting to " + WIFI_SSID + "...")
# Connect to WiFi (no need to call active() first)
nic.connect(WIFI_SSID, WIFI_PASSWORD)
# Wait for connection
timeout = 20
while timeout > 0:
time.sleep(1)
timeout -= 1
if nic.isconnected():
# Successfully connected!
ip_info = nic.ifconfig()
ip = ip_info[0] if ip_info else "Unknown"
display_msg("WiFi OK!", COLOR_GREEN, 70)
display_msg("IP: " + str(ip), COLOR_WHITE, 90)
print("Connected! IP: " + str(ip))
time.sleep(2)
return True
else:
print("Waiting... " + str(timeout) + "s")
# Timeout reached
display_msg("WiFi FAILED!", COLOR_RED, 70)
print("Connection timeout")
return False
except Exception as e:
display_msg("WiFi error!", COLOR_RED, 70)
print("WiFi error: " + str(e))
import sys
sys.print_exception(e)
return False
def test_server():
"""Test connection to Heimdall server"""
display_msg("Testing server...", COLOR_BLUE, 110)
try:
# Try socket connection to server
import socket
url = SERVER_URL + "/health"
print("Trying: " + url)
# Parse URL to get host and port
host = "10.1.10.71"
port = 3006
# Create socket
s = socket.socket()
s.settimeout(5)
print("Connecting to " + host + ":" + str(port))
s.connect((host, port))
# Send HTTP GET request
request = "GET /health HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n"
s.send(request.encode())
# Read response
response = s.recv(1024).decode()
s.close()
print("Server response received")
if "200" in response or "OK" in response:
display_msg("Server OK!", COLOR_GREEN, 130)
print("Server is reachable!")
time.sleep(2)
return True
else:
display_msg("Server responded", COLOR_YELLOW, 130)
print("Response: " + response[:100])
return True # Still counts as success if we got a response
except Exception as e:
display_msg("Server FAILED!", COLOR_RED, 130)
error_msg = str(e)[:30]
display_msg(error_msg, COLOR_RED, 150)
print("Server connection failed: " + str(e))
return False
def test_audio():
"""Test I2S audio initialization"""
display_msg("Testing audio...", COLOR_BLUE, 170)
try:
# Register I2S pins (Maix Duino pinout)
fm.register(20, fm.fpioa.I2S0_IN_D0, force=True)
fm.register(19, fm.fpioa.I2S0_WS, force=True)
fm.register(18, fm.fpioa.I2S0_SCLK, force=True)
# Initialize I2S
rx = I2S(I2S.DEVICE_0)
rx.channel_config(rx.CHANNEL_0, rx.RECEIVER, align_mode=I2S.STANDARD_MODE)
rx.set_sample_rate(16000)
display_msg("Audio OK!", COLOR_GREEN, 190)
print("I2S initialized: " + str(rx))
time.sleep(2)
return True
except Exception as e:
display_msg("Audio FAILED!", COLOR_RED, 190)
print("Audio init failed: " + str(e))
return False
def main():
"""Run all tests"""
print("=" * 40)
print("MaixDuino Voice Assistant Test")
print("=" * 40)
# Test LCD
if not test_lcd():
print("LCD test failed!")
return
# Test WiFi
if not test_wifi():
print("WiFi test failed!")
red_int = (255 << 16) | (0 << 8) | 0 # Red color
lcd.draw_string(10, 210, "STOPPED - Check WiFi", red_int, 0)
return
# Test server connection
server_ok = test_server()
# Test audio
audio_ok = test_audio()
# Summary
lcd.clear(COLOR_BLACK)
display_msg("=== TEST RESULTS ===", COLOR_YELLOW, 10)
display_msg("LCD: OK", COLOR_GREEN, 40)
display_msg("WiFi: OK", COLOR_GREEN, 60)
if server_ok:
display_msg("Server: OK", COLOR_GREEN, 80)
else:
display_msg("Server: FAIL", COLOR_RED, 80)
if audio_ok:
display_msg("Audio: OK", COLOR_GREEN, 100)
else:
display_msg("Audio: FAIL", COLOR_RED, 100)
if server_ok and audio_ok:
display_msg("Ready for voice app!", COLOR_GREEN, 140)
else:
display_msg("Fix errors first", COLOR_YELLOW, 140)
print("\nTest complete!")
# Run the test
if __name__ == "__main__":
main()