BLE enabled Smart Bulb with STM32
Tổng quan: Bóng đèn thông minh được kích hoạt BLE với STM32 & Javascript
Trong dự án này, chúng ta sẽ học cách tạo Bóng đèn thông minh hỗ trợ BLE bằng STM32 & Javascript. Tự động hóa nhà liên quan đến việc tự động hóa thiết bị môi trường gia đình. Để đạt được điều đó, chúng tôi đã tạo ra một bóng đèn thông minh dễ lắp đặt và thiết bị kèm theo có thể được điều khiển qua trình duyệt web hoặc ứng dụng trên điện thoại thông minh. Mục tiêu của dự án này là kiểm soát các thiết bị gia dụng khác nhau bằng trình duyệt web hoặc điện thoại thông minh.
Dự án đang giới thiệu một cách đơn giản sử dụng BLE BleuIO Dongle để bật và tắt bóng đèn Thông minh được kết nối với STM32 Nucleo-144 qua Rơle 5V.
Bạn sẽ cần hai dongle, một kết nối với bo mạch Nucleo và một kết nối với máy tính, chạy tập lệnh web.
Khi BleuIO Dongle được kết nối với cổng USB của bo mạch Nucleo, STM32 sẽ nhận ra nó và trực tiếp bắt đầu quảng cáo. Điều này cho phép Dongle khác kết nối với nó.
Nó cũng sẽ chấp nhận 3 đầu vào khác nhau từ UART:
INPUT | RESULT |
---|
0 | Send ATI (Request device information) command to BlueIO Dongle. |
1 | Manually turn the light bulb on |
2 | Manually turn the light bulb off |
Chúng tôi đã sử dụng bảng phát triển STM32 Nucleo-144 với STM32H743ZI MCU (STM32H743ZI micro mbed-Enabled Development Nucleo-144 series ARM® Cortex®-M7 MCU 32-Bit Embedded Assess Board) cho ví dụ này.
Nếu bạn muốn sử dụng một thiết lập khác, bạn sẽ phải đảm bảo rằng nó hỗ trợ USB Host và lưu ý rằng thiết lập GPIO có thể khác và có thể cần được định cấu hình lại trong tệp .ioc.
CẢNH BÁO - DỰ ÁN NÀY CÓ BẰNG ĐIỆN ÁP CAO CÓ THỂ GÂY RA THƯƠNG HIỆU NGHIÊM TRỌNG HOẶC TỬ THẦN. VUI LÒNG LẤY TẤT CẢ CÁC THẬN TRỌNG CẦN THIẾT, VÀ TẮT TẤT CẢ NGUỒN ĐIỆN VÀO MẠCH TRƯỚC KHI LÀM VIỆC TRÊN ĐÓ.
Kết nối rơ le
Hãy cẩn thận: Luôn luôn rất cẩn thận khi thử nghiệm với AC, điện giật có thể dẫn đến thương tích nghiêm trọng! THÔNG BÁO VỀ RỦI RO; TỪ CHỐI TRÁCH NHIỆM PHÁP LÝ
Sơ đồ chân và kết nối với STM32 Đối với phần DC của mạch Rơ le, kết nối S (tín hiệu) với chân PE4 trên bo mạch STM32 NUCLEO, cũng kết nối Nguồn cấp (+) và nối đất (-) với + 5V và GND tương ứng.
Giới thiệu về mã code:
Bạn có thể lấy dự án TẠI ĐÂY
https://github.com/smart-sensor-devices-ab/stm32_bleuio_lightbulb_example
Dự án này dựa trên dự án STM32 trước đây của chúng tôi (https://github.com/smart-sensor-devices-ab/stm32_bleuio_example) với những thay đổi này trong tệp .ioc:
Trong chế độ xem sơ đồ chân, chúng tôi đặt GPIO PE4 thành OUTPUT và gắn nhãn nó thành 'lightbulb'.
Trong hàm USBH_CDC_ReceiveCallback trong USB_HOST \ usb_host.c, chúng tôi sao chép CDC_RX_Buffer vào một biến bên ngoài có tên là dongle_response có thể truy cập được từ tệp main.c.
void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost)
{
if(phost == &hUsbHostFS)
{
// Handles the data recived from the USB CDC host, here just printing it out to UART
rx_size = USBH_CDC_GetLastReceivedDataSize(phost);
HAL_UART_Transmit(&huart3, CDC_RX_Buffer, rx_size, HAL_MAX_DELAY);
// Copy buffer to external dongle_response buffer
strcpy((char *)dongle_response, (char *)CDC_RX_Buffer);
memset(CDC_RX_Buffer,0,RX_BUFF_SIZE);
USBH_CDC_Receive(phost, CDC_RX_Buffer, RX_BUFF_SIZE);
}
return;
}
In main.c we create a simple intepreter so we can react to the data we are recieving from the dongle.
/**
* @brief Simple dongle interpreter
* @retval None
*/
void dongle_interpreter(uint8_t * input)
{
if(strlen((char *)input) != 0)
{
if(strstr((char *)input, "\r\nADVERTISING...") != NULL)
{
isAdvertising = true;
}
if(strstr((char *)input, "\r\nADVERTISING STOPPED.") != NULL)
{
isAdvertising = false;
}
if(strstr((char *)input, "\r\nCONNECTED") != NULL)
{
isConnected = true;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET);
}
if(strstr((char *)input, "\r\nDISCONNECTED") != NULL)
{
isConnected = false;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
}
if(strstr((char *)input, "L=0") != NULL)
{
isLightBulbOn = false;
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_RESET);
writeToDongle((uint8_t*)DONGLE_SEND_LIGHT_OFF);
uart_buf_len = sprintf(uart_tx_buf, "\r\nLight bulb is %s\r\n", isLightBulbOn ? "on":"off");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
if(strstr((char *)input, "L=1") != NULL)
{
isLightBulbOn = true;
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_SET);
writeToDongle((uint8_t*)DONGLE_SEND_LIGHT_ON);
uart_buf_len = sprintf(uart_tx_buf, "\r\nLight bulb is %s\r\n", isLightBulbOn ? "on":"off");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
}
memset(&dongle_response, 0, RSP_SIZE);
}
We also update the handleUartInput function so we can have manual control over the light bulb via the UART.
/**
* @brief Simple uart input handler
* @retval None
*/
void handleUartInput(UARTCommandTypeDef cmd)
{
switch(cmd)
{
case UART_RX_0:
{
// 0
uart_buf_len = sprintf(uart_tx_buf, "\r\n(0 pressed)\r\n");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
if(isBleuIOReady)
{
writeToDongle((uint8_t*)DONGLE_CMD_ATI);
} else
{
uart_buf_len = sprintf(uart_tx_buf, BLEUIO_NOT_READY_MSG);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_1:
{
// 1
uart_buf_len = sprintf(uart_tx_buf, "\r\n(1 pressed light bulb on!)\r\n");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_SET);
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_2:
{
// 2
uart_buf_len = sprintf(uart_tx_buf, "\r\n(2 pressed light bulb off!)\r\n");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_RESET);
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_NONE:
{
break;
}
default:
{
uartStatus = UART_RX_NONE;
break;
}
}
}
We put the intepreter function inside the main loop.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_USB_HOST_Process();
/* USER CODE BEGIN 3 */
// Simple handler for uart input
handleUartInput(uartStatus);
// Inteprets the dongle data
dongle_interpreter(dongle_response);
// Starts advertising as soon as the Dongle is ready.
if(!isAdvertising && !isConnected && isBleuIOReady)
{
HAL_Delay(200);
writeToDongle((uint8_t*)DONGLE_CMD_AT_ADVSTART);
isAdvertising = true;
}
}
/* USER CODE END 3 */
Cách thiết lập dự án
Tải xuống dự án từ GitHub
Nhận dự án tại đây
https://github.com/smart-sensor-devices-ab/stm32_bleuio_lightbulb_example
Sao chép dự án hoặc tải xuống dưới dạng tệp zip và giải nén nó vào không gian làm việc STM32CubeIDE của bạn.
Nhập như một dự án hiện có
Đảm bảo rằng bạn đã chọn không gian làm việc của mình trong 'Chọn thư mục gốc:'
Bạn sẽ thấy dự án “stm32_bleuio_example”, hãy kiểm tra và nhấp vào ‘Hoàn tất’.
Chạy ví dụ
Trong STMCubeIDE nhấp vào biểu tượng cái búa để xây dựng dự án.
Mở ‘Cổng COM ảo STMicroelectronics STLink’ bằng chương trình mô phỏng thiết bị đầu cuối nối tiếp như TeraTerm, Putty hoặc CoolTerm.
Tốc độ truyền: 115200
Số bit dữ liệu: 8
Tính chẵn lẻ: Không có
Dừng bit: 1
Kiểm soát dòng chảy: Không có
Kết nối BleuIO Dongle trước khi chạy ví dụ.
Trong STMCubeIDE, hãy nhấp vào nút phát màu xanh lục để nhấp nháy và chạy nó trên bảng của bạn. Lần đầu tiên bạn nhấp vào nó, cửa sổ ‘Chạy cấu hình’ sẽ xuất hiện. Bạn chỉ có thể để nguyên như vậy và nhấp vào chạy.
Bạn sẽ được chào đón bởi tin nhắn chào mừng này
Chờ cho đến khi thông báo: “[BleuIO Dongle Ready]” được hiển thị.
Bây giờ bạn có thể kết nối với khóa khác bằng cách sử dụng tập lệnh.
Bạn cũng có thể sử dụng các lệnh uart (0, 1 hoặc 2):
Nhấn 0 để nhận thông tin thiết bị. 1 để bật bóng đèn.
2 để tắt bóng đèn.
Phản hồi dongle sẽ được in tới UART.
Điều khiển ánh sáng từ trình duyệt web
Chúng tôi đã viết một tập lệnh đơn giản kết nối với dongle và gửi tín hiệu để chuyển đổi ánh sáng từ trình duyệt web. Điều này sẽ giúp điều khiển Bóng đèn thông minh bằng STM32 & Javascript.
Để tập lệnh này hoạt động, chúng ta cần
Steps
Tạo một tệp Html đơn giản có tên là index.html, tệp này sẽ đóng vai trò là giao diện người dùng của tập lệnh. Tệp Html này chứa một số nút giúp kết nối và phát tín hiệu đến dongle từ xa, được kết nối với stm32.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous"
/>
<title>Control Light using Bleutooth Low Energy</title>
</head>
<body class="mt-5">
<div class="container mt-5">
<h1 class="mb-5">Control Light using Bleutooth Low Energy</h1>
<button class="btn btn-success" id="connect">Connect</button>
<button class="btn btn-warning" id="lightOn" disabled>Turn On</button>
<button class="btn btn-danger" id="lightOf" disabled>Turn Off</button>
</div>
<div class="container mt-5">
<img id="light" src="light_off.png" alt="" />
</div>
<script src="script.js"></script>
</body>
</html>
Create a js file called script.js and include it at the bottom of the Html file. This js file uses the BleuIO js library to write AT commands and communicate with the other dongle.
import * as my_dongle from "bleuio";
const dongleToConnect = "[0]40:48:FD:E5:35:A5";
import lightOnImg from "./light_on.png";
import lightOfImg from "./light_off.png";
document.getElementById("connect").addEventListener("click", function () {
my_dongle.at_connect();
document.getElementById("lightOn").disabled = false;
document.getElementById("lightOf").disabled = false;
document.getElementById("connect").disabled = true;
});
document.getElementById("lightOn").addEventListener("click", function () {
my_dongle
.ati()
.then((data) => {
//make central if not
if (JSON.stringify(data).includes("Peripheral")) {
console.log("peripheral");
my_dongle.at_central().then((x) => {
console.log("central now");
});
}
})
.then(() => {
// connect to dongle
my_dongle
.at_getconn()
.then((y) => {
if (JSON.stringify(y).includes(dongleToConnect)) {
console.log("already connected");
} else {
my_dongle.at_gapconnect(dongleToConnect).then(() => {
console.log("connected successfully");
});
}
})
.then(() => {
// send command to control light
my_dongle.at_spssend("L=1").then(() => {
console.log("Turned on");
document.getElementById("light").src = lightOnImg;
});
});
});
});
document.getElementById("lightOf").addEventListener("click", function () {
my_dongle
.ati()
.then((data) => {
//make central if not
if (JSON.stringify(data).includes("Peripheral")) {
console.log("peripheral");
my_dongle.at_central().then((x) => {
console.log("central now");
});
}
})
.then(() => {
// connect to dongle
my_dongle
.at_getconn()
.then((y) => {
if (JSON.stringify(y).includes(dongleToConnect)) {
console.log("already connected");
} else {
my_dongle.at_gapconnect(dongleToConnect).then(() => {
console.log("connected successfully");
});
}
})
.then(() => {
// send command to control light
my_dongle.at_spssend("L=0").then(() => {
console.log("Turned off");
document.getElementById("light").src = lightOfImg;
});
});
});
});
Tập tin js script có ba hành động nút; kết nối và điều khiển ánh sáng.
Bây giờ chúng ta cần biết ID của dongle khác được kết nối với STM32 để chúng ta có thể kết nối với nó. Bạn có thể sử dụng thiết bị đầu cuối web này để lấy ID dongle.
Mở trang web này https://bleuio.com/web_terminal.html và nhấp vào kết nối với dongle.
Chọn cổng thích hợp để kết nối.
Khi nó thông báo đã kết nối, hãy nhập “ATI”. Điều này sẽ hiển thị thông tin dongle và trạng thái hiện tại.
Nếu dongle ở vai trò ngoại vi, hãy đặt nó thành trung tâm bằng cách gõ “AT + CENTRAL”
Bây giờ, hãy quét khoảng trống bằng cách nhập “AT + GAPSCAN”
Sau khi bạn nhìn thấy thiết bị bảo vệ phần mềm của mình trên danh sách, hãy dừng quá trình quét bằng cách nhấn Control + c
Sao chép ID và dán vào dòng số 2 của tập lệnh (script.js)
Bạn sẽ cần một trình gói web. Bạn có thể sử dụng parcel.js
Sau khi cài đặt parcel js, hãy chuyển đến thư mục gốc và nhập “parcel index.html”. Điều này sẽ bắt đầu môi trường phát triển của bạn.
Mở tập lệnh trên trình duyệt bằng cách sử dụng bưu kiện js.
Bạn có thể dễ dàng kết nối với dongle và bật-tắt đèn từ đó.
Đây là cách bạn có thể tạo Bóng đèn thông minh hỗ trợ BLE bằng Vi điều khiển STM32 & Javascript.