智能家居DIY连载教程(2)——在实际项目中运用消息队列与邮箱

MQ消息队列的使用(邮件的发送) MQ消息队列的使用(邮件的发送)MQ消息队列A:利用Maven加载相关的jar报,当然也可以自己写MQ,用来生产者的消息jms交给spring进行管理C、生产者配置D、创建生产者消息转换器E、消费者配置,监听器配置:消费者实现MessageListener接口 MQ消息队列 MQ是一种消息队列,目前流行的有RabbitMQ,ActiveMQ等,还有每个互联网公司通常都拥有自己的消息队列的Maven... 阅读详情

前言

千呼万唤始出来,智能家居 DIY 教程连载第二篇终于登场了!本文将重点给大家介绍如何将消息队列与邮箱运用到实际项目中去。一起来看看吧~

DIY

回顾上期:

1、智能家居DIY连载教程(1)——如何正确使用 Sensor 框架

1. 第二周任务回顾

我们来回顾一下第二周安排的任务:

1、通过 ENV 工具获取 nrf24l01软件包,并加载到 MDK 工程里面

2、了解多线程间的通信,了解 IPC 中邮箱和消息队列的特性,并能灵活使用,实现 ds18b20 线程与 nrf24l01 线程之间的数据通信

3、修改 nrf24l01 软件包,实现多点通信功能

上述任务的重点,是要学习去灵活运用邮箱和消息队列。

2. 软件包的获取

软件包可以通过 env 工具十分方便的获取到,并且加载到工程里面去,env 工具的下载链接可以在官网找到,env 下载链接:https://www.rt-thread.org/page/download.html (请复制至外部浏览器打开)env 的使用方法可以查看这里:https://www.rt-thread.org/document/site/tutorial/env-video/进行学习。

值得注意的是,在 env 中获取软件包是需要依赖于 git 的,可以去 git 官网获得下载,git 官网

本周任务中,我们需要用到 nrf24l01 的软件包,只需要在 menuconfig 中选中 nrf24l01 即可:

1RT-Thread online packages  --->
2    peripheral libraries and drivers  --->
3        [*] nRF24L01: Single-chip 2.4GHz wireless transceiver.  --->

选中之后需要将该软件包获取到本地来,在 env 中输入 pkgs --update 命令回车即可。我们在工程目录的 packages 目录下,可以看到,nrf24l01 软件包被获取到本地来了,如下图所示:

不过该软件包现在仅仅只是获取到本地,尚未加载到 MDK 工程当中来。我们在 env 中输入 scons --target=mdk5 命令回车即可,执行完该命令之后打开 MDK5 工程,发现 nrf24l01 软件包成功加载到工程里面去了,如下图所示:

3. IPC 之邮箱实战指南

3.1 为什么要使用邮箱

我们需要通过 nrf24l01 无线模块进行数据发送与接收,定义:通过 nrf24l01 发送数据的是发送节点,通过 nrf24l01 接收数据的是接收节点。(本 DIY 整个项目需要至少用到两个发送节点。)

在发送节点创建一个线程,用于无线发送数据。具体的,nrf24l01 的软件包提供了哪些 API,是如何通过这些 API 实现发送功能的,可以参考该软件包的 samples,路径为:...\packages\nrf24l01-latest\examples。

还记得第一周的任务吗?在 main 函数中创建了一个线程,用于获取 ds18b20 温度数据的。同理的,我们在 main 函数中再创建一个线程,该线程是用来通过 nrf24l01 发送数据的,线程入口函数是 nrf24l01_send_entry:

????滑查看全部

 1int main(void)
 2{
 3    rt_thread_t ds18b20_thread, nrf24l01_thread;
 4
 5    ds18b20_thread = rt_thread_create("18b20tem", read_temp_entry, "temp_ds18b20",
 6                                      640, RT_THREAD_PRIORITY_MAX / 2, 20);
 7    if (ds18b20_thread != RT_NULL)
 8    {
 9        rt_thread_startup(ds18b20_thread);
10    }
11
12    nrf24l01_thread  = rt_thread_create("nrfsend", nrf24l01_send_entry, RT_NULL,
13                                        1024, RT_THREAD_PRIORITY_MAX / 2, 20);
14    if (nrf24l01_thread != RT_NULL)
15    {
16        rt_thread_startup(nrf24l01_thread);
17    }
18
19    return RT_EOK;
20}

这时候,我们的程序当中就存在了两个线程了,ds18b20_thread 线程用来获取温度数据,nrf24l01_thread 线程用来向外无线发送温度数据,那么问题来了:

1、ds18b20_thread 线程如何将温度数据给 nrf24l01_thread 线程?

2、如果ds18b20_thread 线程采集温度数据过快,nrf24l01_thread 线程来不及发送,怎么办?

3、如果nrf24l01_thread 线程发送数据过快,ds18b20_thread 线程来不及采集温度数据,怎么办?

这时候,IPC 中的邮箱(mailbox)可以很好的解决以上问题。不过这里,我们需要将邮箱与内存池(mempool)搭配一起使用。往往而言,在实际项目中,邮箱和内存池这两个 IPC 是经常需要配套着一起使用的。为什么,且慢慢看来。

3.2 邮箱工作原理举例介绍

RT-Thread 的文档中心已经有对邮箱和内存池原理上的详细讲解。这里不在赘述。这里通过举一个生活中的例子,去帮助大家理解邮箱和内存池。

如今,很多人购物都是通过电商平台购买,那避免不了是要收快递的。

图片来源网络

我们拟定一个生活场景。小区内放置有快递柜,快递柜里面有很多快递箱,快递箱里面可以存放快递,快递员把快递存放到快递箱之后,会发短信通知你过来取快递,还会告诉你编号是多少,通过编号你可以找到你的快递存放在快递柜的哪个快递箱里面。

上面这个模型中有几个名词,我们抽取出来:快递、快递柜、快递箱、快递员、你自己、短信、编号。

我们将上面这个生活场景和 IPC 中的邮箱和内存池一一对应起来:

  • 快递:采集到的温度数据

  • 快递柜:内存池

  • 快递箱:内存池里面的内存块

  • 快递员:ds18b20_thread 线程

  • 你自己:nrf24l01_thread 线程

  • 短信:邮箱中的一封邮件

  • 编号:内存块地址指针

邮箱和内存池的使用,其实和上面那个收快递的生活场景是一样的:

  • 在程度的一开始,即 main 函数中,我们创建一个邮箱和一个内存池

  • 在ds18b20_thread 线程里:

  • 1、首先,每当该线程采集到一个温度数据(有快递来了),就在内存池里面申请一个内存块(快递员找一个空快递箱)

    2、然后,把本次采集到的这个温度数据放到内存块里(快递放入快递箱),再把内存块的地址放在邮箱里

    3、最后,邮件发送出去(发短信告知用户)

  • 在nrf24l01_thread 线程里:

  • 1、首先,接收ds18b20_thread 线程发送过来的邮件(用户收到短信)

    2、然后,根据邮箱中的存放的地址,知道了当前温度数据存放在哪个内存块里面,也就是说,nrf24l01_thread 线程找到了(收到了)当前温度数据。(根据短信里的编号知道快递放在哪里了)

    3、最后,用完了这个内存块要及时释放掉(快递取出来了,快递箱空了)

3.3 在项目中运用邮箱

通过代码解读一下。

main 函数中创建一个邮箱和一个内存池是这么做的:

????滑查看全部

1tmp_msg_mb = rt_mb_create("temp_mb0", MB_LEN, RT_IPC_FLAG_FIFO); /* 创建邮箱 */
2tmp_msg_mp = rt_mp_create("temp_mp0", MP_LEN, MP_BLOCK_SIZE);    /* 创建内存池 */

ds18b20_thread 线程的入口函数是 read_temp_entry,如下:

 1static void read_temp_entry(void *parameter)
 2{
 3    struct tmp_msg *msg;
 4    rt_device_t dev = RT_NULL;
 5    rt_size_t res;
 6
 7    dev = rt_device_find(parameter);
 8    if (dev == RT_NULL)
 9    {
10        rt_kprintf("Can't find device:%s\n", parameter);
11        return;
12    }
13
14    if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK)
15    {
16        rt_kprintf("open device failed!\n");
17        return;
18    }
19    rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100);
20
21    while (1)
22    {
23        res = rt_device_read(dev, 0, &sensor_data, 1);
24        if (res != 1)
25        {
26            rt_kprintf("read data failed!size is %d\n", res);
27            rt_device_close(dev);
28            return;
29        }
30        else
31        {
32            /* 申请一块内存 要是内存池满了 就挂起等待 */
33            msg = rt_mp_alloc(tmp_msg_mp, RT_WAITING_FOREVER);
34            msg->timestamp = sensor_data.timestamp;
35            msg->int_value = sensor_data.data.temp;
36            rt_mb_send(tmp_msg_mb, (rt_ubase_t)msg);
37            msg = NULL;
38        }
39        rt_thread_mdelay(100);
40    }
41}

在上述代码中,该线程采集到一个温度数据之后,就会在内存池中申请内存块:

1msg = rt_mp_alloc(tmp_msg_mp, RT_WAITING_FOREVER);

将温度数据存放到刚刚申请到的内存块里面:

1msg->int_value = sensor_data.data.temp;

将这个存放着温度数据的内存块的地址给邮箱,然后发送邮件:

1rt_mb_send(tmp_msg_mb, (rt_ubase_t)msg);

nrf24l01_thread 线程的入口函数是 nrf24l01_send_entry,如下:

 1static void nrf24l01_send_entry(void *parameter)
 2{
 3    struct tmp_msg *msg;
 4    struct hal_nrf24l01_port_cfg halcfg;
 5    nrf24_cfg_t cfg;
 6    uint8_t rbuf[32 + 1] = {0};
 7    uint8_t tbuf[32] = {0};
 8
 9    nrf24_default_param(&cfg);
10    halcfg.ce_pin = NRF24L01_CE_PIN;
11    halcfg.spi_device_name = NRF24L01_SPI_DEVICE;
12    cfg.role = ROLE_PTX;
13    cfg.ud = &halcfg;
14    cfg.use_irq = 0;
15    nrf24_init(&cfg);
16
17    while (1)
18    {
19        rt_thread_mdelay(100);
20
21        if (rt_mb_recv(tmp_msg_mb, (rt_ubase_t*)&msg, RT_WAITING_FOREVER) == RT_EOK)
22        {
23            if (msg->int_value >= 0)
24            {
25                rt_sprintf((char *)tbuf, "temp:+%3d.%dC, ts:%d",
26                           msg->int_value / 10, msg->int_value % 10, msg->timestamp);
27            }
28            else
29            {
30                rt_sprintf((char *)tbuf, "temp:-%2d.%dC, ts:%d",
31                           msg->int_value / 10, msg->int_value % 10, msg->timestamp);
32            }
33            rt_kputs((char *)tbuf);
34            rt_kputs("\n");
35            rt_mp_free(msg); /* 释放内存块 */
36            msg = RT_NULL;   /* 请务必要做 */
37        }
38        if (nrf24_ptx_run(rbuf, tbuf, rt_strlen((char *)tbuf)) < 0)
39        {
40            rt_kputs("Send failed! >>> ");
41        }
42    }
43}

在上述代码中,nrf24l01 软件包提供了发送数据的 API nrf24_ptx_run。

该线程接收ds18b20_thread 线程发送过来的邮件,并收到了温度数据:

1rt_mb_recv(tmp_msg_mb, (rt_ubase_t*)&msg, RT_WAITING_FOREVER)

将温度数据发送出去:

1nrf24_ptx_run(rbuf, tbuf, rt_strlen((char *)tbuf))

用完的内存块释放掉:

1rt_mp_free(msg);
2msg = RT_NULL;

还有两个问题没有解答:

1、如果ds18b20_thread 线程采集温度数据过快,nrf24l01_thread 线程来不及发送,怎么办?

2、如果nrf24l01_thread 线程发送数据过快,ds18b20_thread 线程来不及采集温度数据,怎么办?

这两个问题其实就是解决供过于求和供不应求的问题。

有没有留意到,申请内存块的代码上有一个 RT_WAITING_FOREVER,接收邮件的代码上也有一个 RT_WAITING_FOREVER。

这两个 RT_WAITING_FOREVER 就是用来解决上面两个问题的。

当内存池满了的时候,再也申请不到内存块了,这时候申请内存块里面的 RT_WAITING_FOREVER 会使得 ds18b20_thread 线程阻塞,并挂起,然后 MCU 就会去干别的事情去了,不断的在 nrf24l01_thread 线程中发送存放在内存池中的温度数据,并释放掉内存块。等一有内存块可以申请了,ds18b20_thread 线程被唤醒,又会往里面塞数据了。

同理的,如果内存池是空的,里面没有数据,接收邮件里面的 RT_WAITING_FOREVER 会使得nrf24l01_thread 线程阻塞,并挂起,然后 MCU 就会去干别的事情去了,在 ds18b20_thread 线程中采集温度,并申请内存块塞数据进去,内存块一旦有数据,就会发邮箱,另外一边一有邮箱收到了,就又开始工作了。

4. IPC 之消息队列实战指南

4.1 为什么要使用消息队列

在本次 DIY 中,消息队列其实也是用来解决以下问题的:

  • ds18b20_thread 线程如何将温度数据给 nrf24l01_thread 线程?

  • 如果ds18b20_thread 线程采集温度数据过快,nrf24l01_thread 线程来不及发送,怎么办?

4.2 消息队列工作原理举例介绍

消息队列一般来说,不需要搭配内存池一起使用,因为消息队列创建的时候会申请一段固定大小的内存出来,作用其实和邮箱+内存池是一样的。

每个消息队列对象中包含着多个消息框,每个消息框可以存放一条消息,每个消息框的大小是一样的,存放的消息大小不能超过消息框的大小,即可以相同,可以小于。

类比生活中的例子,存钱罐,发工资了(纸币),把一张张的钱放到存钱罐里去,你自己或者你对象需要花钱了,就从存钱罐里面取钱出来用。

更多对消息队列的讲解,请查看 RT-Thread 文档中心,链接:https://www.rt-thread.org/document/site/programming-manual/ipc2/ipc2/#_13。

4.3 在项目中运用消息队列

因为文章篇幅原因,这里不把代码放出来了,可打开工程查看。工程源码是已经开源了的,链接会在下面给出。

在 main 函数中创建消息队列:

1tmp_msg_mq = rt_mq_create("temp_mq", MQ_BLOCK_SIZE, MQ_LEN, RT_IPC_FLAG_FIFO);

在 ds18b20_thread 线程中转载数据并发送消息队列:

1msg.int_value = sensor_data.data.temp;
2rt_mq_send(tmp_msg_mq, &msg, sizeof msg);

在 nrf24l01_thread 线程中接收消息队列:

1rt_mq_recv(tmp_msg_mq, &msg, sizeof msg, RT_WAITING_FOREVER)

上面这个 RT_WAITING_FOREVER 作用是为了解决下面这个问题,原理和邮箱中的介绍一样:

如果ds18b20_thread 线程采集温度数据过快,nrf24l01_thread 线程来不及发送,怎么办?

即而当消息队列是空的时候,可以挂起读取线程。当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。

5. nrf24l01 的多通道数据接收

nrf24l01 的多通道数据接收与其底层驱动相关,会在后期单独写一篇文章介绍放到 GitHub 上,敬请期待。

6. 结果

这里只是展示三个发送节点的情况,接收节点这边代码上已经把六个节点全部支持了。手头板子够多的话,把六个发送节点全部弄出来也是OK的。

7. 开源代码

为了更进一步便于大家学习,第二周任务的代码已经开源啦:https://github.com/willianchanlovegithub/DIY_projects_base_on_RT-Thread(以上链接复制至外部浏览器打开)

加入智能家居DIY交流群,请添加小师妹为好友

 

#题外话# 喜欢RT-Thread不要忘了在GitHub上留下你的STAR哦,你的star对我们来说非常重要!链接地址:https://github.com/RT-Thread/rt-thread

RT-Thread


让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。Apache2.0协议,可免费在商业产品中使用,不需要公布源码,无潜在商业风险。

长按二维码,关注我们

看这里,求赞!求转发!

点击阅读原文进入GitHub

FIFO实现任意大小队列FIFO 采用C程序实现任意大小的FIFO 立即下载

相关推荐

RTThread邮箱实验.rar

基于博客中Rt-Thread学习笔记-----邮箱(八)的测试工程。里面包含RTThread的互斥量的例程(基于Stm32F103Zet6、Keil5、rtthread3.1.3)

智能家居DIY教程连载(1) ——如何正确使用 Sensor 框架

Hi~各位小伙伴们,距离 DIY 项目的发布已经有一周的时间了,第一周的任务已经完成了吗?会不会遇到了问题无从下手?没关系,这篇文章很好的解决了大家的困惑,一起来看看吧。 1. 第一周任务回顾 我们来回顾一下第一周安排的任务: 正确读取 ds18b20 温度数据 了解 RT-Thread 的 Sensor 框架,并将 ds18b20 对接到 Sensor 框架上 了解线程的使用,创建一个线程,在...

FILLMOREad的博客 778

【RT-Thread作品秀】基于RT-Thread的数据采集-电路方案

概述:这是一个数据采集的装置,本身没有什么亮点。主要是基于RT-Thread操作系统,驱动NB模块-BC26来实现数据的发送。值得一说的是RT-Thread本身有BC-26的驱动包。不过这里并没有使用,而是使用at-device软件包来驱动的BC26。因此稍微改一改内部的代码,就能驱动其他的AT设备。话回正题,我使用at-thread的目的就是驱动BC26建立TCP或UDP连接,使得板卡采集得到的数据能发送到我电脑上的TCP Server。当然,除了数据上传之外,也能实现上位机控制板卡。还有则是在代码中发现利用邮箱+消息队列来进行数据传输和通信真的很爽。 开发环境:硬件部分 ART-Pi (主控) BC-26 (NB-IOT模块) BHT11 (温湿度传感器) RT-Thread版本 RT-Thread V4.0.2 开发工具及版本 RT-Thread Studio V2.0.0 :RT-thread推出的IDE,免费。 Putty V0.73:开源免费的一款工具,我纯把他当成串口助手使用 花生壳 V5 :内网穿透工具。 网络调试助手(MetAssist V4.3.13):网上下的,应该比较出名。 RT-Thread使用情况描述:内核部分 调度器 消息队列 邮箱 组件部分 at_device UART 硬件框架描述先附图一张: 很简单的一个框架,总共只有主控,传感器,执行器,以及比较重要的云平台,这四大部分。传感器可以是任意传感器,只要发送的数值种类不一次性超出两种即可。执行器我在这里使用了板载的LED灯充当。云平台则是利用网络调试助手搭了一个TCP Server来充当。由于我个人没有固定外网IP,所以我如果直接使用网络助手,是无法将ART采集得到的数据传输到我的电脑上的。因此我利用花生壳将我的IP映射到了外网,使得板卡能连接到我创建的TCP Server上。 软件框架说明流程图如下: 本人并不是很会画流程图,所以辛苦大家看一看介绍吧。 其实在这个板卡中是要烧两套程序的,一套是bootloader负责初始化QSPI并且运行QSPI内的程序。所以这份程序是下载到片内Flash的。另一份则是具体的功能添加的比较多的程序。他是运行在QSPI中的。这两个程序必须先运行BootLoader否则QSPI中的程序是无法运行的。而由于BootLoader的职责是让程序从0x08000000跳转到0x90000000运行所以,如果QSPI中没有其他程序的话,Bootloader只会运行一次,表现的现象就是只打印一个LOGO。 其实在RT-Thread中其实有BC26的驱动包,可以直接拿来用,不需要自己再对BC26进行初始化,但是我这里使用的是at_device驱动包,所以自己要写一部分的代码,进行初始化。创建邮箱和消息队列则是为了两者相互配合一起实现发送同步消息的功能。 数据采集线程和数据发送线程之间使用消息队列+邮箱的方式实现消息同步,在这里数据采集线程可以有多个,而数据发送线程我这设立了一个。发送线程会将接收到的信息都发送到云平台中。 数据接收则是利用at_device中的代码实现的。利用内部的代码还可实现云平台发送消息控制板卡上的LED灯或者其他执行器。 软件模块说明消息队列+邮箱的消息同步方式 在使用消息队列+邮箱的方式来进行线程间消息同步的话需要先创建一个结构体,一个动态邮箱,一个消息队列。然后对结构体进行填充后利用消息队列发送出去,具体请看以下代码示例: //创建结构体部分 struct msg //消息队列发送此结构体的地址来实现线程间的同步 { char *str; int vol; float data1; int data2; struct rt_mailbox* ack; }; //创建动态邮箱部分 rt_mailbox_t mail_box1 = RT_NULL; //创建二氧化氮线程应答邮箱控制块 rt_mailbox_t mail_box2 = RT_NULL; //创建二氧化硫线程应答邮箱控制块 rt_mailbox_t mail_box3 = RT_NULL; //创建粉尘数据线程应答邮箱控制块 rt_mailbox_t mail_box4 = RT_NULL; //创建备用线程邮箱控制块 /**************创建多个应答邮箱******************/ int move_mail_box_sample(void) { mail_box1 = rt_mb_create("mail_box1", 1, RT_IPC_FLAG_FIFO); //创建动态邮箱1 mail_box2 = rt_mb_create("mail_box2", 4, RT_IPC_FLAG_FIFO); //创

智能家居 DIY 教程连载4——手把手教你连云

云乃万物互联之本Hi,各位小伙伴,DIY 活动已经来到了尾声,第四周的任务是整个项目中最有趣也是最重要的部分——物联网。本周的任务完成之后,也就意味着整个项目就完全做完啦,是不是迫不及待...

rtthreadiotos的博客 765

【RT-Thread作品秀】快递分拣设备--前端伸缩机-电路方案

快递分拣设备--前端伸缩机简介伸缩皮带输送机的使用,缩短了人工往返搬运物料的距离,可以缩短货物装卸货时间,降低劳动强度,减少货品损伤,降低装卸成本,提高工作效率,伸缩皮带输送机最先用于物流快递,烟草行业。目前伸缩机一般都用PLC来实现,一旦量大了,对于设备厂商来说,价格贵是一方面;还有很多客户想实时得知设备的运行状态,所以做了这款可以联网的伸缩机。 硬件说明本项目,主要实现ARTPI控制系统,执行系统,网络系统。控制系统驱动网络系统与上位机通信。上位机通过指令的发送,通过控制系统来控制执行系统完成伸综缩机上升,下降,伸出,缩回等功能;上位机也可以实时读取当前设备的运行状态。 开发环境 硬件:ART-PI 扩展板:控制底板,W5500网络模块 RT-Thread版本:RT-Thread V 4.0.3 开发工具及版本:MDK 5.26 RT-Thread使用情况概述内核部分:调度器,信号量,消息队列。 调度器:创建多个线程来实现不同的工作。 信号量:用来同步线程。 消息队列:用来实现线程之间传递的数据。 组件部分:SPI框架, SAL 套接字抽象层,LWIP 软件包:WIZnet,netdev,network-sample 本项目主要是两块功能: 1.网络通信 工控行业,还是以有线传输为主。本项目主要采用W5500网络模块,设备为TCP SERVER,与上位机通信,上位机为TCP CLIENT。采集当前信号状态。 2.输入输出控制 检测信号的输入和控制信号的输出。 软件框架说明程序开始,等待各个模块的初始化成功,主任务同时在查询两个队列,一个是输入信号队列是否有数据过来,另外一个是网络队列是否有数据请示。如果有则进行处理,没有则任务实时查询。 软件模块的说明: 1.网络通信任务:TCPPROCESS_TASK(void *parameter) 主要是实时获取上位机的数据,与上位的数据进行收发处理。 2.输入输出任务: main(void) 主要检测IO口的输入输出功能。 3.信号处理任务:MASTER_TASK(void *parameter) 主要是通过接收前面两个任务的信号量,进行数据的判断并数据发送。 硬件现场图视频: 比赛感悟非常感谢这次RT-Thread公司能够提供ART-PI开发板,而且ART-PI非常适合上手,技术支持也做得非常到位。以为一直对RTThread这个系统用得不是很熟练,因为我们公司主要是以做工控为主的,基本上都 是以FreeRTOS为主,因为FreeRTOS更加贴近底层,自己更好掌握,用了RTThread,因为封装了太多层了,生怕万一出了什么问题解决不了。通过这次的大赛,使我增加了对使用RTThread系统 的信心,因为软件包真的太好用了,当然也希望有更多的人,包括自己能够有能力和机会分享和维护软件包。最后感谢主办方提供了这么好的一个平台!

树莓派4B串口舵机控制全攻略:从pigpio库安装到Python脚本调试

本文详细介绍了如何在树莓派4B上通过pigpio库和Python脚本实现串口舵机的精确控制。从硬件串口配置、pigpio库安装到舵机通信协议解析和Python脚本开发,提供了完整的解决方案和调试技巧,适用于机械臂控制等实际项目应用。

k8s6orchestrator的博客 430

[嵌入式系统-58]:RT-Thread-内核:线程间通信,邮箱mailbox、消息队列MsgQueue、信号Signal

目录 线程间通信 1. 邮箱 1.1 邮箱的工作机制 1.2 邮箱控制块 1.3 邮箱的管理方式 (1)创建和删除邮箱 (2)初始化和脱离邮箱 (3)发送邮件 (4)等待方式发送邮件 (5)发送紧急邮件 (6)接收邮件 1.4 邮箱使用示例 1.5 邮箱的使用场合 2. 消息队列 2.1 消息队列的工作机制 2.2 消息队列控制块 2.3 消息队列的管理方式 (1)创建和删除消息队列 (2)初始化和脱离消息队列 (3)发送消息 (4)等待方式发送消息 (5)发送紧

文火冰糖(王文兵)的博客 3498

雷达回波仿真

文章目录前言一、基础理解1.慢时间维度和快时间维度2.脉冲压缩3.MTI4. 脉冲多普勒处理5.cacfar检测二、具体流程1.产生回波信息加入目标时延以及噪声2.解调回波得到基带信号3.脉冲压缩 MTI MTD cafar检测 前言 雷达算法仿真学习,主要流程包括生成目标回波,将基带信号加在载波上其次是加上目标信息和干扰信号后发射,解调回波信号得到基带信号然后MTI,MTD,最后再检测。 一、基础理解 1.慢时间维度和快时间维度 连续M个脉冲回波经过相干解调之后的基带数据形成的一个二维数据矩阵,.

qq_42961235的博客 1万+

RTT(RT-Thread)线程间同步(保姆级)

线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1,如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据time参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。此时线程2可以获取到信号量2,开始执行,执行完之后信号量2自动减1,然后释放信号量1,信号量1加1,然后线程1又开始执行了。那么不管是线程1还是线程2,谁先执行临界区,都会先获取信号量,然后信号量value减1,变成0;

qq_25218501的博客 1660

ROS2+PYTHON VENV虚拟环境配置方法

ROS2+PYTHON VENV配置方法本篇针对的是python。

下雨夏云的博客 556

MacBook 上 LaTeX 环境搭建:从 Mactex 到 Sublime Text 与 Skim 的保姆级配置流程

本文详细介绍了在MacBook上搭建LaTeX环境的完整流程,从Mactex安装到Sublime Text与Skim的配置优化。涵盖基础环境准备、编辑器设置、PDF预览同步等关键步骤,帮助用户快速建立高效的LaTeX工作流,特别适合学术写作和技术文档创作。

weixin_30824599的博客 681

基于 RT-Thread 的智能家居 DIY 教程连载(2)——在实际项目中运用消息队列与邮箱

RT-Thread 的邮箱与内存池实战指南 在实际项目中灵活运用邮箱与内存池 千呼万唤始出来,智能家居 DIY 教程连载第二篇终于登场了!本文将重点给大家介绍如何将内存池与邮箱运用到实际项目中去。一起来看看吧~ 目录 本文文章目录如下,通过以下内容,给大家剖析第二周的任务重点难点。 第二周任务回顾 软件包的获取 IPC 之邮箱实战指南(重点) 3.1 为什么要使用邮箱...

MRccCHEN的博客 1577

从气象预报到物流规划:多尺度地理加权回归(MGWR)在ArcGIS Pro中的实战应用

本文深入探讨了多尺度地理加权回归(MGWR)在ArcGIS Pro中的实战应用。通过对比传统GWR模型,MGWR的核心优势在于能识别不同解释变量的独特空间作用尺度,有效解决空间异质性问题。文章结合气象预报误差修正与物流网点选址两个案例,详细讲解了从数据准备、参数设置、带宽优化到结果解读的全流程,为地理数据分析师处理复杂空间数据提供了强大工具。

egg99的博客 1032

文件系统灵活用——智能家居DIY连载教程3

Hi,各位小伙伴,DIY 活动已经来到了第三周!前两周的任务大家都完成了吗?本周将会迎来新的挑战——文件系统。本文将从 SPI Flash 和 SD Card 两方面给大家讲解如何使用文...

rtthreadiotos的博客 302

ESP32 Arduino学习篇 (一) 引脚和串口的基本使用

简单来讲arduino就是通过源代码控制开发板的信号输入输出从而实现对一些电子元件的控制,例如LED灯,蜂鸣器,按键arduino程序首先来讲arduino程序是基于C语言,而实现类似对于LED灯和蜂鸣器的简单控制只需简单C语言知识即可实现。arduino程序是基于函数的,而在arduino的库有很多函数,我们只需要调用即可。arduino的程序主体是**setup()函数和loop()**函数以及其它在使用过程中需要构建的函数:setup()函数。

DOF526570的博客 1万+

FUXA实战:5步搞定基于Web的SCADA系统搭建(含Node.js版本避坑指南)

本文提供了一份基于开源工具FUXA搭建Web版SCADA系统的实战指南。文章重点解析了从环境准备到生产部署的五个核心步骤,并特别强调了Node.js版本选择对西门子S7 PLC通信兼容性的关键影响,帮助开发者避开常见陷阱,快速构建工业监控界面。

weixin_29172963的博客 140

嵌入式使用RTOS到底是不是大势所趋?

嵌入式设备网络化、功能复杂化的趋势,使越来越多的、过去可以用裸奔实现的嵌入式产品,产生了应用操作系统的需求。芯片成本的连续下降,以及cpu性能和内存资源...

Peter的专栏 1005

新一代XMOS会议四麦方案主控芯片 XVF3800

2023年,知名的音频芯片制造厂商 XMOS 正式发布了新一代会议麦阵芯片片 XVF3800 ,这款芯片采用最先进的四麦音频算法,可在嘈杂的环境中提供高质量语音,算法支持圆形、条形阵列,可根据应用场景组成不同的产品形态。传统的麦阵解决方案,不仅需要捕捉会议中的人声,也会同时捕捉环境中的其他噪声,而 XMOS 先进的语音算法解决了这一问题。声学回声消除功能可消除麦克风音频输入的回声,同时减少远端回声,使 XVF3800 能提取清晰的语音信号。• 180度拾音条形麦克风阵列。• 360度拾音环形麦克风阵列。

PawPaw_electron的博客 784

【文章回看】公众号系列文章合辑

感谢大家的关注,在这里提前祝您五一劳动节快乐~本期我们特别筛选了公众号历史推送中部分的精彩内容,欢迎大家回看!目前公众号内容包括但不限于(由于内容太多只能筛选部分系列内容,有其他需要的小...

FILLMOREad的博客 817

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

rt-thread入门之旅(二)—— rt_kprintf的实现

学习rt-thread主要是为了后期直接拿来玩几个项目,同时rt-thread有很多借鉴linux的地方,很适合用来学习分层架构,因此更多的是介绍实现思想,而不是实现细节。本着不重复造轮子的原则,如果有看到其他写的很好的地方,会直接放链接,不再赘述。最后分析下来,rt_kprintf的本质其实很简单,主要复杂在rt-thread为了平台适配隔离,给做的一套框架,因此学习rt-thread对我来说主要就是了解这个框架。总的来说,其实就是linux的框架的简单版本。

“社会大学三年级”的博客 2777

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

RT-Thread内核基础

RT-Thread内核基础 1、RT-Thread 内核介绍 下图为 RT-Thread 内核架构图,内核处于硬件层之上,内核部分包括内核库、实时内核实现。 实时内核的实现包括:对象管理、线程管理及调度器、线程间通信管理、时钟管理及内存管理等等,内核最小的资源占用情况是3KB ROM,1.2KB RAM。 1.线程调度   线程是 RT-Thread 操作系统中最小的调度单位,线程调度算法是基于优先级的全抢占式多线程调度算法,即在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外

yunshengbixiao的博客 1298

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

消息邮箱和消息队列

参考:http://bbs.youkuaiyun.com/topics/290026540 邮箱是一个通过在系统共享存储区内传递消息来实现同步和通信的对象。 每个邮箱包含一个用于发送消息的消息队列和一个用来接受消息的消息队列。由于是在共享存储区域,因此它对每个任务都是可见的。 而一般的消息队列,还可用来处理任务与外部事件之间的通信。比如一个按键消息。然后其中一个任务可以在消息队列中尝试去获取消息

s_sunnyy的博客 1万+

UCOSII-消息邮箱与消息队列

本文介绍了消息邮箱和消息队列的原理及使用方法,消息邮箱是消息队列的特殊情况,因此可以看做一起,消息对垒在任务之间进行消息(指针)传递应用方便,供大家参考,谢谢!

tutu_hu的博客 7005

RT-THREAD 内核快速入门(四)邮箱,消息队列,信号

系列文章目录 RT-THREAD 内核快速入门(一)线程 RT-THREAD 内核快速入门(二)定时器 RT-THREAD 内核快速入门(三) 信号量,互斥量,事件 文章目录系列文章目录前言一、邮箱工作方式二、队列工作方式1.引入库2.读入数据总结 前言 这是这是快速入门系列的第四篇,也就是编程篇里面最后的倒数第二篇,之后还有一个内存管理篇,这两篇完成就是深入篇,也就是原理篇。理解原理能够帮助更好的编程和调试。 这篇是线程间的通信,也就是线程间的数据传递与前篇的同步稍微不一样。同步一般不涉及线程间的数据

weixin_46185705的博客 7777

RTOS消息队列和邮箱区别

消息队列可以发送多条消息,消息邮箱只能发送一条消息;消息队列遵守FIFO特性,只能一条一条读和写 在rtx系统里面,消息邮箱就是消息队列。

天使也有爱 8744
上一篇: FreeModbus 应用笔记(1)——如何在潘多拉开发板上运行 Modbus 主机
下一篇: FreeModbus 应用笔记(2)——运行 Modbus 从机并使用网络通信
RT-Thread物联网操作系统
博客等级 码龄6年 2万+粉丝 392原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值