基于CircuitPython与CPX的智能小船:嵌入式系统入门实践
1. 项目概述:一个能“看”会“听”的智能小船
几年前,当我第一次把一块微控制器(MCU)连接到伺服电机上,看着它按照我的指令精准地转动时,那种“代码驱动物理世界”的兴奋感至今难忘。今天,我想和大家分享一个将这种兴奋感实体化的项目——一个基于CircuitPython和Adafruit Circuit Playground Express(CPX)的智能小船。这不仅仅是一个会动的玩具船,它是一个集成了环境感知、逻辑判断与精准执行于一体的微型嵌入式系统原型。
这个项目的核心,是让一艘3D打印的小船,能够根据周围环境“自主”做出反应:当环境光线足够明亮时,它启动螺旋桨前进;当检测到较大声响(比如你拍手或吹口哨)时,船上的LED彩灯会闪烁红光并模拟鸣笛;而当你拿起小船摇晃它时,它会立刻停止所有动作,进入“待机”状态。整个过程,由一块巴掌大的CPX板子作为大脑,一个连续旋转的微型伺服电机作为心脏,再配合我们编写的几十行CircuitPython代码,共同实现。
对于刚接触硬件的朋友,CircuitPython是入门嵌入式编程的绝佳选择。它语法接近Python,无需复杂的编译环境,像操作U盘一样拖拽代码文件就能运行,极大地降低了门槛。而伺服电机,特别是连续旋转型号,在这里被我们“改造”成了动力十足的螺旋桨推进器。通过这个项目,你不仅能学到如何将3D建模、电子焊接、嵌入式编程这些技能串联起来,更能深刻理解一个智能设备从传感器输入、到中央处理器决策、再到执行器输出的完整闭环是如何构建的。无论你是创客教育者、硬件爱好者,还是想给孩子做一个酷炫的科技手工,这个项目都能提供一条清晰、有趣且充满成就感的实践路径。
2. 核心硬件选型与设计思路解析
2.1 为什么选择Adafruit Circuit Playground Express (CPX)?
在众多微控制器开发板中,选择CPX作为本项目核心,是经过深思熟虑的,绝非随意之举。对于一个小型、集成化的创客项目,CPX几乎是一个“开箱即用”的完美解决方案。
首先, 极高的集成度 是关键。一块标准的CPX板载了10颗可编程的NeoPixel RGB LED、一个运动传感器(加速度计)、一个温度传感器、一个光传感器、一个声音传感器,甚至还有一个红外收发器和一个蜂鸣器。这意味着,要实现我们小船的光感、声控和震动停止功能,你 完全不需要额外焊接任何传感器模块 。光敏电阻、麦克风、加速度计都已经妥帖地集成在板子上,这极大地简化了电路设计,降低了硬件连接出错的风险,也让整个项目更紧凑、更可靠。
其次, 对CircuitPython的原生友好支持 。CPX是Adafruit公司为推广CircuitPython而设计的旗舰产品之一。其固件更新、库支持都非常完善。我们项目中用到的 adafruit_circuitplayground 库,就是官方为CPX量身定制的,它用极其简洁的API(如 cp.light , cp.sound_level , cp.shake() )封装了所有板载传感器的读写操作,让编程体验如同在电脑上写Python脚本一样直观。相比之下,如果使用传统的Arduino Uno,你需要分别连接光敏电阻模块、声音传感器模块和MPU6050等,并处理复杂的模拟信号读取和数字滤波,对新手极不友好。
最后, 供电与接口的便利性 。CPX可以通过其USB-C接口或旁边的JST PH 2mm电池接口供电,非常灵活。其上的多个鳄鱼夹/杜邦线兼容的焊盘,使得连接外部伺服电机变得轻而易举,无需额外的扩展板。综合来看,CPX用一块板子的成本和空间,解决了感知、控制和基础人机交互(灯光、声音)三大需求,是小型智能原型项目的效率之选。
2.2 伺服电机的奥秘:从角度控制到连续旋转
伺服电机(Servo Motor)是机器人领域的常见执行器,但很多人对其工作原理一知半解。普通舵机(如SG90)通过接收PWM(脉冲宽度调制)信号来控制输出轴旋转到某个特定角度(通常是0-180度)。PWM信号的脉冲宽度(高电平持续时间)与目标角度呈线性关系。例如,1.5ms的脉冲可能对应90度中点位置。
而我们项目中使用的,是一种特殊的 连续旋转伺服电机 。它在内部结构上做了一点“手脚”:移除了位置反馈电位器,并将控制电路修改为根据PWM信号的脉冲宽度来控制电机的 转速和方向 ,而不是固定角度。通常,1.5ms的脉冲对应停止状态,小于1.5ms(如1.0ms)的脉冲让电机全速正向旋转,大于1.5ms(如2.0ms)的脉冲则让电机全速反向旋转。脉冲宽度与转速之间近似线性。
注意 :市面上有些连续旋转舵机需要经过校准(Calibration)才能找到精确的“停止点”(即
throttle = 0.0对应的脉冲宽度)。Adafruit出品的舵机通常已校准好,但如果你使用其他品牌,可能需要通过代码微调min_pulse和max_pulse参数来匹配。
在本项目中,我们将这个连续旋转伺服电机竖直固定在小船尾部,并将其输出轴直接与3D打印的螺旋桨相连。这样,通过代码控制 cp.servo1.throttle 的值(在-1.0到1.0之间),就能直接控制螺旋桨的推力大小和方向,从而驱动小船前进、后退或停止。这种设计比使用普通的直流电机加齿轮箱方案更简洁,因为伺服电机内部已经集成了减速齿轮和驱动电路,输出扭矩大,控制接口统一(仅需一根信号线)。
2.3 船体设计与3D打印的工程考量
一个能在水里稳定运行的船体,其设计远比一个简单的“盒子”复杂。我们的3D模型需要同时满足 浮力 、 稳定性 、 防水 和 设备安装 四大需求。
浮力与稳定性 :船体底部通常设计成具有一定体积的“船型”或平底舱结构,以提供足够的排水体积来产生浮力,承载CPX、电池、伺服电机的重量。重心要尽可能低,并且位于船体中心偏下的位置。这就是为什么我们将较重的电池包放置在船体内部最底部,而将相对较轻的CPX放在较高的“船舱”内。一个宽大的船底也有助于防止侧翻。
防水与设备安装 :这是设计中的重中之重。船体后部需要为伺服电机预留一个尺寸精准的安装孔,确保电机轴能垂直伸出船尾,且电机壳体与船体之间缝隙要小,便于用热熔胶密封防水。前部的“船舱”设计,其核心目的是为CPX提供一个 高于水面的安全空间 。即使有小浪花打到船体上,船舱也能像一个小房子一样保护内部的电子设备。船舱顶部最好有盖板,或者设计成让CPX卡紧在其中,避免其晃动或脱落。
3D打印实践要点 :
- 材料选择 :推荐使用 PETG 或 ASA 材料。它们比常见的PLA具有更好的耐水性、耐候性和韧性。PLA长时间接触水可能会缓慢吸水变脆。
- 打印设置 :
- 层高 :0.2mm可以提供较好的表面质量和强度平衡。
- 填充密度 :建议20%-25%。过低的填充可能导致船体强度不足,过高的填充则浪费材料和时间,对浮力影响不大。
- 壁厚 :至少3层(约1.2mm),确保船体结构坚固,不易渗水。
- 支撑 :对于船舱的悬空部分或船体内部的复杂结构, 必须启用支撑 。原文提到的“breakaway supports”是指易剥离的支撑,这样在打印完成后可以比较干净地去除,不影响内部空间和设备安装。
- 后处理 :打印完成后,仔细检查并清理所有支撑材料。对于关键密封部位(如伺服电机安装孔、船舱接缝),可以在内部涂抹一层 环氧树脂胶 或专用的 防水密封胶 ,静置固化,这比单纯依赖热熔胶的防水效果要持久和可靠得多。
3. 电路连接与防水处理实战指南
3.1 从原理图到实物接线:一步步说清
电路连接是整个项目的物理基础,接线错误轻则功能失常,重则损坏设备。我们遵循“先信号后电源,先低压后高压”的原则进行操作。
伺服电机与CPX的连接详解 :
- 识别线序 :标准的微型伺服电机线缆为三根线,颜色通常是棕色(Brown)、红色(Red)和橙色(Orange)。但不同厂家可能有差异, 万变不离其宗的原则是:黑色或深色(棕/黑)为地线(GND),红色为电源正极(VCC/V+),黄色或橙色为信号线(Signal/PWM) 。在连接前,务必用万用表确认或查阅电机说明书。
- 连接到CPX :
- 地线(GND) :连接到CPX板上任意一个标记为 “GND” 的焊盘。所有GND在板内都是相通的。
- 电源线(VCC) :这是关键!微型伺服电机在工作,特别是启动和堵转时,瞬间电流可能超过500mA。CPX板载的3.3V稳压器无法提供如此大的电流。因此,我们必须将伺服电机的电源直接接到 外部电池的供电线上 ,或者像本项目一样,接到CPX上专为外设供电的 “VOUT” 焊盘。 VOUT 引脚直接连通到CPX的电源输入(USB或电池),绕过了板载稳压器,能够提供更大的电流。
- 信号线(Signal) :连接到CPX上任意一个支持PWM输出的 模拟输入/输出引脚 ,例如 A1 、 A2 、 A3 等。在代码中,我们需要初始化对应的引脚为伺服电机控制引脚。
电池供电方案 :为了保持小船无线运行,我们使用一个3.7V的锂聚合物(LiPo)电池或4节1.5V的AAA电池盒(输出6V)。CPX的输入电压范围是3.5V-6V,而常见微型伺服电机的工作电压范围是4.8V-6V。因此,一个 标称3.7V,满电4.2V的LiPo电池 是兼顾尺寸、重量和兼容性的好选择。将电池的JST插头连接到CPX的电池接口,CPX的VOUT就会输出与电池相同的电压(约3.7V-4.2V)给伺服电机。
3.2 防水绝缘:热缩管与热熔胶的艺术
水是电子设备的头号杀手。我们的船只要下水,防水处理就必须做到位。
线缆接头的防水(热缩管) : 伺服电机的三根线通常是通过杜邦头或直接焊接与CPX连接的。这些金属接头一旦沾水短路,后果严重。
- 选择热缩管 :根据接头大小,选择直径合适的热缩管。其收缩前内径应略大于接头最大处,收缩比一般为2:1或3:1。
- 操作步骤 : 务必在通电测试所有功能正常后,再进行此步骤! 将一段足够长的热缩管提前套在一根电线上。完成焊接或插接后,将热缩管滑动到覆盖整个金属接头及部分线缆的位置。
- 加热收缩 :使用热风枪或打火机(小心火焰)从热缩管中部开始加热,均匀地向两端移动。你会看到热缩管紧紧包裹住接头。 确保加热充分,直到热缩管完全紧贴,没有褶皱和空隙 。对于关键部位(如船体穿线孔附近),可以使用双层热缩管或涂抹少量热熔胶加强密封。
设备固定与缝隙密封(热熔胶) : 热熔胶防水性一般,但其快速固化、易于塑形和绝缘的特性,非常适合用于设备固定和辅助密封。
- 固定伺服电机 :在将伺服电机塞入船尾孔洞前,在电机壳体侧面和船体孔洞边缘涂抹一圈热熔胶,然后迅速插入并按压几秒钟。胶体冷却后既能固定又能起到一定的防水作用。 注意不要将胶涂到电机的输出轴或齿轮部位 。
- 密封船舱与穿线孔 :CPX放入船舱后,所有电线应从船舱底部或侧面的小孔穿出。在电线穿出后,在孔洞内外两侧都点一些热熔胶,确保水不会沿电线渗入船舱。船舱盖板与船体的接缝处,也可以涂抹一层薄薄的热熔胶。
- 重要提示 :热熔胶在低温或长时间浸泡后可能开胶。对于追求长期可靠性的项目,可以在热熔胶初步固定后,在关键缝隙处再涂抹一层 硅酮密封胶(如704胶) ,它弹性好、耐水性强,是电子设备防水的常用材料。
4. CircuitPython代码深度剖析与优化
4.1 主循环逻辑:状态机思维
让我们逐行分析提供的核心代码,并理解其背后的控制逻辑。这本质上是一个简单的 事件驱动型状态机 。
from adafruit_circuitplayground import cp
import time
# 伺服电机控制设置:校准脉冲宽度范围,确保throttle控制准确
cp.servo1.set_pulse_width_range(min_pulse=500, max_pulse=2500) # 单位:微秒
# 常量定义:阈值需要根据实际测试环境调整
LIGHT_THRESHOLD = 300 # 光强阈值,高于此值认为环境足够亮
SOUND_THRESHOLD = 500 # 声音阈值,高于此值认为检测到声音
while True: # 主循环,永不停止
# 优先级1:光感控制推进
if cp.light > LIGHT_THRESHOLD:
cp.servo1.throttle = 1.0 # 电机全速正转,船前进
# 优先级2:声控灯光与音效(仅在光线不足时生效)
elif cp.sound_level > SOUND_THRESHOLD:
cp.pixels.fill((255, 0, 0)) # 所有NeoPixel LED亮红色
time.sleep(0.5) # 保持红色0.5秒,模拟灯光闪烁
cp.pixels.fill((0, 0, 0)) # 关闭所有LED
# 此处可以添加 cp.play_tone(440, 0.5) 来增加鸣笛音效
# 优先级3:震动停止(仅在无光、无声时生效)
elif cp.shake(shake_threshold=20):
cp.servo1.throttle = 0.0 # 电机停止
# 循环延迟,降低CPU占用并稳定传感器读数
time.sleep(0.1)
逻辑优先级解读 :代码使用了 if-elif-elif 结构,这意味着条件判断是 有先后顺序的 。当光线足够强时,无论是否有声音或震动,小船都会优先执行前进指令。这种设计模拟了一个“白天自动巡航,夜晚静默待命(但可声控互动),紧急时(摇晃)立即停止”的智能行为。你可以通过调整判断顺序来改变行为的优先级。
4.2 传感器阈值校准:让小船更“聪明”
代码中的 LIGHT_THRESHOLD 和 SOUND_THRESHOLD 是两个至关重要的魔法数字,直接决定了小船的“灵敏度”。如何找到适合你所在环境的准确值?
交互式校准法 :我们可以写一个简单的校准程序,在串行终端里实时读取传感器数值。
# calibration.py - 上传到CPX运行,打开串行监视器查看数值
import time
from adafruit_circuitplayground import cp
while True:
light_val = cp.light
sound_val = cp.sound_level
# 打印当前的光感和声音传感器原始值
print(f"Light: {light_val:4d} | Sound: {sound_val:5.1f}")
time.sleep(0.5)
- 校准光感阈值 :将小船放在你希望它启动的典型环境光下(如室内灯光下),运行上述程序,观察
Light的读数。这个读数可能波动,取一个平均值。例如,读数为450。那么,你可以将LIGHT_THRESHOLD设置为比这个值稍低一点的数,比如400,这样能确保可靠触发。再将小船放到阴暗处(如抽屉里),读数可能降到50以下。这样,400的阈值就能很好地区分“亮”和“暗”。 - 校准声音阈值 :在典型环境噪音下(如安静的房间里),观察
Sound的读数,可能只有几十。然后拍一下手,读数可能会飙升到几百甚至上千。SOUND_THRESHOLD应该设置在环境噪音最大值和拍手产生的最小值之间。例如,环境噪音最大80,拍手最低能到300,那么阈值设为200就比较合适。
实操心得 :阈值不要设得过于临界,留出一定的“缓冲带”( hysteresis ),可以防止传感器噪声造成的误触发。例如,光线在阈值附近轻微波动会导致电机频繁启停。一个更健壮的做法是使用“迟滞比较”,比如“光线高于350启动,低于300才停止”。
4.3 功能扩展与代码优化建议
基础功能实现后,我们可以让小船变得更智能、更互动。
1. 增加鸣笛音效 : CPX板载了一个小型蜂鸣器,可以播放简单的音调。在声控灯光的同时加入鸣笛,体验更佳。
elif cp.sound_level > SOUND_THRESHOLD:
cp.pixels.fill((255, 0, 0))
cp.play_tone(440, 0.3) # 播放440Hz(标准A音)的音调,持续0.3秒
time.sleep(0.2) # 灯光比声音多亮一会儿
cp.pixels.fill((0, 0, 0))
2. 实现缓启动与缓停止 : 让伺服电机瞬间从0到全速,可能会对齿轮造成冲击,也耗电更多。我们可以实现一个速度渐变的效果。
def smooth_start(servo, target_throttle, duration=1.0):
steps = 20
step_time = duration / steps
increment = target_throttle / steps
current = 0
for i in range(steps):
current += increment
servo.throttle = current
time.sleep(step_time)
# 在光感触发部分调用
if cp.light > LIGHT_THRESHOLD and cp.servo1.throttle < 0.1:
smooth_start(cp.servo1, 1.0, duration=1.5) # 用1.5秒缓慢加速到全速
3. 添加“低电量警示”功能 : 通过监测CPX的电池电压,在电量低时让LED闪烁特定颜色(如黄色),并逐渐降低电机功率。
import analogio
import board
vbat_voltage = analogio.AnalogIn(board.VOLTAGE_MONITOR)
# 需要根据分压电路计算实际电压,此处为示例逻辑
if vbat_voltage.value < LOW_BAT_THRESHOLD:
# 闪烁黄灯警告
cp.pixels.fill((255, 150, 0))
time.sleep(0.2)
cp.pixels.fill((0, 0, 0))
# 限制电机功率为一半
cp.servo1.throttle = 0.5
5. 总装、调试与水上测试全记录
5.1 分步总装流程与检查清单
将所有部件组装成一条完整的小船,需要耐心和条理。遵循以下步骤,可以避免很多返工。
-
船体与动力总成安装 :
- 确保3D打印的船体内部完全干燥、清洁,无支撑残留。
- 将伺服电机从船体内部塞入尾部预留孔,让输出轴垂直伸出船尾。在电机壳体与船体接触的四周均匀涂抹热熔胶,固定并初步防水。 等待胶体完全冷却固化 。
- 将螺旋桨安装到伺服电机的输出轴上。如果轴是D型轴,确保螺旋桨的D型孔与之对齐。可以用一小滴可拆卸的螺丝胶或一点点热熔胶(小心勿渗入轴承)加强固定,防止螺旋桨在水下脱落。
-
电子设备安装与布线 :
- 将CPX放入船舱,屏幕和传感器(特别是光感、声音传感器)最好朝向船舱的开口或透明窗口,以确保其能正常感知环境。
- 布线管理 :将连接伺服电机的三根线以及电池的电源线,整齐地沿着船体内侧走线,并用一小块电工胶布或扎带固定,防止它们缠绕或卡住活动部件。所有线缆从船舱底部或侧面的小孔穿出,连接至CPX对应焊盘。
- 连接与测试(陆上) :先不要密封船舱!连接好所有线缆,装上电池。将代码上传到CPX。用手电筒照射光传感器,观察螺旋桨是否转动;拍手或制造声音,观察LED是否闪烁;轻轻摇晃小船,观察螺旋桨是否停止。 确保所有基础功能在陆地上正常工作 。
-
最终密封与合盖 :
- 陆上测试通过后,断开电池。
- 在所有电线穿舱的孔洞处,仔细涂抹热熔胶或硅酮密封胶,确保水密。
- 将电池用尼龙搭扣或少量热熔胶固定在船体底部中央,以降低重心。
- 最后,盖上船舱的顶盖。如果顶盖是可拆卸的,可以在接合处贴一圈薄海绵胶条来增强密封性;如果是永久性的,则在接缝处涂抹密封胶。
5.2 水池测试与性能调优
第一次下水总是令人兴奋又紧张。请选择一个 安静、浅水、干净 的水域进行测试,比如家里的浴缸、大的整理箱,或者平静的池塘边缘。
下水前最终检查 :
- 重心检查 :将组装好的小船平放在桌面,从侧面看,船体是否基本水平?前后左右摇晃是否稳定?
- 防水复查 :用手电筒仔细照射所有胶封处,看是否有明显缝隙或孔洞。
- 螺旋桨检查 :手动转动螺旋桨,确保其旋转顺畅,不会刮擦到船体。
测试流程与问题诊断 :
- 浮力与平衡测试 :轻轻将小船放入水中,松手。观察它是否平稳漂浮,有无严重侧倾或首尾倾斜。如果船头下沉,可能是电池太靠前;如果侧倾,检查左右重量是否平衡。可以通过微调内部配重(如粘贴配重块)来解决。
- 功能水上测试 :
- 光感测试 :在自然光或灯光下,小船应开始前进。用手遮挡光传感器,它应停止(如果代码逻辑是
elif结构,需无光无声无震动时才停)。 常见问题 :船舱盖板颜色太深或材质不透光,导致舱内光线不足,光传感器永远达不到阈值。解决方案:在传感器对应位置开窗,或使用透明/半透明材料打印船舱。 - 声控测试 :在光线较暗处(或遮挡光感),拍手测试LED和蜂鸣器响应。
- 震动停止测试 :在小船前进时,轻轻抬起船体或晃动水面,模拟“触礁”或“被拿起”,电机应立即停止。
- 光感测试 :在自然光或灯光下,小船应开始前进。用手遮挡光传感器,它应停止(如果代码逻辑是
- 航行性能调优 :
- 跑偏问题 :如果小船不是直线前进,而是转圈,可能原因有:a) 船体左右不对称或水下有附着物;b) 螺旋桨轴心与船体中轴线不重合;c) 水流扰动。调整螺旋桨安装位置,确保其正对船尾中心。
- 速度/推力不足 :伺服电机推力有限。如果小船负载过重或船体阻力太大,可能前进缓慢。可以尝试:a) 减轻船体重量(优化3D打印填充率);b) 使用更大直径或更高螺距的螺旋桨(需重新设计打印);c) 检查电池电压是否充足。
5.3 常见问题排查速查表
下表汇总了在制作和测试过程中可能遇到的典型问题及其解决方法:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 上电后无任何反应 | 1. 电池没电或接触不良。 2. CPX未正确供电或损坏。 3. 电源线连接错误。 |
1. 用万用表测量电池电压,或更换新电池。 2. 通过USB连接电脑,看CPX是否被识别,板载LED是否亮起。 3. 检查电池插头是否插反,VOUT与伺服电机VCC连接是否牢固。 |
| 螺旋桨不转,但LED正常 | 1. 伺服电机信号线连接错误或接触不良。 2. 代码中伺服电机控制引脚定义错误。 3. 伺服电机损坏。 4. 电源功率不足(电池老化)。 |
1. 检查信号线是否连接到CPX正确的引脚(如A1),并重新插拔。 2. 确认代码中 cp.servo1 是否初始化在正确的引脚上(CPX上A1对应 board.A1 )。 3. 将伺服电机直接连接到标准的舵机测试器或另一块开发板上测试。 4. 更换一块电量充足的电池试试。 |
| 光感/声控不触发 | 1. 传感器阈值设置不当。 2. 传感器被遮挡或朝向错误。 3. 环境干扰(如环境光太强/太弱,环境噪音太大)。 |
1. 运行校准程序,重新测定并调整 LIGHT_THRESHOLD 和 SOUND_THRESHOLD 。 2. 确保CPX的光敏电阻和麦克风没有被胶水或结构遮挡,最好朝向船舱外。 3. 在代码中加入打印语句,实时输出传感器数值,观察是否正常变化。 |
| 小船在水中侧翻或进水 | 1. 重心过高或偏移。 2. 船体密封不严。 3. 船体设计缺陷,稳性不足。 |
1. 将电池等重物尽可能固定在船底中央。检查设备安装是否对称。 2. 捞出小船,彻底擦干并晾干内部。仔细检查所有接缝、穿线孔,用密封胶加强。 3. 考虑加宽船体,或在下一次打印时增加船体宽度和干舷高度。 |
| 功能互相干扰(如声控时电机也动) | 代码逻辑判断优先级或条件设置问题。 | 检查 if-elif 逻辑链。确保每个条件分支是互斥的。如果想实现声控时电机停止,需要调整判断顺序和条件。 |
这个项目从一张设计图到一条在水池中欢快巡弋的智能小船,整个过程充满了动手的乐趣和解决问题的成就感。它完美地诠释了“快速原型设计”的理念:用集成度高的硬件降低入门门槛,用高级语言简化编程,用3D打印快速迭代结构。当你看到自己编写的几行代码,真正地让一个物理实体“活”起来,并与环境互动时,那种感觉是无可替代的。希望这份详细的指南能帮你绕过我当年踩过的一些坑,更顺畅地体验到创造智能硬件的魅力。如果想让小船更进阶,可以考虑加上蓝牙遥控,或者用陀螺仪实现自动平衡,甚至加上一个小摄像头……创客的世界,边界只在于你的想象力。
更多推荐


所有评论(0)