Last Updated on : 2024-06-24 06:21:40download
The MCU SDK enables you to interface your MCU with Tuya’s module so that your hardware can be connected to the Tuya Developer Platform and access cloud services. The SDK is specific to the product functions you defined on the platform. It includes basic and advanced feature implementation with samples, making it easier to develop IoT applications. This topic describes how to port the MCU SDK to your hardware platform.
SDK requirements for the MCU are as follows. If your hardware is constrained in resources, you can refer to functions in the SDK and port the protocol yourself.
Memory: 4 KB
RAM: About 100 bytes of the RAM are required, depending on the data length of the data point (DP). If you enable OTA updates, it must be greater than 260 bytes.
Nested function: 9-level.
If you develop with an Arduino development board, see Connect Arduino to Tuya.
Files | Description |
---|---|
mcu_api.c |
Contains functions that can be called. |
mcu_api.h |
Contains declarations for functions in mcu_api.c . |
protocol.c |
Contains functions for processing protocol data. You can add write code to enable your MCU to receive data from the Wi-Fi module. |
protocol.h |
protocol.h contains the following information:
|
system.c |
Contains the implementation of parsing the serial protocol. |
system.h |
system.h contains the following information:
|
wifi.h |
Contains macro definitions for Wi-Fi communication. |
mcu_sdk
for door locks, lock_api.c
and lock_api.h
are included to implement lock functionality.mcu_sdk
for devices with the GPRS feature, the file name of wifi.h
is changed to gprs.h
.protocol.h
.protocol.c
file and the function call.In your original project, initialize the MCU peripherals, including serial port, external interrupt (button), timer (LED indicator), and more.
Copy the .c
and .h
files in the MCU SDK folder to your project directory where other .c
and .h
files are located.
protocol.h
Product information
Define the product ID (PID). PRODUCT_KEY
is the macro defined for the PID. PID is the unique identifier assigned to each product.
#define PRODUCT_KEY "ax23rawjo4np****"
If the PRODUCT_KEY
and the PID are inconsistent, you can go to Hardware Development > Download Documents section, and download the latest SDK.
Define the version number. MCU_VER
defines the software version, which defaults to 1.0.0
. If you enable OTA updates for the MCU firmware, you need to update the MCU version number after the firmware update is installed.
#define MCU_VER "1.0.0"
Define the working mode of the Wi-Fi module. CONFIG_MODE
defines the pairing mode that can be the default mode (switching between AP mode and EZ mode), the safe mode, and the anti-misoperation mode. The anti-misoperation mode is recommended.
The following describes the three modes.
Default mode: The pairing mode can switch between AP mode and EZ mode. If the module is not paired or removed, it will keep a state pending pairing after power on.
#define CONFIG_MODE CONFIG_MODE_DEFAULT
Safe mode: The module does not enter the pairing mode after power on until the MCU sends the reset command. If the module is not paired within a specified time period (three minutes by default), it will automatically exit the pairing mode. You need to repeat the reset process to make the module enter pairing mode again.
#define CONFIG_MODE CONFIG_MODE_LOWPOWER
Anti-misoperation mode: A paired module that is physically reset will resume its network connection if it is not paired within a specified time period (three minutes by default). Similarly, if a device that is physically reset is shut down due to an outage, it will resume its network connection after power on. In this mode, if a user removed a device from the app, the network connection history of this device will be cleared.
#define CONFIG_MODE CONFIG_MODE_SPECIAL
Define the hold-time of the pairing mode. If you select safe mode or anti-misoperation mode, you can enable the macro CONFIG_MODE_DELAY_TIME
and set the hold-time of the pairing mode. The hold-time can be between 3 and 10 minutes. If you do not enable this macro, the hold-time defaults to three minutes.
#define CONFIG_MODE_DELAY_TIME 10
Specify a pairing mode. You can set the coexistence of EZ mode and AP mode or only AP mode available through CONFIG_MODE_CHOOSE
.
0
: indicates the coexistence of EZ mode and AP mode. This way, it is not necessary to switch between modes.
#define CONFIG_MODE_CHOOSE 0
1
: indicates only AP mode is supported.
#define CONFIG_MODE_CHOOSE 1
Set the infrared feature. You can set the TX and RX pins used for the infrared feature through ENABLE_MODULE_IR_FUN
.
//#define ENABLE_MODULE_IR_FUN // Enable the infrared feature.
#ifdef ENABLE_MODULE_IR_FUN
#define MODULE_IR_PIN_TX 5 // TX pin of infrared.
#define MODULE_IR_PIN_RX 12 // RX pin of infrared.
#endif
Set low power mode. You can enable low power mode through LONG_CONN_LOWPOWER
, which is disabled by default.
//#define LONG_CONN_LOWPOWER 0 // Disable low power mode.
//#define LONG_CONN_LOWPOWER 1 // Enable low power mode.
(Optional) OTA updates
Enable OTA updates. To support OTA firmware updates, define SUPPORT_MCU_FIRM_UPDATE
. OTA updates are disabled by default.
#define SUPPORT_MCU_FIRM_UPDATE
Define the size of a single packet.
#ifdef SUPPORT_MCU_FIRM_UPDATE
#define PACKAGE_SIZE 0 // One update package is 256 bytes.
//#define PACKAGE_SIZE 1 // One update package is 512 bytes.
//#define PACKAGE_SIZE 2 // One update package is 1024 bytes.
#endif
For more information about the OTA updates, see OTA Update Guide.
(Optional) Transmit and receive buffer
Serial receive buffer: The buffer size depends on how often the serial data handler is called. If the MCU can quickly process serial data, the buffer size can be reduced.
Serial transmit buffer: The buffer size must be greater than the maximum length of DP data.
Buffer for serial data processing: The buffer size must be greater than the maximum length of DP data. If OTA updates and specific weather services are enabled, the buffer size must be greater than the maximum amount of payload.
/******************************************************************************
3: Define the transmit and receive buffer:
If your MCU has insufficient RAM, you can change the buffer size to 24 bytes.
******************************************************************************/
#ifndef SUPPORT_MCU_FIRM_UPDATE
#define WIFI_UART_RECV_BUF_LMT 16 // The serial receive buffer size, which can be reduced if your MCU has insufficient RAM.
#define WIFI_DATA_PROCESS_LMT 24 // The buffer size for serial data processing. It depends on the amount of DP data but must be greater than 24 bytes.
#else
#define WIFI_UART_RECV_BUF_LMT 128 // The serial receive buffer size, which can be reduced if your MCU has insufficient RAM.
// Set the proper buffer size. Consider the defined update package and specific weather services, if applicable.
#define WIFI_DATA_PROCESS_LMT 300 // The buffer size for serial data processing. When OTA updates are enabled, if you set the size of a single update package to 256 bytes, the buffer size must be greater than 260 bytes. If weather services are also enabled, more buffer is required.
//#define WIFI_DATA_PROCESS_LMT 600 // The buffer size for serial data processing. When OTA updates are enabled, if you set the size of a single update package to 512 bytes, the buffer size must be greater than 520 bytes. If weather services are also enabled, more buffer is required.
//#define WIFI_DATA_PROCESS_LMT 1200 // The buffer size for serial data processing. When OTA updates are enabled, if you set the size of a single update package to 1024 bytes, the buffer size must be greater than 1030 bytes. If weather services are also enabled, more buffer is required.
#endif
#define WIFIR_UART_SEND_BUF_LMT 48 // It depends on the amount of DP data but must be greater than 48 bytes.
(Required) Working mode of module
If the reset button and LED indicator for network status are connected to the MCU, the module works with the MCU to process network events, which is most commonly used. You need to comment out the macro WIFI_CONTROL_SELF_MODE
.
//#define WIFI_CONTROL_SELF_MODE // The module processes the reset button and LED indicator itself. If you use an external reset button or LED indicator, disable this macro.
If the reset button and LED indicator for network status are connected to the Wi-Fi module, the module processes network events itself. You need to enable the macro WIFI_CONTROL_SELF_MODE
. Specify the GPIO pins connected to the indicator and the button in the following two macros.
#ifdef WIFI_CONTROL_SELF_MODE // The module processes network events itself.
#define WF_STATE_KEY 14 // The indicator for network status. Set it according to your circuit.
#define WF_RESERT_KEY 0 // The button for Wi-Fi module reset. Set it according to your circuit.
#endif
(Optional) Production test feature
The production test feature for the Wi-Fi module is enabled by default. To help you smoothly and efficiently carry out mass production, it is recommended to enable the production test feature.
#define WIFI_TEST_ENABLE // Enable the production test feature.
For more information, see Production Test Guide.
(Optional) Weather services
After the module is connected to the router, you can define WEATHER_ENABLE
to enable weather services. Once the module is connected to the cloud, the server sends weather data immediately and then every 30 minutes.
Enable weather services. Define WEATHER_ENABLE
.
//#define WEATHER_ENABLE // Enable weather services.
Specify the supported weather service. You can select the supported weather parameters from the weather_choose
array in the protocol.c
file.
#ifdef WEATHER_ENABLE
/**
* @var weather_choose
* @brief The array of weather parameters.
* @note You can define the supported parameters and comment out the undesired ones.
*/
const char *weather_choose[WEATHER_CHOOSE_CNT] = {
"temp",
"humidity",
"condition",
"pm25",
/*"pressure",
"realFeel",
"uvi",
"tips",
"windDir",
"windLevel",
"windSpeed",
"sunRise",
"sunSet",
"aqi",
"so2 ",
"rank",
"pm10",
"o3",
"no2",
"co",*/
};
#endif
Specify the number of supported weather conditions. Define the number of supported weather conditions in WEATHER_CHOOSE_CNT
.
#define WEATHER_CHOOSE_CNT 4
Specify the number of days for which the server returns forecast data. The module with the new version of the firmware supports a 7-day weather forecast. You can define the number of days for which the server returns forecast data in the macro WEATHER_FORECAST_DAYS_NUM
.
1
: returns the weather of the current day.0
or greater than 7
: The module returns an error. Weather services failed to be enabled.#define WEATHER_FORECAST_DAYS_NUM 1
The weather data sent by the module contains information about the forecast days. 0
indicates the current day.
(Optional) Streaming service
Streaming service suits the needs of the MCU on the robot vacuum to transmit a large amount of data. You can enable this service through WIFI_STREAM_ENABLE
.
//#define WIFI_STREAM_ENABLE
(Optional) Other features
You can complete corresponding functions to implement specific features.
protocol.c
file and function callsCopy the wifi.h
file to the folder where Wi-Fi files are stored, such as the main.c
folder.
Call wifi_protocol_init()
function in the mcu_api.c
file after the MCU serial port and other peripherals are initialized.
Specify the serial transmission function in uart_transmit_output
in the protocol.c
file, and delete #error
.
Example:
/**
* @brief Send serial data
* @param[in] {value} The one byte of data to be sent by UART.
* @return Null
*/
void uart_transmit_output(unsigned char value)
{
//#error "Specify the UART transmission function and delete this line"
UART3_SendByte(value);
/*
//Example:
extern void Uart_PutChar(unsigned char value);
Uart_PutChar(value); // Serial port transmitting function
*/
}
In the interrupt handler for serial data reception, call uart_receive_input
in the mcu_api.c
file. Use the returned value as the parameter.
Example:
void USART3_IRQHandler(void)
{
unsigned char Res=0;
if((USART3->SR&UART_FLAG_RXNE) != 0)
{
Res=USART3->DR;
uart_receive_input(Res);
}
}
After the MCU runs in the while(1)
loop, it calls the wifi_uart_service()
function in the mcu_api.c
file. The sample code in main.c
is as follows:
#include "wifi.h"
...
void main(void)
{
wifi_protocol_init();
...
while(1)
{
wifi_uart_service();
...
}
...
}
The MCU must directly call wifi_uart_service()
function in the mcu_api.c
file in the while(1)
loop. After the program is initialized, if an interrupt service routine (ISR) is necessary, you must keep it as short as possible and do not call the data reporting function to avoid loss of data.
The DP supports six data types.
Types | Description |
---|---|
Boolean | Used for DPs of switch products, such as the switch, ECO, and screen. |
Enum | Used for DPs that have multiple kinds of status, such as working mode, fan speed, and swing direction. |
Value | Used for DPs that have integer values, such as temperature and battery level. |
fault | Used for reporting device faults, denoted in bitmap format. |
string | Used for DPs of string type. Used for DPs that transmit data in string format. You can choose this string type if other data types are not applicable. |
Raw | Used for DPs that have no requirements for data format, transmitting raw data either in plaintext or encrypted text. The data format, packet, and data parsing must be unified in the sender and the receiver. |
Scenario 1: Report data of all DPs
After the module is restarted or paired again, it will initiate a status query. The MCU must return the status of all DPs.
Open protocol.c
and find the function all_data_update(void)
.
Specify the initial values in corresponding functions for all DPs to be reported. These values will be displayed on the control panel in the app.
Do not call all_data_update()
because this function will be called at the specified time.
/**
* @brief Upload the status of all DPs for synchronization with the app.
* @param Null
* @return Null
* @note The MCU implements the data reporting in this function, which must support two data transfer types, namely send only as well as send and report.
*/
void all_data_update(void)
{
//#error "Complete the example of two data transfer types and delete this line"
/*
// This code is automatically generated. You need to edit it based on the actual DPs.
mcu_dp_bool_update(DPID_SWITCH,current on/off status); // Report Boolean data
mcu_dp_value_update(DPID_TEMP_SET,current temperature setting); // Report value data
mcu_dp_value_update(DPID_TEMP_CURRENT,current temperature); // Report value data
mcu_dp_enum_update(DPID_MODE,current mode); // Report enum data
mcu_dp_enum_update(DPID_FAN_SPEED_ENUM,current speed); // Report enum data
mcu_dp_enum_update(DPID_STATUS,current status); // Report enum data
mcu_dp_bool_update(DPID_ECO,current ECO mode); // Report Boolean data
mcu_dp_bool_update(DPID_DRYING,current drying mode); // Report Boolean data
mcu_dp_bool_update(DPID_VENTILATION,current ventilation mode); // Report Boolean data
mcu_dp_bool_update(DPID_HEAT,current auxiliary heat); // Report Boolean data
mcu_dp_bool_update(DPID_LIGHT,current light); // Report Boolean data
mcu_dp_bool_update(DPID_CHILD_LOCK,current child lock); // Report Boolean data
mcu_dp_bool_update(DPID_BEEP,current beep); // Report Boolean data
mcu_dp_value_update(DPID_HUMIDITY_SET,current humidity setting); // Report value data
mcu_dp_value_update(DPID_HUMIDITY_CURRENT,current humidity); // Report value data
mcu_dp_enum_update(DPID_TEMP_UNIT_CONVERT,current temperature unit conversion); // Report enum data
mcu_dp_enum_update(DPID_COUNTDOWN_SET,current countdown); // Report enum data
mcu_dp_value_update(DPID_COUNTDOWN_LEFT,time remaining of current countdown); // Report value data
mcu_dp_fault_update(DPID_FAULT,current fault alert); // Report fault data
mcu_dp_value_update(DPID_TEMP_CURRENT_F,current temperature in °F); // Report value data
mcu_dp_value_update(DPID_TEMP_SET_F,current temperature setting in °F); // Report value data
mcu_dp_bool_update(DPID_SLEEP,current sleep feature); // Report Boolean data
mcu_dp_bool_update(DPID_CLEANING,current self-cleaning); // Report Boolean data
mcu_dp_bool_update(DPID_SWITCH_VERTICAL,current vertical swing); // Report Boolean data
mcu_dp_enum_update(DPID_GEAR_VERTICAL,current vertical swing level); // Report enum data
mcu_dp_value_update(DPID_ANGLE_VERTICAL,current vertical swing angle); // Report value data
mcu_dp_bool_update(DPID_SWITCH_HORIZONTAL,current horizontal swing); // Report Boolean data
mcu_dp_enum_update(DPID_GEAR_HORIZONTAL,current horizontal swing level); // Report enum data
mcu_dp_value_update(DPID_ANGLE_HORIZONTAL,current horizontal swing angle); // Report value data
mcu_dp_bool_update(DPID_DISPLAY,current screen display switch); // Report Boolean data
*/
}
Scenario 2: Report a single DP
When the status of a single DP changes, the MCU must actively report the current DP status to sync with the app. The data format is mcu_dp_xxxx_updata(DPID_X,n)
, where DPID_X
is the DP whose status changes. You can call each function in all_data_update()
individually.
Example:
mcu_dp_bool_update(DPID_SWITCH,1); // Report Boolean data
mcu_dp_value_update(DPID_TEMPER_SET,25); // Report value data
mcu_dp_string_update(DPID_DAY,"1234",4); // Report string data
Scenario 3: Send DP commands
In protocol.c
, each DP that can send control commands has an individual command handler. The format is dp_download_xxx_handle()
, where xxx
is the DP that can send commands. After the function parses the DP, the MCU will execute commands accordingly. Take the received switch DP data as an example:
/*****************************************************************************
Function name: dp_download_switch_handle
Feature description: a processing function for `DPID_SWITCH`.
Input parameters: value indicates the data source
length: the length of the data
Return parameters: Returns SUCCESS on success, and ERROR on failure.
Note: For the type of send and report, the module must return the result to the cloud for synchronization with the app.
*****************************************************************************/
static unsigned char dp_download_switch_handle(const unsigned char value[], unsigned short length)
{
// For example, a DP of Boolean type
unsigned char ret;
// 0: indicates off. 1: indicates on.
unsigned char switch1;
switch1 = mcu_get_dp_download_bool(value,length);
if(switch1 == 0)
{
// The switch is off.
MCU_OFF_switch1();
}
else
{
// The switch is on.
MCU_ON_switch1();
}
// Feedback after a command is executed
ret = mcu_dp_bool_update(DPID_SWITCH,switch1);
if(ret == SUCCESS)
return SUCCESS;
else
return ERROR;
}
If the change of device status is not triggered by control commands, the MCU will call mcu_dp_bool_update(DPID_SWITCH_1,switch_1);
to upload the current status of the DP for feedback. You can also choose the reporting time as needed.
The function of pairing and LED indicator is required only when the module works with the MCU to process network events.
To implement device pairing, add the pairing command and LED indicator function. If the module works with the MCU to process network events, you can customize the ways to pair devices and indicate pairing status. Generally, you can set the keypress trigger and LED indication.
Two pairing modes are available.
We recommend that you implement both modes to handle different scenarios.
Command of device pairing
You can implement the pairing command through two functions mcu_reset_wifi()
and mcu_set_wifi_mode()
, which are called in the button processing function after pairing is triggered by button-press.
mcu_reset_wifi()
Call this function to reset the Wi-Fi module. All the pairing information will be cleared after a reset. Each time mcu_reset_wifi()
is called, the pairing mode is toggled from AP mode to EZ mode or EZ mode to AP mode.
mcu_set_wifi_mode()
It has two parameters SMART_CONFIG
and AP_CONFIG
. After the function is called, all pairing information will be cleared and the module enters EZ mode or AP mode.
Pairing guide
To get Wi-Fi module’s network status, call mcu_get_wifi_work_state()
during while(1)
loop. Write the blinking mode of the LED indicator according to the network status.
Network status | Description | Status value | LED indicator |
---|---|---|---|
Status 1 | Pair a device in EZ mode. | 0x00 | The LED blinks quickly at an interval of 250 milliseconds. |
Status 2 | Pair a device in AP mode. | 0x01 | The LED blinks slowly at an interval of 1,500 milliseconds. |
Status 3 | The Wi-Fi network is set up, but the device is not connected to the router. | 0x02 | The LED is off. |
Status 4 | The Wi-Fi network is set up, and the device is connected to the router. The device can be controlled over a local area network (LAN). | 0x03 | The LED indicator is steady on. |
Status 5 | The device is connected to the router and the cloud. The device can be controlled over a local area network (LAN) or from the cloud. | 0x04 | The LED indicator is steady on. |
Status 6 | The Wi-Fi device is in low power mode. | 0x05 | The LED is off. |
Status 7 | EZ mode and AP mode coexist. | 0x06 | The LED blinks quickly at an interval of 250 milliseconds. |
Call mcu_get_wifi_work_state()
to get connection status.
void main(void)
{
...
while(1)
{
...
switch(mcu_get_wifi_work_state())
{
case SMART_CONFIG_STATE:
// In EZ mode, the LED flickers quickly.
break;
case AP_STATE:
// In AP mode, the LED flickers slowly.
break;
case WIFI_NOT_CONNECTED:
// The Wi-Fi network has been set up and is connecting to the router. The LED is off.
break;
case WIFI_CONNECTED:
// The Wi-Fi network is connected to the router. The LED is steady on.
break;
default:break;
}
...
}
}
The production test supports three test items. You can select them as needed.
For more information, see Production Test Guide.
Data communication must start after the initialization is completed.
For more information about the frame format, see Frame format description.
After the MCU and the module are powered on, the initialization configuration starts. Initialization communication includes but is not limited to:
Heartbeat
A heartbeat is a type of communication packet between the module and the MCU to check whether the communication was lost. We recommend that the frame of the first communication between the MCU and the module be used as the heartbeat. The communication can work properly only when the heartbeat is sent and responded successfully.
Query product information.
After the module builds communication with the MCU, it will query the MCU firmware version and the following information.
Set working mode of the module
The module works with the MCU to process the network event or processes it itself. The working mode is determined by the hardware connection of the LED indicator and reset button on the Wi-Fi module.
The following block diagram shows the initialization communication.
In the following two network states, the device can report DP data to and receive DP commands from the app.
This section describes the OTA data communication between the MCU and the Wi-Fi module.
File download works the same way as OTA data communication.
OTA starts
When the Wi-Fi module detects an MCU update, it will send a command to start updates.
OTA data transmission starts
After sending a package, if the Wi-Fi module does not receive a response from the MCU within five seconds, it will resend the package three times. If the MCU still does not respond, the OTA updates fail.
OTA transmission is completed
You can determine whether the OTA transmission is completed in the following two ways.
0x0004
, indicating the packet is zero bytes.We recommend using both ways to verify OTA transmission.
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback