关于作者

Ari Mahpour

Ari 是一位在设计、制造、测试以及集成电气、机械和软件系统方面拥有丰富经验的工程师。他热衷于将设计、验证和测试工程师凝聚成一个高效团队,共同工作。

最新文章

使用ATmega328P开始嵌入式系统的DevOps入门 使用ATmega328P开始嵌入式系统的DevOps入门 1 min Blog Electrical Engineers Electrical Engineers Electrical Engineers DevOps和敏捷方法论已经通过强调协作、自动化和持续改进,彻底改变了软件开发。将DevOps原则应用到我的设计和项目中,已经成为改变游戏规则的一步,提高了效率和可靠性。在这篇文章中,我们将介绍如何为一个使用 ATmega328P微控制器的 现有嵌入式系统项目设置持续集成(CI)工作流。通过本文,你将看到这些实践如何简化你的开发过程并交付更高质量的产品。 理解嵌入式系统的DevOps和敏捷 DevOps是一套实践,由软件界推广,它将软件开发(Dev)和IT运维(Ops)融合为一个持续的流程。在软件界,开发软件然后“扔过墙”给运维团队让他们部署给客户曾是常态。DevOps引入了一种方式,不仅拆除了这堵墙,还将整个过程自动化。在硬件界,我们发现产品开发和生产之间有相似之处,不断地将设计“扔过墙”给我们的制造工程团队,以确保一切都为生产做好了准备。 在嵌入式产品设计中,我们仍然需要将软件通过生产,但面临着比以往任何时候都要快的挑战,并且要以尽可能高的质量交付。通过DevOps原则,我们旨在解决其中的一些挑战。 硬件依赖性:嵌入式系统依赖于硬件和这些PCB的特定修订版。如果不简化为自动化和高度可扩展,测试和部署可能会变得复杂。DevOps实践通过使用相同的硬件和软件设置,并将其通过自动化的持续集成(CI)系统,帮助自动化这些过程。 长时间构建:构建嵌入式软件可能难以设置,并导致长时间的构建。CI通过将构建卸载到云端,利用开发者通常无法访问的更强大的实例,自动化并加速了这一过程。 手动测试:在实际硬件上进行测试是必不可少的,但通常是手动的、乏味的和耗时的。通过硬件在环(HIL)测试的自动化提高效率和准确性,并可以卸载到配置有CI系统的自动化测试设备的设置中。 通过应用DevOps原则,我们能够使用敏捷方法论在构建-测试-部署范式中快速迭代,为我们希望发布到生产的每个附加功能。 它是如何工作的 “构建、测试和部署”是你在讨论DevOps时经常会听到的一组常用词汇。在嵌入式系统中,我们做的事情也是一样的,因为我们的部署同样会进入生产环节(然后是最终客户)。在 项目的仓库中,我们使用Gitlab CI来驱动我们的端到端工作流程,以实现嵌入式DevOps。我们使用所谓的“管道”来创建完成特定任务的作业,例如编译软件、在目标上运行测试或将其作为官方包发布。在Gitlab中,管道是一系列按顺序流动的作业集合,如下所示: 图1:在Gitlab中使用的ATmega328P DevOps工作流程示例管道 这里是CI脚本(.gitlab-ci.yml文件)的细节分解,以给你一个如何工作的概念。 Docker:如 容器化构建和运行环境以进行硬件在环测试中所讨论的,这个阶段构建Docker镜像,以创建一个一致的环境来构建、测试和刷新代码。这确保了在不同的机器和架构(例如桌面PC与树莓派)上构建过程的可重现性。 测试:这个阶段运行单元测试,以验证你的代码是否按照你的意图进行操作。自动化测试在修改或重构现有代码时快速且重要。 阅读文章
嵌入式系统架构:当您的产品拥有多个PCB时 嵌入式系统架构:当您的产品拥有多个PCB时 1 min Altium Designer Projects Electrical Engineers Electrical Engineers Electrical Engineers 在当今技术驱动的世界中,嵌入式系统无处不在。无论是联网的剃须刀还是复杂的汽车,嵌入式设备都是我们今天使用的大多数电子设备的核心。由一个或多个微处理器组成,嵌入式系统可以通过将复杂性卸载到软件来简化电子产品。随着嵌入式设备变得更大更复杂,印刷电路板(PCBs)也是如此。这些设备往往会发展成多个板并成为比最初预期更大的组装。 在本文中,我们将探讨由多个PCB组成的嵌入式系统的架构权衡和考虑因素。我们将讨论多PCB系统的好处、设计考虑因素和挑战。 为什么使用多个PCBs? 虽然将设备保持在单个PCB上是理想选择(无论是简单性还是成本),但有时我们必须将设计分成两个甚至更多的PCB,以实现我们的设计目标。我们想要将产品分成多个板的一些原因包括: 模块化:将组装分成多个板意味着如有必要,您只能更换产品的一部分。例如,如果单个PCB失败,可以更换它而不影响整个系统。如果正确执行,这可以减少制造商的成本和时间。 空间优化:通过在多个板上分配组件,设计师可以实现更紧凑、更高效的布局。想象一个非常长、狭窄的单板与几个短的、堆叠的板,由于包装的原因,高度并不重要。 热管理:可以在不同的PCB上分配产生大量热量的组件,以改善热量散发。通过在整个组装中均匀分配热量,您可以大大提高系统的可靠性。 可扩展性:使用多个PCB设计允许增量功能添加,可以通过单个板而不是整个组装来更换。想象一下,升级传感器或相机而不替换整个计算系统。 出于这些(以及更多)原因,我们考虑设计一个由多个PCB组成的组装,但嵌入式固件方面的挑战并非没有复杂性。 针对多PCB组装的嵌入式设计考虑因素 现在我们已经确定了使用多个PCB(在适用的情况下)的理由,理解在架构嵌入式系统时的设计考虑因素很重要。无论是从硬件还是软件的角度来看,当我们把一切都放在单个板上时,我们不倾向于仔细权衡的细微差别。 首先我们应该考虑的是板与板之间的通信问题。每块板如何相互通信?每块板上有什么样的处理能力(如果有的话)?或许其中一块板是大脑,而其他的是传感器?当我们仔细选择传输协议,无论是I2C、SPI、UART、以太网等,我们还必须考虑传输线、信号完整性,最重要的是,通过板与板之间的连接器进行信号传输。对设计师来说,最糟糕的事情(相信我,我经历过)就是设计完整个系统并从制造商那里收到你的PCB,只为了意识到你漏掉了一个或两个时钟信号。我们也倾向于忘记在我们的板与板连接器上保留备用引脚,试图将每个引脚数量最大化。这真的可能最终对我们不利。设计时要考虑到多板项目,如 Altium Designer中的多板组装功能,在PCB之间布线如此多的通信线时这是必须的。 我们还需要考虑如何分配电源,特别是如果我们将用我们的微处理器监控电源总线。我们希望能够访问“大脑”以便它能监控任何灾难性事件,但我们也需要考虑切换电源噪声、重负载的电源分配,以及我们的板与板连接器引脚是否能承受那种电力。 最后,虽然这与嵌入式系统的软件本身不直接相关,但机械设计也扮演着重要角色。按键、触摸屏和其他用户的物理接口仍然连接到微处理器,必须考虑在内。我们能否以这样的方式布线,以便微处理器可以访问它的输入?我们是否考虑了当我们从一块板传递到另一块板时高速数字输出的信号完整性?这些是我们在构建我们的嵌入式设备时必须考虑的事情。 挑战与解决方案 我一次又一次在规模扩大的初创公司(甚至是大公司)中看到的最被低估的挑战之一,就是软件和硬件之间版本控制方案的困扰。管理软件发布与PCB修订版之间的关系已成为一个永无止境的战斗,这经常导致混淆、延迟,甚至产品失败。 例如,在我参与的一个初创公司中,PCB的轻微修改需要重新旋转,因此,需要更新固件(尽管很小)。由于版本控制不善,工程团队在旧版PCB上部署了新固件,导致意外的电源下降和偶尔的烟雾。幸运的是,我们在产品发货前发现了这个问题,但这绝对是连续几天的噩梦。 为了避免这些陷阱,建立一个坚固的版本控制方案并确保硬件和软件团队之间的清晰沟通至关重要。即使是一个简单的版本控制方案,如固件的Git哈希(或语义版本)以及硬件修订版的基本支持查找表,也足以开始。随着时间的推移,更复杂的机制,如在固件中检测硬件修订版(从而检查兼容性),也大大减少了混淆。 阅读文章
使用生成式AI编写和运行嵌入式代码 使用生成式AI编写和运行嵌入式代码 1 min Altium Designer Projects 在 如何构建自定义GPT操作以与您的硬件对话和 构建AI实验室助手中,我们学习了如何使用生成式AI控制我们的硬件。通过在ChatGPT中使用自定义GPT操作,我们能够赋予ChatGPT不仅能让树莓派上的LED灯闪烁,还能控制实验室仪器并获取数据的能力。这意味着我们可以使用人工智能作为我们的实验室助手,并处理它从我们的仪器中获取的数据。在这篇文章中,我们将更进一步,让生成式AI不仅为我们编写代码,还能在嵌入式目标上执行代码并在此过程中接收反馈。 背景 使用生成式AI编写代码,即使是对于嵌入式系统,也不是什么新鲜事。已经有很多工具在建议或完全从头开始编写代码。最受欢迎的大型语言模型,如ChatGPT、Gemini和Claude,都已经变得相当擅长编写代码(参见 Gemini与ChatGPT:谁写的代码更好进行比较)。我已经写了一年多关于ChatGPT生成代码的文章了(参见 使用ChatGPT进行自动化测试),并宣称这是如今开发的唯一方式。真正的挑战是将AI纳入你的开发循环中。 代码生成只能带你走这么远,但要验证并确保它有效,当涉及到生成式AI时需要采取不同的方法。ChatGPT的代码解释器提供了一个封装的Python环境,可以在一定程度上运行生成的代码并验证它对你是否有效。我想更进一步,看看我们是否能在嵌入式系统上实现同样的事情。有两种方法可以使用OpenAI的ChatGPT。最常见的方法是创建一个使用OpenAI API的封闭循环应用。它会提示并从大型语言模型(LLM)使用API获取代码,编译它,将其加载到Arduino上,并使用额外的自定义代码来验证生成代码的功能。我决定采取不同的方法,使用GPT操作来使其更像是一种“代码配对体验”。这就是那种体验的样子: 图1:GPT操作示例 虽然这个例子可能很简单(即闪烁一个板载LED),但上面的演示总结了一切。我能够给我的自定义GPT清晰的指令,它完全按照我的预期执行了指令。我还能确认它确实上传到了我的设备,并以1秒的频率让LED闪烁。与封闭循环系统相比,使用自定义GPT的好处是我可以在提示符内很容易地进行迭代: 图2:在Arduino草图上进行迭代 现在你已经看到了一些例子,让我们来看看这一切是如何工作的。 工作原理 就像我们在其他自定义GPT文章中看到的那样,这个项目的GPT Actions设置或多或少是相同的。Dockerfile、Docker Compose、SSL证书以及仓库的总体结构并没有太大变化。当然,设计代码本身和OpenAPI YAML文件显著不同(这是意料之中的)。 这段代码(与之前的例子相比)最大的变化是我们在Python中引入了一个“子进程”来调用外部程序,在这个案例中是Arduino IDE。我们的OpenAPI 阅读文章