An offline voice recognition hub, no internet connection, no wifi router. Just a pair of ESP8266 with ESPNOW protocol running on them. This is what I want in my room. The devices can either be controlled by pressing switches or by voice. A central hub like alexa is there to respond to your commands. And this is the article which explains how things work. The idea comes to mind when I am operating my lab lights with an IR remote, this can be seen in one of the very previous articles I have made. Then to switch a little bit towards smart home keeping every data personal at my end, I made a plan to keep it offline. As I already have a voice recognition module lane around from DF, Gravity: Offline Language Learning Voice Recognition.
I also made a getting started tutorial on this module which can be seen from here. It explains types of commands and pre- programming required for the sensor. Although the current article provides all the required information. I made a solid state relay PCB to use this with AC mains.
Big thanks to PCBWay for sponsoring the PCBs for this project! Their high-quality manufacturing and quick turnaround made this build possible.
Offline Voice recognition module:This offline speech recognition sensor is built around an offline voice recognition chip, which can be directly used without an internet connection. It comes with 121 built-in fixed command words and supports the addition of 17 custom command words.
This small sensor can be interfaced with any microcontroller board and then different actions can be performed over voice. It will be the same as Alexa but with much more restricted commands and answers. Because overall it is a small ML model working on a little microcontroller. Some popular applications are such as various smart home appliances, toys, lighting fixtures, and robotics projects, among others.
Types of commands:I will try to keep it as simple as possible, I will divide all the words in 3 sections as per action. See the block diagram given below.
1)Wake-Up words: The wake-up word refers to the word that switches a product from standby mode to operational mode. It is the first command which is given to wake the module. It is similar to saying “Alexa”, “Hey Siri”, “OK Google”. Same as that here the default wake up word is “Hello Robot” and it is the default one. We can also add one more wake work which is demonstrated below as “JARVIS”.
2)Command words: Fixed command words refers to the designated vocabulary used by users to issue specific instructions. Here these words are essential because, after all, this is an offline module and does not have external data/server from the internet to process. So these are the already processed, trained words which are stored in the memory of the module and whenever triggered produce the corresponding ID, which can be used to specify the different actions later on. There are a total of 121 words which are already defined for specific functions over different ID’s.
Now whenever working on a project it is not always good luck that these commands work for you. Means sometimes we need some other commands. Which is possible to do here, known as a custom command word. And there are a total of 17 Custom command words you can train the model on. See all commands from here.
3)Learning Related Commands (Control Commands): These are the command words which are used to interact with the Machine learning model. These are the Controlling commands which initiates the learning and deleting of Wake-up words and command words.
ESP-NOW is a wireless communication protocol based on the data-link layer, which reduces the five layers of the OSI model to only one. This way, the data need not be transmitted through the network layer, the transport layer, the session layer, the presentation layer, and the application layer. Also, there is no need for packet headers or unpackers on each layer, which leads to a quick response reducing the delay caused by packet loss in congested networks. More details about the protocol can be found on the official website.
System Integration, Local and wireless host:The idea is to first connect the local host to an offline voice recognition module and connect the wireless host over ESPNOW. In this way multiple GPIOs can be used to control different appliances. In this way multiple wireless hosts can be connected to the network and the central local voice recognition hub sends commands to each of them in order to switch ON/OFF. But that is the topic for another day.
Code for Transmitter ESP:In the code below, the transmitter (local host) has two control units, defined as CAMERA and SPEAKER. And four control units LIGHT OSCILLOSCOPE SOLDER POWER for wireless (receiver) hosts. The circuit diagram explaining the connection can be used for the reference.
// Modified by Sagar saini 10-4-2025
// No license required.
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Wire.h>
#include "DFRobot_DF2301Q.h"
#define camera 14 // d5
#define speaker 12 // d6
//I2C communication
DFRobot_DF2301Q_I2C DF2301Q;
int btn1State = 0; // LIGHT
int btn2State = 0; // OSCILLOSCOPE (2PIN)
int btn3State = 0; // SOLDER
int btn4State = 0; // POWER
//int btn5State = 0; // SPEAKER (LOCAL)
//int btn6State = 0; // CAMERA (LOCAL)
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xA8, 0x48, 0xFA, 0xE2, 0x43, 0xC7};
// Structure to declare variables
typedef struct myStruct {
int a;
int b;
int c;
int d;
} myStruct;
// Create a myStruct object called structObj
myStruct structObj;
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
if (sendStatus == 0){
Serial.println("Delivery success");
}
else{
Serial.println("Delivery fail");
}
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
while( !( DF2301Q.begin() ) ) {
Serial.println("Communication with device failed, please check connection");
delay(3000);
}
Serial.println("Begin ok!");
DF2301Q.setVolume(10);
DF2301Q.setMuteMode(0);
DF2301Q.setWakeTime(25);
uint8_t wakeTime = 0;
wakeTime = DF2301Q.getWakeTime();
Serial.print("wakeTime = ");
Serial.println(wakeTime);
// DF2301Q.playByCMDID(1); // Wake-up command
DF2301Q.playByCMDID(23); // Common word ID
pinMode(camera, OUTPUT);
pinMode(speaker, OUTPUT);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); //set role
esp_now_register_send_cb(OnDataSent); //set callback
// Register peer
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
delay(1000);
uint8_t CMDID = 0;
CMDID = DF2301Q.getCMDID();
if(0 != CMDID) {
Serial.print("CMDID = ");
Serial.println(CMDID);
}
if(CMDID == 82) { //RESET
btn1State = 100;
btn2State = 100;
btn3State = 100;
btn4State = 100;
}
if(CMDID == 6) { //GOODBYE
btn1State = 200;
btn2State = 200;
btn3State = 200;
btn4State = 200;
}
if(CMDID == 103) { // TURN ON THE LIGHT
btn1State = 100;
}
if(CMDID == 104) { // TURN OFF THE LIGHT
btn1State = 200;
}
if(CMDID == 7) { // POWER ON
btn4State = 100;
}
if(CMDID == 8) { // POWER OFF
btn4State = 200;
}
if(CMDID == 9) { // SOLDER ON
btn3State = 100;
}
if(CMDID == 10) { // SOLDER OFF
btn3State = 200;
}
if(CMDID == 80) { // START OSCILLATING
btn2State = 100;
}
if(CMDID == 81) { // STOP OSCILLATING
btn2State = 200;
}
if(CMDID == 73) { // TURN ON THE CAMERA // GPIO 14
digitalWrite(camera, HIGH);
}
if(CMDID == 74) { // TURN OFF THE CAMERA
digitalWrite(camera, LOW);
}
if(CMDID == 90) { // TURN ON THE SPEAKER // GPIO 12
digitalWrite(speaker, HIGH);
}
if(CMDID == 91) { // TURN OFF THE SPEAKER
digitalWrite(speaker, LOW);
}
structObj.a = btn1State;
structObj.b = btn2State;
structObj.c = btn3State;
structObj.d = btn4State;
// Send message via ESP-NOW
esp_now_send(broadcastAddress, (uint8_t *) &structObj, sizeof(structObj));
delay(1000);
}
Code for Receiver ESP:// Modified by Sagar saini 10-4-2025
// No license required.
#include <ESP8266WiFi.h>
#include <espnow.h>
#define led1 4 // light
#define led2 5 // oscilloscope
#define led3 0 // solder
#define led4 2 // power
// Structure to declare variable
typedef struct myStruct {
int a;
int b;
int c;
int d;
} myStruct;
// Create a myStruct called structObj
myStruct structObj;
// Callback function
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
memcpy(&structObj, incomingData, sizeof(structObj));
// Serial.print("Bytes received: ");
// Serial.println(len);
// Serial.print("D1 button state: ");
// Serial.println(structObj.a);
// Serial.print("D3 button state: ");
// Serial.println(structObj.b);
// Serial.println();
digitalWrite(led1, (structObj.a == 100) ? HIGH : LOW);
digitalWrite(led1, (structObj.a == 200) ? LOW : HIGH);
digitalWrite(led2, (structObj.b == 100) ? HIGH : LOW);
digitalWrite(led2, (structObj.b == 200) ? LOW : HIGH);
digitalWrite(led3, (structObj.c == 100) ? HIGH : LOW);
digitalWrite(led3, (structObj.c == 200) ? LOW : HIGH);
digitalWrite(led4, (structObj.d == 100) ? HIGH : LOW);
digitalWrite(led4, (structObj.d == 200) ? LOW : HIGH);
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); //set role
esp_now_register_recv_cb(OnDataRecv); // set callback
}
void loop() {
}
PCB for Relay Switching AC application:I have designed a solid state relay to connect the receiver esp, in order to control the AC mains. This is a simple and minimal design and designed in a small form factor to be fit in any housing. The main advantage of solid state relay, it will not make such noises. Overall small and control the applications in a better way.
Special thanks to PCBWay for sponsoring the PCBs. Their quality and service are unmatched in the industry! Sign-up now and get free coupons on your next order. All the required files Gerber, BOM and CPL are uplaoded on GITHUB, can be downlaoded from there.
The ESPNOW is good protocol to use wireless, but using it with ESP8266 gives some difficulties, if not properly written in the program it ruins everything. I tested my units many times and was happy to see that they are in working condition every time.
I have tested the voice commands and they are working perfectly, the video for the same is attached here for your reference. The ESPNOW is easy to use just plug and power both ESPs and it will automatically make a connection, see the code for wifi MAC settings. After a successful connection serial prints the same information to validate the connection.
Comments
Please log in or sign up to comment.