发动态
图文
列表
智慧校园,然而在今年2021年来看,原本行业做2.4G学生卡+校徽等等的厂家用量明显有大幅度下滑。经过调查,早在前几年就已经有迭代化产品在部署,才会导致原有的产品在新的一年没有继续上涨。这就是现在所要讲学生卡片机(电子学生证),在2019年中旬,部发布2G即将关掉,迎来的是一波想要用4G来代替2G的想法,但是怎么实现呢?成本是明显增加的,而且怎么推动呢?如果只是跟原有的系统一样,只要发送信息给家长通讯,那用4G是不是很鸡肋?刚好在2021年教育部接着公布,严谨中小学生带进入校园。这就解决了用4G区替代2G最直接的一个说辞了。电子学生证与学生白卡/校徽的区别:1.在每个学校的校门口安装2.4G-ID远距离刷卡检测设备。通过2.4G识别器A和B对学生进出学校进行判别。2. 每个学校的2.4G远距离刷卡考勤监测设备连接到集中式管理平台的考勤机/短信服务器,方便监控设备和考勤信息接收。3. 学生只需在进出校门时,佩戴用2.4G有源电子标签卡+Mifare1 S50制作的非接触复合“学生卡”即可实现远距离刷卡考勤。电子学生证的种种应用方式以及系统其实大同小异的。都是3方合作,运营商+终端厂家+学校!所以对于运营模式来讲,没人会在乎需求量冲突,只希望能跟着新产品的变化,稳固自己现有的市场。毕竟新的东西起来,必是有因素,都有他存在的道理。从2019年往前几年看,早有挺多厂家在研发这一种学生卡片机,有些大佬有大概估算了一些整个市场投入资金不少于两个亿!不过皇天不负有心人,2021年开始某些地区学校已经用上了。重点不止是解决学生进去校门做考勤,具有GPS+北斗定位,让学生校内校外的人生安全得到更进一步保障,情亲通话(结合运营的优惠套餐,实现一年365天免费打电话)。增加了移动支付,坐公交 图书馆借阅 食堂吃饭 饮水统一一牌搞定,sos一键警报报警,拥有所谓的白名单,设置,拒绝陌生来电,保护学生安全。进而很多人可能在想,那卡片机电量这块如何保证,看起来很耗电,一般都是充满即可用1-2周时间,所以在原有跟我司合作SI24R2E做白卡/校徽的客户群体,在新的卡片机应用,我们是更加推荐用SI24R2F,这款芯片是R2E的迭代
有源RFID SI24R2-------校园学生考勤
硬创社
有一些朋友问到有没有开源的printf直接可以拿来用的,不想再重复造轮子了,一些老维护项目软件架构也不能随便换,只是想加入这个组件方便以后排查问题,那当然是有的,毕竟开源界的道友们还是非常无私的。那么接下来就给大家推荐三个轮子,后续自己根据实际项目需求进行修一修基本就能用了~1、xprintfxprintf 是一个紧凑的字符串 I/O 库。 它非常适用于程序存储器不足以用于常规 printf 函数的微型微控制器。 推荐的用途是:将格式化的字符串写入 LCD 或 UART 以及用于调试/维护控制台。可以使用配置选项配置 xprintf 以减小模块大小。下表显示了 Cortex-M3 (gcc -Os) 中代码大小的示例。 long long 和 float 需要 C99 或更高版本。源码和使用说明都在如下路径:http://elm-chan.org/fsw/strf/xprintf_j.html2、lwprintflwprintf-Lightweight printf library optimized for embedded systems,lwprintf是针对嵌入式系统优化的轻量级 stdio 管理器。 用 C 语言 (C11) 编写,实现了与 printf、vprintf、snprintf、sprintf 和 vsnprintf 兼容的输出函数,只需要几 kB 的非易失性存储器,较低的内存占用,适用于嵌入式系统.并且对所有 API 函数的可重入访问,能够在多个线程打印到同一输出流可选支持,还允许多个输出流函数(与仅支持一个输出流函数的标准不同)来分离应用程序的各个部分。所以整体lwprinf功能的选择会更加的丰富,而且这个项目文档案例也比较丰富,根据自己的情况进行功能的选择,挺香的。开源地址如下:https://github.com/MaJerle/lwprintf
开源轻量级printf,修一修就能跑~
开源硬件平台
大家好,我是bug菌,又见面了~最近在做设计评审时,下面工程师在对用UDP和TCP中展开了激烈的讨论,而一个同事发表了这样的观点:"能用TCP绝不用UDP,UDP实在是太不靠谱了~"说实在的我也很理解,但是对于这样的言论也容易误导人,导致很多初学者在尝试使用UDP设计的时候,只要出现一些埋得比较深的问题就会一棍子把UDP给拍死,这是我觉得不应该的。其实UDP并没有那么不靠谱。1、UDP数据包首先我们看看UDP的数据包格式,数据内容本身的正确性是由UDP的**校验和(Checksum)**机制保证的:如果数据包在传输中发生比特错误(如电磁干扰),接收端会直接丢弃该包,不会将错误数据传递给应用层。然而UDP的“不可靠”主要是如下三点:不保证数据包到达(可能丢包)不保证顺序性(可能乱序)不主动控制发送速率(可能拥塞丢包)所以有些数据错乱问题的过,真不该让UDP来背,往往有时候就是自己设计的应用层逻辑设计不当。比如下面常见的一些场景:场景1:乱序未处理• 问题:接收端先收到后发送的包(如视频流的第2帧早于第1帧到达)。• 根因:应用层未实现乱序重组逻辑,直接按接收顺序处理数据。• 改进:在数据包头部添加序列号(Sequence Number),由应用层缓存并排序。场景2:分包/合包逻辑缺失• 问题:发送端传输了超过MTU的大数据包,IP层自动分片,但接收端未正确处理。• 根因:应用层未实现手动分包/合包逻辑,依赖IP分片(可靠性差)。• 改进:在应用层主动将大数据拆分为≤1472字节的块,并为每个块添加序号和偏移量。场景3:未区分丢包与延迟• 问题:误将延迟较高的包视为丢失,导致逻辑错误。• 根因:未设置合理的超时重传机制。• 改进:为关键数据添加ACK确认与重传,非关键数据允许丢弃(如实时音视频)。2、丢包原因其实UDP的丢包主要还是与网络环境有关,网络拥塞:路由器缓冲区溢出时,UDP包被优先丢弃(TCP会主动降速,UDP不会)。链路质量差:无线网络(如Wi-Fi、4G)易受干扰,物理层丢包率上升。IP分片丢失:若数据包超过MTU被分片,任一碎片丢失会导致整个UDP包不可用。虽然会丢包,但丢包 ≠ 数据错乱, 丢包只会导致部分数据缺失(如视频卡顿、语音中断),不会破坏已接收数据的正确性,数据内容错误,已被UDP校验和过滤。3、可靠的UDP协议设计从前面UDP的结构大家就知道,其实它挺简洁的,UDP既然不解决这些问题,那就应用层去弥补,说实在有更多的灵活度。UDP应用层需解决乱序、完整性、丢包三个问题就本上就比较靠谱了。比如传输协议中增加一些字段:| 序列号 (4B) | 时间戳 (4B) | 载荷长度 (2B) | 载荷数据 (N B) | 为了处理乱序、重复、丢包检测等问题。对于一些关键数据添加ACK确认与重传,一些实时数据丢包了也没关系,就不需要应答了~最好是避免IP分片,控制数据包大小≤1472字节(假设MTU=1500),大数据传输时,主动在应用层分包并添加序号。如果你加快异常时的收发效率,可以采用前向纠错(FEC),通过发送冗余数据包,允许接收端通过算法恢复部分丢失数据(如RTP协议中的FEC机制)。
UDP通信哪有那么不靠谱呀~
硬创社
2、cjson在单片机中的主要应用1、动态配置管理痛点:传统配置方式需将参数硬编码在代码中,修改配置需重新编译固件,无法动态更新。解决方案:将配置存储在JSON文件中,通过cJSON解析,增删都很方便,有较好的兼容性,支持OTA动态更新,当然还是会占一些内存。示例代码:解析Wi-Fi配置// config.json { "wifi": { "ssid": "MyIoT", "password": "123456" }, "sampling_interval": 5000 } voidload_config(void){ // 从Flash或SD卡读取JSON文件 char *json_str = read_file("config.json"); cJSON *root = cJSON_Parse(json_str); cJSON *wifi = cJSON_GetObjectItem(root, "wifi"); char *ssid = cJSON_GetObjectItem(wifi, "ssid")->valuestring; char *password = cJSON_GetObjectItem(wifi, "password")->valuestring; int interval = cJSON_GetObjectItem(root, "sampling_interval")->valueint; printf("Wi-Fi: %s/%s, 采样间隔: %dms\n", ssid, password, interval); cJSON_Delete(root); free(json_str); } 2、设备间通信协议痛点:自定义二进制协议调试困难,扩展性差。解决方案:使用JSON定义通信指令,可读性不错,方便调试扯皮,扩展性不错增删都能够较好兼容。下面的例子是一个非常有意思的玩法,作为参数动态扩展。示例代码:解析控制指令// 收到指令:{"cmd": "set_led", "args": {"id": 1, "brightness": 80}} voidhandle_command(const char *json_str){ cJSON *root = cJSON_Parse(json_str); char *cmd = cJSON_GetObjectItem(root, "cmd")->valuestring; if (strcmp(cmd, "set_led") == 0) { cJSON *args = cJSON_GetObjectItem(root, "args"); int id = cJSON_GetObjectItem(args, "id")->valueint; int brightness = cJSON_GetObjectItem(args, "brightness")->valueint; led_set(id, brightness); // 实际控制函数 } cJSON_Delete(root); } 3、本地数据存储与日志记录痛点:传感器数据若以二进制格式存储,导出后需专用工具解析。解决方案:将数据序列化为JSON字符串,直接存储为文本文件。示例代码:记录温度数据voidlog_sensor_data(float temp, float humidity){ cJSON *root = cJSON_CreateObject(); cJSON_AddNumberToObject(root, "temp", temp); cJSON_AddNumberToObject(root, "humidity", humidity); cJSON_AddStringToObject(root, "timestamp", "2023-08-15T14:30:00Z"); char *json_str = cJSON_PrintUnformatted(root); // 紧凑模式节省空间 write_to_sd_card("log.json", json_str); free(json_str); cJSON_Delete(root); } 3、使用过程的注意事项1、要注意调用cJSON_Delete()和free()及时的释放资源,防止内存泄漏,不然跑着跑着就奔了~。2、想省一些内存和带宽,json相关的命名最好不要太长。3、cjson支持cJSON_ParseWithOpts流式解析,这在解析大型JSON时比较有用。每接收到一部分数据即可立即解析,无需等待全部数据到达,算是一种低延时的增量处理。而且对于单片机的RAM资源有限,一次性加载大型JSON字符串可能导致内存溢出。有了流式解析后,解析完部分数据后,可立即释放相关内存,维持低内存占用。(完结)
老听说json,在单片机软件开发中有啥用?(下)
硬创社
#DIY设计##创享2025##嘉立创##畅聊专区#今天跟大家聊聊json这玩意,json说实在的bug菌也是后面联网的项目越来越多才用上了这玩意,玩物联网和智能硬件的朋友应该用得比较多。这不最近一个"小项目"又把这玩意拿过来用用,整体还是挺舒适的,主要是json易读也比较容易把握,那顺便聊聊吧~1、什么是cjson在资源受限的单片机上解析JSON,开发者常面临内存不足、解析性能差等问题,所以在单片机上用cjson比较合适,一款专为嵌入式设计的开源JSON解析库,设计简洁高效,用得挺多的。下面简单介绍下cjson:cJSON是由Dave Gamble开发的超轻量级C语言JSON解析库,代码仅一个.h和一个.c文件,完全开源,专为嵌入式环境优化。 GitHub地址:https://github.com/DaveGamble/cJSON核心特点• 极简内存占用:解析时仅需几KB内存,适合RAM稀缺的单片机(如STM32F103、ESP8266)。• 纯C实现:无第三方依赖,跨平台支持(Keil、IAR、GCC均可编译),就两个文件,移植起来太简单了。• 易用性:API简洁,10分钟即可上手。• 灵活性:支持动态创建、修改、序列化和反序列化JSON数据。下面是简单的cjson使用示例 :1. 示例代码:创建JSON并输出字符串#include"cJSON.h" voidcreate_json(void){ // 1. 创建根对象 cJSON *root = cJSON_CreateObject(); // 2. 添加键值对 cJSON_AddStringToObject(root, "device", "ESP32"); cJSON_AddNumberToObject(root, "temperature", 25.6); // 3. 添加嵌套对象 cJSON *location = cJSON_CreateObject(); cJSON_AddNumberToObject(location, "lat", 35.6895); cJSON_AddNumberToObject(location, "lon", 139.6917); cJSON_AddItemToObject(root, "location", location); // 4. 生成JSON字符串 char *json_str = cJSON_Print(root); printf("JSON: %s\n", json_str); // 5. 释放内存(重要!) free(json_str); cJSON_Delete(root); } 输出结果:{ "device": "ESP32", "temperature": 25.6, "location": { "lat": 35.6895, "lon": 139.6917 } } 2. 解析JSON数据voidparse_json(constchar *json_str){ cJSON *root = cJSON_Parse(json_str); if (root == NULL) { printf("JSON解析失败!\n"); return; } // 提取字段 cJSON *device = cJSON_GetObjectItem(root, "device"); cJSON *temp = cJSON_GetObjectItem(root, "temperature"); cJSON *location = cJSON_GetObjectItem(root, "location"); printf("设备名: %s, 温度: %.1f\n", device->valuestring, temp->valuedouble); printf("经纬度: (%.4f, %.4f)\n", cJSON_GetObjectItem(location, "lat")->valuedouble, cJSON_GetObjectItem(location, "lon")->valuedouble); cJSON_Delete(root); } 由于字数限制,请看下篇~~~~~
老听说json,在单片机软件开发中有啥用?(上)
硬创社
大家好,我是bug菌~大家在网上应该经常有看到机器狗,机器人动起来需要反复的原地踏步,或者是转个弯都得多踏几次步,会给一种机械味很重的感觉。那么今天bug菌将跟大家聊一些这种跺脚深层次一点的原因,解解惑~1、人类胜利与机器困局人体站立平衡人类的平衡是神经系统、生物力学与多感官整合的精密协作: 看似静止的站立实为动态调控,人体如同倒置钟摆,依赖肌肉持续张力(非单纯跟腱弹性)维持基础支撑,同时通过多层级神经反馈(脊髓反射30-50ms延迟+脑部200ms高级整合)快速修正失衡,并以前馈机制预判风险(如预收紧肌肉)。前庭系统捕捉低频晃动(<0.1Hz),视觉追踪高频位移(>1Hz),足底触觉提供实时接触信息,三者滤波融合后消除环境干扰。修正动作实际频率仅1-3Hz,高频震颤(5-15Hz)多为肌肉被动振荡,而“每秒百次调节”实为跨时间尺度的协同控制(脊髓毫秒级微调+脑部秒级策略优化),所以人体平衡是多模态实时调控体系,属实复杂。机器人平衡人玩过平衡车的都知道,基本上都是闭环反馈控制,只是相对控制会更加复杂一点,bug菌画了张示意图,如下:可以说这个数字闭环中的每个环节都在积累误差,最终都必须通过物理运动来消除不确定性。2、工程现实问题根据现有技术,要做机器人不得不面临着各种现实的问题。首先对于反馈系统,传感器的性能品质是要直面的问题,精度、准度、噪声等稳定性,现在IMU采用的加速度噪声都不小,及时再小的误差经过积分运算,长时间也会导致较大的位置漂移,这说明了为何算法上需要周期性重定位。既然简单聊了传感器,该谈一下执行结构了,执行机构的非线性是非常影响控制效果的,如下是人类的肌肉与电机特性,简单那比较:这导致电机必须持续运动来补偿静态误差,如同相机防抖的微动机制。最后肯定是控制算法了,如果单纯用经典控制,像PID、频率法,相对就比较吃力,难以处理多变量耦合、非线性(如柔性关节摩擦)和强干扰环境。由于需要处理动态平衡和复杂的地形适应,通常需要更高级的控制策略。例如,模型预测控制、阻抗控制、以及基于强化学习的自适应控制。这些方法属于现代控制理论,甚至超越传统现代控制,进入智能控制的范畴。但在一个大系统中然而可以看到经典控制的身影,比如一些电机的控制等单输入单输出(SISO)的控制模块。然而经典控制理论中的摩擦极限环现象:当系统存在静摩擦时,PID控制必然引发小幅振荡,为克服静摩擦,控制器必须主动注入能量,这正是跺脚动作的能量来源。虽然现代控制通过非线性建模、实时补偿和优化预测,理论上可根除经典摩擦极限环,但在工程实践中仍需权衡模型精度、计算负载和硬件限制。3、机器人剁脚的好处大家有学习过在现代控制理论的话,就一定会接触到观测器,如果不运动,反而系统相关状态变量是不可观测的。非线性掩盖效应静摩擦力、齿轮间隙等非线性因素在静止时主导系统行为,掩盖真实动力学特性。例如,关节静摩擦力可能被观测器误判为外部负载,导致状态估计偏差。传感器信息局限常规传感器(如编码器)在静止时仅提供位置数据,无法直接测量速度、摩擦力等隐含状态。若无动态激励,观测器无法通过微分或滤波推算隐藏变量。 那也就无法较好的控制,所以机器人老剁脚就是因为就是一种主动的进行扰动注入,然后从噪声中提取信息,这样也就增加了系统对环境感知能力,噪声扰动成为系统辨识的探针,研究控制理论的确实是一帮天才。当然还有一些其他好处,比如运动起来的冲击能量被循环用于运动控制,机械振动转化为可存储电能等等。运动不仅是控制目标,更是感知手段——通过动态暴露隐藏状态,实现“以动致静”的精准估计。好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个赞~
技术角度谈"机器人为何老爱跺脚"~
硬创社
社区数据
今日帖子
-
今日互动量
-
在线人数
-
帖子总量
-
用户总量
-
推荐话题 换一批
#DIY设计#
#嘉立创PCB#
#创享2025#
#嘉立创#
#畅聊专区#
#ESP8266/32#
#星火计划2025#
#嘉立创免费3D打印#
查看更多热门话题
功能讨论
()
主题
打赏记录
粤公网安备44030002004666号 · 粤ICP备2023121300号 · 用户协议 · 隐私政策 · 侵权举报 · ISO/IEC · Copyright © 2024 嘉立创社区版权所有
服务热线:18682363881 ·  服务时间:周一至周六 9::00-18:00 · 联系地址:中国·深圳(福田区商报路奥林匹克大厦27楼) · 媒体沟通:pr@jlc.com · 集团介绍
移动社区