开发者成长激励计划-基于TencentOS Tiny 的加热不燃烧烟具温度检测设备

2022-08-08 20:37:02 浏览数 (2)

一、作品简介:

代码语言:txt复制
   我们在开发加热不燃烧烟具的过程中,需要吧烟具内部的温度加到一个比较高的温度(200-300摄氏度),烟具内部本身有测温器件,但是不能保证烟具自己测试的温度就是准确的,所以就需要一个外部也要增加设备来辅助测试一下,并且把整个加热过程中的温度变化画出曲线,有助于对整个设备的研究。所以我们这次开发所用的硬件除了赤兔CH32V307开发板以外,还增加一个NTC的检测电路。如下图所示:
开发板加上NTC测温器件开发板加上NTC测温器件
NTC原理图NTC原理图

二、软件开发过程

1、软件环境

此次开发和编译坏境是沁恒微的MounRiver Studio软件,此软件用熟了感觉你keil好用太多了,并且还是免费的开发软件。具体如何好,只有真正使用来开发的各位工程师能明白,在此就不多说了。界面如下图所示:

MounRiver Studio开发软件界面MounRiver Studio开发软件界面

2、基础例程测试:

本次设计的基础例程是本次活动提供的例程“TencentOS_DVP”。此代码已经包含了LCD屏的驱动,摄像头的驱动,以及AT指令以及MQTT协议等功能。只要稍加运用就可以做成一个可以连上腾讯云的网络产品。如下图所示就是本次测试连到腾讯云的日志记录:

腾讯云端日志图腾讯云端日志图

3、云端开发:

根据学习视频和PPT学习,自己测试了一些简单的测试开发,开发还是比较方便的。只是时间紧,工作忙,没有实际真正开发成产品,等忙完这段时间,过段时间直接在公司立个预研项目直接开发,从此一个单片机工程师转变成一个全能物联网工程师还是有可能的。开发小程序如下图所示:

腾讯云小程序开发界面图腾讯云小程序开发界面图

4、温度检测程序实现

NTC的温度检测,其原理就是使用热敏电阻的特性,根据厂家给出的热敏电阻对应温度参数,然后设计一个电路,使用电阻分压的情况下读取分压电阻的电压值,从而查表得出测试环境的实际温度值。程序代码如下:

代码语言:javascript复制
#include "debug.h"
#include "tos_k.h"
#include "lcd.h"
#include "lcd_init.h"
#include "user_read_temperature.h"
#define M_COUNT_OF(Obj)         (sizeof(Obj) / sizeof(Obj[0]))//总长度除以个体长度等于个数

Dev_ADC vDev_ADC;

s16 Calibrattion_Val = 0;
const uint16_t list_N_V[330] =
{
4090,4089,4089,4088,4088,4087,4087,4086,4086,4085,
4085,4084,4083,4083,4082,4081,4080,4080,4079,4078,
4077,4076,4075,4074,4073,4071,4070,4069,4067,4066,
4065,4063,4061,4060,4058,4056,4054,4052,4050,4048,
4046,4044,4041,4039,4036,4034,4031,4028,4025,4022,
4019,4015,4012,4008,4004,4000,3996,3992,3988,3983,
3978,3973,3968,3963,3958,3952,3946,3940,3934,3927,
3921,3914,3907,3899,3892,3884,3876,3868,3859,3850,
3841,3832,3822,3812,3802,3791,3781,3770,3758,3747,
3735,3722,3710,3697,3684,3670,3656,3642,3628,3613,
3598,3582,3566,3550,3534,3517,3500,3482,3464,3446,
3427,3409,3389,3370,3350,3330,3309,3288,3267,3246,
3224,3201,3178,3154,3131,3107,3082,3058,3033,3007,
2982,2956,2930,2904,2877,2851,2824,2797,2770,2742,
2714,2687,2659,2631,2603,2574,2546,2517,2489,2460,
2414,2368,2340,2312,2284,2255,2227,2199,2171,2143,
2115,2087,2059,2031,2004,1976,1949,1922,1895,1868,
1841,1815,1788,1762,1737,1711,1685,1660,1635,1610,
1585,1561,1537,1514,1491,1467,1445,1422,1400,1377,
1355,1334,1312,1291,1270,1249,1229,1209,1189,1169,
1150,1131,1112,1093,1075,1057,1039,1021,1004,987 ,
970 ,954 ,937 ,921 ,905 ,890 ,874 ,859 ,845 ,830 ,
815 ,801 ,787 ,773 ,760 ,747 ,734 ,721 ,709 ,696 ,
684 ,672 ,661 ,649 ,638 ,626 ,616 ,605 ,594 ,584 ,
574 ,564 ,554 ,545 ,535 ,526 ,517 ,508 ,499 ,490 ,
482 ,474 ,465 ,457 ,450 ,442 ,434 ,427 ,420 ,413 ,
405 ,398 ,392 ,385 ,379 ,372 ,366 ,360 ,354 ,348 ,
342 ,336 ,331 ,325 ,320 ,315 ,309 ,304 ,299 ,294 ,
289 ,285 ,280 ,276 ,271 ,267 ,262 ,258 ,254 ,250 ,
245 ,242 ,238 ,234 ,230 ,226 ,223 ,220 ,216 ,213 ,
209 ,206 ,203 ,200 ,197 ,194 ,191 ,188 ,185 ,182 ,
179 ,176 ,174 ,171 ,168 ,166 ,163 ,161 ,159 ,156 ,
153 ,151 ,149 ,147 ,145 ,143 ,140 ,138 ,136 ,135 ,
};
int uGetHeaterTemperature(uint8_t ch)//NTC测温
{
    int data_len,x=0;
    static uint16_t Adcn;
    data_len=M_COUNT_OF(list_N_V);
    Adcn = vDev_ADC.Read_ADC[ch];//userADC_var.ADC_uDATA[ch];
    if((Adcn<=list_N_V[0])&&(Adcn>=list_N_V[data_len-1]))
    {
        for(x=0;x<data_len-1;x  )
        {
            if(Adcn>=list_N_V[x])
            {
                break;
            }
        }
    }
    return x;
}
/*********************************************************************
 * @fn      ADC_Function_Init
 *
 * @brief   Initializes ADC collection.
 *
 * @return  none
 */
void ADC_Function_Init(void)
{
    ADC_InitTypeDef ADC_InitStructure={0};
    GPIO_InitTypeDef GPIO_InitStructure={0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    ADC_DeInit(ADC1);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_DMACmd(ADC1, ENABLE);
    ADC_Cmd(ADC1, ENABLE);

    ADC_BufferCmd(ADC1, DISABLE);   //disable buffe
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
    Calibrattion_Val = Get_CalibrationValue(ADC1);

    ADC_BufferCmd(ADC1, ENABLE);   //enable buffe
}

/*********************************************************************
 * @fn      Get_ADC_Val
 *
 * @brief   Returns ADCx conversion result data.
 *
 * @param   ch - ADC channel.
 *            ADC_Channel_0 - ADC Channel0 selected.
 *            ADC_Channel_1 - ADC Channel1 selected.
 *            ADC_Channel_2 - ADC Channel2 selected.
 *            ADC_Channel_3 - ADC Channel3 selected.
 *            ADC_Channel_4 - ADC Channel4 selected.
 *            ADC_Channel_5 - ADC Channel5 selected.
 *            ADC_Channel_6 - ADC Channel6 selected.
 *            ADC_Channel_7 - ADC Channel7 selected.
 *            ADC_Channel_8 - ADC Channel8 selected.
 *            ADC_Channel_9 - ADC Channel9 selected.
 *            ADC_Channel_10 - ADC Channel10 selected.
 *            ADC_Channel_11 - ADC Channel11 selected.
 *            ADC_Channel_12 - ADC Channel12 selected.
 *            ADC_Channel_13 - ADC Channel13 selected.
 *            ADC_Channel_14 - ADC Channel14 selected.
 *            ADC_Channel_15 - ADC Channel15 selected.
 *            ADC_Channel_16 - ADC Channel16 selected.
 *            ADC_Channel_17 - ADC Channel17 selected.
 *
 * @return  none
 */
u16 Get_ADC_Val(u8 ch)
{
    u16 val;

    ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
    val = ADC_GetConversionValue(ADC1);

    return val;
}
/*********************************************************************
 * @fn      DMA_Tx_Init
 *
 * @brief   Initializes the DMAy Channelx configuration.
 *
 * @param   DMA_CHx - x can be 1 to 7.
 *          ppadr - Peripheral base address.
 *          memadr - Memory base address.
 *          bufsize - DMA channel buffer size.
 *
 * @return  none
 */
void DMA_Tx_Init( DMA_Channel_TypeDef* DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
{
    DMA_InitTypeDef DMA_InitStructure={0};

    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

    DMA_DeInit(DMA_CHx);
    DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
    DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = bufsize;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init( DMA_CHx, &DMA_InitStructure );
}
/*********************************************************************
 * @fn      Get_ConversionVal
 *
 * @brief   Get Conversion Value.
 *
 * @param   val - Sampling value
 *
 * @return  val Calibrattion_Val - Conversion Value.
 */
u16 Get_ConversionVal(s16 val)
{
    if((val Calibrattion_Val)<0) return 0;
    if((Calibrattion_Val val)>4095||val==4095) return 4095;
    return (val Calibrattion_Val);
}

void user_Read_ADC(void)
{
    uint8_t temp_D[50];
    u16 ADC_Buf[1],Temperature[2];
    ADC_Function_Init();
    printf("CalibrattionValue:%dn", Calibrattion_Val);
    while(1)
    {
        ADC_Buf[0] = Get_ADC_Val(ADC_Channel_8);
        //Temperature[1] = TempSensor_Volt_To_Temper(Get_ADC_Val(ADC_Channel_TempSensor));
        vDev_ADC.Read_ADC[0] = Get_ConversionVal(ADC_Buf[0]);
        Temperature[0] = uGetHeaterTemperature(ADC_CH8);
        sprintf(temp_D,"%d     ",Temperature[0] );
        printf("Temperature:%drn", Temperature[0]);
        LCD_ShowString(30,140 16 16 16,"T=:",YELLOW,BLACK,32,0);        
        LCD_ShowString(100,140 16 16 16,temp_D,BRRED,BLACK,32,0);
        tos_task_delay(500);
    }
}

5、测量结果

通过串口示波器软件打印出来分析,与我们设计的温度曲线基本吻合。打印的图如下所示:

6、视频展示测试过程:

设备测试过程

三、开发总结

本次开发的TencentOS Tiny系统的最大优势在可以直接使用手上的硬件链接到腾讯云的工作。大大简化了开发的流程和工作量。只是对于之前只是做单片机开发的我来说,还是有难度的。因为之前连腾讯小程序都还没开发成功过。但是通钢这次的学习,发现了使用智能硬件联网并不是特别难的事情。后续将通过更多的学习,把单片机联网来开发。这样才能使自己不落后于这个时代。

0 人点赞