搜索

[uCOS/RTOS] 【RTOS】+ RTT大赛提交 +智能冰箱

[复制链接]
1472|0
 楼主 | 2020-7-2 11:01 | 显示全部楼层 |阅读模式
本帖最后由 北方西门吹雪 于 2020-7-6 13:38 编辑

【RT-Thread作品秀】智能冰箱
作者:北方西门吹雪


概述
      智能冰箱是通过采集冰箱内的温度变化,自动调节启动停止方式,实现节能的效果。
      使用的硬件是龙芯教育板。基于MIPS指令集的一款完全国产化的SoC集成芯片。搭载 2K1000 处理器(主频 1GHz),板载 DDR3 颗粒,实现 DDR3 的运行存储功能。实现了 GPIO 的输入输出,中断功能。板上集成 1 个网 口,集成 3 个 USB 接口,HDMI 接口,LCD 接口,音频输入/输出,集成 SD 卡接口,集成 2 个 CAN 接口,集成 RTC 计时功能。可以外扩 WIFI 模块。2K 龙芯派可以广泛应用于信息安 全、电力、轨道交通、工业控制、信号处理、数据通信、信息教育等领域。
搭载 2K1000 处理器(主频 1GHz),板载 DDR3 颗粒,实现 DDR3 的运行存储功能。实现了 GPIO 的输入输出,中断功能。板上集成 1 个网 口,集成 3 个 USB 接口,HDMI 接口,LCD 接口,音频输入/输出,集成 SD 卡接口,集成 2 个 CAN 接口,集成 RTC 计时功能。可以外扩 WIFI 模块。2K 龙芯派可以广泛应用于信息安 全、电力、轨道交通、工业控制、信号处理、数据通信、信息教育等领域,选择嵌入式应用是龙芯工业版的领域,这次使用的是龙芯教育版,更多是适合桌面系统。

      本项目实现的功能是实时采集环境温度,并根据温度变化及时调整智能冰箱的通断。
      补充说明:
      最初提出的设计方案,主要包括连接摄像头驱动,导入深度学习引擎tensorflowlite实现图像分割和图像分类的方式,自动记录冰箱内的物品。因为开发的时间短,提供的RTT硬件驱动只有GPIO和UART,因此主要的时间用在RTT的BSP部分开发,主要时间用于完成了I2C的驱动开发,智能完成智能冰箱温控的基本功能。
     RTT调试口使用RS232-UART0。同时编译调试需要进行如下修改,
rtconfig.py,使用自己安装后的路径。
#        EXEC_PATH   = r'D:\Development\DesignParks\codebench\bin'
修改SConstruct这个文件:
rtconfig.AFLAGS += ' -I' + RTT_ROOT + '/libcpu/mips/common'
rtconfig.AFLAGS += ' -I' + str(Dir('#'))
可以写入U盘,然后进入pmon加载
1. load /dev/fs/fat@usb0/rtthread.elf
2. 或者load (usb0,0)/rtthread.elf
3. g

RT-Thread使用情况概述
      RTT内核,使用了I2C,GPIO的硬件驱动,同时使用了thread线程管理,实现RTOS的基本功能。其他组件,软件包,均没有采用。主要是因为适应的驱动生态不够完善,也没有测试,短时还不具备使用条件。
     主要的工作在驱动编写和测试,因为驱动编写的过程比较长,所有按照反方向介绍,更容易理解。所以总结一下RTT的i2c驱动编写过程。
    1. RTT的驱动和开发板的驱动之间是需要一个函数连接,这样使用标准RTT的语句,就重定向到了开发板的专用驱动函数中。不同的硬件,需要不同的语句,对于I2C,需要执行的是总线注册,
rt_i2c_bus_device_register(&l2k_i2c->parent, "i2c0");
这个语句把如下结构体关联到了标准RTT的i2c语句中,
  1. static const struct rt_i2c_bus_device_ops l2k_i2c_ops =
  2. {
  3.   rt_i2c_master_xfer,
  4.   RT_NULL,
  5.   rt_i2c_bus_control
  6. };
复制代码

     在标准的RTT驱动中,i2c就是通过这样的注册过程,重定向到了在BSP目录下的对应driver。
    2. 然后就是上述对应函数的编写,
  1. rt_size_t rt_i2c_master_xfer(struct rt_i2c_bus_device *bus,  struct rt_i2c_msg *msgs,  rt_uint32_t num)
  2. {
  3.   struct l2k_i2c_bus * i2c_bus = (struct l2k_i2c_bus *)bus;
  4.   l2k_i2c_info_t i2c_info;
  5.   struct rt_i2c_msg *msg;
  6.   int i;
  7.   rt_int32_t ret = RT_EOK;
  8.   i2c_info.clock = 50000; // 50kb/s
  9.   i2c_info.I2Cx = i2c_bus->u32Module;
  10.   i2c_init(&i2c_info);
  11.   for (i = 0; i < num; i++)
  12.   {
  13.   msg = &msgs[i];
  14.   if (msg->flags == RT_I2C_RD)
  15.   {
  16.   i2c_send_start_and_addr(&i2c_info, msg->addr, L2K_I2C_DIRECTION_READ);
  17.   i2c_receive_ack(&i2c_info);
  18.   i2c_receive_data(&i2c_info, (rt_uint8_t *)msg->buf, msg->len);
  19.   i2c_send_stop(&i2c_info);
  20.   }
  21.   else if(msg->flags == RT_I2C_WR)
  22.   {
  23.   i2c_send_start_and_addr(&i2c_info, msg->addr, L2K_I2C_DIRECTION_WRITE);
  24.   i2c_receive_ack(&i2c_info);
  25.   i2c_send_data(&i2c_info, (rt_uint8_t *)msg->buf, msg->len);
  26.   i2c_send_stop(&i2c_info);
  27.   }
  28.   ret++;
  29.   }
  30.   return ret;
  31. }
复制代码

    在rt_i2c_master_xfer()函数中,   

3. 根据i2c的传输协议需要写入对应的地址和msg内容,并引用新的语句,如
i2c_send_start_and_addr(&i2c_info, msg->addr, L2K_I2C_DIRECTION_READ);  

代码如下,
  1. l2k_i2c_ret_t i2c_send_start_and_addr(l2k_i2c_info_t *i2c_info_p,  unsigned char slave_addr,  l2k_i2c_direction_t direction)
  2. {
  3.   void *i2c_base = i2c_get_base(i2c_info_p->I2Cx);
  4.   unsigned char data = 0;
  5.   if (!i2c_poll_status(i2c_info_p, L2K_I2C_STATUS_BUSY))
  6.   return L2K_I2C_RET_TIMEOUT;
  7.   data = (slave_addr << 1) | ((L2K_I2C_DIRECTION_READ == direction) ? 1 : 0);
  8.   reg_write_8(data , i2c_base + L2K_I2C_DATA_OFFSET);
  9.   i2c_cmd_start(i2c_info_p);
  10.   if (!i2c_poll_status(i2c_info_p, L2K_I2C_STATUS_TIP))
  11.   return L2K_I2C_RET_TIMEOUT;
  12.   return L2K_I2C_RET_OK;
  13. }
复制代码


4.   这时就开始接触到硬件部分了
    reg_write_8(data , i2c_base + L2K_I2C_DATA_OFFSET);
    这句直接对内存赋值,赋值的地址是在头文件中选择的基址,如,
#define I2C_BASE_ADDR 0xbfe01000
#define I2C0_OFF   0x0  //0x8 for I2C1, [11]bit of 1
#define I2C0_BASE CKSEG1ADDR(I2C0_BASE_ADDR + I2C0_OFF)

    5. 所以,小结一下就是,首先要按照芯片的手册,获得主要的外围设备访问地址以及控制逻辑。基本上都是大力出奇迹,用直接读写地址和寄存器数据更新的方法。然后,按照RTT的struct 结构体要求,封装控制函数,通过注册函数关联起来。
    6. 驱动编写完成,需要在ENV环境启动menuconfig先构建工程,使用i2c必须选择这个driver,否则在link的过程中显示无法找到 rt_i2c_bus_device_register(),
在配置好环境后,直接输入scons就生产二进制文件。
losoon_20.PNG
然后按照pmon管理的方式加载到内存,运行就可以显示结果了。
硬件框架
      硬件主要包括龙芯L2K开发板,12V-10A直流电源,驱动风扇和电机,半导体制冷片。
      调试引脚是RS232_UART_TX=59,RS232_UART_RX=60,
      温度传感器引脚I2C1_SDA=3,I2C1_CLK=5,
      冰箱开关控制 GPIO_07=7,
      公用引脚是P3V3=1,GND=9,
硬件框架图如下。
sf1.PNG
引脚的编号图,
lspins.PNG
采用的主要元件,
温度传感器
2069620648.jpg
组装的半导体制冷片,
1432663042.jpg 997950184.jpg
元件的整体连接图,
1799734915.jpg

软件框架说明
      软件采用RTT实现主要线程管理,并且实现基本的闭环控制,并具备升级到智能节能方案。
方案框图如下,
sf2.PNG

流程图如下,
sf3.PNG

软件模块说明
      软件部分包括2个并发的线程,第一个线程实现闭环的温度控制,第二个线程实现智能记录和节能管理。
     使用RTT,就需要使用thread功能,先创建两个thread-entry,然后启动线程管理就可以了。进入RTT编程阶段就非常简单和逻辑清晰了。

演示效果
使用scons编译通过,
ls_build.PNG
复制文件到U盘G:
ls_build_1.PNG
程序启动直接进入缺省的rtt文件,在SSD硬盘,
ls_build_2.PNG
启动后按C键,进入PMON,
ls_build_3.PNG
按照从u盘加载load之后运行的方式执行,进入smart_fridge的程序循环。

ls_build_4.PNG

代码地址代码在BSP目录下,直接scons就可以了。 Fridge.rar (1.62 MB, 下载次数: 3)

使用特权

评论回复

相关帖子

扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表