无论是因为睡得怪怪的、玩手机太多,还是弯腰坐着盯着电脑看几个小时,我们大多数人都会时不时地处理脖子上的扭结。缓解颈部疼痛的最佳方法之一是按摩疗法。因此,我们改造了传统的颈部按摩器,让它变得聪明,轻松消除压力。
颈部放松按摩器结合了中国传统理疗中的多种按摩手法,采用低频电脉冲技术模拟真人按摩。能促进局部血液循环,有效缓解颈部疲劳和肌肉紧张。由于我们已经使这款按摩器支持物联网,因此我们只需一部手机即可控制它。
使用涂鸦智能或智能生活应用程序实现远程控制,我们使用涂鸦的BTU 网络模块作为微控制器。
电路由BTU模块、电池充电、语音播放、按键检测、低频脉冲电流输出、加热、温度检测等部分组成。
NTC热敏电阻是环氧树脂涂层的小尺寸,用于温度测量。它具有电阻范围广、精度稳定性和灵敏度高、响应速度快等特点。对于热敏电阻的参数,我们使用:B=3950,R=10k。
模块的 ADC 收集电压并将其转换为温度值。然后,模块相应地调整温度。
白线是发热丝。
模块上的P7输出PWM波来调节电热丝的温度。当 P7 输出低电平时,加热关闭。当 P7 以某个频率输出方波时,发热处于低水平。当 P7 输出高电平时,加热处于高电平。
在单线串口模式下,BTU模块可以通过DATA线控制和发送数据到语音芯片,进行语音播放、停止、循环等。
按摩器上有两个不锈钢电极垫。
低频脉冲电流输出
P24 和 P9 输出的脉冲是对称的。这两个引脚不能同时输出高电平。
P17 输出高电平。它输出两个低频对称脉冲。
P17 输出低电平。它输出两个低频对称脉冲。
P24 和 P9 输出的脉冲是不对称的。PB5 和 PCO 都输出高电平。
二极管D4参数
我们买了一块700毫安的锂聚合物电池,额定电压为3.7V,充电电压为4.2V。内置保护电路,防止过充、过放、过流、短路。
尺寸:10 毫米(厚)x 23 毫米(宽)x 30 毫米(长)
电池充电器电路和升压电路
本节介绍如何在涂鸦IoT平台上创建智能颈椎按摩器。有关详细信息,请参阅创建产品。
1.登录涂鸦IoT平台。
2.在标准类别选项卡上,单击运动与健康>运动与健康。填写产品信息并选择蓝牙作为协议。
3.点击创建后,出现添加标准函数对话框。保留三个选定的所需功能。在自定义函数部分中,单击添加并创建两个函数。有关要设置的项目,请参见下面的屏幕截图。
4.在设备面板步骤中,选择DIY风格面板。然后,进入硬件开发,选择涂鸦标准模块 SDK和BT3L 蓝牙模块。单击屏幕右侧的获取 10 个免费许可证。您将在编码中获得 UUID、密钥和 MAC 地址。
README.md
.安装 IDE 后,导入您的项目。
2.编辑auth_key
、device_id
和mac
。
3.编译代码。
1.8258
选择芯片类型和EVK
下载模式。单击文件并选择bin
要下载到开发板的文件,该文件位于tuya_ble_sdk_Demo_Project_tlsr8253\telink_kite_ble_sdk_v3.4.0_20190816\ble_sdk_multimode\8258_module\8258_module.bin
.
2.下载后点击Reset运行。
3.我们使用泰凌的作家。将板上的 SWM 接头连接到写入器上的 SWM 接头。
注意:日志打印的引脚默认为TL_C2
,波特率为230400。由于我们没有足够的I/O,我们将日志打印的引脚改为TL_D3
。您可以在编辑后编译代码。配置文件位于tuya_ble_sdk_Demo_Project_tlsr8253\telink_kite_ble_sdk_v3.4.0_20190816\ble_sdk_multimode\vendor\8258_module\app_config.h
. 当 GPIO 读高时,它返回一个大于 1 的值,可能是 1、2 或 128。
在第 47 行:
#define DEBUG_INFO_TX_PIN GPIO_PC2
变成:
#define DEBUG_INFO_TX_PIN GPIO_PD3
电脉冲按摩器采用中国传统物理疗法的电脉冲模拟,可促进血液循环,放松局部肌肉,电极垫设计达到双重按摩效果。
我们实现了五种脉冲模式:智能、放松、主动、敲击和刮擦。
模式 时间间隔 放松模式 30 毫秒 主动模式 20 毫秒 轻敲模式 40 毫秒 抓取模式 50 毫秒 智能模式 20 毫秒、30 毫秒、40 毫秒或 50 毫秒随机生成。
P9 和 P24 控制三极管的开/关以产生电脉冲并启用不同的脉冲模式。
P9 和 P24 输出 PWM 信号,正占空比为 26.5%,周期为 1 ms。注意这两个引脚不能同时输出高电平。否则三极管会烧坏。
以 30 ms 的间隔一次输出四个 PWM 波,以实现放松模式。
一个脉冲有四个 PWM 波,如上图所示。以 30 ms 的间隔产生脉冲。
五种脉冲模式是通过改变脉冲间隔来实现的,如下表所示。
引脚初始化
void pattern_pin_init(void)
{
gpio_set_func(PATTERN_PIN_A, AS_PWM1_N);
gpio_set_func(PATTERN_PIN_B, AS_PWM5);
gpio_set_func(HEAT_PIN, AS_GPIO);
gpio_set_output_en(PATTERN_PIN_A, 1);
gpio_set_output_en(PATTERN_PIN_B, 1);
gpio_set_output_en(HEAT_PIN, 1);
gpio_write(PATTERN_PIN_A, 0);
gpio_write(PATTERN_PIN_B, 0);
// gpio_write(HEAT_PIN, 1);
//PWM0 1ms cycle 26.5% duty 1,000 Hz
pwm_set_mode(PWM1_ID, PWM_NORMAL_MODE);
pwm_set_clk(CLOCK_SYS_CLOCK_HZ, CLOCK_SYS_CLOCK_HZ);
pwm_set_phase(PWM1_ID, 0); // No phase at PWM beginning
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );
pwm_polo_enable(PWM1_ID, 1); // Enable the PWM polarity
pwm_start(PWM1_ID);
// PWM5 1 ms cycle, 26.5% duty 1,000 Hz
pwm_set_mode(PWM5_ID, PWM_NORMAL_MODE);
pwm_set_clk(CLOCK_SYS_CLOCK_HZ, CLOCK_SYS_CLOCK_HZ);
pwm_set_phase(PWM5_ID, 0); // No phase at PWM beginning
pwm_set_cycle_and_duty(PWM5_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (265 * CLOCK_SYS_CLOCK_1US) );
}
GPIO_PC1 (PATTERN_PIN_A)
和电平调整引脚都GPIO_PC2 (BOOST_PIN)
使用 PWM 功能。管脚GPIO_PC1 (PATTERN_PIN_A)
只支持PWM_0
通道,所以GPIO_PC2 (BOOST_PIN)
使用PWM_0
通道。GPIO_PC1 (PATTERN_PIN_A)
使用AS_PWM1_N
通道,因此您只需要编辑pwm_polo_enable(PWM1_ID, 1)
即可更改 PWM 极性。
由于 PWM 波的数量和脉冲间隔是通过时间延迟来实现的,因此会产生误差。程序运行在裸机上,而不是 RTOS,所以这个函数必须while(1)
循环运行。
void switching_pattern(unsigned char pat)
{
if (pat > 4) {
TUYA_APP_LOG_ERROR("*********No such model!!!**********");
}
switch (pat) {
case relieve:
pwm_start(PWM5_ID);
sleep_us(450); // Delay 480 μs to prevent the triode from being burned out.
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (265 * CLOCK_SYS_CLOCK_1US) );
sleep_us(5 * TIME_MS);
pwm_stop(PWM5_ID);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );
sleep_us(30 * TIME_MS);
break;
case vitality:
pwm_start(PWM5_ID);
sleep_us(450);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (265 * CLOCK_SYS_CLOCK_1US) );
sleep_us(5 * TIME_MS);
pwm_stop(PWM5_ID);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );
sleep_us(20 * TIME_MS);
break;
case hammering:
pwm_start(PWM5_ID);
sleep_us(450);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (265 * CLOCK_SYS_CLOCK_1US) );
sleep_us(5 * TIME_MS);
pwm_stop(PWM5_ID);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );
sleep_us(40 * TIME_MS);
break;
case scraping_therapy:
pwm_start(PWM5_ID);
sleep_us(450);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (265 * CLOCK_SYS_CLOCK_1US) );
sleep_us(5 * TIME_MS);
pwm_stop(PWM5_ID);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );
sleep_us(50 * TIME_MS);
break;
case intelligent:
pwm_start(PWM5_ID);
sleep_us(450);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (265 * CLOCK_SYS_CLOCK_1US) );
sleep_us(5 * TIME_MS);
pwm_stop(PWM5_ID);
pwm_set_cycle_and_duty(PWM1_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );
sleep_us(((rand() % 4 + 2) * 10) * TIME_MS); // 20 ms, 30 ms, 40 ms, or 50 ms is generated randomly.
break;
default:
break;
}
return;
}
我们已经实现了五种脉冲模式,接下来是语音提示、加热和电平调节。
WTN6是一款多功能单语音芯片,语音合成4位MCU。
单线串行通讯
在单线串口模式下,BTU模块可以通过DATA线控制和发送数据到语音芯片,进行语音播放、停止、循环等。
引脚 描述 PA1 DATA PA2 BUSY 数据(十六进制) 功能 00H 不播放音频。01H 第一次音频播放。02H 第二次音频播放。…… …… DFH 第 222 段音频播放。
单线串口时序图
将数据线拉低至 5ms,然后发送 8 位数据,先低位,后高位。用高电平与低电平的比值来表示每个数据位的值。
实现代码
void voice_prompt_init(void)
{
gpio_set_func(WTN6_DATA_PIN | WTN6_BUSY_PIN, AS_GPIO);
gpio_set_input_en(WTN6_BUSY_PIN, 1);
gpio_set_output_en(WTN6_DATA_PIN, 1);
gpio_write(WTN6_BUSY_PIN, 0);
}
void voice_playing(uint8_t sb_data)
{
uint8_t s_data, j;
bool b_data;
s_data = sb_data;
gpio_write(WTN6_DATA_PIN, 0);
sleep_us(5000); // Delay 5 ms
b_data = s_data & 0X01;
for (j=0; j<8; j++) {
if (b_data == 1) {
gpio_write(WTN6_DATA_PIN, 1);
sleep_us(600); // Delay 600 μs
gpio_write(WTN6_DATA_PIN, 0);
sleep_us(200); // Delay 200 μs
} else {
gpio_write(WTN6_DATA_PIN, 1);
sleep_us(200); // Delay 200 μs
gpio_write(WTN6_DATA_PIN, 0);
sleep_us(600); // Delay 600 μs
}
s_data = s_data >> 1;
b_data = s_data & 0X01;
}
gpio_write(WTN6_DATA_PIN, 1);
}
指定参数voice_playing(0x01)
以播放离线音频。
我们向上或向下拉 P7 来控制加热的开/关。颈部按摩器有一个内置传感器来检测温度。当温度超过 40°C 时,将关闭加热以避免过热。
int switching_heat(unsigned char warm)
{
if (warm > 1) {
TUYA_APP_LOG_ERROR("*********No such model!!!**********");
}
// printf("wram%d massage_state.heat%d\r\n", warm, massage_state.heat);
switch (warm) {
case strong_heat:
TUYA_APP_LOG_INFO("**********strong_heat************");
gpio_write(HEAT_PIN, 1);
temperature_detection();
break;
case off_heat:
TUYA_APP_LOG_INFO("**********off_heat************");
gpio_write(HEAT_PIN, 0);
break;
default:
break;
}
return 0;
}
/*Temperature detection, which is called when heating feature is in high or low level.*/
int temperature_detection(void)
{
int Rntc = 0, Vcc = 0;
adc_channel_checkout(channel_x1);
Vcc = adc_sample_and_get_result(); // Unit: mV
Rntc = Vcc*R25 / (3300-Vcc);
TUYA_APP_LOG_INFO("Rntc_val=%dΩ", Rntc);
if (Rntc >= 5311) { // NTC resistance value is 5311Ω at 40°C.
TUYA_APP_LOG_WARNING("********High Temperature Warning!!!********");
gpio_write(HEAT_PIN, 0); // When the temperature exceeds 40°C, heating will be turned off.
}
return 0;
}
有关 NTC 温度如何与电阻相关的更多信息,请参阅温度和电阻之间的关系。
按摩器提供从弱到强的 15 级强度。我们使用升压电路实现此功能。
我们可以改变 P8 输出的 PWM 波的正占空比来提升电压。下表列出了具体值。
强度通过按钮调整。单按可增加等级,双按可降低等级。由于 SDK 配置,P8 在固件刷新后模块复位时被拉高。因此,我们需要下拉P8。
void boost_init(void)
{
gpio_set_func(BOOST_PIN, AS_PWM0);
gpio_set_output_en(BOOST_PIN, 1);
// PWM0 1ms cycle
pwm_set_mode(PWM0_ID, PWM_NORMAL_MODE);
pwm_set_clk(CLOCK_SYS_CLOCK_HZ, BOOST_PWM_CLOCK_HZ); // When voltage is stepped up, the frequency of PWM is 16M / (968-1) ≈ 16.55 kHz.
pwm_set_phase(PWM0_ID, 0); // No phase at PWM beginning
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );
pwm_start(PWM0_ID);
}
初始化后,您可以指定占空比的值来升压。
void switching_gear(unsigned char gears)
{
if (gears > 15) {
TUYA_APP_LOG_ERROR("*********There is no such gear!!!**********");
}
switch (gears) {
case first_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (10 * CLOCK_SYS_CLOCK_1US) );
break;
case second_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (20 * CLOCK_SYS_CLOCK_1US) );
break;
case third_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (40 * CLOCK_SYS_CLOCK_1US) );
break;
case fourth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (60 * CLOCK_SYS_CLOCK_1US) );
break;
case fifth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (70 * CLOCK_SYS_CLOCK_1US) );
break;
case sixth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (90 * CLOCK_SYS_CLOCK_1US) );
break;
case seventh_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (120 * CLOCK_SYS_CLOCK_1US) );
break;
case eighth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (160 * CLOCK_SYS_CLOCK_1US) );
break;
case ninth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (180 * CLOCK_SYS_CLOCK_1US) );
break;
case tenth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (220 * CLOCK_SYS_CLOCK_1US) );
break;
case eleventh_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (240 * CLOCK_SYS_CLOCK_1US) );
break;
case twelfth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (260 * CLOCK_SYS_CLOCK_1US) );
break;
case thirteenth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (300 * CLOCK_SYS_CLOCK_1US) );
break;
case fourteenth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (340 * CLOCK_SYS_CLOCK_1US) );
break;
case fifteenth_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (360 * CLOCK_SYS_CLOCK_1US) );
break;
case max_gear:
pwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (360 * CLOCK_SYS_CLOCK_1US) );
break;
default:
break;
}
}
将设备掉电前的状态数据写入可用的闪存中。当设备再次上电时从闪存中读取数据。这样,设备上电后可以恢复到之前的状态。
TLSR8253芯片的flash如下图所示。
0x040000
to0x060000
是设备可以写入数据的未使用空间。
1.将状态写入闪存。
/***********************************************************
* Function: write_massage_status_to_flash
* Input: none
* Output: none
* Return: none
* Notice: Write massager status to the flash memory.
***********************************************************/
void write_massage_status_to_flash(void)
{
Flash_Write_Buff[0] = massage_state.on_off;
Flash_Write_Buff[1] = massage_state.pattern;
Flash_Write_Buff[2] = massage_state.gear;
Flash_Write_Buff[3] = massage_state.heat;
flash_write_page(FLASH_ADDR, FLASH_BUFF_LEN, (unsigned char *)Flash_Write_Buff);
return;
}
2.从闪存中读取状态。
/***********************************************************
* Function: write_massage_status_to_flash
* Input: none
* Output: none
* Return: none
* Notice: Write massager status to the flash memory.
***********************************************************/
void write_massage_status_to_flash(void)
{
Flash_Write_Buff[0] = massage_state.on_off;
Flash_Write_Buff[1] = massage_state.pattern;
Flash_Write_Buff[2] = massage_state.gear;
Flash_Write_Buff[3] = massage_state.heat;
flash_write_page(FLASH_ADDR, FLASH_BUFF_LEN, (unsigned char *)Flash_Write_Buff);
return;
}/**********************************************************************
* Function: read_massage_status_to_flash
* Input: none
* Output: none
* Return: none
* Notice: Read the massager status data before power-off from the flash memory, and save it to the status struct.
**********************************************************************/
void read_massage_status_to_flash(void)
{
flash_read_page(FLASH_ADDR, FLASH_BUFF_LEN, (unsigned char *)Flash_Read_Buff);
// Store the data read from the flash memory into the struct.
massage_state.on_off = Flash_Read_Buff[0];
massage_state.pattern = Flash_Read_Buff[1];
massage_state.gear = Flash_Read_Buff[2];
massage_state.heat = Flash_Read_Buff[3];
return;
}
/***********************************************************
* Function: erase_massage_flash
* Input: none
* Output: none
* Return: none
* Notice: Restore defaults
***********************************************************/
void erase_massage_flash(void)
{
massage_state.on_off = OFF;
massage_state.pattern = relieve;
massage_state.gear = first_gear;
massage_state.heat = off_heat;
Flash_Write_Buff[0] = OFF;
Flash_Write_Buff[1] = relieve;
Flash_Write_Buff[2] = first_gear;
Flash_Write_Buff[3] = off_heat;
flash_write_page(FLASH_ADDR, FLASH_BUFF_LEN, (unsigned char *)Flash_Write_Buff);
return;
}
/***********************************************************
* Function: erase_massage_flash
* Input: none
* Output: none
* Return: none
* Notice: Restore defaults
***********************************************************/
void erase_massage_flash(void)
{
massage_state.on_off = OFF;
massage_state.pattern = relieve;
massage_state.gear = first_gear;
massage_state.heat = off_heat;
Flash_Write_Buff[0] = OFF;
Flash_Write_Buff[1] = relieve;
Flash_Write_Buff[2] = first_gear;
Flash_Write_Buff[3] = off_heat;
flash_write_page(FLASH_ADDR, FLASH_BUFF_LEN, (unsigned char *)Flash_Write_Buff);
return;
}
对于低功耗蓝牙模块,单个数据点 (DP) 的所有数据都存储在一个数组中。以 DP ID 104 为例。它的数组如下。
unsigned char mode_buf[] = {0x68, 0x04, 0x01, 0x00}; //{DP_ID, DP_type, DP_len, DP_data}
tuya_ble_dp_data_report(mode_buf, 4); // Data reporting function.
调用tuya_ble_dp_data_report(uint8_t *p_data,uint32_t len)
将单个DP的状态数据上报到云端。
来自移动应用程序的控制命令存储在数组中dp_data_array[255+3]
。您可以编写一个DP数据发送处理函数,并dp_data_array[255+3]
作为参数传递给该函数tuya_cb_handler(tuya_ble_cb_evt_param_t* event)
,tuya_ble_demo.c
以实现从移动应用程序发送命令。
void app_dp_handle(uint8_t *dp_data)
{
printf("dp_data:%d %d %d %d\r\n", dp_data[0], dp_data[1], dp_data[2], dp_data[3]);
switch (dp_data[0]) {
case 0x66:
if (dp_data[3] == strong_heat) {
massage_state.heat = strong_heat;
} else {
massage_state.heat = off_heat;
}
printf("dp_data[3]:%d massage_state.heat:%d\r\n", dp_data[3], massage_state.heat);
if (!app_flag) {
switching_heat(massage_state.heat);
}
break;
case 0x67:
printf("dp_data[3]:%d \r\n", dp_data[3]);
switch (dp_data[3]) {
case first_gear:
massage_state.gear = first_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case second_gear:
massage_state.gear = second_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case third_gear:
massage_state.gear = third_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case fourth_gear:
massage_state.gear = fourth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case fifth_gear:
massage_state.gear = fifth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case sixth_gear:
massage_state.gear = sixth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case seventh_gear:
massage_state.gear = seventh_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case eighth_gear:
massage_state.gear = eighth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case ninth_gear:
massage_state.gear = ninth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case tenth_gear:
massage_state.gear = tenth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case eleventh_gear:
massage_state.gear = eleventh_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case twelfth_gear:
massage_state.gear = twelfth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case thirteenth_gear:
massage_state.gear = thirteenth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case fourteenth_gear:
massage_state.gear = fourteenth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case fifteenth_gear:
massage_state.gear = fifteenth_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
case max_gear:
massage_state.gear = max_gear;
if (!app_flag) {
switching_gear(massage_state.gear);
}
break;
default:
break;
}
break;
case 0x68:
if (dp_data[3] == relieve) {
massage_state.pattern = relieve;
} else if (dp_data[3] == vitality) {
massage_state.pattern = vitality;
} else if (dp_data[3] == hammering) {
massage_state.pattern = hammering;
} else if (dp_data[3] == scraping_therapy) {
massage_state.pattern = scraping_therapy;
} else {
massage_state.pattern = intelligent;
}
break;
case 0x69:
if (dp_data[3] == ON) {
massage_state.on_off = ON;
rs2255_init();
voice_prompt_init();
pattern_pin_init();
app_flag = 0;
} else {
massage_state.on_off = OFF;
power_off_init();
app_flag = 1;
}
break;
default:
break;
}
}
在手机上安装涂鸦智能应用或智能生活应用。它们在移动应用市场上可用。打开应用程序并单击右上角的+图标以配对设备。设备连接后,您可以通过应用程序对其进行控制。
恭喜!您已成功设计出智能颈部按摩器的原型。
这款多功能物联网按摩器与 TENS 技术相结合,有助于缓解颈部酸痛和疼痛。内置NTC传感器,采用先进的精确恒温控制技术,可改善血液循环,缓解疼痛、结节和肌肉紧张。基于这个项目,您可以探索更多很棒的功能!
涂鸦物联网平台提供便捷的物联网开发工具和服务,旨在让您的物联网项目更轻松、更高效。查看并发现更多很棒的想法。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !