当前位置:   article > 正文

这两天用鸿蒙开发板做了个“自动门锁”

usleep(led-interval-time-u s)

    关注、星标公众号,直达精彩内容

0680a28330ef1c14f96fe5d343c38064.png

来源|  鸿蒙技术社区

有一天半夜宿舍门被一个喝晕的哥们打开了,(说他晕吧他居然知道钥匙在门框上)于是有了设计自动门锁的想法。正好一直想用 Hi3861 做一个 IoT 落地项目,一切刚好!

bb5984698aac44dba916c19a61b9c17e.png

需求分析

如下:

  • 无钥匙进入

  • 手机端操作

  • 不影响使用钥匙开门

  • 无损安装、卸载自动开门机构

宿舍门锁考察

水平向右移动拉闩 1cm 左右即可开门,由于宿舍们老旧,拉力实测在 2.5L 水左右。

经过粗略计算,如果使用 9g 舵机来驱动,单杠驱动结构的话,杠杆长度比为 2500/9≈278,尺寸有些夸张。

不想在机械结构上费时间,所以选取大扭矩舵机驱动。

f8e7914a298e28174ee8f5123af36792.png

方案设计

①机械结构

典型的曲柄滑块结构。选取了绳索拉动、连杆方案。综合考虑耐用度和安装便携性,选取绳索驱动方案。

使用套壳的方式安装在门锁体上,拉闩自由移动,不影响手动开门。

847cacc0d9c0ab8536bb1c750fb73d75.png

②控制逻辑

Hi3861 根据 web 端发送过来的质量控制舵机转动即可。控制信号来源于 web 端,采用 MQTT 协议来处理数据,电源使用 5V 2A 模块,一路单独给舵机。

561e9b7967fc3df1c3b87591c68e9a88.png

软件层

①MQTT 移值

这个直接参考连老师的这篇文章《如何在鸿蒙系统中移植 Paho-MQTT 实现 MQTT 协议》即可,感谢连老师!

https://harmonyos.51cto.com/posts/1384

本项目只需要将:服务器地址改为自己的 IP、订阅自己 web 端的 Topic、提取消息数据。

主要代码如下:

  1. /*连接web端  只展示主要逻辑,完整见附件*/
  2. int mqtt_connect(void)
  3. {   
  4.       //0.连接web端
  5.     char* payload = "Hello Kun,have a Nice Day!";
  6.     int payloadlen = strlen(payload);
  7.     int len = 0;
  8.     char *host = "192.168.xxx.xx";  //自己的ip
  9.     int port = 1883;                //mqtt服务端口
  10.     mysock = transport_open(host, port);
  11.     /* 1.订阅web端话题  */
  12.     topicString.cstring = "porsche";
  13.     if (MQTTPacket_read(buf, buflen, transport_getdata) == SUBACK)  /* wait for suback */
  14.     { 
  15.         rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
  16.     }
  17.     /*2. 循环接收发布者的话题消息 */
  18.     topicString.cstring = "hi3861";
  19.     char door_passward[] ="notfound404"//开门密令
  20.     char cmd_msg[12]; //存储web端发来的数据
  21.     while (!toStop)
  22.     {
  23.         if (MQTTPacket_read(buf, buflen, transport_getdata) == PUBLISH)
  24.         {
  25.             MQTTString receivedTopic;
  26.             rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
  27.                     &payload_in, &payloadlen_in, buf, buflen);
  28.             for ( i = 0; i < payloadlen_in; i++)
  29.             {
  30.                 cmd_msg[i]=*payload_in; //save message from MQTT web
  31.                 payload_in++; //pointer 
  32.                 printf("%c",cmd_msg[i]);
  33.             }
  34.             printf("cmd_msg:%s\n",cmd_msg); 
  35.         }
  36. }

②舵机控制

Hi3861 控制舵机之前这篇文章有配置过:

https://harmonyos.51cto.com/posts/8645

调整 20ms 控制周期内高电平的占空比模拟 PWM 代码如下,进行了一下简单的封装,使用哪个 IO 口记得要初始化输出即可。

  1. /** * @brief  Servo  control *
  2.  @param servoID number of servo (GPIO) 7-8-9-10 * 
  3.  @param angle  input value: 0-200 *              
  4. */
  5. void My_servo(uint8_t servoID,int angle)
  6. {       
  7.      int j=0;    
  8.      int k=2000/200//实际应该是2000/180
  9.      angle = k*angle;    
  10.      for (j=0;j<5;j++)
  11.       {        
  12.            GpioSetOutputVal(servoID, 1);        
  13.             hi_udelay(angle); //angle ms        
  14.            GpioSetOutputVal(servoID, 0);        
  15.            hi_udelay(20000-angle);//    
  16.        }//20ms 控制舵机            
  17. }

③业务逻辑

获取 web 端数据、匹配开门密令是否一致、一致则开门、每次输入密令可以开门三次、也可以一键上锁。

项目完整工程见附件 1,主要代码如下:

  1. /*逻辑代码为了适应另外一个iot项目。看起来比较臃肿,但能用*/
  2. int count =3; //开门次数
  3. switch (cmd_msg[0])
  4. {
  5.     case 'a'//一键开门
  6.         printf("up\n");
  7.         cmd_msg[0]='n';
  8.         break;
  9.     case 'z'//一键上锁
  10.         printf("down\n");
  11.         cmd_msg[0]='p';
  12.         count = 3;
  13.         break;
  14.     case 's'//连接上led闪烁
  15.         printf("Start\n");
  16.         GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, 0);
  17.         usleep(LED_INTERVAL_TIME_US);
  18.         GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, 1);
  19.         usleep(LED_INTERVAL_TIME_US);
  20.         break;
  21.     default:
  22.         break;
  23. }
  24. if(!(strcmp(cmd_msg,door_passward)))
  25. {
  26.     if(count)
  27.     {   count --;
  28.         printf("Open the Door!\n");
  29.         My_servo(10,100);
  30.     }
  31.     else count = 0;
  32. }
  33. else 
  34. {
  35.     printf("Close the Door!\n");
  36.     My_servo(10,50);
  37. }

测试

d56daf72a834876d4ab76c0c5439b258.png

其他案例

①心率传感器

使用 I2C 通信,查看数据手册后,更具时许来读取数据,比较简单,参考 MPU6050 的读取方式。

这里展示一下读取 max30102 原始数据的函数,完整资源见附件 2。代码如下:

  1. /**
  2.  * @brief Send Write command to MAX30102 device before Read a register.
  3.  * @param regAddr the register address to Read or Writen.
  4.  * @return Returns{@link IOT_SUCCESS} if the operation is successful;
  5.  *  returns an error code defined in {@link iot_errno.h} otherwise.
  6.  * */ 
  7. uint8_t MAX_Cmd(uint8_t regAddr)
  8.     hi_i2c_idx id = MAX_I2C_IDX;
  9.     uint8_t buffer[] = {regAddr};
  10.     hi_i2c_data i2cData;
  11.     i2cData.receive_buf = NULL;
  12.     i2cData.receive_len = 0;
  13.     i2cData.send_buf = buffer;
  14.     i2cData.send_len = sizeof(buffer)/sizeof(buffer[0]);
  15.     return hi_i2c_write((hi_i2c_idx)id, MAX30102_WR_address, &i2cData); //==发送器件地址+写命令 + 寄存器regAddr 
  16. }
  17. /**
  18.  * @brief Read a data byte from  MAX30102 device.
  19.  * @param  regAddr the register address.  8bit data
  20.  * @return *data
  21.  * */
  22. uint32_t MAX_Read_Data(uint8_t regAddr, uint8_t *data, unsigned int dataLen)
  23. {
  24.     hi_i2c_idx id = MAX_I2C_IDX;
  25.     hi_i2c_data i2cData;
  26.     i2cData.send_buf = NULL;
  27.     i2cData.send_len = 0;
  28.     i2cData.receive_buf = data;
  29.     i2cData.receive_len = dataLen;
  30.     MAX_Cmd(regAddr); // write device add 0xAE + reg_ADD [目标寄存器]
  31.     return hi_i2c_read((hi_i2c_idx)id, I2C_READ_ADDR, &i2cData);
  32. }
  33. /**
  34.  * @brief read FIFO data in max30102 FIFO register 0x07
  35.  * 
  36.  * @param RED_channel_data 
  37.  * @param IR_channel_data 
  38.  */
  39. void max30102_FIFO_Read_Data(uint8_t *RED_channel_data, uint8_t *IR_channel_data)
  40. {
  41.     uint8_t buff[6]; //LSB
  42.     /*组合数据
  43.     uint8_t H,M,L;
  44.     H=buff[0]&0x03; //bit17-bit16
  45.     M=buff[1];      //bit8-bit15
  46.     L=buff[2];      //bit0-bit7
  47.     *RED_channel_data = (H<<16)|(M<<8)|L; */
  48.     int res;
  49.     res=MAX_Read_Data(REG_FIFO_DATA, &buff ,6);
  50.     if(res == IOT_SUCCESS)
  51.     {
  52.        *RED_channel_data=((buff[0]<<16)|(buff[1]<<8)|(buff[2]) & 0x03ffff);  //buff[0-2] 组合
  53.        *IR_channel_data=((buff[3]<<16)|(buff[4]<<8)|(buff[5]) & 0x03ffff);  //buff[3-5] 组合
  54.     }
  55. }

读取到的数据:

ae90af8eef27f8c7ac730bd71238c8cd.png

②Hi3861-润和套件开发案例

套件的模块除了 NFC 之外,其他都开发了一遍,不一一细说了,具体内容见附件 3-个人开发 PPT。

08c6124164c6bca8f40cfba35359cc18.png

c5d9354cb873deb8c8cb7e989b016fcd.png

结语

NFC 开门是不是更加便捷呢?手里没有运行 HarmoneyOS 的手机,软总线方案技术上自己估计做不到,先做做硬件层的吧,下一步抽空实现,只要有 NFC 功能的手机都可开门~估计得明年喽!

https://harmonyos.51cto.com/posts/9822

版权归原作者所有,如有侵权,请联系删除。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“加群”按规则加入技术交流群。
关注公众号,回复“pdf”获取程序员必读经典书单,一起编程一起进阶。
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/293903?site
推荐阅读
相关标签
  

闽ICP备14008679号