鴻蒙設備開發(fā)Hi3861-IoT落地-自動門鎖
1. 項目來源
有一天半夜宿舍門被一個喝暈的哥們打開了,(說他暈吧他居然知道鑰匙在門框上)于是有了設計自動門鎖的想法。正好一直想用Hi3861做一個iot落地項目【之前挖的坑】,一切剛好!
2. 需求分析
無鑰匙進入
手機端操作
不影響使用鑰匙開門
無損安裝、卸載自動開門機構(gòu)
3. 宿舍門鎖考察
水平向右移動拉閂1cm左右即可開門,由于宿舍們老舊,拉力實測在2.5L水左右。經(jīng)過粗略計算,如果使用9g舵機來驅(qū)動,單杠驅(qū)動結(jié)構(gòu)的話,杠桿長度比為2500/9≈278,尺寸有些夸張。不想在機械結(jié)構(gòu)上費時間,所以選取大扭矩舵機驅(qū)動。
4.方案設計
4.1 機械結(jié)構(gòu)
典型的曲柄滑塊結(jié)構(gòu)。選取了繩索拉動、連桿方案。綜合考慮耐用度和安裝便攜性,選取繩索驅(qū)動方案。
使用套殼的方式安裝在門鎖體上,拉閂自由移動,不影響手動開門。

4.2 控制邏輯
Hi3861根據(jù)web端發(fā)送過來的質(zhì)量控制舵機轉(zhuǎn)動即可。控制信號來源于web端,采用MQTT協(xié)議來處理數(shù)據(jù),電源使用5V 2A模塊,一路單獨給舵機。

5. 軟件層
5.1 MQTT移值
這個直接參考連老師的這篇文章【如何在鴻蒙系統(tǒng)中移植 Paho-MQTT 實現(xiàn)MQTT協(xié)議】即可,感謝連老師!
本項目只需要將:服務器地址改為自己的IP、訂閱自己web端的Topic、提取消息數(shù)據(jù)。
主要代碼如下:
- /*連接web端 只展示主要邏輯,完整見附件*/
- int mqtt_connect(void)
- {
- //0.連接web端
- char* payload = "Hello Kun,have a Nice Day!";
- int payloadlen = strlen(payload);
- int len = 0;
- char *host = "192.168.xxx.xx"; //自己的ip
- int port = 1883; //mqtt服務端口
- mysock = transport_open(host, port);
- /* 1.訂閱web端話題 */
- topicString.cstring = "porsche";
- if (MQTTPacket_read(buf, buflen, transport_getdata) == SUBACK) /* wait for suback */
- {
- rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
- }
- /*2. 循環(huán)接收發(fā)布者的話題消息 */
- topicString.cstring = "hi3861";
- char door_passward[] ="notfound404"; //開門密令
- char cmd_msg[12]; //存儲web端發(fā)來的數(shù)據(jù)
- while (!toStop)
- {
- if (MQTTPacket_read(buf, buflen, transport_getdata) == PUBLISH)
- {
- MQTTString receivedTopic;
- rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
- &payload_in, &payloadlen_in, buf, buflen);
- for ( i = 0; i < payloadlen_in; i++)
- {
- cmd_msg[i]=*payload_in; //save message from MQTT web
- payload_in++; //pointer
- printf("%c",cmd_msg[i]);
- }
- printf("cmd_msg:%s\n",cmd_msg);
- }
- }
5.2 .舵機控制
Hi3861控制舵機之前【這篇文章】有配置過,調(diào)整20ms控制周期內(nèi)高電平的占空比模擬PWM代碼如下,進行了一下簡單的封裝,使用哪個IO口記得要初始化輸出即可。
- /** * @brief Servo control *
- @param servoID number of servo (GPIO) 7-8-9-10 *
- @param angle input value: 0-200 *
- */
- void My_servo(uint8_t servoID,int angle)
- {
- int j=0;
- int k=2000/200; //實際應該是2000/180
- angle = k*angle;
- for (j=0;j<5;j++)
- {
- GpioSetOutputVal(servoID, 1);
- hi_udelay(angle); //angle ms
- GpioSetOutputVal(servoID, 0);
- hi_udelay(20000-angle);//
- }//20ms 控制舵機
- }
5.3 業(yè)務邏輯
獲取web端數(shù)據(jù)、匹配開門密令是否一致、一致則開門、每次輸入密令可以開門三次、也可以一鍵上鎖。
項目完整工程見附件1主要代碼如下:
- /*邏輯代碼為了適應另外一個iot項目??雌饋肀容^臃腫,但能用*/
- int count =3; //開門次數(shù)
- switch (cmd_msg[0])
- {
- case 'a': //一鍵開門
- printf("up\n");
- cmd_msg[0]='n';
- break;
- case 'z': //一鍵上鎖
- printf("down\n");
- cmd_msg[0]='p';
- count = 3;
- break;
- case 's': //連接上led閃爍
- printf("Start\n");
- GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, 0);
- usleep(LED_INTERVAL_TIME_US);
- GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, 1);
- usleep(LED_INTERVAL_TIME_US);
- break;
- default:
- break;
- }
- if(!(strcmp(cmd_msg,door_passward)))
- {
- if(count)
- { count --;
- printf("Open the Door!\n");
- My_servo(10,100);
- }
- else count = 0;
- }
- else
- {
- printf("Close the Door!\n");
- My_servo(10,50);
- }
6. 測試 【見視頻-3min10s】

7. 其他案例
7.1 心率傳感器
使用I2C通信,查看數(shù)據(jù)手冊后,更具時許來讀取數(shù)據(jù),比較簡單,參考MPU6050的讀取方式。
這里展示一下讀取max30102原始數(shù)據(jù)的函數(shù),完整資源見附件2。代碼如下:
- /**
- * @brief Send Write command to MAX30102 device before Read a register.
- * @param regAddr the register address to Read or Writen.
- * @return Returns{@link IOT_SUCCESS} if the operation is successful;
- * returns an error code defined in {@link iot_errno.h} otherwise.
- * */
- uint8_t MAX_Cmd(uint8_t regAddr)
- {
- hi_i2c_idx id = MAX_I2C_IDX;
- uint8_t buffer[] = {regAddr};
- hi_i2c_data i2cData;
- i2cData.receive_buf = NULL;
- i2cData.receive_len = 0;
- i2cData.send_buf = buffer;
- i2cData.send_len = sizeof(buffer)/sizeof(buffer[0]);
- return hi_i2c_write((hi_i2c_idx)id, MAX30102_WR_address, &i2cData); //==發(fā)送器件地址+寫命令 + 寄存器regAddr
- }
- /**
- * @brief Read a data byte from MAX30102 device.
- * @param regAddr the register address. 8bit data
- * @return *data
- * */
- uint32_t MAX_Read_Data(uint8_t regAddr, uint8_t *data, unsigned int dataLen)
- {
- hi_i2c_idx id = MAX_I2C_IDX;
- hi_i2c_data i2cData;
- i2cData.send_buf = NULL;
- i2cData.send_len = 0;
- i2cData.receive_buf = data;
- i2cData.receive_len = dataLen;
- MAX_Cmd(regAddr); // write device add 0xAE + reg_ADD [目標寄存器]
- return hi_i2c_read((hi_i2c_idx)id, I2C_READ_ADDR, &i2cData);
- }
- /**
- * @brief read FIFO data in max30102 FIFO register 0x07
- *
- * @param RED_channel_data
- * @param IR_channel_data
- */
- void max30102_FIFO_Read_Data(uint8_t *RED_channel_data, uint8_t *IR_channel_data)
- {
- uint8_t buff[6]; //LSB
- /*組合數(shù)據(jù)
- uint8_t H,M,L;
- H=buff[0]&0x03; //bit17-bit16
- M=buff[1]; //bit8-bit15
- L=buff[2]; //bit0-bit7
- *RED_channel_data = (H<<16)|(M<<8)|L; */
- int res;
- res=MAX_Read_Data(REG_FIFO_DATA, &buff ,6);
- if(res == IOT_SUCCESS)
- {
- *RED_channel_data=((buff[0]<<16)|(buff[1]<<8)|(buff[2]) & 0x03ffff); //buff[0-2] 組合
- *IR_channel_data=((buff[3]<<16)|(buff[4]<<8)|(buff[5]) & 0x03ffff); //buff[3-5] 組合
- }
- }
讀取到的數(shù)據(jù):

7.2 Hi3861-潤和套件開發(fā)案例
套件的模塊除了NFC之外,其他都開發(fā)了一遍,不一一細說了,具體內(nèi)容見附件3-個人開發(fā)PPT。


結(jié)語:
NFC開門是不是更加便捷呢? 手里沒有運行HarmoneyOS的手機,軟總線方案技術上自己估計做不到,先做做硬件層的吧,下一步抽空實現(xiàn),只要有NFC功能的手機都可開門~估計得明年嘍
文章相關附件可以點擊下面的原文鏈接前往下載
https://harmonyos.51cto.com/resource/1627
https://harmonyos.51cto.com/resource/1628
https://harmonyos.51cto.com/resource/1629