Простой пример: BLE Beacon аналогового датчика
Подключение: Подайте сигнал на GPIO1 (A0 на Xiao ESP32S3). Например:
- Потенциометр (средний пин → GPIO1, края → 3V3/GND)
- Фоторезистор + резистор 10kΩ
- Любые 0-3.3V
import time
import board
import _bleio
import analogio
print("BLE Analog Beacon starting!")
# Аналоговый вход (GPIO1 = A0 на Xiao ESP32S3)
analog_in = analogio.AnalogIn(board.GP1) # Измените на ваш пин!
# LED для индикации
led = _bleio.DigitalInOut(board.LED)
led.direction = _bleio.DigitalInOut.Direction.OUTPUT
# BLE адаптер
adapter = _bleio.Adapter()
# Создаем сервис (для beacon не обязательно, но добавим)
service = _bleio.Service(_bleio.UUID("12345678-1234-5678-1234-56789abcdef0"))
char = _bleio.Characteristic(
service,
_bleio.UUID("87654321-4321-8765-4321-fedcba987654"),
properties=_bleio.Characteristic.READ,
initial_value=b"0"
)
service.add_characteristic(char)
adapter.register_services(service)
# Рекламный пакет — ЗДЕСЬ МАГИЯ!
advertisement = _bleio.Advertisement()
advertisement.complete_local_name = "AnalogSensor"
def value_to_bytes(value):
"""Конвертируем 0-65535 в 2 байта"""
return value.to_bytes(2, 'little')
def update_advertisement(analog_value):
"""Обновляем рекламу новым значением"""
# Manufacturer Data: первые 2 байта = значение АЦП
data = b'\xFF\x01' + value_to_bytes(analog_value) # \xFF\x01 = наш код
advertisement.manufacturer_data = (_bleio.UUID(0xFFFF), data)
advertisement.service_uuid = service.uuid
print("Broadcasting analog value every 500ms...")
while True:
# Читаем аналоговый вход (0-65535)
raw_value = analog_in.value
voltage = analog_in.voltage # 0-3.3V
print(f"Raw: {raw_value}, Voltage: {voltage:.2f}V")
# Обновляем характеристику (для подключенных клиентов)
char.value = f"{raw_value:05d}".encode()
# Обновляем рекламу БЕЗ ПЕРЕРЫВА!
update_advertisement(raw_value)
# Начинаем/обновляем рекламу
if not adapter.advertising:
adapter.start_advertising(advertisement)
led.value = True
time.sleep(0.5) # Каждые 500мс
led.value = False
time.sleep(0.1)
🎯 Как это работает:
| Компонент | Что делает |
|-----------|------------|
| analog_in.value | Читает 0-65535 (16 бит) |
| manufacturer_data | 2 байта в рекламе = текущее значение |
| Реклама каждые 500мс | БЕЗ подключения! Смартфон видит данные |
| char.value | Для подключенных клиентов (бонус) |
📱 Чтение на смартфоне (БЕЗ ПОДКЛЮЧЕНИЯ!)
1. nRF Connect (Android/iOS) — ПРОСТО:
1. Сканируйте → найдите "AnalogSensor"
2. НЕ подключайтесь! Нажмите на устройство
3. Manufacturer Data: увидите FF 01 XX YY
XX YY= значение АЦП (пример:FF 01 34 12= 0x1234 = 4660)
2. Bluefruit Connect — UART Mode:
- Подключитесь → UART → увидите "04660" (из характеристики)
3. Собственное приложение:
// Пример для BLE-сканера
function onAdvertisement(device, advertisement) {
let data = advertisement.manufacturerData;
if (data && data[0] === 0xFF && data[1] === 0x01) {
let value = (data[3] << 8) | data[2]; // 0-65535
let voltage = (value / 65535) * 3.3;
console.log(`Voltage: ${voltage.toFixed(2)}V`);
}
}
🚀 УЛУЧШЕННАЯ ВЕРСИЯ с фильтрацией:
# Добавьте в начало основного кода:
smoothed_value = 0
alpha = 0.1 # Коэффициент сглаживания
# В цикле замените чтение на:
raw_value = analog_in.value
smoothed_value = alpha * raw_value + (1 - alpha) * smoothed_value
📋 Таблица пинов АЦП для Xiao ESP32S3:
| Пин | GPIO | Название |
|-----|------|----------|
| A0 | GP1 | Рекомендую! |
| A1 | GP2 | - |
| A2 | GP3 | - |
| A3 | GP4 | - |
| A4 | GP5 | - |
| A5 | GP6 | - |
| A6 | GP7 | - |
| A7 | GP8 | - |
🎯 Тестирование за 30 секунд:
1. Код на плату → LED мигает
2. Потенциометр на GP1
3. nRF Connect → Manufacturer Data меняется при вращении!
4. Готово! Данные в эфире 24/7
💡 Идеи применения:
- IoT датчик (температура, влажность)
- Умный дом (освещенность)
- Беспроводной вольтметр
- Мониторинг батареи
=========== Клиент (исполнительное устройство) ============
import time
import board
import digitalio
import adafruit_ble
from adafruit_ble.advertising.standard import Advertisement, ProvideServicesAdvertisement
from adafruit_ble.uuid import UUID
print("BLE Client starting! Scanning for AnalogSensor...")
Реле на D2 (GPIO2, высокий уровень — ВКЛ)
try:
relay = digitalio.DigitalInOut(board.D2)
relay.direction = digitalio.Direction.OUTPUT
relay.value = False
except AttributeError:
print("Error: Pin D2 not found. Check board pinout!")
while True:
pass
LED на D3 (GPIO3)
try:
led = digitalio.DigitalInOut(board.D3)
led.direction = digitalio.Direction.OUTPUT
led.value = False
except AttributeError:
print("Error: Pin D3 not found. Using built-in LED instead.")
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
led.value = False
BLE радио
ble = adafruit_ble.BLERadio()
UUID сервиса и характеристики
SERVICE_UUID = UUID("12345678-1234-5678-1234-56789abcdef0")
CHAR_UUID = UUID("87654321-4321-8765-4321-fedcba987654")
Порог напряжения
VOLT_THRESHOLD = 1.5
MAX_RAW = 65535
MAX_VOLT = 3.3
while True:
print("Scanning...")
try:
Сканируем устройства
found = set()
for adv in ble.start_scan(ProvideServicesAdvertisement, Advertisement, timeout=5):
if adv.complete_name == "AnalogSensor" and adv.address not in found:
found.add(adv.address)
print("Found AnalogSensor!")
try:
connection = ble.connect(adv)
print("Connected!")
Находим сервис и характеристику
service = connection[SERVICE_UUID]
char = service[CHAR_UUID]
Читаем значение
raw_bytes = char.value
if raw_bytes:
raw_value = int(raw_bytes.decode().strip())
voltage = (raw_value / MAX_RAW) * MAX_VOLT
print(f"Received: Raw={raw_value}, Voltage={voltage:.2f}V")
Управление реле
if voltage < VOLT_THRESHOLD:
relay.value = True
led.value = True
print("Relay ON (voltage low)!")
else:
relay.value = False
led.value = False
print("Relay OFF")
connection.disconnect()
except Exception as e:
print("Connection error:", e)
break # Выходим после нахождения первого подходящего устройства
ble.stop_scan()
except Exception as e:
print("Scan error:", e)
if not ble.connected:
print("No AnalogSensor found. Retrying...")
relay.value = False
led.value = False
time.sleep(5)
[file-name 000264_2025-10-18_18-16-00.txt]