close
当前位置: 物联网在线 > 物联网设计开发 > RF/无线 >

使用CircuitPython开发板简化基于ARM®Cortex®-M0 +的物联网嵌入式设计

许多嵌入式应用使用先进的MCU,但只需要基本的硬件控制功能,而不需要高级嵌入式设计的“硬实时”要求。开发商和制造商经常沉浸在硬件设计,C / C ++编程和实时操作系统的细节中。幸运的是,有一个更简单的方法。
本文将通过Adafruit Industries的一对微型开发板展示一种更易于使用的方法,它将Python编程语言的嵌入式设计变体与基于ARM Cortex-M0 +处理器的高级32位MCU相结合。

高级MCU简化了设计

先进的MCU通过集成全面的模拟和数字外设以及强大的处理器内核来帮助简化硬件设计。例如,Microchip Technology ATSAMD21G18 MCU采用10 x 10 mm薄型四方扁平封装(TQFP),结合了ARM Cortex-M0 +内核,256 KB闪存,32 KB SRAM,高级控制子系统和大量外设)包(图1)。
Microchip Technology SAM D21 MCU系列的图表
图1:基于超低功耗ARM®Cortex®-M0 +,Microchip Technology SAM D21 MCU系列澳门美高梅娱乐在线全部提供了一整套功能模块和外设,仅在特定数量的内存和外设通道上有所不同。(图片来源:Microchip Technology)
除了32个GPIO外,ATSAMD21G18 MCU的外设包括多个高级串行通信(SERCOM)通道,波形输出通道,多通道12位模数转换器(ADC),模拟比较器和10位数字模拟转换器(DAC)。

设计挑战

这类先进的MCU消除了开发人员花时间查找和连接外部外围设备的需要,但是它仍然对MCU如何设计到系统中提出了严格的要求。例如,在集成多种类型的电路时,ATSAMD21G18 MCU的设计通过一组相应的域来供电。因此,开发人员必须处理处理器内核V DDCORE,其内部稳压器(V DDIN),外设(V DDIO)和模拟模块(V DDANA)(图2)的多个电源和接地引脚。
在设计过程中,开发人员需要遵循具体的电源供应,接地连接,选择和放置去耦电容的建议 - 这对于有经验的工程师来说并不是什么不寻常的事情,但是对于嵌入式MCU硬件设计的开发人员来说却是一个潜在的问题。
Microchip Technology ATSAMD21G18 MCU的图片
图2:Microchip Technology ATSAMD21G18 MCU使用多个电源域来提供各种模拟和数字模块,并且需要小心地为这些域供电。(图片来源:Microchip Technology)
同样,使用这些设备进行软件开发看起来势不可挡。通常情况下,新的嵌入式系统开发人员发现自己陷入了从嵌入式开发材料中学习C / C ++相关的细节,这些材料更适合于具有实时要求的应用程序。这些应用通常对中断延迟和确定性响应具有关键的时序要求。然而,物联网(IoT)的许多新兴传感器设计需要(或可以容易地容忍)对数据采集或致动器操作的更宽松的要求。

简化嵌入式开发

旨在消除嵌入式开发人员的这些硬件和软件障碍,Adafruit的一套开发板提供了一个针对各种应用需求的特别有效的解决方案。基于ATSAMD21G18 MCU,Adafruit Metro M0 Express和Feather M0 Express均提供完整的嵌入式系统,包括串行接口(USB,SPI,I 2 C和UART),脉宽调制(PWM),中断输入作为多个模拟IO和GPIO。这些板仅在尺寸和数量上有所不同:2.8英寸x 2.1英寸x 0.28英寸Metro M0 Express提供25个GPIO,而较小的2.0英寸x 0.9英寸x 0.28英寸Feather M0 Express提供20个GPIO。
与大多数高级MCU一样,SAM D21 MCU系列提供比物理引脚多得多的外设通道,但提供了引脚映射功能,可将外设功能分配给特定的硬件引脚。因此,即使尺寸较小,每个电路板也使用共用引脚来提供全面的MCU广泛的外设功能(图3)。
Adafruit Feather M0 Express开发板的示意图
图3:Adafruit利用引脚多路复用澳门美高梅娱乐城在其微型Feather M0 Express开发板上提供ATSAMD21G18外设功能的丰富子集。(图片来源:Adafruit)
但是对于开发人员来说,这些细节是透明的。Adafruit已经在其开源软件包(清单1)中为特定模块中的每块板提供了特定配置。
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
    { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
    { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) },
    { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) },
    { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) },
    { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) },
    { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) },
    { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) },
    { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) },
    { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) },
    { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) },
    { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) },
    { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) },
    { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) },
    { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
    { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
    { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) },
    { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) },
    { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) },
    { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) },
    { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) },
    { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) },
    { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) },
    { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA06) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
清单1:Adafruit开源CircuitPython库使用特定于电路板的引脚映射来抽象硬件细节,例如这里显示的Feather M0 Express电路板。(代码来源:Adafruit)
要开始开发,用户可以将电路板插入USB端口,并使用带有Arduino IDE的内置USB Bootloader 。为了更简单地介绍嵌入式软件设计,开发人员可以使用内置功能轻松地将CircuitPython加载到其电路板上,并开始构建嵌入式应用程序。

使用CircuitPython简化开发

为了帮助简化嵌入式开发学习曲线,CircuitPython实际上是从Python的更直接的后代MicroPython中派生出来的。通过简单,清晰的语法和支持模块的广泛可用性,Python已经成为流行的语言。但是,它的代码足迹太大,不适用于嵌入式系统。
MicroPython削减了Python的一些体积庞大的功能,使得一个版本能够满足嵌入式系统的逻辑约束,同时保留了该语言的核心功能。在创建CircuitPython的过程中,Adafruit已经更进一步,消除了新的嵌入式系统程序员认为不必要的模块。
Adafruit与CircuitPython的目标是提供一种非常适合教育的语言,使开发人员能够熟练掌握嵌入式设计,而不会陷入低层次的开发细节。CircuitPython从Python传统中获得的一个令人满意的功能是其解释性,它允许开发人员交互式地探索外部模块的接口。例如,CircuitPython中的一个基本模块是电路板模块 - 一个电路板专用模块,用于访问相关电路板的I / O引脚。开发人员可以从控制台启动CircuitPython,导入电路板模块,并立即查看支持的引脚名称(清单2)。
>>> import board
>>> dir(board)
['A0', 'SPEAKER', 'A1', 'A2', 'A3', 'A4', 'SCL', 'A5', 'SDA', 'A6', 'RX',
'A7', 'TX', 'LIGHT', 'A8', 'TEMPERATURE', 'A9', 'BUTTON_A', 'D4', 'BUTTON_B',
'D5', 'SLIDE_SWITCH', 'D7', 'NEOPIXEL', 'D8', 'D13', 'REMOTEIN', 'IR_RX',
'REMOTEOUT', 'IR_TX', 'IR_PROXIMITY', 'MICROPHONE_SCK', 'MICROPHONE_DO',
'ACCELEROMETER_INTERRUPT', 'ACCELEROMETER_SDA', 'ACCELEROMETER_SCL',
'SPEAKER_ENABLE', 'SCK', 'MOSI', 'MISO', 'FLASH_CS']
清单2:在解释器控制台提示符(>>)处,程序员可以导入board模块并进入dir(board)以查看特定于电路板模块中提供的引脚名称。(代码来源:Adafruit)
主板模块提供到底层硬件的连接,提供访问Metro M0 Express和Feather M0 Express主板引脚的简单方法。例如,A0模拟引脚简称为board.A0。另一方面,具体的硬件功能驻留在模拟模拟模块中,数字digitalio; 用于I 2 C,SPI和UART的busio ; 以及用于PWM和其他基于脉冲的协议等的脉冲。因此,读取CircuitPython中的A0模拟输入非常简单,只需导入关联的模块并读取关联设备实例(清单3)的值即可。
import board
import analogio
 
def adc_to_voltage(val):
   return val / 65535 * 3.3
 
adc = analogio.AnalogIn(board.A0)
pinA0voltage = adc_to_voltage(adc.value)
清单3:与Python一样,CircuitPython提供了许多开发人员将自己的代码导入的高级模块; 与Python不同,CircuitPython还提供了让程序员执行硬件级操作的模块,例如读取adc.valueADC输入引脚(board.A0)的值()。(代码来源:Adafruit)
开发人员可以通过直接访问模拟或数字IO引脚轻松扩展其硬件功能。例如,他们可以通过将面板上的LED指示灯连接到电路板的A0连接(图4)并使用模拟模块使LED闪烁(表4)来探索模拟输出。
Metro M0 Express板的A0模拟输出的图像
图4:开发人员可以通过将具有限流电阻的LED等布线电路连接到Metro M0 Express板的A0模拟输出,从而实现MCU的DAC,从而快速构建外部硬件的原型。(图片来源:Adafruit)
import board
import analogio
led = analogio.AnalogOut(board.A0)
 
while True:
    led.value = 65535   # max brightness
    time.sleep(0.5)     # stay on for 1/2 sec
    led.value = 0       # off
    time.sleep(0.5)     # stay off for 1/2 sec
清单4:对于图4所示的展开式电路,开发人员使用CircuitPython analogio模块创建绑定到电路板A0引脚的Analogout类实例(led),并修改其值属性以控制LED的亮度。(代码来源:Adafruit)
大多数现代“智能”传感器和执行器都提供I 2 C或SPI接口,用于读取,写入和监视外围设备。虽然开发人员可以在设备轻松连接到任何一块板的SPI或I 2个 I2C接口,软件接口可能需要额外的努力。
为了尽量减少这种努力,Adafruit为一些流行的设备提供CircuitPython模块,例如Silicon Labs SI7021温度/湿度传感器。与模拟I / O模块一样,在定义了所需的I 2 C接口对象(清单5)之后,SI7021 CircuitPython模块允许程序员只需使用相应类对象的实例即可访问传感器。
import adafruit_si7021
 
from busio import I2C
from board import SCL, SDA
 
# create the I2C interface object
i2c = I2C(SCL, SDA) 
 
# and use it to instantiate the sensor object
sensor = adafruit_si7021.SI7021(i2c)
 
# and perform the sensor measurements
current_temperature = sensor.temperature
current_relative_humidity = sensor.relative_humidity
清单5:Adafruit开源软件库提供了CircuitPython模块,可以使用Silicon Labs SI7021传感器简化对附加硬件功能的访问,如温度和湿度测量。(代码来源:Adafruit)
虽然主要是作为一个学习平台,但是Adafruit开发板和CircuitPython开源库的结合可以用来创建相当复杂的物联网设备和其他嵌入式设计。同时,开发人员需要认识到,像MicroPython / CircuitPython这样的解释型语言在解决硬实时要求的能力方面有很大的局限性。不过,对于许多嵌入式应用来说,这个学习平台为扩展提供了坚实的基础。
为了增加硬件功能,开发者可以在Feather M0 Express板上堆叠可用的Adafruit FeatherWing子卡,甚至可以使用FeatherWing Proto原型板添加他们自己的电路。为了增加对CircuitPython中额外硬件功能的支持,开发人员需要创建定制软件来添加所需的底层驱动程序。然而,即使是这样的努力,通过开放源码库和Python本身的性质的结合,也被最小化了。
通过检查开源库,程序员可以研究用于实现硬件支持的关键设计模式。例如,Adafruit的SI7021模块演示了一个适当的“Pythonic”类结构,包括构造函数和辅助函数(清单6)。通过遵循这种方法,开发人员可以以最小的努力添加自己的硬件。
from micropython import const
import ustruct
import sys
 
from adafruit_bus_device.i2c_device import I2CDevice
 
 
HUMIDITY = const(0xf5)
TEMPERATURE = const(0xf3)
_RESET = const(0xfe)
_READ_USER1 = const(0xe7)
_USER1_VAL = const(0x3a)
 
 
def _crc(data):
    crc = 0
    for byte in data:
        crc ^= byte
        for i in range(8):
            if crc & 0x80:
                crc <<= 1
                crc ^= 0x131
            else:
                crc <<= 1
    return crc
 
 
class SI7021:
    """
    A driver for the SI7021 temperature and humidity sensor.
    """
 
    def __init__(self, i2c, address=0x40):
        self.i2c_device = I2CDevice(i2c, address)
        self.init()
        self._measurement = 0
 
    def init(self):
        self.reset()
        # Make sure the USER1 settings are correct.
        while True:
            # While restarting, the sensor doesn't respond to reads or writes.
            try:
                data = bytearray([_READ_USER1])
                with self.i2c_device as i2c:
                    i2c.write(data, stop=False)
                    i2c.read_into(data)
                value = data[0]
            except OSError as e:
                if e.args[0] not in ('I2C bus error', 19): # errno 19 ENODEV
                    raise
            else:
                break
        if value != _USER1_VAL:
            raise RuntimeError("bad USER1 register (%x!=%x)" % (
                value, _USER1_VAL))
 
    def _command(self, command):
        with self.i2c_device as i2c:
            i2c.write(ustruct.pack('B', command))
 
    def _data(self):
        data = bytearray(3)
        data[0] = 0xff
        while True:
            # While busy, the sensor doesn't respond to reads.
            try:
                with self.i2c_device as i2c:
                    i2c.read_into(data)
            except OSError as e:
                if e.args[0] not in ('I2C bus error', 19): # errno 19 ENODEV
                    raise
            else:
                if data[0] != 0xff: # Check if read succeeded.
                    break
        value, checksum = ustruct.unpack('>HB', data)
        if checksum != _crc(data[:2]):
            raise ValueError("CRC mismatch")
        return value
 
    def reset(self):
        self._command(_RESET)
 
    @property
    def relative_humidity(self):
        """The measured relative humidity in percents."""
        self.start_measurement(HUMIDITY)
        value = self._data()
        self._measurement = 0
        return value * 125 / 65536 - 6
 
    @property
    def temperature(self):
        """The measured temperature in degrees Celcius."""
        self.start_measurement(TEMPERATURE)
        value = self._data()
        self._measurement = 0
        return value * 175.72 / 65536 - 46.85
 
    def start_measurement(self, what):
        """
        Starts a measurement.
 
        Starts a measurement of either ``HUMIDITY`` or ``TEMPERATURE``
        depending on the ``what`` argument. Returns immediately, and the
        result of the measurement can be retrieved with the
        ``temperature`` and ``relative_humidity`` properties. This way it
        will take much less time.
 
        This can be useful if you want to start the measurement, but don't
        want the call to block until the measurement is ready -- for instance,
        when you are doing other things at the same time.
        """
        if what not in (HUMIDITY, TEMPERATURE):
            raise ValueError()
        if not self._measurement:
            self._command(what)
        elif self._measurement != what:
            raise RuntimeError("other measurement in progress")
        self._measurement = what
清单6:为了将自定义硬件添加到他们的CircuitPython应用程序中,开发人员可以使用开源软件,例如SiLabs si7021的Adafruit CircuitPython驱动程序,该驱动程序演示了SI7021用隐式(__init__)和显式(init)构造函数,并通过串行总线(本例中为I 2 C总线)访问硬件本身。(代码来源:Adafruit)
其他模块,特别是在图书馆的硬件抽象层(HAL)中,提供了较低级别的C语言服务,并实现了对物理硬件的访问。完成自定义模块后,开发人员可以利用可用的分步配方来描述Python,MicroPython和CircuitPython内置的特定钩子的使用,以将自定义的C和Python代码添加到环境中。虽然增强过程在桌面或服务器Python环境的这一点结束,但是嵌入式环境需要额外的步骤来使用增强的代码图像更新电路板的固件。
Adafruit为主板提供了一个内置的自举程序,可自动加载USB Flashing Format(UF2)图像。开发人员通过按下电路板的RESET按钮两次来触发引导加载程序进程,这会导致在用户的主机文件系统中出现一个新的“引导”可移动驱动器。开发人员只需将UF2映像从主机系统拖放到代表主板的可移动驱动器(图5)。这与最初加载CircuitPython的过程相同。在这种情况下,开发人员只需删除使用自定义代码构建的UF2图像。引导加载程序会自动执行以使新图像闪烁。
Adafruit的图像通过提供一个引导程序来简化闪烁
图5:Adafruit通过向开发板提供引导加载程序来简化闪存,当通过按下开发板的RESET按钮启动引导程序时,引导BOOT可移动驱动器出现在其文件系统(此处显示的MAC OS)中,开发人员只需将其新的UF2映像。(图片来源:Adafruit)

结论

对于希望获得嵌入式设计经验的开发人员来说,解决“硬”实时需求所需的工具和澳门美高梅娱乐城只是过分的。与此同时,开发人员希望能够随时访问能够提供广泛的模拟和数字IO功能的先进的32位MCU。
Adafruit的开源CircuitPython包提供了一个更简单的开发环境,能够满足这些更简单的要求。通过将CircuitPython与Adafruit的Metro M0 Express或Feather M0 Express开发板相结合,新开发人员可以快速获得嵌入式系统的经验,而更有经验的开发人员可以快速构建嵌入式应用程序原型。
CircuitPython和Adafruit开发板一起为嵌入式应用程序开发提供了一个可访问但功能强大的平台。
Digi-Key电子商标

(责任编辑:ioter)

用户喜欢...

公共安全物联网:利用数据让城市更安全

2017年10月1日,拉斯维加斯市曼德勒海湾酒店附近发生枪击事件。截止10月3日,枪案已造成至少59人死亡,527人受伤 。...


Zynq 7015 linux跑起来之构建ARM核

首先,这里跑linux主要是PS部分的,这里暂时不用PL部分。 打开vivado新建一个project. 项目名和保存路径 RTL project next next next 选Board,如果选器件,是一样的,只是需要去根据实际情况设置一些东...


[原创] NXP i.MX 6UltraLitePICO入门板开发方案

NXP公司的i.MX 6UltraLite是高性能超高效率处理器系列,采用先进的单核ARM Cortex-A,运行速度最高支持528 MHz,包括一个集成的...


[原创] ST STM32L4R9I高性能超低功耗ARM MCU开发方案

ST公司的STM32L4R9I是高性能超低功耗MCU系列澳门美高梅娱乐在线,基于Arm Cortex-M4 32位RISC核,工作频率高达120MHz,支持所有ARM单精度数据处理...


Vivado 学习笔记 (五)编写IP核并通过AXI协议与ARM通信

参考资料:xilinx大学计划 实验平台:PYNQ开发板 最近发现了一块好玩的板子,PYNQ 这块板子最大的特点就是可以将所写的IP核封装成Python库的形式,然后通过在板载的xlinux系统下用户可以选择...


IDT P9242-R3+P9221-R3 15W双向数据通信无线充电解决方案

IDT公司的P9242-R3是高度集成15W磁感应无线功率发送器,具有双向数据通信,包括了32位ARM Cortex-M0处理器,外部物体检测(F...


使用CircuitPython开发板简化基于ARM®Cortex®-M0 +的物联网嵌入式设计

许多嵌入式应用使用高级MCU,但只需要基本的硬件控制功能,而不需要高级嵌入式设计的硬实时要求。开发商和制造商经常沉浸在硬件设计,C / C ++编程和实时操作系统的细节中。幸运的是,有...


意法半导体STM32H7系列微控制器利用全新Arm 平台安全架构强化互联智能设备保护功能

• Arm平台安全架构(PSA)采用高性价比、领先澳门美高梅娱乐城全面提升物联网市场的安全澳门美高梅娱乐城支持 • 基于STM32H7系列开发的Arm® Cortex®-M7微控制器整合PSA概念和先进的安全功能服务 意法半导体(STMicroelec...


Arm推出MbedEdge延伸Mbed Cloud设备管理能力到物联网边缘

Arm宣布推出MbedEdge,进一步拓展Mbed Cloud的设备管理能力,在边缘侧,即物联网网关上实现设备的接入、控制和管理。...


ARM从芯片到云端加速实现安全物联网

ARM针对物联网(IoT)近日推出了有史以来最全面的澳门美高梅娱乐在线组合,将其安全性、能效、低功耗连接和设备生命周期管理提...


博聚网