一、档位切换实现
1、档位实现原理
按摩仪共设置15个档位,可以控制按摩的力度,通过BOOST升压电路实现。
通过P8口产生PWM波,调节PWM输出的正占空比来实现升压,详细的硬件原理可参考硬件部分关于升压原理的介绍,具体数值如下:
档位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 最大档 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
升压值(V) | 12 | 15 | 19 | 22 | 26 | 29 | 33 | 36 | 40 | 43 | 47 | 50 | 54 | 57 | 60 | 60 |
占空比(%) | 1 | 2 | 4 | 6 | 7 | 9 | 12 | 16 | 18 | 22 | 24 | 26 | 30 | 34 | 36 | 36 |
档位调节是通过按键的单击和双击来实现的,单击档位加,双击档位减。由于SDK配置原因,在程序烧录后复位模组时P8口已经被拉高,所以在此处对其做拉低处理。
void boost_init(void)
{gpio_set_func(BOOST_PIN, AS_PWM0);gpio_set_output_en(BOOST_PIN, 1);//PWM0 1ms cyclepwm_set_mode(PWM0_ID, PWM_NORMAL_MODE);pwm_set_clk(CLOCK_SYS_CLOCK_HZ, BOOST_PWM_CLOCK_HZ); //设定BOOST升压时PWM频率为 16M / (968-1) ≈ 16.55KHzpwm_set_phase(PWM0_ID, 0); //no phase at pwm beginningpwm_set_cycle_and_duty(PWM0_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US), (u16) (0 * CLOCK_SYS_CLOCK_1US) );pwm_start(PWM0_ID);
}
2、实现过程
初始化完成后通过输入参数的具体值改变占空比升压到对应值。
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;}
}
二、语音播报
1、功能简述
本次用到了WTN6系列的离线语音模块,WTN6系列产品为多功能单芯片语音合成4位元为控制器。
(1) 工作电压:2.4V~5.2V
(2) 待机模式下,静态电流小于5uA
(3) 精准的+/-1%内部震荡,有低压复位(LVR=1.8V)看门狗计时
(4) 12位元PWM纯音频输出,可直接驱动8Ω/0.5W喇叭和蜂鸣器,DAC音频输出,可外接功放
(5) 内置看门狗;
(6) 具备串口控制模式:一线串口,两线串口(最多可以加载224段语音,后续有详解),数脉冲
(7) 支持BUSY状态输出功能
Pad Name | Pad No. | ATTR. | Description 描述 |
---|---|---|---|
PA2 | 1 | I/O | 忙信号输出 |
PA1 | 2 | I/O | 两线串口时钟信号输入端/一线串口数据信号输入端/数脉冲数据信号输入端 |
PA0 | 3 | I/O | 两线串口数据信号输入端/复位脚 |
PA3 | 4 | I/O | 暂未使用(NC) |
PWM- | 5 | out | PWM 输出脚 |
VDD | 6 | Power | 电源正极 |
PWM+/DAC | 7 | I/O | PWM、DAC 输出脚 |
GND | 8 | Power | 电源负极 |
2、一线串口通讯
本次仅用到了一线串口通讯,一线串口模式可以利用 MCU 通过 DATA 线给 WTN6 系列语音芯片发送数据以达到控制的目的。可以实现控制语音播放、停止、循环等。
(1)管脚分配:
管脚 | 作用 |
---|---|
PA1 | DATA |
PA2 | BUSY |
(2)一线语音地址对应关系:
数据(十六进制) | 功能 |
---|---|
00H | 播放第 0 段语音 |
01H | 播放第 1 段语音 |
02H | 播放第 2 段语音 |
…… | …… |
DFH | 播放第 222 段语音 |
3、一线串口时序图
先把数据线拉低 5ms 后,发送 8 位数据,先发送低位,再发送高位,使用高电平和低电平比例来表示
每个数据位的值。
(1)功能引脚初始化
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);
}
(2)声音播放
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); //延时 5msb_data = s_data & 0X01;for (j=0; j<8; j++) {if (b_data == 1) {gpio_write(WTN6_DATA_PIN, 1);sleep_us(600); //延时 600usgpio_write(WTN6_DATA_PIN, 0);sleep_us(200); //延时 200us} else {gpio_write(WTN6_DATA_PIN, 1);sleep_us(200); //延时 200usgpio_write(WTN6_DATA_PIN, 0);sleep_us(600); //延时 600us}s_data = s_data >> 1;b_data = s_data & 0X01;}gpio_write(WTN6_DATA_PIN, 1);
}
输入参数填入对应地址voice_playing(0x01)
即可播放离线语音。
三、加热功能
加热功能是通过控制P7引脚的拉高拉低来实现加热开、加热关的,内置温度检测模块,加热时当温度超过40℃会自动关闭加热功能以免过热引起不适或被烫伤。
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;
}
/*温度检测,弱热强热功能开启时调用*/
int temperature_detection(void)
{int Rntc = 0, Vcc = 0;adc_channel_checkout(channel_x1);Vcc = adc_sample_and_get_result(); //uint:mvRntc = Vcc*R25 / (3300-Vcc);TUYA_APP_LOG_INFO("Rntc_val=%dΩ", Rntc);if (Rntc >= 5311) { // NTC在40℃时电阻值为5311ΩTUYA_APP_LOG_WARNING("********High Temperature Warning!!!********");gpio_write(HEAT_PIN, 0); //超过40℃关闭加热功能}return 0;
}
NTC温度与阻值对照表
戳我:更多物联网应用在这里!