启航KS_IoT智能开发套件案例及代码(第二部分) 原创 精华

发布于 2022-2-28 11:05
浏览
10收藏

启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区

1.案例简介

启航KS包括1块核心板和4块扩展板,本文档包括以下功能案例:
启航KS核心板实现的案例
1)OLED显示
2)温湿度监测
3)超声波测距
4)人体红外感应
5)电机控制
6)蜂鸣器
7)光照强度监测
8)按键功能
9)RGB呼吸灯
10)NFC
11)Wi-Fi
12)光电开关监测
13)可燃气体监测
启航KS扩展板实现的案例
1)PM2.5监测
2)甲醛监测
3)BDS/GPS定位
4)姿态监测

2.启航KS核心板功能实现

核心板功能区分布图如下:
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区

2.9.RGB呼吸灯功能实现

2.9.1.RGB呼吸灯功能原理

RGB呼吸灯功能是通过循环控制PWM占空比,调节LED亮度,实现RGB呼吸灯效果。

2.9.2.RGB呼吸灯硬件接口

RGB
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区
按键控制使用的GPIO接口为GPIO10, GPIO11, GPIO12。其引脚连接说明如下:
RED ----- GPIO12
BLUE ----- GPIO10
GREEN ----- GPIO11
RGB呼吸灯功能中,GPIO10、GPIO11、GPIO12引脚配置设置见4.6章节
用跳线帽连接下图原理图中紫色方框位置
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区

2.9.3.RGB呼吸灯功能软件实现

代码目录:
applications\sample\wifi-iot\app\issdemo
|—iss_led
|—iss_led.c
|—iss_led.h
1、配置GPIO引脚为PWM

uint32_t IssInitLedByPwmPinFunc(hi_pwm_port pwmPort, hi_gpio_idx gpioIdx, hi_io_name ioName,
                                hi_io_func_gpio_10 gpioFunc)
{
    uint32_t state = HI_ERR_FAILURE;
    state = hi_pwm_init(pwmPort);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "init pwm failure.state=0x%x", state);
    // Set the function of the specified pin as PWM output
    state = hi_io_set_func(ioName, gpioFunc);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "io set GPIO failure.state=0x%x", state);
    // Sets the direction of the pin to output
    state = IoTGpioSetDir(gpioIdx, HI_GPIO_DIR_OUT);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "io set dir  failure.state=0x%x", state);
    return HI_ERR_SUCCESS;
}

2、PWM配置
配置PWM1,PWM2,PWM3的硬件引脚

uint32_t IssInitLedByPwm(void)
{
    uint32_t state = HI_ERR_FAILURE;
    state = IssInitLedByPwmPinFunc(HI_PWM_PORT_PWM1, HI_GPIO_IDX_10, HI_IO_NAME_GPIO_10,
                           HI_IO_FUNC_GPIO_10_PWM1_OUT);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "IssInitLedByPwmPinFunc HI_PWM_PORT_PWM1 failure.state=0x%x", state);
    state = IssInitLedByPwmPinFunc(HI_PWM_PORT_PWM2, HI_GPIO_IDX_11, HI_IO_NAME_GPIO_11,
                           HI_IO_FUNC_GPIO_11_PWM2_OUT);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "IssInitLedByPwmPinFunc HI_PWM_PORT_PWM2 failure.state=0x%x", state);
    state = IssInitLedByPwmPinFunc(HI_PWM_PORT_PWM3, HI_GPIO_IDX_12, HI_IO_NAME_GPIO_12,
                           HI_IO_FUNC_GPIO_12_PWM3_OUT);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "IssInitLedByPwmPinFunc HI_PWM_PORT_PWM3 failure.state=0x%x", state);
    return HI_ERR_SUCCESS;
}

3、PWM启动

uint32_t IssPwmOut(hi_pwm_port pwmPort, uint16_t duty, uint32_t freq)
{
    uint32_t state = HI_ERR_FAILURE;
    state = hi_pwm_start(pwmPort, duty, freq); /* duty: 750 freq:1500      scope:1~65535*/
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "pwm start failure.state=0x%x", state);
    return HI_ERR_SUCCESS;
}

4、RGB呼吸灯开关控制
通过PWM打开所有RGB呼吸灯

uint32_t IssTurnOnAllLedByPwm()
{
    // PWM is used to control the light on
    uint32_t state = HI_ERR_FAILURE;
    state = IssPwmOut(HI_PWM_PORT_PWM1, 40000, 40000);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "HI_PWM_PORT_PWM1 failure,state=0x%x", state);
    state = IssPwmOut(HI_PWM_PORT_PWM2, 40000, 40000);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "HI_PWM_PORT_PWM2 failure,state=0x%x", state);
    state = IssPwmOut(HI_PWM_PORT_PWM3, 40000, 40000);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "HI_PWM_PORT_PWM3 failure,state=0x%x", state);
    return HI_ERR_SUCCESS;
}

通过PWM关闭所有RGB呼吸灯

uint32_t IssTurnOffAllLedByPwm()
{
    // PWM is used to control the lamp off
    uint32_t state = HI_ERR_FAILURE;
    state = IoTPwmStop(HI_PWM_PORT_PWM1);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "HI_PWM_PORT_PWM1 failure,state=0x%x", state);
    state = IoTPwmStop(HI_PWM_PORT_PWM2);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "HI_PWM_PORT_PWM2 failure,state=0x%x", state);
    state = IoTPwmStop(HI_PWM_PORT_PWM3);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "HI_PWM_PORT_PWM3 failure,state=0x%x", state);
    return HI_ERR_SUCCESS;
}

2.10.NFC感应器实现

2.10.1.NFC感应器原理

NFC感应器,型号为FM11NC8,实现NFC感应器控制。

  1. NFC 是一种近场无线通信技术,通信距离理论上可以在 10cm(实际中需要贴的很近),以13.56MHz RFID 技术为基础,与现有的非接触式智能卡国际标准相兼容。 数据传输速率 106kbit/s、212kbit/s、424kbit/s。
    2.通信原理是基于感应近场,在近场区域内感应场强弱与电磁辐射源以及天线的距离相关,近则强远则弱。
  2. NFC 通信一般有两种模式:主动模式和被动模式。
    1)主动模式:两个设备发起端(标签设备)和目标端(读卡器)都必须发射出本身的射频场,以实现向对方系统设备之间发送数据。
    2)被动模式:相对于主动模式,被动模式只有一方提供射频场,提供射频场的都是通信发起端设备,另一端目标不需要产生射频场,目标设备能量的产生由发起方射频场的感应电动势进行供电,目标端使用负载调制的方式,以相同的速率将数据回传给发起端设备。在整个双方通信过程中发起方设备的射频场必须存在,一旦关闭目标端设备的供电就会结束,数据交换无法进行。
    本案例采用被动模式。

2.10.2.NFC感应器硬件接口

NFC
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区
NFC采用I2C协议进行数据通信。使用的GPIO 引脚分别是 GPIO13,GPIO14,其引脚连接说明如下:
SDA ----- GPIO13
SCL ----- GPIO14
用跳线帽连接下图原理图中紫色方框位置
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区

2.10.3.NFC感应器软件实现

NFC 软件驱动实现:
代码目录:
applications\sample\wifi-iot\app\issdemo
|—iss_nfc
|—iss_nfc_demo.c
|—iss_nfc_demo.h
|—iss_nfc_interface.c
|—iss_nfc_interface.h
|—iss_nfc_regvalue.c
|—iss_nfc_regvalue.h
1、NFC初始化
I2C硬件引脚IDX_0 初始化
设置I2C波特率
设置GPIO13为I2C0SDA
设置GPIO14为I2C0SCL
NFC和OLED使用共同的I2C0接口,在OLED模块中已初始化,这里不需要重复初始化
2、NFC驱动实现
1)寄存器读写接口实现

u32 WriteRead(u16 reg, u8 *recvData, u8 sendLen, u8 readLen)
{
    hi_i2c_data readBuffer = {0};
    u8 userCmd[2] = {(reg & 0xFF00) >> 8, reg & 0x00FF};

    memset(recvData, 0x0, sizeof(recvData));
    memset(&readBuffer, 0x0, sizeof(hi_i2c_data));

    readBuffer.send_buf = userCmd;
    readBuffer.send_len = sendLen;

    readBuffer.receive_buf = recvData;
    readBuffer.receive_len = readLen;

    hi_i2c_writeread(NFC_I2C_CHANNEL, ISS_CHIP_NFC_ADDR & 0xFE, &readBuffer);
    return 0;
}

/**********************************************
*    nfc interface write register buffer
**********************************************/
u32 WriteBuffToReg(u16 reg, u8 *dataBuff, u8 len)
{
    hi_i2c_data writeBuffer = {0};
    u8 userCmd[64] = {(reg & 0xFF00) >> 8, reg & 0x00FF};

    writeBuffer.send_buf = userCmd;
    writeBuffer.send_len = 2 + len;
    for (u8 i = 0; i < len; i++) {
        userCmd[2 + i] = *(dataBuff + i);
    }
    IoTI2cWrite(NFC_I2C_CHANNEL, ISS_CHIP_NFC_ADDR & 0xFE, writeBuffer.send_buf, writeBuffer.send_len);
    return 0;
}

/**********************************************
*    nfc interface write register byte
**********************************************/
u32 WriteByteToReg(u16 reg, u8 dataBuff)
{
    hi_i2c_data writeBuffer = {0};
    u8 userCmd[64] = {(reg & 0xFF00) >> 8, reg & 0x00FF, dataBuff};

    writeBuffer.send_buf = userCmd;
    writeBuffer.send_len = 3;

    IoTI2cWrite(NFC_I2C_CHANNEL, ISS_CHIP_NFC_ADDR & 0xFE, writeBuffer.send_buf, writeBuffer.send_len);
    return 0;
}

/**********************************************
*    nfc interface write buffer
**********************************************/
u32 WriteBuffer(u8 *dataBuff, u8 len)
{
    hi_i2c_data writeBuffer = {0};
    u8 userCmd[128] = {0};

    memset(userCmd, 0x0, sizeof(userCmd));

    userCmd[0] = 0xff;
    userCmd[1] = 0xf0;

    for (int i = 0; i < len; i++) {
        userCmd[2 + i] = *(dataBuff + i);
    }
    writeBuffer.send_buf = userCmd;
    writeBuffer.send_len = 2 + len;

    hi_i2c_writeread(NFC_I2C_CHANNEL, ISS_CHIP_NFC_ADDR & 0xFE, &writeBuffer);
    return 0;
}

2)读取中断标志

void ReadNfcIrqFlag(u8 *flag)
{
    u8 irqFlag = 0;
    u8 ret = 0;

    irqFlag = ChipControl.readReg(ISS_MAIN_IRQ);
    if (irqFlag & ISS_MAIN_IRQ_FIFO) {
        ret = ChipControl.readReg(ISS_FIFO_IRQ);
        if (ret & ISS_FIFO_IRQ_WL) {
            flag[1] = 1;
        }
    }
    if (irqFlag & ISS_MAIN_IRQ_AUX) {
        ret = ChipControl.readReg(ISS_AUX_IRQ);
        ChipControl.writeReg(ISS_FIFO_FLUSH, 0xFF);
    }
    if (irqFlag & ISS_MAIN_IRQ_RX_START) {
        flag[0] = 1;
    }
    if (irqFlag & ISS_MAIN_IRQ_RX_DONE) {
        flag[2] = 1;
    }
}

3)读取缓冲区

u32 ChipDataRecv(u8 *revBuffer)
{
    u8 flag[3] = {0};
    u32 revLen = 0;
    u32 lastCount = 0;
    (void)revBuffer;
    flag[1] = 0;
    ReadNfcIrqFlag(flag);
    if ((flag[0] == 1) && (flag[1] == 1)) {
        flag[1] = 0;
        ChipReadFifo(FIFO_MAX_COUNT, &revBuffer[revLen]);
        revLen += FIFO_MAX_COUNT;
    }
    if (flag[2] == 1) {
        lastCount = (u32)(ChipControl.readReg(ISS_FIFO_WORDCNT) & 0x3F);
        ChipReadFifo(lastCount, &revBuffer[revLen]);
        revLen = revLen + lastCount;
        flag[0] = 0;
    }
    if (revLen <= 2) {
        return 0;
    }
    return (revLen - 2);
}

4)读取卡数据

u8 AppI2cNfcMaster(BoardEnvInfoValue *info)
{
    u8 cardLen = 0;

    static u8 cardValid = 0;
    static u8 oldCardValid = 0xff;
    static u16 timeOut = 0;
    cardLen = ChipControl.dataRecv(readCardFifo);
    timeOut++;
    if (cardLen > 0) {
        timeOut = 0;
        cardValid = 1;
        printf("nfc 1\r\n");
        if (cardValid != oldCardValid) {
            oldCardValid = cardValid;
            info->nfcState = 1;
            return 0;
        }
    }
    if (timeOut > 20) {
        timeOut = 0;
        cardValid = 0;
        oldCardValid = 0xff;
        info->nfcState = 0;
    }
    return 0;
}

2.11.Wi-Fi功能实现

2.11.1.Wi-Fi功能原理

Wi-Fi模组集成在Hi3861中,可以工作在STA,也可以工作在AP。
工作在STA时,启航KS要连接上指定的热点(可用手机做热点测试);工作在AP状态时,手机可以连接启航KS生成的热点。

2.11.2.Wi-Fi功能软件实现

代码目录:

applications\sample\wifi-iot\app\issdemo\
    |---iss_thread
           |---iss_wifi_sta.c
           	 |---iss_wifi_sta.h
    |---iss_wifi
           |---iss_udp_server.c
           	 |---iss_udp_server.h
1、初始化Wi-Fi配置
uint32_t IssInitWifiConfig(void)
{
    uint32_t state = HI_ERR_FAILURE;

    char ifname[WIFI_IFNAME_MAX_SIZE + 1] = {0};
    int len = sizeof(ifname);

    state = hi_wifi_init(APP_INIT_VAP_NUM, APP_INIT_USR_NUM);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "hi_wifi_init failure.state=0x%x", state);

    state = hi_wifi_sta_start(ifname, &len);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "wifi sta start failure.state=0x%x", state);
    /* register call back function to receive wifi event, etc scan results event,
     * connected event, disconnected event.
     */
    g_lwip_netif = netifapi_netif_find(ifname);
    RUNTIME_ERR_RET_FAIL(g_lwip_netif == NULL, "netifapi_netif_find failure.state=0x%x", state);

    state = hi_wifi_register_event_callback(IssWifiWpaEventCallback);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "wifi register event callback failure.state=0x%x", state);
    return state;
}

2、连接热点

int hi_wifi_start_connect(char *ssid, char *key, hi_wifi_auth_mode auth_mode)
{
    hi_wifi_assoc_request assoc_req = {0};

    /* copy SSID to assoc_req */
    if (memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, ssid, HI_WIFI_MAX_SSID_LEN) != EOK) {
        printf("%s memcpy_s failed\r\n", __func__);
        return HISI_FAIL;
    }
    /* copy KEY to assoc_req */
    if (memcpy_s(assoc_req.key, HI_WIFI_MAX_KEY_LEN + 1, key, strlen(key)) != EOK) {
        printf("%s memcpy_s failed\r\n", __func__);
        return HISI_FAIL;
    }
    /*
     * OPEN mode
     * for WPA2-PSK mode:
     * set assoc_req.auth as HI_WIFI_SECURITY_WPA2PSK,
     * then memcpy(assoc_req.key, "12345678", 8).
     */
    assoc_req.auth = auth_mode;

    if (hi_wifi_sta_connect(&assoc_req) != HISI_OK) {
        return HISI_FAIL;
    }
    return HISI_OK;
}

3、启动UDP server

void StartUdpServer(void)
{
    struct sockaddr_in servaddr;
    int socketHandle = socket(PF_INET, SOCK_DGRAM, 0);

    // server ip port
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT_8088);

    bind(socketHandle, (struct sockaddr *)&servaddr, sizeof(servaddr));

    while (TRUE) {
        PSocketData pSocketData = (PSocketData)malloc(sizeof(SocketData));
        memset(pSocketData, 0, sizeof(SocketData));

        pSocketData->socketHandle = socketHandle;
        int sizeClientAddr = sizeof(struct sockaddr_in);
        printf("wait recvfrom...\r\n");
        int ret = recvfrom(socketHandle, pSocketData->recvBuf, SOCKET_BUF_SIZE, 0,
                           (struct sockaddr *)&pSocketData->addrClient, (socklen_t *)&sizeClientAddr);

        RUNTIME_ERR_CONTINUE_WITH_LOG(ret <= 0, "recvfrom Execute failed.");
        printf(":::::::::::\t recvBuf=%s.::::::::::::\r\n", pSocketData->recvBuf);
        CreateUdpHandleThread(pSocketData);
        usleep(20);
    }
}

2.12.光电开关监测实现

2.12.1.光电开关监测原理

光电开关是用硫化镉或硒化镉等半导体材料制成的特殊电阻器,其工作原理是基于内光电效应。光照愈强,阻值就愈低,随着光照强度的升高,电阻值迅速降低。

2.12.2.光电开关硬件接口

PHO_RES
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区
引脚连接说明如下:
光敏传感器使用的GPIO接口为GPIO06
用跳线帽连接下图原理图中紫色方框位置
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区
额外功能说明:
光电开关联动光照灯D6,需要按下SW1。当光电开关感应到夜晚时,打开光照灯;当光电开关感应到白天时,关闭光照灯。
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区

2.12.3.光电开关监测软件实现

代码目录:
applications\sample\wifi-iot\app\issdemo
|—iss_photosensitive
|—iss_photosensitive.c
|—iss_photosensitive.h
初始化GPIO

int32_t IssInitPhotoSensitive(void)
{
    int32_t state = HI_ERR_FAILURE;
    state = hi_io_set_func(PHOTOSENSITIVE_GPIO_NAME, PHOTOSENSITIVE_GPIO_FUNC);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "PHOTOSENSITIVE_GPIO_NAME IoSetFunc error");
    state = IoTGpioSetDir(PHOTOSENSITIVE_GPIO_IDX, HI_GPIO_DIR_IN);
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "PHOTOSENSITIVE_GPIO_NAME IoTGpioSetDir error");
    return HI_ERR_SUCCESS;
}

获取光电开关数据

int32_t IssReadPhotoSensitive(BoardEnvInfoValue *envInfo)
{
    int32_t state = HI_ERR_FAILURE;
    IotGpioValue value = HI_GPIO_VALUE0;
    state = IoTGpioGetInputVal(PHOTOSENSITIVE_GPIO_IDX, &value);
    if (state != HI_ERR_SUCCESS) {
        envInfo->photoSensitive = -1;
    }
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "PHOTOSENSITIVE_GPIO_NAME IoTGpioSetDir error");
    envInfo->photoSensitive = value;
    return state;
}

2.13.可燃气体监测实现

2.13.1.可燃气体监测原理

通过ADC接口实时采集当前环境可燃气体浓度,超过阈值时蜂鸣器会发出警报。

2.13.2.可燃气体监测硬件接口

MQ-4
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区
特殊说明:
使用该功能,需要按下SW1按键,此时该功能才有效。
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区
引脚连接说明:
ADC ----- GPIO11
可燃气体监测功能中,GPIO10引脚配置设置见4.8章节
用跳线帽连接下图原理图中紫色方框位置
启航KS_IoT智能开发套件案例及代码(第二部分)-开源基础软件社区
Rs 为传感器当前阻值,R0 为洁净空气中的值,ppm为可燃气体浓度。三者之间的关系为:
① Rs/R0 = 11.5428ppm^(-0.6549) 。由上图的电路图可得出
② (Vc – V2)/Rs = V2/R2。 Vc = 5V, V2 位 R25 电阻电压, 即 ADC 采集到的电压, R25= 1k。在空气洁净时测出电压为 0.25V 左右。故 R0 = 19K。
通过公式①,②可以推导出电压 V2 与 ppm 值的关系为:
ppm = pow(11.5428
19* V2/(5- V2),1.0/0.6549);
函数 pow 为计算 x 的 y 次方,x, y 均为 double 类型。

2.13.3.可燃气体监测软件实现

读取ADC电压数值,将电压值转换为可燃气体数值。
代码目录:
applications\sample\wifi-iot\app\issdemo
|—iss_combustible_gas
|—iss_combustible_gas.c
|—iss_combustible_gas.h
可燃气体数据转换和获取

int32_t IssGasAdcRead(BoardEnvInfoValue *envInfo)
{
    int32_t state = HI_ERR_FAILURE;
    uint16_t data = 0;
    float voltage;
    uint32_t gas;
    state = hi_adc_read(HI_ADC_CHANNEL_5, &data, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0xFF);
    if (state != HI_ERR_SUCCESS) {
        envInfo->gasVal.voltageVal = -1;
        envInfo->gasVal.gasPpmVal = -1;
    }
    RUNTIME_ERR_RET_FAIL(state != HI_ERR_SUCCESS, "adc channel5 read failure.");
    voltage = hi_adc_convert_to_voltage(data);
    gas = pow(11.54 * 19 * voltage / (5 - voltage), 1.0 / 0.65);
    envInfo->gasVal.voltageVal = voltage;
    envInfo->gasVal.gasPpmVal = gas;
    return state;
}

更多原创内容请关注:软通动力HarmonyOS学院

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-2-28 11:05:48修改
11
收藏 10
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐