LORA 射频自组网 两级中继

2023-05-16

基于sx1276lora模块,进行多个模块之间自组网,组网形式为1个集中器加多个终端。模块之间距离较远时,集中器无法直接与某个终端进行通信,其他终端本身可作为中继给该终端作为中继与集中器通信。lora调制方式,发送数据为星型通信方式,为自组网提供了便利。

终端接收心跳存储:

typedef struct
{
    uint32_t     Id;//接收的ID
    uint8_t      Rssi;//信号强度
}RECV_TERMINAL_T;

RECV_TERMINAL_T    RecvTerminal[RECV_NUM];

集中器接收心跳存储、发送路径存储:

typedef struct
{
    uint32_t     Id;//ID设备号
    uint8_t      index;// 
    uint8_t      relay;//
}TERMINAL_ID_LOCATION_T;

typedef struct
{
    uint32_t    Id[ROUTING_LAYERS];//接收的ID
    uint8_t     Rssi[ROUTING_LAYERS];//信号强度
}RECV_TERMINAL_T;

TERMINAL_ID_LOCATION_T  TerminalId[REGISTER_ID_NUM];  // 注册的终端ID 由配置传入   

RECV_TERMINAL_T         RecvTerminal[ ID_ROUTE_NUM];

1.1、路径存储形式:

二维数组RecvTerminal[i].Id[j];使用i表示所有不同的路径信息,j=0表示是直连、j=1即1级中继、j=2即2级中继。

集中器上的注册ID填写至结构体TerminalId;TerminalId.Id为注册ID,TerminalId.index为要发送到改地址的路径信息位置,TerminalId.relay为需要发送到该地址所需经过的中继层数。

1.2、终端处理流程:

终端定义每隔5分钟(时间根据测试修改)发送一次心跳报文。

在接收数据时,判断若是接收到心跳报文,则进行填本终端所接收到的心跳结构体RecvTerminal[n];

判断若是终端发送的非心跳报文,则进行判断,若报文目的地址非本地地址,则进行中继转发判断,判断本地地址是否为该报文中继,若是则进行转发判断到下一中继或者转发到目的地址;

判断若是集中器下发的报文,若目的地址为本地地址,则直接进行解包处理。若目的地址不为本地地址,则进行中继转发判断到下一中继或转发到目的地址。

终端回复集中器报文时,自动根据集中器下发的路径来巡回路径。

1.3、集中器端:

1.3.1 直连通信:

集中器接收到终端的心跳报文,则进行填表处理RecvTerminal[i++].Id[0],TerminalId.index=i,TerminalId.relay=0。若在集中器注册的ID存在接收不到心跳,则需要进行中继召唤处理,若能接收到全部心跳报文,则不进行一下处理。

1.3.2 一级中继:

集中器下发召唤命令到已填表的IDrecv=RecvTerminal[i++].Id[0],要求该IDrecv上送其所能接收到的心跳终端(RecvTerminal[n])。查询RecvTerminal里是否有存在集中器无接收到心跳的Idnorecv,若存在,则填表RecvTerminal[i++].Id[0]=IDrecv,RecvTerminal[i].Id[1]=Idnorecv;该Idnorecv的TerminalId.index=i,TerminalId.relay=1;表示集中器需要与Idnorecv通信时,需要通过终端IDrecv作为中继才能发送成功。

1.3.3 二级中继:

一级中继召唤命令完成后,依旧存在集中器注的IDnorecv接收不到心跳报文也无路径信息,即IDnorecv对应的结构体的index==0。则集中器下发召唤命令到已填表中TerminalId.relay为1的Idrecv,由于Idrecv的relay为1,则该终端本身需要通过一个中继终端RelayId作为中继来进行通信。集中器要求该Idrecv上送其所能接收到的心跳终端(RecvTerminal[n]),再根据终端回应的报文查询RecvTerminal里是否有存在集中器无接收到的心跳IDnorecv,若存在则填表RecvTerminal[i++].Id[0]=RelayId,RecvTerminal[i].Id[1]=Idrecv,

RecvTerminal[i].Id[2]=Idnorecv;该Idnorecv的TerminalId.index=i,TerminalId.relay=2。表示当集中器要与Idnorecv通信时,需要通过RelayId、Idrecv两级作为该终端中继才能通信成功。

1.3.4 集中器下发报文路径:

报文中包含relaynum中继个数,relayID具体的中继ID,即路径。例如需要通信ID=0x0001,0x0001对应的结构体TerminalId.Id=0x0001,TerminalId.index=5;

TerminalId.relay=2. 则集中器下发的报文中relaynum=2,relayID1=RecvTerminal[5].Id[0],

relayID2=RecvTerminal[5].Id[1]。如此集中器即能与0x0001通信。


终端部分代码:

#define    ROUTING_LAYERS     3
#define    REGISTER_ID_NUM    5
#define  RECV_NUM  10
typedef enum
{
    UPLOAD_TERMINAL_RELAY = 0x01,
}COMMAND_OPERATION_TYPE_E; // 命令操作类型


typedef enum
{
    UPLOAD_MESSAGE_FIRST_RELAY,
    UPLOAD_MESSAGE_SECOND_RELAY,

}COMMAND_PROCESSING_E; // 命令处理


typedef struct
{
    uint8_t           DevType;                      /* 设备类型*/    
    uint32_t          DevAddr;                     /* 设备地址 */     
    uint8_t           TypeId;                          /* 操作类型 例如遥控 遥测*/    
    uint8_t           Func;                             /* 功能码,例如具体遥控什么*/     
    uint8_t           RelayNum;//经过中继个数
    uint32_t          RfAddr;                       /* RF 地址*/
    uint8_t           Data[16];                      /* 数据域 */
    uint8_t           Len;                              /* data数据报文长度 */   
}MESSAGE_FORMAT_T; // message format 报文格式

typedef struct
{
    uint8_t           Buf[64]; 
    uint8_t           Len;                        /* 数据长度*/
    uint32_t          Addr;                       /* 远方地址*/
}MESSAGE_BUFFER;

typedef struct
{
    BYTE           Cache[MACRO_RFPROC_RECV_CACHE_SIZE];
    CircleQueue    Queue; 
}MESSAGE_QUEUE;

typedef struct
{
    uint32_t     Id;//接收的ID
    uint8_t      Rssi;//信号强度
}RECV_TERMINAL_T;

typedef struct
{
    uint8_t                 Num; // 注册终端ID个数 由配置传入
    uint8_t                 index; // 检测注册终端第index个是否收到心跳
    uint8_t                 Route;
    uint8_t                 NetworkFlag;// 开启组网标志
}REGISTER_TERMINAL_T;
    
typedef struct
{

    RECV_TERMINAL_T    RecvTerminal[RECV_NUM];

    uint8_t                 n;
    MESSAGE_FORMAT_T        SendFrame;              /* 发送帧数据*/
    MESSAGE_FORMAT_T        RecvFrame;                 /* 接收存放帧*/      
    MESSAGE_BUFFER          SendBuf;
    MESSAGE_QUEUE           RecvQueue;
}PROTOCOL_T;
extern __no_init PROTOCOL_T   g_ProData;

/*
 * 函数名称    :   HeartBeatPackets
 * 函数功能    :   心跳
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   无
 * 其它说明    :   5s发送一次
 * */
static void  HeartBeatPackets(void)
{
    uint8_t index = 0;
    uint8_t i = 0;
    uint8_t cs = 0;
    uint8_t TypeId = 0x55;
    g_ProData.SendBuf.Buf[index++] = 0x10;    
    g_ProData.SendBuf.Buf[index++] = TypeId;
    uint8_t *pAddr = (uint8_t *)&g_ProData.SendFrame.DevAddr;
    for(i = 0;i < 3;i++)
    {
        g_ProData.SendBuf.Buf[index++] = pAddr[3-i];
    }
    for(i = 1;i < index;i++)
    {
        cs += g_ProData.SendBuf.Buf[i];
    }
    g_ProData.SendBuf.Buf[index++] = cs;
    g_ProData.SendBuf.Buf[index++] = 0x16;    
    g_ProData.SendBuf.Addr = 0x00;
    g_ProData.SendBuf.Len = index;
    SX1276_Data->G_LoRaConfig.PayloadLength = g_ProData.SendBuf.Len;    
    Send();
}

/*
 * 函数名称    :   RF436_Unpack10
 * 函数功能    :   解包
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   成功返回true 失败返回FALSE
 * 其它说明    :   无
 * */
static bool Unpack10(void)
{   
    uint8_t cs = 0;
    uint32_t RfAddr = 0;
    static uint8_t i=0;
    
    ..........
     RfAddr = RF436_GetULongFromCache(&g_ProData.RecvQueue.Queue,2,3);
    if(i!=0)
    {
        for(int j=0;j<i;j++)
        {        
            if(RfAddr == g_ProData.RecvTerminal[j].Id) // 已存在 刷新数据
            {
                g_ProData.RecvTerminal[j].Id = RfAddr;
                g_ProData.RecvTerminal[j].Rssi = g_Sx1276.LoraParam.Rssi;
                
                CircleQueue_Remove(&g_ProData.RecvQueue.Queue,7);/* 读取完成一包,下移一包*/
                return TRUE;
            }   
        }  
        // 不存在 增加填表
        g_ProData.RecvTerminal[i++].Id = RfAddr;
        g_ProData.RecvTerminal[i].Rssi = g_Sx1276.LoraParam.Rssi;
        g_ProData.n = i;
    } 
    else
    {
        g_ProData.RecvTerminal[0].Id = RfAddr;
        g_ProData.RecvTerminal[0].Rssi = g_Sx1276.LoraParam.Rssi;
        i++;
        g_ProData.n = 1;
    }
    
    CircleQueue_Remove(&g_ProData.RecvQueue.Queue,7);/* 读取完成一包,下移一包*/
    return TRUE;
}  

/*
 * 函数名称    :   SendHeartBeatId
 * 函数功能    :   发送接收的心跳终端地址
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   无
 * 其它说明    :   集中器召唤时发送
 * */
static void SendHeartBeatId(uint8_t TypeId,uint8_t Func)
{
    uint8_t  index = 0;
    uint8_t  i = 0;
    uint8_t  cs = 0;
    g_ProData.SendFrame.DevType = 0x5e; 
    g_ProData.SendFrame.TypeId = UPLOAD_TERMINAL_RELAY;
    g_ProData.SendFrame.Func = UPLOAD_MESSAGE_FIRST_RELAY;
    g_ProData.SendFrame.RelayNum = 0;    
    g_ProData.SendFrame.Len = (g_ProData.n)*(sizeof(RECV_TERMINAL_T));    
    g_ProData.SendBuf.Buf[index++] = 0x68;
    index+=2;
    g_ProData.SendBuf.Buf[index++] = 0x68;
    g_ProData.SendBuf.Buf[index++] = g_ProData.SendFrame.DevType;
    index += RF436_GetBytesFromOther(&g_ProData.SendFrame.DevAddr,sizeof(ULONG), g_ProData.SendBuf.Buf + index,3); 
    g_ProData.SendBuf.Buf[index++] = g_ProData.SendFrame.TypeId;
    g_ProData.SendBuf.Buf[index++] = g_ProData.SendFrame.Func;
    g_ProData.SendBuf.Buf[index++] = g_ProData.SendFrame.RelayNum;
    index += RF436_GetBytesFromOther(&g_ProData.SendFrame.RfAddr,sizeof(uint32_t),g_ProData.SendBuf.Buf + index, 3);    
    memcpy(g_ProData.SendFrame.Data,&g_ProData.RecvTerminal,(g_ProData.n)*(sizeof(RECV_TERMINAL_T)));
    for(i = 0;i < g_ProData.SendFrame.Len;i++)
    {
        g_ProData.SendBuf.Buf[index++] = g_ProData.SendFrame.Data[i];/* pframedata[i];,..... */
    }
    for(i = 4;i < index;i++)
    {
        cs += g_ProData.SendBuf.Buf[i];
    }    
    g_ProData.SendBuf.Buf[index++] = cs;
    g_ProData.SendBuf.Buf[index++] = 0x16;
    g_ProData.SendBuf.Buf[1] = index-6;
    g_ProData.SendBuf.Buf[2] = index-6;
    g_ProData.SendBuf.Len = index;
    g_ProData.SendBuf.Addr = g_ProData.SendFrame.RfAddr;    
    Send();     
}

///

集中器部分代码

#define    ID_ROUTE_NUM       30 
#define    ROUTING_LAYERS     3
#define    REGISTER_ID_NUM    5
typedef enum
{
    UPLOAD_TERMINAL_RELAY = 0x01;
    
}COMMAND_OPERATION_TYPE_E; // 命令操作类型

typedef enum
{
    UPLOAD_MESSAGE_FIRST_RELAY = 0x10,
    UPLOAD_MESSAGE_SECOND_RELAY = 0x11,

}COMMAND_PROCESSING_E; // 命令处理

typedef enum
{
    COMMUNICATION_NONE,
    COMMUNICATION_NETWORK,
    
}COMMUNICATION_STATE_E; // 

typedef struct
{
    uint8_t           DevType;                    /* 设备类型*/   
    uint32_t          DevAddr;                    /* 设备地址 */     
    uint8_t           TypeId;                     /* 操作类型 例如遥控 遥测*/    
    uint8_t           Func;                       /* 功能码,例如具体遥控什么*/     
    uint8_t           RelayNum;//经过中继个数
    uint32_t          RfAddr;                     /* RF 地址*/
    uint8_t           Data[16]; /* 数据域 */
    uint8_t           Len;                        /* data数据报文长度 */   
}MESSAGE_FORMAT_T; // message format 报文格式
typedef struct
{
    uint8_t           Buf[64]; 
    uint8_t           Len;                        /* 数据长度*/
    uint32_t          Addr;                       /* 远方地址*/
}MESSAGE_BUFFER;
typedef struct
{
    BYTE           Cache[MACRO_RFPROC_RECV_CACHE_SIZE];
    CircleQueue    Queue; 
}MESSAGE_QUEUE;

typedef struct
{
    uint32_t    Id[ROUTING_LAYERS];//接收的ID
    uint8_t     Rssi[ROUTING_LAYERS];//信号强度
}RECV_TERMINAL_T;

typedef struct
{
    uint32_t     Id;//ID设备号
    uint8_t      index;// 
    uint8_t      relay;//

}TERMINAL_ID_LOCATION_T;

typedef struct
{
    TERMINAL_ID_LOCATION_T  TerminalId[REGISTER_ID_NUM];  // 注册的终端ID 由配置传入  
    uint8_t                 Num; // 注册终端ID个数 由配置传入
    uint8_t                 index; // 检测注册终端第index个是否收到心跳
    uint8_t                 Route;
    uint8_t                 NetworkFlag;// 开启组网标志
}REGISTER_TERMINAL_T;
    
typedef struct
{
    RECV_TERMINAL_T         RecvTerminal[ ID_ROUTE_NUM];
    REGISTER_TERMINAL_T     Register;
    
    COMMUNICATION_STATE_E   CommunicationState;
    MESSAGE_FORMAT_T        SendFrame;              /* 发送帧数据*/
    MESSAGE_FORMAT_T        RecvFrame;                 /* 接收存放帧*/      
    MESSAGE_BUFFER          SendBuf;
    MESSAGE_QUEUE           RecvQueue;
}PROTOCOL_T;
    
extern __no_init PROTOCOL_T   g_ProData;

/*
 * 函数名称    :   Unpack10
 * 函数功能    :   解包
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   成功返回true 失败返回FALSE
 * 其它说明    :   解包与终端填充方式不同
 * */
static bool Unpack10(void)
{   
    uint8_t cs = 0;
    uint32_t RfAddr = 0;

   ........................
    RfAddr = RF436_GetULongFromCache(&g_ProData.RecvQueue.Queue,2,3);
    SX1276_GetRecvRSSI();
    
    for(int j = 1;j < g_ProData.Register.Route;j++)
    {        
        if(RfAddr == g_ProData.RecvTerminal[j].Id[0]) // 已存在 刷新数据
        {
            g_ProData.RecvTerminal[j].Id[0] = RfAddr;
            g_ProData.RecvTerminal[j].Rssi[0] = g_Sx1276.LoraParam.Rssi;
                
            CircleQueue_Remove(&g_ProData.RecvQueue.Queue,7);/* 读取完成一包,下移一包*/
            return TRUE;
        }   
    }  
    // 不存在 增加填表
    g_ProData.RecvTerminal[g_ProData.Register.Route].Id[0] = RfAddr;
    g_ProData.RecvTerminal[g_ProData.Register.Route].Rssi[0] = g_Sx1276.LoraParam.Rssi;
    for(int j = 0;j < g_ProData.Register.Num;j++) // 填写直连通信路径
    {
        if(RfAddr == g_ProData.Register.TerminalId[j].Id )
        {
            g_ProData.Register.TerminalId[j].index = g_ProData.Register.Route;
            g_ProData.Register.TerminalId[j].relay = 0;
        }
    }
    g_ProData.Register.Route++; 
   
    CircleQueue_Remove(&g_ProData.RecvQueue.Queue,7);/* 读取完成一包,下移一包*/
    return TRUE;
}    

/*
 * 函数名称    :   
 * 函数功能    :   写入绑定终端ID
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   
 * 其它说明    :   无
 * */
static void RegisterId(void)
{
    
    g_ProData.Register.Num = 5;
    g_ProData.Register.TerminalId[0].Id = 0xA00001;
    g_ProData.Register.TerminalId[1].Id = 0xA00002;
    g_ProData.Register.TerminalId[2].Id = 0xA00003;
    g_ProData.Register.TerminalId[3].Id = 0xA00004;
    g_ProData.Register.TerminalId[4].Id = 0xA00005;
        
}
void StartNetwork(void)
{
    
    g_Data.Run.NetWorkTime = 120000; //120s
    g_Data.Run.Section1time = 30000; 
    
}
/*
 * 函数名称    :   NetworkContinueTime
 * 函数功能    :   组网持续时间
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   
 * 其它说明    :  
 * */
static void NetworkContinueTime(void)
{
    if(g_Data.Run.NetWorkTime)
    {
        g_ProData.Register.NetworkFlag = true;
    }
    else
    {
        g_ProData.Register.NetworkFlag = false;
    }  
}

/*
 * 函数名称    :   
 * 函数功能    :   
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   
 * 其它说明    :  
 * */
static void CheckAndCallTerminal(uint8_t i)
{
    if(g_ProData.Register.TerminalId[i].index == 0)// 判断是否存在有注册ID没收到心跳
    {
        if(g_Data.Run.Section1time)
        {
            Level1relay(); // 发送一级中继召唤
        }
        else
        {
            g_Data.Run.Section2time = 30000;
        }
         // 等待30s 后进行二级中继召唤     
        if(g_Data.Run.Section2time)// 阶段二
        {
             Level2relay(); // 发送二级中继召唤
        }
    }
}
/*
 * 函数名称    :   NetWorking
 * 函数功能    :   组网
 * 输入参数    :   无
 * 输出参数    :   无
 * 返 回 值    :   
 * 其它说明    :   间隔5分钟,或者在长时间无接收到某终端数据后进行调用 
                        组网时,阶段时间切换 3个时间,1、一级中继召唤时间 2、二级中继召唤时间 3、组网共花费时间
 * */
static void NetWorking(void)
{
    if(g_Data.Run.SystemTick < 15000) // 开机后接收15s心跳后在进行组网
    {
        return;
    }
    NetworkContinueTime();
    if((!g_Data.Run.DetectionTime) && (g_ProData.Register.NetworkFlag))
    {
        if(g_ProData.Register.index < g_ProData.Register.Num)
        {
            CheckAndCallTerminal(g_ProData.Register.index);
            g_ProData.Register.index++;
        }
        else
        {
            g_ProData.Register.index = 0;
        }
        g_Data.Run.DetectionTime = 3000; // 开启组网后 3s一次进入检测组网 
    }
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LORA 射频自组网 两级中继 的相关文章

  • PX4原生固件源码分析(挖坑)--1、代码结构

    写在开头 最近开始学习PX4源码 xff0c 并进行二次开发 xff0c 苦于网上缺少有关PX4源码的分析 xff0c 于是在这开个坑 xff0c 记录自己学习PX4的过程 xff0c 以此自勉 xff0c 笔者第一次写博客 xff0c 若
  • PX4原生固件源码分析(开填)--2、uORB消息

    写在开头 众所周知 xff0c PX4是通过Mavlink协议进行通信 xff0c 但是Mavlink只是用于外部的通信 xff0c 也就是和QGC地面站进行通信 xff0c 那么PX4中各任务模块相对独立 xff0c 它们之间是怎么通信的
  • 【超详细】基于大疆RoboMaster开发板C型的BMI088数据读取

    超详细 基于大疆RoboMaster开发板C型的BMI088数据读取 这里以博世传感器公司产出的BMI088型号的IMU为例 xff0c 其里面有3轴高精度加速度计和3轴高精度陀螺仪 xff0c 其他的特性不再介绍 同时这里的IMU是安装在
  • IMU综述

    IMU xff08 Inertial measurement unit xff09 xff0c 惯性测量单元 其作用是测量本身的加速度以及角速度 xff0c 有时还通过磁力计来测量朝向 xff0c 当包含磁力计时 xff0c IMU一般被称
  • 【超详细】磁力计数据读取--以IST8310为例

    这里以iSentek公司产出的IST8310型号的磁力计为例 xff0c 尺寸为 3 0 3 0 1 0mm xff0c 支持快速 I2C 通信 xff0c 可达 400kHz xff0c 14 位磁场数据 xff0c 测量范围可达1600
  • 【ADRC】扩张状态观测器(ESO)

    扩张状态观测器是自抗扰控制中非常重要的一个环节 xff0c 在我学习这部分内容后 xff0c 在写本篇文章时 xff0c 大致可以按照三个步骤来做实验 xff0c 推导 xff0c 由这三个步骤来由浅入深地去理解扩张状态观测器 ESO xf
  • 冰冻三尺非一日之寒-自学篇 浅谈个人学习方法

    昨晚还在看比赛 xff08 war3 xff09 xff0c 小源跑过来问我明天1024 xff0c 不写篇文章么 xff0c 想想也是 xff0c 1024这也算个热点 xff0c 赶紧来蹭蹭 xff0c 哈 xff0c 开个玩笑 上次谈
  • 栈中存储什么?

    一条线程对应一个栈 xff0c 一个方法对应一个栈帧 栈中 xff0c 存储的是一个一个的栈帧 xff0c 栈帧存储的是什么呢 xff1f 局部变量表 xff1a 存储的局部变量 xff0c 0位置代表this 操作数栈 xff1a 作用是
  • pdf导入pcb

    分为下面几步 xff1a 1 Illustrator 打开pdf 文件 导出为dxf 2 autocad 打开 xff0c 看看比例对不对 xff0c 缩放比例正确以后 xff0c 保存 旋转命令为rotate 测量为di 放大为sc 3
  • 如何在raspiberry pi上运行x86程序

    如何在raspiberry pi上运行x86程序 第一步 xff1a 下载ExaGear 步骤 xff1a 首选项 gt Add Remove Software gt 搜索ExaGear gt 下载搜索出来的四个包 第二步 xff1a 下载
  • 基于TINY4412的Andorid开发-------简单的LED灯控制【转】

    基于TINY4412的Andorid开发 简单的LED灯控制 阅读目录 Content 一 编写驱动程序二 编写代码测试驱动程序三 编写HAL代码四 编写Framework代码五 编写JNI代码六 编写App 参考资料 xff1a Andr
  • 计算机视觉——opencv-python

    opencv xff1a question1 10 main contentoriginal materialtrouble shootingq1 通道交换q2 灰度化q3 二值化q3 大津二值化算法 xff08 Otsu 39 s Met
  • 数字一阶低通滤波器simulink仿真

    数字一阶低通滤波器simulink仿真 原理程序所用公式滤波系数计算方法 仿真根据公式搭建使用simulink自带模型 原理 程序所用公式 y n 61 q x n 43 1 q y n 1 其中 xff0c y n 表示当前的输出 xff
  • SDFormat

    http sdformat org
  • putty远程连接不上虚拟机里的linux

    昨天跟着阿铭的视频在虚拟机中搭建了centos6 xff0c 然后用putty远程连接成功 今天中午鼓弄putty 的时候 xff0c 连接就报错了 xff1a network error xff1a connection refuse 网
  • 【ADRC】根据ADRC的思想改进PID

    根据前面两篇关于ADRC的文章以及PID原理的文章 xff0c 我们可以利用ADRC的思想来对PID算法做一些改进来看看效果 xff0c 可以将改进的PID称之为非线性PID 主要可以利用跟踪微分器 xff0c 针对PID的两个缺陷来进行改
  • STM32F1 TCA9548A 驱动多个IIC器件

    TCA9548A的用途就是IIC扩展 xff0c 每个TCA9548A可以扩展出8路IIC TCA9548A芯片带有地址选择引脚A0 A1 A2 xff0c 根据高低电平不同 xff0c 从MCU的一路IIC最多可以接入8个TCA9548A
  • 无限 for 循环的实现【Python】

    for 循环怎么才能无限循环下去呢 xff1f 1 最 low 的方法 xff1a 一个无限的列表 理解 for 在干什么 xff0c 在遍历 xff0c 那我们给他一个无限长的东西 xff0c 不就无限循环了 list span clas
  • VirtualBox 安装增强功能时无工具栏

    最近在学Ros xff0c 老师虚拟机用的是VirtualBox xff0c 在安装增强功能时 xff0c 找不到窗口顶部的工具栏 xff0c 如图 1 1所示 查了不少解决方案 xff0c 总结如下 图 1 1 Virtu alBox虚拟
  • Eigen库中的Identity()函数作用

    今天学习Eigen库 xff0c 看到示例代码中有这样一行 xff1a Matrix3d rotation matrix 61 Matrix3d Identity Matrix3d xff1a Eigen库中typedef的数据类型 xff

随机推荐

  • SLAM十四讲-ch3-vistalizegeometry编译问题

    最近在学高翔博士的 SLAM十四讲 xff0c 在ch3中运行vistalizegeometry这个demo的时候 xff0c 出现如下报错信息 xff08 图片版报错看不清的话 xff0c 文末 附文字版的报错信息 xff09 xff1a
  • C++库fmt缺失导致编译失败的解决方案【SLAM十四讲/ch4】

    最近学习高翔博士的SLAM十四讲 xff0c 学到ch4的时候 xff0c 实际运行demo报错 查看CMakeLists txt xff0c 发现Ubuntu20 04需要额外安装fmt库才可以编译通过 解决方法 xff1a 直接去fmt
  • SLAM十四讲编译全过程记录与错误与解决方案汇总

    章节目录 ch2 ch3 ch4 ch5 ch7 ch8 ch9 ch10 ch11 ch2 编译正常 xff0c log如下 xff1a slambook2 master ch2 mkdir build amp amp cd build
  • ROS安装:一键解决人生烦恼

    首先 xff0c 这个方法不是我发明的 xff0c 详情请见文末链接 不管你是unbuntu 16 18 20 xff0c 不管你是新安装的系统 xff0c 还是ROS装了一部分进行不下去的烂摊子都适用 xff01 直接输入下面这一行代码
  • 【Eigen库使用】角轴、旋转矩阵、欧拉角、四元数转换

    零 前言 在slam中经常用到的四种描述机器人orientation的变量 xff0c 他们之间可以相互转化 xff0c 使用Eigen库可以很容易的做到这一点 xff0c 需要特别关注的是 xff1a 欧拉角与其余量之间的转换关系 xff
  • 【Gazebo/ROS】阿克曼小车仿真环境设置中的心得体会

    最近科研需要在gazebo中做一个阿克曼小车的仿真 xff0c 要求小车运动能够通过话题来控制 xff0c 小车上要安装激光雷达 imu 相机等传感器用于SLAM定位建图 由于是第一次接触gazebo仿真 xff0c 所以分享一下学习心得
  • 【ADRC】自抗扰控制

    在根据前面四篇文章的自抗扰控制各个功能部分的分解介绍以及对于PID算法原理的分析之后 xff0c 具体可以查看我的主页 之后我们可以画出自抗扰控制的框图 xff0c 并作出自抗扰的仿真了 自抗扰的组成部分 ADRC说得更直白一些 xff0c
  • 【磕盐随记】对两种机器人ROS代码结构的思考与总结

    本帖看似短小 xff0c 但是凝结了我这一个月的全部心得体会 xff0c 日后打算专门出一期视频专门说说ros机器人的代码结构和类设计 xff0c 今天先在这里简单记录一下 到目前我接触过两种架构 xff0c 根据多节点式和单节点式 自己发
  • 【磕盐随记】IMU数据的运用——姿态R对时间t求导

    一 前言 IMU能够测量到三轴加速度和角速度 xff0c 那么如何在slam中使用imu测量得到的数据呢 xff1f Fast lio的论文中有很好的演示 xff1a 上述公式中 xff0c 最让我不能理解的就是这个 d R d
  • 【磕盐随记】Nodelet类的简明使用

    前言 一直不太懂ROS的Nodelet xff0c 今天佳爷给我拿他的 Elastic Tracker 作为例子给我讲了一下 xff0c 在此简单记录 xff0c 方便后续使用 一 Nodelet的工作原理 nodelet是用来方便ros的
  • 有功功率、无功功率、视在功率、功率因素

    有功功率 xff08 平均功率 xff09 P 61 UI cos 单位为W xff08 瓦 xff09 U单位V xff08 伏 xff09 xff0c I单位A xff08 安 xff09 无功功率 Q 61 UI sin 单位为Var
  • KEIL 生成bin文件 MDK 51 ram bin 文件

    使用keil做项目开发 xff0c 并且需要做IAP功能时 xff0c 就需生成bin文件 xff0c bin文件相比于hex文件更小 xff0c 一般用 bin文件作为升级文件 keil无法像iar一样通过工程设置直接输出bin文件 xf
  • ADC 采样数据抖动

    MSP430或STM32 xff0c 在使用内部ADC出现的采样数据异常抖动问题 采样设计 xff1a 用于检测供电线路电流及电压 产品运行在两种模式下 xff0c 1 低功耗静态模式 xff08 仓储态 xff09 xff0c 2 全功能
  • CC1310 基于CCS工程建立+Sensor Controller ADC

    基于TIRTOS xff0c PacketTx 43 Sensor Controller ADC 43 CCS工程建立 需要的工具 xff1a 1 simplelink cc13x0 sdk 3 20 00 23 CC1310的SDK xf
  • linux w5500 驱动及使用

    1 驱动 驱动来源 a 内核驱动 xff1b b xff1a 官方驱动 a 内核 xff1a linux内核w5500驱动 xff0c 包含两个源文件w5100 c和w5100 spi c kernel drivers net ethern
  • 扩展 IO pca95555 linux驱动 及使用

    驱动 xff1a 内核驱动 xff1a kernel drivers gpio gpio pca953x c make menuconfig配置编译 或拷贝出来手动编译成模块加载 设备树 xff1a 使用2个芯片 xff0c 在同一i2c总
  • Linux内核崩溃 dump调试

    内核 crash 崩溃 xff0c oops消息 xff0c dump oops xff08 也称 panic xff09 xff0c 称程序运行崩溃 xff0c 程序崩溃后会产生oops消息 应用程序或内核线程的崩溃都会产生oops消息
  • 【路径规划】VFH

    简介 在没有全局地图或者是应对动态障碍物的情况下 xff0c 往往是运用局部规划来进行绕障 xff0c 在局部规划的经典算法中 xff0c 比较常用的是 DWA 与 VFH xff0c VFH 全名向量场直方图算法 xff0c 不同于 DW
  • keil5 编译程序出现错误Error: L6411E: No compatible library exists with a definition of startup symbol __main

    Error L6411E No compatible library exists with a definition of startup symbol main 之前装过ADS xff0c ADS与MDK冲突 xff0c 依据网友提供的
  • LORA 射频自组网 两级中继

    基于sx1276lora模块 xff0c 进行多个模块之间自组网 xff0c 组网形式为1个集中器加多个终端 模块之间距离较远时 xff0c 集中器无法直接与某个终端进行通信 xff0c 其他终端本身可作为中继给该终端作为中继与集中器通信