用于科研的 Arduino 教程(三)

随笔4个月前发布 妖怪
52 0 0

原文:Arduino in Science

协议:CC BY-NC-SA 4.0

八、计数事件和计时

本练习考虑在物理计算中处理时间测量的可用方法。软件或硬件可以用来直接测量时间或时间间隔。然后,通过计算固定时间单位内发生的事件数量,可以使用时间间隔进行频率测量,或者在评估时间间隔内行驶的距离时确定速度和加速度。

确定一天中的时间和事件之间的时间是收集科学数据和过程控制中的重要参数。开灯或从 9:05 到 9:35 收集数据可以被分类为“绝对”或“一天中的时间”格式,而测量球通过粘性液体下落固定距离所需的时间可以被称为差分时间测量。

DAQFactory 的用户手册建议不要试图用软件脚本在少于半秒或四分之一秒的时间框架内工作。几分之一秒大约是高级软件在保持系统状态显示屏用户界面的同时处理用于数据处理的代码线程的能力的极限。毫秒、微秒或更短时间帧的测量通常需要使用汇编语言编程进行软件计时,或使用物理计时设备进行硬件计时。有几种可用的硬件计时器件,如 LabJack HMI、Arduino 微控制器板或 555 定时器集成电路,所有这些器件都能够在毫秒和微秒的时间范围内工作。本章的第一部分研究了数字时间概念的基础,并展示了软件的局限性。本章的其余部分和练习涉及通过集成电路硬件可用的短时标和频率的介绍性概念。

在电子学中,时间是用产生固定电压(5.0 或 3.3 伏)方波信号的振荡器时钟来测量的,方波信号的频率可能在兆赫兹和千兆赫兹范围内。(MHz 为每秒 10 6 个周期,GHz 为每秒 10 9 个周期。)撰写本文的个人电脑的时钟速度为 1.48 GHz,而 Arduino 微控制器的时钟速度为 16 MHz,各种型号的 Raspberry Pi 的时钟速度为 800 MHz 至 1.5 GHz。

由石英晶体调节到高精度和准确度的电子振荡器可以被配置成产生方波的脉冲序列,该脉冲序列可以被单独计数以测量时间。凭借非常稳定的 MHz 和 GHz 振荡器频率以及独立脉冲计数能力,可以非常精确地测量微秒和纳秒时间帧。

当计算设备关闭时,台式、便携式和网络连接的计算设备能够通过网络连接或电池备用系统来跟踪一天中的时间。一些设备,如 Raspberry Pi 和 Arduino 微控制器,需要添加一个称为“实时时钟”(RTC)的附件,该附件具有备用电池,可以在设备断电时准确跟踪一天中的时间。

软件时间和计时

DAQFactory SCADA 软件是一个独立的程序,可在基于 Windows 的操作系统上运行。当计算机在操作会话之间关闭时,电池用于维持操作系统时间计数。自 1970 年以来,DAQFactory 中的时间以微秒为单位进行测量。当 DAQFactory 会话启动时,程序从操作系统获取日期和时间,初始化内部计数器,并从 1970 年 1 月 1 日开始以秒为单位保持时间计数。DAQFactory 时钟独立于操作系统定时器运行,并产生十进制秒时间分辨率。DAQFactory 中可用的时间函数在用户手册的“表达式”部分有详细说明。本练习的第一部分使用了可用的软件时间功能来创建两个分辨率为 1 秒的屏幕激活定时器,用于启动和停止外部试验板上的电子操作,并测量手动观察事件之间的经过时间或累计时间,就像手持秒表一样。基本软件时间评估屏幕如图 8-1 所示。

用于科研的 Arduino 教程(三)

图 8-1

三种计时操作的图形用户界面

基本时间变量

图 8-2 描述了几个基本的当前 DAQFactory 时间值。

用于科研的 Arduino 教程(三)

图 8-2

当前定时操作和值的 GUI

基本变量屏幕由六个变量值组件(VVC)组成,在以红色表示的日期和时间拍摄。配置面板上的条目将有助于理解计数器“时钟滴答”的数学操作及其与我们循环时间概念中的小时、分钟和秒钟的关系:

  1. 第一行变量值组件(VVC)表达式是 SysTime(),它显示自 1970 年 1 月 1 日以来经过的秒数。

  2. 第 2 行使用 VVC 表达式框中的语句“FormatDateTime(“%c “,SysTime())”来生成显示的时间。用户手册中列出了大量可供使用的格式。为了突出视觉效果,显示屏上用了红色大字。

  3. 第 3–5 行使用模记数法将 SysTime()的总滴答计数转换为各种计时值,而第 6 行产生逻辑 1 和 0 之间的一秒调制切换。

预定事件计时器

标题为预定时间计时器的清单 8-1 (在本章末尾与所有其他清单一起提供)的脚本控制图 8-3 所示的 GUI 面板。

用于科研的 Arduino 教程(三)

图 8-3

DAQFactory 预定事件定时器图形用户界面

秒表计时器

图 8-4 中描述的标称控件组实现秒表式计时,并由清单 8-2 的代码控制。

用于科研的 Arduino 教程(三)

图 8-4

秒表计时器 GUI

秒表计时器由清单 8-3 和 8-4 中的三个 DAQFactory 序列激活。启动/停止按钮(列表 8-2 )启动或终止计时动作,从而定义间隔。鼠标点击累计时间按钮,将当前时间间隔加入累计时间总和。单击重置显示将 GUI 重置为零。

硬件时序、事件计数和频率确定

我们世界中的任何物理行为,如开门、进入房间和开灯,都可以被传感器转换为电子系统可以监控和记录的电转换。典型的灯开关的激活导致施加到光源上的电功率从打开极限跳到关闭极限。由开灯、让灯亮一段时间 t、然后关掉灯的动作产生的电波形可以被认为是“持续时间为 t 的脉冲”。电脉冲可以通过将机械、光学和电磁事件转换成电信号电平的急剧变化来产生。

脉冲计数通过使用双极晶体管或 CMOS 集成电路来实现,其中互连的晶体管开关能够以二进制格式记录施加到芯片输入引脚的电子信号中出现的 0 到 5(或 3.3)伏之间的转换次数。对给定时间段内的电子跃迁次数进行计数是对输入信号频率的测量,而对从过去的起始点开始已经发生的脉冲总数进行计数是对经过时间或总时间流逝的测量。

用于存储二进制信息的基本单元被称为“触发器”或“锁存器”触发器是稳定在两种状态之一的开关配置,其中锁存器或触发器的输入导致输出在 1 和 0 两个二进制逻辑状态之间变化。触发器、多谐振荡器或锁存器的基本电路如图 8-5 所示。

用于科研的 Arduino 教程(三)

图 8-5

基极结晶体管触发器

简单的触发器最初由电流控制器件制成,如真空管,后来由双极晶体管制成,最后由极低电流消耗的电压控制器件制成,如场效应晶体管(fet)和金属氧化物半导体场效应晶体管(MOSFETs)。这些通常被称为多谐振荡器,并被称为双稳态电路。该电路保持在其两个稳定状态中的任一个,直到施加控制信号将其切换到另一个稳定状态。

为了理解基本电路是如何工作的,我们可以在图 8-5 中看到,如果 V1 接地,那么将没有基极电流通过 Q2 的基极。在双极晶体管中,通过集电极和发射极的电流(发射极箭头表示正电流)由基极电流控制。没有基极电流的晶体管 Q2 将没有集电极-发射极电流。从 Vcc 通过 R2 的电流全部流入 Q1 的基极,然后导致更大的电流流过 Q1。对于对称电路,如果 V2 接地,则 Q1 的基极电流被切断,并且通过 R1 的电流流入 Q2 的基极,当电路切换到第二稳定状态时,导致更大的电流流过 Q2。

简单的触发器是大量主要是极低电流消耗的互补金属氧化物半导体压控集成电路的基本构建模块,这些集成电路提供诸如存储器存储、逻辑和数学功能的功能。(参见第章 1 ,图 1-15 。)

锁存器、触发器、数字逻辑计数、振荡器时钟以及各种集成电路逻辑芯片组家族的应用的细节可以在几本参考著作中找到。 1

LabJack HMI 上标有 CNT 的端子提供对集成电路的访问,该集成电路能够计数电压电平从+5 变到 0 再变回+5 伏的次数。这种事件计数由设备的集成电路以二进制进行,结果以十进制格式显示在系统屏幕上。要计数的事件必须转换成前面提到的电压电平变化。LabJack 计数器具有 32 位容量,允许总共计数 2 个 32 个或 4,294,967,296 个事件。因为事件计数器是一个集成电路,它可以以高达 1 MHz 的频率计数。

在下面的练习中,将创建一个手动事件计数器,它可以由任意数量的传感器递增,例如日光级别的变化、物体经过某个点或单击系统屏幕图标。LabJack 和 DAQFactory 软件组合的实验设置或过程控制系统的配置涉及以秒或更长时间测量的时间跨度,这不是问题。用户手册中的文件表明,许多指令的执行时间为 20 ms,这为基于视觉的 SCADA 系统可合理预期的最短时间响应建立了下限。高速信号变化最好用称为流或突发模式操作的技术来记录。对于采集后处理,以非常快的硬件速度获取速度或频率远远超出肉眼分辨能力的高速信号变化。用户手册中详细介绍了高速操作,后续章节和练习中也会涉及到。

LabJack 计数器被视为硬件设备,因此不受软件执行时间的限制。被称为 555 定时器的集成电路设备可以与计数器结合使用,以在比软件执行开销所强加的时间跨度更短的时间跨度内工作。555 定时器也是一个基于“硬件”的集成电路,因此,像 LabJack 计数器一样,能够在从微秒到小时的时间范围内工作。双极性晶体管和 CMOS 555 定时器 IC 的详细信息可以在许多参考文献中找到,包括前面提到的参考文献。各种形式的定时器之间的差异在于它们的功率处理能力,双极形式是高电流类型,而 CMOS 形式是基于低电压的。

实验的

五金器具

1)简单的手动事件计数

2)简单的连续事件计数或频率确定

蓝色 LED 和 470ω限流电阻可用于演示屏幕启动事件的手动计数。

电路原理图

二极管和限流电阻器的配置如第章第一部分图 1-3 所示,红色二极管的串联对的连接点连接到 CB25 端子板上的 D9。

软件

为了演示计数器使用的两种模式,创建了图 8-6 中带有两个按钮、两个变量值组件和一个描述性文本组件的面板。

用于科研的 Arduino 教程(三)

图 8-6

LabJack U12 计数器使用演示

对于手动激活的事件计数,创建一个屏幕按钮图标,适当标记,并链接到一个输出通道。作者的按钮标有“Initiate Event”,配置为激活清单 8-5“A _ Counter _ Event”的脚本,该脚本通过一个创建为“DigOut_9_EvntCntr”的通道应用 5–0–5 伏转换,该通道连接到 CB25 板端子上的输出引脚 9。点击屏幕按钮从而驱动 D9 输出从 5 伏到 0 伏,然后回到 5 伏,依次关闭蓝色 LED,然后再打开。计数器端子 CNT 用于监控蓝色 LED 与其 470ω限流电阻连接点处的电压电平。手动点击“启动事件”按钮,通过列表 8-5 DAQFactory 序列递增计数器。

DAQFactory LabJack 手册 2 第十部分详细说明了单个 LabJack 计数器的操作。由于只有一个计数器,所有数据都通过计数器通道 0 传递。默认情况下,每次读取通道时,计数器值都会重置为 0,因此在本练习的第一部分,必须关闭默认值,以便不断增加其值,直到手动将其重置为 0。在本练习中,我们创建一个名为“EventsCounted”的通道,其 I/O 类型为计数器;在“频道表视图”中,在 Quick Note / Special / OPC 标题下,应该可以看到一个位于单元格右侧的按钮,上面有三个点(…)。点击按钮,调出通道参数窗口,并在下拉列表中选择重置。唯一的参数是“重置?”,选择“是”或“否”、“确定”和“应用”将立即配置计数器通道,使其在读取通道值进行显示时不会重置为零。

第二个标记为“ResetCounter”的按钮被配置为启动清单 8-6 的简短“Reset Counter”脚本,该脚本将“EventsCounted”通道 events count[0]的最新值设置为零。事件计数[0]的可变值组件显示位于按钮下方,用于指示计数的事件数。图 8-6 中描述了为演示简单计数器用法而创建的面板。

点击启动事件按钮,激活练习代码列表中的列表 8-5 。

点击屏幕按钮“启动事件”,蓝色灯亮起,事件计数器增加。点击“重置计数器”(列表 8-6 )将“计数的事件”变量值显示设置回 0。

脚本

清单 8-5 和清单 8-6 是 DAQFactory 序列,其脚本创建用于频率测量的方波信号,带有 time – goto 脚本和用于手动清除计数器和关闭任何可能留在 on 配置中的 LED 的代码。

如前所述,“重置计数器”按钮激活列表 8-6 的短序列,该序列由单行活动代码组成,用于将计数器通道的值设置为 0。

通过将 LabJack 计数器通道切换回默认设置“读取计数值后复位”并以一秒的计数间隔配置新的计数器通道,新的计数器通道被配置为每秒读取一次频率。

电路

白色 LED 和 470ω限流电阻器的配置如第章第一部分图 1-3 所示,红色二极管的串联对的接点连接到 CB25 端子板上的 D8。

软件

必须产生一个脉冲序列,以形成具有可测频率的重复信号。清单 8-7 中的脚本是一个 PWM 或可变脉冲宽度发生器,可与图 8-7 中所示的屏幕按钮和指令文本结合使用,以启动和停止方波脉冲序列。

用于科研的 Arduino 教程(三)

图 8-7

DAQFactory 脉冲序列发生器面板

启动/停止按钮用于激活本章代码列表中列出的 DAQFactory 序列 PWM _ Script8-7。

脚本和动作

虽然使用“time – goto”语句并不被认为是良好的编程实践,但它确实简化了方波信号的创建。创建计数练习的两个面板后,将“Delay (0.5)”语句中的值更改为 0.25 和 0.1。在产生方波和显示频率的同时,快速前后移动鼠标光标,观察 LED 和显示的频率值。

观察

在两个计数器练习中包含蓝色和白色发光二极管,作为跟踪系统操作的视觉辅助。(参见“讨论”)

讨论

时间测定

数字电子电路由晶体控制振荡器“时钟”激活晶体振荡器产生非常稳定的固定频率方波脉冲序列,提供纳秒时间分辨率(10 -9 s)。方波由从 0 到+5 伏或从逻辑 0 到逻辑 1 的一系列二进制转换组成。时间可以分为由时钟方波波前的间隔确定的相对时间和来自固定事件的绝对时间。DAQFactory 程序的绝对时间由 1970 年 1 月 1 日的秒数决定。用户手册中详细讨论了图 8-2 的时间变量及其语法。

手动和自动事件计数

按钮启动的手动事件在通常与 DAQFactory 软件计时不冲突的时间范围内创建。但是,可以证明,试图用脚本创建一个波形来生成一个以足够快的速度变化的信号,可能会与操作系统软件定时相冲突。

作为本练习的一部分,使用了一个脚本来生成递增 LabJack 计数器所需的电压波形。蓝色 LED 作为系统验证的可视指示器已包含在练习中。然而,计数器硬件将事件记录为双转换操作,其中高信号下降到低值,然后低信号上升到高电压值。双跃迁“事件”受一个脚本影响,该脚本将引脚电压电平保持在 5 V,进而为电路中的蓝色 LED 供电。为了关闭 LED,我们在由 Reset Counter 按钮激活的脚本中包含了一行代码,用于将引脚 9 设置回 0 V,而不会被记录为“事件”的一半。

通过改变 PWM_Script 中的延迟值,可以改变信号保持在 0 或标称 5 V 的时间宽度。LabJack 计数器仅将+5 至 0 至+5 伏的转换记录为单个事件,以实现计数器递增的目的,因此在 0 伏时停留时间的宽度是在频率测定中被计为单个事件或周期的参数。

任何图形显示都必须由二维元素阵列组成,这些元素可以被单独照亮以形成图像。GUI 的更新消耗了大量的计算资源,因为阵列的各个元素被不断地扫描以实现任何所需的改变。如果用于驱动图 8-7 的脉冲发生器面板的程序(如脉冲发生器)被调用,延迟时间不到一秒,软件冲突可能会出现。

当使用脉冲产生程序为白色 LED 供电时,延迟时间变得非常短,只有几分之一秒,LED 脉冲频率和光标移动都变得不稳定。观察到的硬件和软件冲突证明了在不到一秒的时间跨度内使用软件脚本的局限性。

硬件时间和计时

我们对时间的硬件控制的讨论集中在 555 集成电路定时器芯片上,该芯片已经制造、改进和使用了 40 多年。该芯片通过使其输出以受控的时间间隔从高电压电平变为低电压电平来工作。时序间隔可以很容易地在多个数量级上变化,以产生长延迟(单稳态工作模式)或产生高速脉冲序列(非稳态工作模式)。由电阻和电容组成的简单外部元件可以用来产生所需的时间间隔。555 芯片提供双极晶体管和 CMOS 两种格式,功耗、功率输出和高频操作各不相同。

555 芯片以三个 5kω电阻的串联串命名,这些电阻连接到电源电压和地,以建立电路逻辑使用的 1/3 和 2/3 电源电压参考电平。该电路包含两个比较运算放大器,其输出信号馈入数字置位-复位触发器。模拟比较器使用 1/3 和 2/3 电压参考点来改变它们的输出状态,这使得触发器基于比较器输入来改变状态。数字触发器输出控制输出驱动器电路。

图 8-8 和 8-9 显示了定时器电路的一些操作和配置。

用于科研的 Arduino 教程(三)

图 8-9

一个 555 定时器 IC 框图

用于科研的 Arduino 教程(三)

图 8-8

555 IC 定时器工作模式

当如图 8-8 右下角的非稳态模式示意图所示配置的 555 IC 通电时,随着电流流经 R1 和 R2,电容器开始充电。随着引脚 2 和 6 上的电压上升,然后达到电源电压的 2/3(由内部分压器确定),输出变为低电平。随着输出变低,NPN 晶体管导通,555 的放电引脚有效地接地,通过 R2 对 C1 放电。当电容上的电压降至电源电压的 1/3 时,晶体管关断,电容开始通过串联对充电,循环重复。因此,C 上的电压在电源的 1/3 和 2/3 之间循环,周期为 T = 0.693(R1 + 2R2)C 或频率为 f = 1.4/(R1 + 2R2)C。输出信号的时间周期可分为两部分,包括电压高的时间(见图 8-8 ,右下角)和信号低的时间。高电平时间通常被称为“标记时间”,低电平时间被称为“空时”,占空比被定义为高电平时间或标记时间与信号的总和或时间周期的比值,以百分比值表示。

555 定时器产生脉冲序列的能力在实验科学中具有非常重要的应用,该脉冲序列的电子特性由外部电阻和电容值决定。以下练习直观地演示了方波或时钟信号的概念,以及脉冲宽度随外部传感器物理变化的变化。

许多网站、参考资料和教科书都详细讨论了定时器芯片的特性以及电路设计参数值表。

在下面的练习中,将演示方波输出信号和占空比的概念,以及使用定时器芯片改变脉冲宽度的基础。利用主要 IC 供应商在线提供的数据手册中的设计程序,可以组装一个输出频率为 6–7 赫兹的电路,为不同颜色的 led 供电,以直观显示电路工作情况。

实验的

用于科研的 Arduino 教程(三)

图 8-10

受控高低 555 定时器 ic 输出变化示意图

  1. 在非稳态模式下配置的 555 定时器芯片(见图 8-8 ,右下角)。

  2. 100kω可变电阻用作 R2,10kω电阻用作 R1。

  3. 一个 1 uF 电容用作定时电容或 C1。可以使用电解电容,因为该元件的较高漏电流率对电路性能并不重要。

  4. 带有 470ω限流电阻的两个不同颜色的 led 连接在芯片的输出引脚和电源轨之间,以便交替闪烁指示高低输出状态。

  5. 图 8-10 的原理图是用+5 V 电源绘制的,但是电路可以用 3 到 18v 之间的任何电源供电(调整电压> +5 的 CLR 值)。

图解的

观察

使用图 8-10 所示的电路,当 100kω电位计接近其最大极限时,红黄对在 13 秒内交替闪烁十次,当接近零值时,电路连续闪烁。

讨论

在“非稳态”配置中,定时器芯片能够改变输出开启或关闭的时间。开关时间或“占空比”之间的测量比值取决于 R2 的电阻,在这种情况下,该电阻是可变电阻器上的轴的机械位置。电位计轴的旋转机械运动因此可以转换成变化的电子方波信号。任何能够将物理现象转换成可变电阻的传感器也可以用来产生方波信号,其开/关时间的比率与被监测的物理现象产生的电阻成比例。热敏电阻是热敏电阻。负温度系数(NTC)热敏电阻对环境温度的升高表现出较低的比例电阻。将 NTC 热敏电阻插入 555 定时器 IC 的定时电路将导致输出方波的频率与热敏电阻珠的热环境成比例地变化,从而形成数字温度计。通过使用输出信号来打开和关闭功率晶体管,可以控制更大的电流。对于固定频率,可变“占空比”格式信号作为“脉宽调制”技术。PWM 电流控制可用于改变电机速度或控制施加到加热器的电流。

在非稳态模式下,555 产生的方波频率取决于 R1、R2 和 c 的值,频率由下式给出:

f = 1/ln(2)* c *(R1+R2)(ln(2)= 0.6931)

图 8-11 显示了 555 的非稳态循环。

用于科研的 Arduino 教程(三)

图 8-11

555 不稳定循环

输出频率可以由 RC 网络的三个值控制。图 8-12 中显示了占空比或高电平时间与低电平时间之比的百分比值。

用于科研的 Arduino 教程(三)

图 8-12

555 定时器输出的占空比变化

输出的高电平时间由下式给出

高时间= ln(2) * (R1 + R2) * C

低时间由下式给出

低时间= ln(2) R2 * C (ln(2) = 0.6931) (R 单位为ω,C 单位为 uF)

当电容器被流经 R1 和 R2 的电流充电时,输出信号为高。当它放电时,它仅通过 R2 放电,因此 R2 值引入占空比的变化是有限的。如果电阻对被电位计取代,电位计的游标端连接到定时器的引脚 7,则 R1 + R2 的总电阻是恒定的,而占空比可以通过改变游标的位置来改变。为避免 R2 设为 0 时出现不必要的问题,应在电容和可变电阻之间串联一个小电阻,以避免在低电位计电阻值时出现不可预测的结果。如果使用固定电阻器来建立小于 50%的所需占空比,则指向电容器的二极管将允许电容器在周期的高时间部分仅通过 R1 电阻器充电。

微控制器时钟、计时和事件计数

几乎所有与主机和外围设备(如传感器或过程控制)通信的微控制器都配备了板载晶体控制振荡器,用作系统时钟。通常,基于硬件的时钟信号可以通过微控制器软件访问,并用于计时和事件计数。

Arduino 微控制器使用晶体控制的 16 MHz 振荡器作为系统时钟。当操作系统通电时,它开始计算毫秒数(1/1000 或 10 -3 s)作为函数 millis()的值,以及微秒数(1/1000000 或 10 -6 s)作为函数 micros()的值。(由于调用 micros()时的二进制计数和硬件限制,微秒时间分辨率被限制在最接近的 4 μs 或 4 x 10 -6 s。)

这两个函数存储为无符号长整数,在滚动到 0 之前,其最大值为 4,294,967,295。最大值限制为毫秒()计数提供了大约 50 天的时间跨度,为毫秒()计数提供了 70 分钟的时间跨度。Millis 计数精确到最接近的一位数,但 micros 值表示到最接近的四位数(2 2 )。以毫秒()为单位的计时误差为 0.18 秒/小时、4.32 秒/天和 129.6 秒/月。

DAQFactory 提供了一种替代方法来演示微控制器(如 Arduino)的计时和事件计数概念。有许多公开的程序使用机械开关和相应的大量库以及用于处理机械“开关触点弹跳”的其他方法,为微控制器创建倒计时、秒表和其他计时应用。 3

DAQFactory 屏幕按钮和串行端口消除了对机械开关和机械开关触点反弹的需要。

实验的

为了演示廉价的串行端口连接微控制器的基本计时功能,需要两个程序,第一个程序在主机屏幕上显示 SCADA 软件中的计时器控制面板,第二个程序在微控制器上实现选定的计时功能。Arduino 代码见清单 8-8 ,DAQFactory 快速序列见清单 8-9 。

图 8-13 显示了 DAQFactory SCADA 软件中设置的简单秒表计时器的简单基本配置。

用于科研的 Arduino 教程(三)

图 8-13

简单的 DAQFactory 秒表控制面板

三个按钮中的每一个都被配置为激活快速序列码,该快速序列码向串行端口写入“b”、“s”或“r”以开始计时会话、停止计时会话并将 millis()计数传输回 SCADA 软件,或者将计时器重置为零并开始另一个计时会话。

图 8-13 中看到的非活动(红色 X)变量值显示在使用“s”命令停止计时会话时接收来自 Arduino 的总 millis()计数。图 8-14 显示了在组合计时系统开发期间,为验证而运行的简单启动和停止计时会话期间的 DAQFactory 串行监视器活动。

用于科研的 Arduino 教程(三)

图 8-14

简单 Arduino 定时会话的 DAQFactory 串行端口监视器记录

回想一下,数据发送到串行端口后,DAQFactory 串行端口代码需要回车(CR,ASCII 代码 13)和换行符(LF,ASCII 代码 10)。通过 DAQFactory 串行端口传递的数据可以读入通道或全局变量。在主要代码开发过程中,在 DAQFactory 软件中配置了一个名为 millisVlu 的通道,然后将变量值屏幕组件设置为将从 Arduino 接收的 millis()值除以 1000,以获得计时器记录的整秒数和毫秒数。后来的代码版本使用了全局变量“elapsed”和快速序列来实现简单的计时功能(参见“观察”中的图 8-15 以及清单 8-8 和 8-9 )。

用于科研的 Arduino 教程(三)

图 8-15

用于秒表程序开发的 Arduino 串行端口输出

DAQFactory 串行端口使用第六章中清单 6-10 中的“接收”代码,从串行端口将数值读入通道或用作全局变量的值。

观察

在图 8-15 中,Arduino 串行端口已被编程以帮助验证微控制器的命令解释,典型的时序结果显示如图 8-16 所示。

用于科研的 Arduino 教程(三)

图 8-16

典型的简单毫秒分辨率定时会话

简单秒表计时器的开发首先是通过使用 Arduino 自己的串行端口手动发送“b”、“s”和“r”命令来产生如图 8-15 所示的输出,使 Arduino 作为独立计时器运行。有了一个正常运行的 Arduino 程序,代码被精简为清单 8-8 中的代码,其中唯一的输出是 Arduino 代码行“Serial.println(elapsed)”,它将 elapsed time 变量的内容发送到带有必需的 CR 和 LF 的串行端口。

检查清单 8-8 和 8-9 会发现两个程序中的复位功能不同。更简单的方法是将复位代码分为串行端口两侧的两个动作。Arduino 代码重置开始计时循环和停止计时的状态标志,并打印到串行端口动作,而 DAQFactory 快速序列码实际上将运行时间变量和计时秒显示设置回零。

一旦进行了初始计时测量,应使用复位按钮来复位 Arduino 代码中的单个动作标志。

讨论

图 8-15 展示了一种开发 Arduino 代码的简单技术,该代码将对 SCADA 软件在本练习的最后一次迭代中写入串行端口的单字母命令做出响应。Arduino 代码的完整开发是通过使用 IDE 的串行监视器“发送”功能,并将图 8-15 中的响应写入开发代码,以在最终组合 SCADA 和微控制器操作之前验证代码的操作。通过重写或注释掉不需要的行,可以将功能秒表代码减少到与 DAQFactory 面板结合使用。

还可以通过将经过的毫秒时间值(可以延伸到接近 50 天)转换成分钟、小时和天来配置更复杂的定时器功能,这些时间值会受到前面提到的时间误差的影响。

在可能的情况下,可以使用屏幕激活按钮来避免由机械开关触点反弹引起的问题。

使用 Python 和 Raspberry Pi 计数事件和计时

Python 语言解释器的时间测量是从运行程序的主机上获得的。Raspberry Pi 的基本概念是面向互联网接入的。互联网连接可用于传输操作系统、应用软件和更新。互联网连接通过互联网时间服务器提供精确的计时。如果 RPi 用于时间相关的实验或测量应用,而这些应用又无法访问互联网,则需要安装一个实时时钟(RTC ),以提供精确的计时基础。 4

在图 8-17 中,一个非常简单的控制台请求显示了自 1970 年 1 月 1 日开始计时以来发生的“滴答”数。

用于科研的 Arduino 教程(三)

图 8-17

对滴答计数的控制台请求

在 Unix/Linux 操作系统中,滴答数可以转换为秒、分、小时和天,以提供任何所需的计时操作。图 8-18 是刻度到当前时间显示的控制台转换。

用于科研的 Arduino 教程(三)

图 8-18

来自滴答计数的当前时间的控制台请求

如图 8-19 所示,可以在交互式控制台上使用 asctime()函数获得更熟悉的时间格式。

用于科研的 Arduino 教程(三)

图 8-19

熟悉的当前时间格式

已经发布了许多简单的按钮定时器 GUI 和定时器模块,用于用 Python 编写定时器应用程序,在图 8-20 中描述了一个使用 tkinter Python 模块的三按钮 GUI。代码在清单 8-10 中列出。该规范已对 2002 年出版的原版进行了修改。??

用于科研的 Arduino 教程(三)

图 8-20

三按钮秒表计时器

安排事件

除了前面列出的时间显示函数,Python 还有几个库,如 sched 和 schedule,它们使用时间模块作为调度事件的基础。实质上,sched 和 schedule 模块为实验者提供了一个可编程的起点,从该起点可以在启动单个事件或编程代码序列之前指定延迟。

标题为 Scheduled_PgmCntrl_LED.py 的清单 8-11 将逻辑高电平和低电平编程应用于 GPIO 引脚 20 和 21(板引脚 38 和 40),通过限流电阻打开和关闭连接到引脚的两个 led 作为“事件”

对代码的检查显示了一个 scheduler 对象实例的典型创建,其代码行为 scheduler = sched . scheduler(time . time,time.sleep)。下面两行定义了将来要运行的两个事件:

  • scheduler.enter(2,1,actvt_GrnLed,(“绿色 Led 首先激活”,))

  • scheduler.enter(5,1,actvt_RedLed,(“红色 Led 第二个激活”,))

sched 模块的文档规定了 enter()函数的四个参数,包括从处理启动函数 start()开始的时间延迟(以秒为单位)的数值、指定事件优先级的数值、要调用的事件函数的名称,以及需要时要传递给被调用函数的数据。列表 8-11 是重叠事件的一个例子,其中 led 点亮的时间比事件的预期开始时间长。shed 模块执行所有被调用的函数,没有一个函数丢失,但是事件的时间会因为进程重叠的量而在时间上偏移得更远。

图 8-21 是调度程序的典型输出。要点亮的红色和绿色发光二极管的接线如图 8-22 中电路 A 所示。

用于科研的 Arduino 教程(三)

图 8-22

用于 GPIO 编程演示的吸收或提供电信号的电路

用于科研的 Arduino 教程(三)

图 8-21

重叠事件的调度程序输出

安排事件可能是一个复杂的问题,在使用这些模块时,应该检查 Python 参考文档以获得更多细节。 6

检测和计数事件

RPi 上外部事件的检测和计数既需要能够确定 GPIO 阵列的各个引脚上是否存在电压,也需要能够检测引脚电压的转换。GPIO 引脚上的电压转换可以通过两种技术来监控,称为“轮询”和使用“中断”。在任意时间点寻找电压变化称为“轮询”引脚。轮询的缺点在于,要监控的事件可能发生在进行引脚状态观察的时间帧之前或之后。轮询通常通过软件循环编码来实现,这会消耗大量的处理器时间,同时阻止 CPU 执行其他任务处理。

确定电压转换的第二种方法使用中断或“边沿检测”,其中记录从高到低(下降沿)或从低到高(上升沿)的变化。

简而言之,可以说大多数现代操作系统是分时操作,管理多个程序,这些程序对用户来说似乎是同时运行的。操作系统运行的每个程序在 Unix 中称为进程(在 Windows 中称为任务),并且只运行很短的一段时间。周期性地,当前运行的程序用完其分配的“时间片”,这由从硬件或软件定时器发送到中央处理单元的中断信号的产生来确定。中断使 CPU 暂停或“中断”手头的正常任务,以处理或服务于高优先级事件。中断使 CPU 保存其当前计算,切换到处理中断服务程序(ISR)(或事件处理程序),并在完成 ISR 后恢复正常操作。输入输出操作可以编码到 ISR 中,这样 CPU 就可以在监视 I/O 操作和正常计算功能之间分配处理资源。CPU 时间的第一个程序片的处理、中断信号的产生、ISR 的处理以及切换到下一个要处理的程序都发生在如此短的时间内,以至于对用户来说,几个程序似乎在同时运行。

线程是程序代码中较小的部分,可以交叉使用,以产生两个代码部分同时运行的预期效果。(实际上,只有多核处理硬件才能同时运行多个线程。)线程化可以用来避免 GPIO 操作中轮询的缺点。中断和 ISR 可用于检查 GPIO 引脚的状态,如果它无效,则继续正常程序处理。轮询包括对事件的连续检查,而中断则定期进行。轮询消耗所有的资源,而中断只消耗一部分。轮询使用专注于事件检测的单线程,但是 Python 和 RPi。GPIO 库允许创建两个或多个线程,其中事件检测代码可以独立运行。次级线程中事件的检测激活代码,该代码回调主线程以启动中断服务例程。有许多非常简单、易于实现的多按钮、线程回调演示程序已经发布,以支持描述 GPIO 阵列输入和输出使用的库文档。在线提供了一个简单线程库的文档。 7

在前面的练习中,可以使用三个库来处理 RPi。GPIO 引脚已被引入,这些不同的模块将根据需要用于生成简单的定时器程序或监控引脚状态,并在手稿的剩余部分记录引脚状态变化之间的时间。

RPi。GPIO 和 gpiozero 库非常易于使用,并得到大量代码文档的支持,这些代码是为大量可以通过 GPIO 引脚与 RPi 接口的常见设备开发的。

然而,前两个库不能精确、短时间地计时。在前面的练习中,在简单的 LED 电源控制应用中可以看到的“抖动”是由基于 Unix 的 Linux 操作系统暂停 GPIO 操作以处理优先级高于 RPi 输入输出代码的内部进程引起的。

作为 pigpio 导入的第三个库已经开发出来,用于能够提供微秒计时精度的 RPi。pigpio 模块中的计时精度是通过使用 C 代码编写库和使用运行在 RPi 上的 Python-Linux/Unix 接口程序访问 gpio 引脚来实现的。在系统后台运行的 Unix 实用程序或服务程序通常被称为“守护程序”

如上所述,RPi 上 GPIO 引脚的物理计算可以被视为计算机与外界的接口。RPi 能够通过在几乎任何时间点测量其电压来检测阵列中每个引脚的状态。当 Python 解释器使用 RPi 时,系统和软件开销限制了 RPi 对任何 GPIO 引脚上电压变化的响应时间。GPIO 或 gpiozero 库。如上所述,为了改善 RPi 对其 GPIO 引脚阵列的短时间响应,用执行速度非常快的 C 语言编写的库已经通过 Linux/Unix 守护程序或称为“pigpiod”的实用程序与 Python 解释器连接利用 C 库模块,可以在 GPIO 引脚操作中可靠地访问微秒级时标。

pigpio 库可供具有各种编程能力的研究者使用,如果需要,可以查阅大量的文档。

时序和低频事件计数可以通过 Python 程序来实现,Python 程序使用适当的 GPIO 引脚管理库来完成手头的任务。使用 RPi 可以实现简单、低级、易于编码和实现的接口。GPIO 库,而更复杂的传感器最好使用 gpiozero 库。使用 pigpio 库及其快速准确的时间管理功能和在 RPi 操作系统后台运行的接口实用程序守护进程需要中级到高级的编程技能。

实验的

基于 GUI 的软件秒表计时器的实现不需要与 GPIO 阵列交互。

调度事件既可用于普通 Python 代码应用程序编程,也可用于利用 GPIO 阵列的物理计算过程,如本练习的以下部分所述。

由于传感器、致动器、电机和开关的所有输入和输出动作必须以从 0 到 3.3 或 5 伏的转换形式进行,图 8-22 中所示的两个电路可分别用于以电路 A 或 B 的形式提供或接收电激活信号。

在图 8-22 的电路 B 中使用 LED,虽然不是激活 RPi GPIO 代码所必需的,但确实为研究者提供了额外的诊断能力,以防代码部分对点击按钮没有反应。一个按钮点击应该会导致 LED 灯和代码等待按钮点击按预期被激活。当点击按钮时,如果 LED 没有点亮,则可以确定代码没有响应的根本原因(参见“观察”和“讨论”)。

列表 8-12 使用按钮式机械开关,如图 8-22 电路 B 所示配置,提供“上升沿事件”来触发时间测量程序的动作。

该程序使用两个上升沿检测功能,在 RPi 等待上升沿出现时阻止所有计算操作。如果按钮开关的激活是程序关注的唯一操作,如定时器示例中的情况,那么阻塞功能实现起来既简单又足以解决手头的问题。图 8-24 是上升沿定时器程序的典型输出,而图 8-25 在编程代码开发期间捕捉到一个开关触点“弹跳”。

如前所述,监控机械开关(如按钮、触发器或磁激励簧片)的高速数字定时器和计数器必须适应开关提供连续闭合触点之前发生的触点弹跳。RPI。GPIO 库都有估计开关触点弹跳的规定,这种弹跳可能在即将进行的实验中遇到,并且将接受实验者忽略第二个事件的毫秒时间尺度。

当要监控高速事件时,例如在光束阻挡配置中遇到的事件,通常可以使用电容来抑制杂散噪声或电磁干扰。

轮询和中断事件检测虽然易于用按钮设备实现教育目的,但对于检测和计数更高速的事件来说价值有限。在随后的物理计算练习和测量中会遇到的电机旋转速度、高速物体计数和固定距离上的精确计时,都可以用中断光束光学技术来实现。在第十章中,红外中断光束探测器用于计算电机转数,以确定电机转速。

图 8-23 描绘了一个不可见红外(IR,波长为 940 nm)阻断光束电路,它可以配置在原型试验板上,并连接到 RPi 40 引脚 GPIO 阵列。(电路描述中提供了 BCM GPIO 值和 BN 或板号值。)

用于科研的 Arduino 教程(三)

图 8-23

一种红外断路电路

断梁系统没有金属触点,不会“反弹”,但可能会出现电尖峰或噪声,从而产生虚假信号响应。因此,在为即将进行的实验汇编和编写代码时,实现第二信号抑制的反弹时间或使用电容吸收杂散信号是研究者的判断或实验问题。

以下中断光束程序设计用于连续操作,并使用 while 循环监控光束完整性。回路软件具有用于干净退出方案的内置代码,该方案使用 Ctrl+C 击键组合来终止主程序光束扫描回路,并执行适当的电路关闭程序,该程序通常关闭 IR 光束,移除不再使用的代码,并重置端口配置。

根据图 8-22 A,监控红外光束的三个 RPi 程序的清单 8-13 、 8-14 和 8-15 在主 while 循环中有额外的代码激活两个二极管,一个红色和一个绿色,连接到电路板阵列(BCM GPIO 20 和 21)上的引脚 38 和 40。红外光束不可见,添加的代码在光束中断时打开红色二极管,在光束中断时点亮绿色二极管这两个二极管用作不可见红外光束状态的远程指示器。

列表 8-13 和 8-14 是红外二极管和光电晶体管探测器可用于演示更高速事件监控的两种方式,并展示了该技术的实际应用。

观察

上升沿定时器程序的输出被大量注释,以描述在经过时间测量期间发生的事件,如图 8-24 所示。

用于科研的 Arduino 教程(三)

图 8-24

典型的上升沿按钮定时器输出

有时,点击按钮不会产生预期的结果,代码等待电气转换。如图 8-25 所示,当试图激活定时器程序时,该程序使用按钮的两次连续点击来测量运行时间,代码确认并执行“开始计时会话”初始事件,然后几乎立即正确地结束计时会话,记录分数秒的运行时间。(参见“讨论”)

用于科研的 Arduino 教程(三)

图 8-25

意外的短经过时间确定

在图 8-25 中,测得 0.049 或 49 ms(毫秒)的运行时间,这是机械开关“弹跳”的特征。

有时,初次点击按钮不会激活等待转换的代码。这种现象在本质上是随机的,并且有时偶然被追踪到开关触点没有闭合或没有闭合足够的表面积接触来提供点亮二极管或激活转换识别码所需的能量。(参见“讨论”)

图 8-26 是一个简单程序的输出,该程序使用简单的 while 循环轮询方法来监控红外光束的状态。从作者在光束中快速手动振动一支笔所产生的输出可以看出,当光束未中断时,光电晶体管或二极管充当接地短路,与 IR 敏感元件相连的 GPIO 引脚被拉低至几乎 0 V,光束阻断消除了接地短路,GPIO 引脚上升至 3.3 V,将输入引脚驱动至高电平。

用于科研的 Arduino 教程(三)

图 8-26

轮询程序输出

while 循环以系统软硬件组合允许的最快速度不断循环,并输出引脚的高/低值。

通过使用“Ctrl+C”击键序列,仅轮询输入引脚的连续循环被正确终止。通过将 while 循环封装在一个 try-except 键盘中断组合中来识别该序列,该组合允许循环终止并将控制传递给程序的其余部分。循环终止后,程序代码关闭可能开启的二极管,复位可能已被修改的 GPIO 配置,并发出程序终止信号。笔在光束中的快速振动不会改变交互式终端中打印数据的速率。可以看到轮询遗漏了波束中断事件。

图 8-27 显示了列表 8-13 的上升沿检测中断代码的输出。

用于科研的 Arduino 教程(三)

图 8-27

中断事件检测程序输出

红外光束中笔轴的快速振动导致数据输出速率相应快速增加。如前面的数据输出所示,输出失真似乎是由于交互式屏幕输出无法响应光束阻断事件的快速中断检测。

通过使用 RPi 的 add_event_detect 函数,在程序中创建了一个事件检测过程中断。GPIO 库。添加的函数接受几个指定 GPIO 管脚号的参数;动作的事件条件,上升/下降沿或两者;以及当接收到中断信号时转移到或“回调到”的函数的名称。

在所监控的 GPIO 引脚上遇到选定的电子转换之前,程序的主循环会打印出预期的“输入= 0 光电二极管开启”,并且程序控制不会转移到专为遇到转换时使用而创建的功能。由于 GPIO 引脚上没有活动,中断实际上在后台运行。然而,电子活动触发分支发生,程序控制转移到“跳转、执行和返回”功能,该功能执行研究者要求的动作。在图 8-27 中,输入引脚状态被打印出来,直到遇到一个上升沿,导致程序分支到专门创建的函数,该函数检查引脚状态,将其打印出来,并返回到原来的程序循环程序。RPI 的添加事件检测功能。GPIO 库执行速度如此之快,以至于控制输出显示的较慢代码无法跟上红外光束中笔的快速移动,从而导致图 8-27 所示的输出损坏。线程的使用使得高速中断技术成为可能。

清单 8-15 使用中断技术来驱动事件计数器。计数器在独立于主程序的线程中运行,并且仅当被监控的引脚上发生指定的电子转换时才被访问。计数器值存储在 Python 全局变量中,以便对主程序循环的输出部分可见,在计数器递增函数工作的线程之外。主循环根据程序代码的执行定期打印出计数器值,但是计数器值通过中断激活的事件检测增加,该事件检测分支到计数器递增的线程。如图 8-28 所示,通过在红外光束中振动一支笔,计数器记录光束中断的次数,并在主程序正常、几乎恒定的数据输出间隔期间将它们加到总计数中。

用于科研的 Arduino 教程(三)

图 8-28

中断驱动的事件计数器输出

讨论

通过 GPIO 引脚和三个接口库之一将传感器与 RPi 直接接口,是收集数据或监控传感器的最经济、最简单的选择之一。这三个库都有独特的特性和不同程度的复杂性。GPIO 最适合简单的数字系统,gpiozero 适合集成电路、传感器或传感设备和机器人电机控制,而 pigpio 更复杂、速度非常快、时序准确,同时能够与各种机电系统接口。

所有三个 I/O 库都能够适应机械开关“反弹”,这可能是在手边的系统中根据经验估计的最佳结果。忽略第二或第三信号的时间窗口的大小由研究者希望测量的最小信号的时间宽度决定。

选择使用轮询循环监控事件的程序还是中断驱动的程序,只需考虑数据发送到 GPIO 引脚的速率。每秒一次或两次轮询对于监控开门传感器来说已经足够了,而中断驱动监控器应该用于高速旋转测量。

Python 基于时间的测量都是基于运行程序的系统的节拍数。系统的时基是从互联网时间服务器提供的互联网时间中获得的。如前所述,对于“离线”进行的时间测量,如现场测量,必须在 RPi 上安装实时时钟(RTC)。

在脚注 6 的 URL 中可以找到调度器模块使用的完整描述,在使用这些 Python 函数时应该参考这些描述。对于一周中的所有日子,使用具有分钟、小时、日和一天中的小时的模块需要在应用程序中小心谨慎,以根据需要运行,并且应该为真实世界的应用程序仔细设置。

通过使用适当缩放的感兴趣的信号,可以使用光学中断光束电路的快速响应速率来测量信号的频率,以给 IR 二极管源供电。然后,可以对计数器软件进行编码,以使用中断驱动的计数器来测量程序主输出循环的定时和定义的迭代次数所累积的事件数。

代码列表

// send begin signal b
device.ardyBluBrd.Write('b')

// send stop signal s
global Elapsed
device.ardyBluBrd.Write('s')
private string datain
datain = device.ardyBluBrd.ReadUntil(13)
Elapsed = strToDouble(datain)

// send re-set signal r
device.ardyBluBrd.Write('r')
Elapsed = 0

Listing 8-9DAQFactory Quick Sequences for b, s, and r

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
/* A stopwatch program using a DAQFactory panel and the serial port to avoid the debouncing problems associated with
mechanical switches. The program uses the letters b, s, and r
to branch in an Arduion case statement using b for begin,
s for stop and r for re-set. Always ensure that data sent
from the Arduino to the DAQFactory software code is
Serial.println(data);
*/
char incmngByte;                        // a variableto hold the incoming byte from the serial port
unsigned long start, finished, elapsed; // timing variables
bool tsipFlg = LOW;                     // timing session in progress flag
bool wtspFlg = LOW;                     // write to serial port once only flag
bool rstFlg = LOW;                      // re-set b and s flags
//
void setup() {
  Serial.begin(9600);                   // start the serial port

}
//
void loop() {
 if(Serial.available() > 0) {           // check port for incoming character
  incmngByte = Serial.read();           // set character into variable
  }
switch(incmngByte) {                    // the case statement for decisions
  case'b':                              // begin a timing session
  if (tsipFlg == LOW) {                 // check the status flag
  start = millis();                     // set the start time
  //Serial.print(start);                // diagnostic
  tsipFlg = HIGH;                       // set the status flag to timing in progress
  }
  rstFlg = LOW;
  break;
  case's':                              // stop the timer
  if (wtspFlg == LOW) {                 // check the status flag
  finished = millis();                  // set the finish time
  //Serial.println(finished);           // diagnostic
  elapsed = finished - start;           // calculate the elapsed time
  Serial.println(elapsed);              // write the elapsed time to the serial port
  wtspFlg = HIGH;                       // set the status flag to write only once

  }
  rstFlg = LOW;
  break;
  case'r':                              // re-set b and s functions
  if (rstFlg == LOW) {                  // check the status flag
  tsipFlg = LOW;
  wtspFlg = LOW;
  rstFlg = HIGH;
  }
  break;
 }
}

Listing 8-8Arduino Stopwatch Timer Code

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
// PWM_Script (Pulse Width Manipulation) Script for pulse
// width variation - Oct. 21/09 Rvn. Jan. 2/11, Aug. 3/17
// A "time - goto" loop is used with delay statements to set // D8 to 1 then 0 thus raising and lowering the channel
// DigOut_8_PWM output between 0 and 5 volts in a continuous // manner. The continuously varying voltage creates a square
// wave train. The 0.002 and 0.098 can be considered as the // time on time off duty cycle. With the lower duty cycle the
// pulsing of a powered light source is quite evident. // Various duty cycles must be entered manually into the simple
// program which is started and stopped with the sequence
// pop-up menu displayed by right clocking on the sequence name.
time 0
DigOut_8_PWM = 1
Delay (0.002)
DigOut_8_PWM = 0
Delay (0.098)
goto 0

Listing 8-7DAQFactory Sequence PWM Script

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
// ResetCounter - Fall/09 Revn Jan 1/11 The script manually
// resets the displayed number of events counted, by the LabJack // counter after the defaut "Reset after polling" has been
// turned off. The counter is activated after it detects a
// falling edge waveform followed by a rising edge waveform. // The "event" counted thus consists of a 5 to 0 - 0 to 5 volt
// transition which leaves the Pin 9 at 5 volts. For the manually // activated counter exercise the blue LED thus remains ON as
// long as the manually activated counting session is in
// progress, re-setting the counter then turns the LED off.
//
EventsCounted[0] = 0
DigOut_9_EventCntr = 0
// By using the default setting of "Reset" after polling (reading) // the number of 5-0-5 volt transitions in a given period of
// time, the frequency can be determined.
RawCounts[0] = 0
DigOut_8_PWM = 0

Listing 8-6DAQFactory Sequence Reset Counter

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
// A_Counter_Event - Jan. 1/11 - The LabJack counter is activated // by a 5 to 0 volt falling edge followed by a 0 to 5 volt
// rising edge. The following script applies the 5 - 0 - 5 volt // profile to the DigOut_9_EventCntr channel that activates
// pin D9 onthe CB-25 board. This script is activated by
// clicking on the screen button labelled "Initiate Event".
//
// Set the pin voltage to 5 volts
DigOut_9_EventCntr = 5
// Create the falling edge by setting the pin voltage to 0
DigOut_9_EventCntr = 0
// Create the rising edge by setting the pin voltage back to 5
DigOut_9_EventCntr = 5
// For ease of configuration the voltage is left on for 1/2 a second so as the lit LED can be
// used to validate a functioning system.
//Delay(0.5)
//DigOut_9_EventCntr = 0

Listing 8-5DAQFactory Sequence Counting Events

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
// CumulativeTimeOfIntervals Nov. 27, 2010 is a summation of // the previous collected intervals Each interval timed is
// measured in clock ticks that are converted into sec, min // and hrs for display. When the current interval is to be
// summed into the accumulation the Cumulative Time button is // used to add the current interval’s total seconds to the
// accumulating sum of total seconds. The previous hrs, min.
// and seconds used for the previous display are discarded and // a new total time is calculated for an up-dated display.
//
global TtlHrs
global TtlMin
global TtlSec
global Hrs
global Minutes
global Sec
global TSixtySecTm
global TSxtyMinTm
global ElapsedTime
global IntrvlMin
//
TtlSec = TtlSec + Sec
TtlHrs = Floor(TtlSec/3600) // just divide total time in seconds by 3600 to get hours
TtlMin = Floor(TtlSec/60) // total minutes is calculated

   TSxtyMinTm = (Floor(TtlSec/60))%60
   Sec = (TtlSec - ((TtlSec - (TtlSec % 3600)) % 60))
   TSixtySecTm = (TtlSec - ((TtlSec - (TtlSec % 3600)) % 60)) % 60

Listing 8-4DAQFactory Sequence Cumulative Time of Intervals

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
// Reset Stopwatch Display Oct. 6, 2010
// The sequence resets the timer variables
//
InitialTime = 0
CurrentTime = 0
ElapsedTime = 0
Hrs = 0
Minutes = 0
Sec = 0
SxtySecTm = 0
TSixtySecTm = 0
SxtyMinTm = 0
TSxtyMinTm = 0
TtlHrs = 0
TtlMin = 0
TtlSec = 0

Listing 8-3DAQFactory Sequence Reset Stopwatch

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
The Stopwatch Timer DAQFactory Sequence Code
// Stop Watch Timer Oct.6 - Nov. 17 2010  (Min is a reserved // word!) The timer sequence is started and stopped by a screen
// button that simultaneously sets a timing flag for a while
// loop and starts the sequence StopWatchTimer. The SysTime()
// function is used in a wait(0.05) delayed while loop, that // calculates the total number of clock ticks between the current
// value of SysTime() and the initial interval starting value. // The total elapsed time in seconds is calculated then divided
// into hours, minutes and seconds for display. The main screen // display provides the operator with two modes of timing
// operation that record either a single interval time or the // cumulative total of multiple intervals. The cumulative total
// option must determine the number of seconds that have elapsed // in the current interval and keep track of the sum of the
// accumulated interval times.
//
//
//
global InitialTime // the start of the current interval
global ElapsedTime // the elapsed time of the current interval
global Hrs = 0
global Minutes = 0
global SxtyMinTm
global Sec = 0
global SxtySecTm
global TimingFlg // the main while timer loop condition flag

//
//
InitialTime = SysTime() // Set the initial time value
//
while(TimingFlg) // start the main program loop
   ElapsedTime = SysTime() - InitialTime
   wait (0.05)
   Hrs = Floor(ElapsedTime/3600) // just divide total time in seconds by 3600 to get hours
   Minutes = Floor(ElapsedTime/60) // total minutes is calculated

   SxtyMinTm = (Floor(ElapsedTime/60))%60
   Sec = (ElapsedTime - ((ElapsedTime - (ElapsedTime % 3600)) % 60))
   SxtySecTm = (ElapsedTime - ((ElapsedTime - (ElapsedTime % 3600)) % 60)) % 60
   Endwhile

Listing 8-2DAQFactory Stopwatch Timer

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
// Scheduled Time Timer
// Oct. 2 to 15, 2010
// A screen Start/Stop button is used to initiate the // Schdld_Time_Tmr sequence. The sequence accepts a start and // stop time at which to run a "scheduled event" from two,
// labelled, date and time edit boxes.
// The sequence verifies that both times are in the future and // that the start time is before the finish time. Beneath the edit
// entry boxes a panel display shows the time left before event // activation together with the elapsed and remaining times of
// the scheduled event.
//
//
global EvStartTime  // the starting time of the scheduled event
global EvEndTime   // the ending time of the event
global EvElapsedTime // time the event has been running
global EvRemainingTime // the time remaining in the timed event
global CurrentTime // the current time
global TimeToGo   // the variable for the count down timer
global HrsToGo
global MinToGo
global SecToGo
global EvHrsToGo
global EvMinToGo
global EvSecToGo
global EvElpsdHrs
global EvElpsdMin
global EvElpsdSec

//
// verify validity of entered time values
//if (EvStartTime < EvEndTime)
//if (CurrentTime < EvStartTime)
//
// Count down to start of timed event
//
CurrentTime = SysTime()
while (EvStartTime - CurrentTime > 0)
CurrentTime = SysTime()
TimeToGo = EvStartTime - CurrentTime
//Calculate the count down times for display
HrsToGo = floor(TimeToGo/3600)
MinToGo = floor(TimeToGo - (floor(HrsToGo) * 3600))/60
SecToGo = TimeToGo - (floor(HrsToGo * 3600) + (floor(MinToGo) * 60))
delay(0.01)
// zero count down timer display
HrsToGo = 0
MinToGo = 0
SecToGo = 0
endwhile
//
// Start Scheduled Event Timer
//
While (EvEndTime - CurrentTime > 0 )
CurrentTime = SysTime()
// Start actual event 

RedLed = 5
//
TimeToGo = EvEndTime - CurrentTime
//Calculate the count down times to the end of the scheduled event for display
EvElapsedTime = CurrentTime - EvStartTime
EvElpsdSec = (EvElapsedTime)%60
EvElpsdMin = (EvElapsedTime/60)%60
EvElpsdSec = (EvElapsedTime/3600)
EvHrsToGo = floor(TimeToGo/3600)
EvMinToGo = floor(TimeToGo - (floor(EvHrsToGo) * 3600))/60
EvSecToGo = TimeToGo - (floor(EvHrsToGo * 3600) + (floor(EvMinToGo) * 60))
delay (0.01)
endwhile
// Stop Timed Event
RedLed = 0

Listing 8-1DAQFactory Sequence Scheduled Time Timer

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

Raspberry Pi 程序代码

# Break Beam Interrupt Driven Counter: counts & prints number of interruptions in beam
# Input from pin 7 (board) (GPIO 4) system ground at pin 6
# IR photodiode pull-up with 1M ohm pullup btwn 7 & 1 (3.3v)
# IR LED pin 11 supplies IR illumination gnd pin 6
#
import RPi.GPIO as GPIO   # get GPIO library
import time
#
GPIO.setmode(GPIO.BOARD)     # use RPi board pin numbers
GPIO.setup(11, GPIO.OUT)     # set pin 11 (GPIO 17) as output to power IR LED
GPIO.setup(7, GPIO.IN)       # set pin 7 (GPIO 4) as input
#
counter = 0 # declare and initialize counter variable
#
# Function "add_event_detect" runs at input change
def counterPlus(channel):
    global counter                 # declared global to share with system & threads
    if GPIO.input(channel) > 0.5:  # pin 7 = 3.3v. photodiode off
        counter += 1               # recognize blocked beam
    else:
        counter += 0               # 0v, no-op
#
# On input change, run input change function
GPIO.add_event_detect(7, GPIO.RISING, callback=counterPlus)
#
GPIO.output(11, True)         # turn on the IR LED
time.sleep(1)                 # give LED time to turn fully on
try:
    while True:
        print("Count = ", counter)   # output current counter value
        time.sleep(1)                # time delay before looping
except KeyboardInterrupt:
    pass
#
print("Final counter value = ", counter)  # output final counter value

GPIO.output(11, False)                    # turn IR source off
GPIO.cleanup()                            # reset ports
print("Diodes off and GPIO ports reset")

Listing 8-15An IR Break Beam Interrupt-Driven Counter

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
# PRi Detecting Input Events with Interrupts
# Program to get input from pin 7 (board) Gnd is pin 6
import RPi.GPIO as GPIO
import time
#
GPIO.setmode(GPIO.BOARD)   # get library
GPIO.setup(11, GPIO.OUT)   # set pin 11 as output to power IR LED
GPIO.setup(38, GPIO.OUT)   # green led beam intact indicator
GPIO.setup(40, GPIO.OUT)   # red led beam broken indicator
GPIO.setup(7, GPIO.IN)     # set pin 7 as IR Photodiode input
#
#   Function that "add event detect" runs at input change
def inputChng(channel):
    print("Input pin status changed to ", GPIO.input(7))
#
# On input change, run input change function
GPIO.add_event_detect(7, GPIO.RISING, callback=inputChng)
#
GPIO.output(11, True)         # turn IR LED on
time.sleep(1)
try:
    while True:
        if GPIO.input(7) > 0.5:
            print("Input =", GPIO.input(7), "Photodiode OFF")  # detects 3.3v power from pin 1
            GPIO.output(38, 0)  # grn led off as beam has been broken
            GPIO.output(40, 1)  # red led on to indicate beam is broken
            time.sleep(0.5)     # wait time before next iteration
        else:
            print("Input = ",GPIO.input(7), "Photodiode ON")  # detects 0v (diode-on acts like short)
            GPIO.output(40, 0)  # red led off as beam restored
            GPIO.output(38, 1)  # grn led on as beam intact
            time.sleep(0.5)     # wait time before next iteration
except KeyboardInterrupt:
    pass
#
#
GPIO.output(11, False)        # turn OFF the LED
GPIO.remove_event_detect(7)   # Turn off event detect interrupt

GPIO.cleanup()                # reset ports
print("Led Off, event detect interrupt removed and GPIO cleanup run")

Listing 8-14An IR Break Beam Monitor with Interrupt Activity

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
# Code for PRi Detecting Input Events by Polling
# Program to get input from pin 7 (board) Gnd is pin 6
import RPi.GPIO as GPIO
import time
#
GPIO.setmode(GPIO.BOARD)  # get library
GPIO.setwarnings(False)
GPIO.setup(11, GPIO.OUT)  # set pin 11 as output to power IR LED
GPIO.setup(38, GPIO.OUT)  # green led beam intact indicator
GPIO.setup(40, GPIO.OUT)  # red led beam broken indicator
GPIO.setup(7, GPIO.IN)    # set pin 7 as IR Photodiode input
#
#  Main program loop
GPIO.output(11, True)     # turn LED on
try:
    while (1):            # continuous loop
        if GPIO.input(7):
            print("Beam off, photodiode off input pulled hi ")  # detects 3.3v power from pin 1
            GPIO.output(38, 0)   # grn led off as beam has been broken
            GPIO.output(40, 1)   # red led on to indicate beam is broken
            time.sleep(0.5)
        else:
            print("Beam on, photodiode on, input pulled low ")  # detects 0v (diode-on acts like short)
            GPIO.output(40, 0)   # red led off as beam restored
            GPIO.output(38, 1)   # grn led on as beam intact
            time.sleep(0.5);     # wait time before next loop
except KeyboardInterrupt:
    pass
#
#
GPIO.output(11, False)                   # turn OFF the IR LED
GPIO.cleanup()                           # reset ports
print("Diodes off and ports reset ")     # indicate end of pgm

Listing 8-13A Polling IR Break Beam Monitor Program

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
# A push button activated rising edge transition starts a timer and a second
# stops the elapsed time measurement. GPIO 21 is pin 40 on the pi board and
# is connected to the junction of the series connected PBS and LED CLR circuit
# A bounce time of 100 ms is used to avoid false triggering.
#
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# set up the pin-channel, board is 40 bcm is 21
GPIO.setup(21, GPIO.IN)
#
GPIO.wait_for_edge(21, GPIO.RISING, bouncetime=100) # a blocking action while waiting
#
# wait for the event, print an alert and start a timer

#
if GPIO.input(21):
    print("A rising edge was detected.")
    # start a timer to count ticks
    ticks_initl = time.time()
    print("A timer was started at tick count ", ticks_initl)
    GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)# reset the GPIO pin low
#
# wait for the second event to occur and measure the elapsed time
GPIO.wait_for_edge(21, GPIO.RISING, bouncetime=100) # again a blocking action while waiting
#
if GPIO.input(21):
    print("A second or stop timing event has been detected.")
    ticks_fnl = time.time()
    print("A stop timing event has been detected at tick count ", ticks_fnl)
#
# calculate and display the elapsed time.
print("The elapsed time = ", round(ticks_fnl - ticks_initl, 2), "seconds")

Listing 8-12A Raspberry Pi RPi.GPIO Push Button Timer

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
# Scheduled Program Control of LEDs, green and red LEDs wth CLRs are connected
# to GPIO pins 20 and 21 or pins 38 and 40 of the RPi array. Pgm calls two
# sequential events with defined delays between events to light the leds and
# print out tick time and current times.
#
import RPi.GPIO as GPIO
import sched
import time
#
scheduler = sched.scheduler(time.time, time.sleep) # create an instance of scheduler
#
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(20, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)
#
# Activate green led for a measured length of time, timestamp event, pass in text
# and document actions
def actvt_GrnLed(name):
    print(name) # text or data passed in --> Green led activated firt
    print("Green LED on")
    frstsched_tm = time.asctime(time.localtime(time.time())) # local time code processed
    print("First scheduled event run at ", frstsched_tm)
    print("Green led on at ", time.time()) # the tick count at grn led on
    GPIO.output(20,GPIO.HIGH)
    time.sleep(3)
    print("Green LED off at ", time.time()) # tick count at grn led off
    GPIO.output(20,GPIO.LOW)
    print() # format spacing for output
#
# Activate red led for a measured length of time, timestamp event, pass in text

# and document actions
def actvt_RedLed(name):
    print(name)
    print("Red LED on")
    scndsched_tm = time.asctime(time.localtime(time.time()))
    print("Second scheduled event run at ", scndsched_tm)
    print("Red Led on at ", time.time())
    GPIO.output(21,GPIO.HIGH)
    time.sleep(5)
    print("Red LED off at ", time.time())
    GPIO.output(21,GPIO.LOW)
    print() # format output spacing
    fnsh_tm = time.asctime(time.localtime(time.time()))
    print("Program local finish time = ", fnsh_tm)
    print("Finish time = ", time.time())
#
print("Start time in ticks = ", time.time())
pgm_strt_tm = time.asctime(time.localtime(time.time()))
print("Program local time start = ", pgm_strt_tm)
print()
#
scheduler.enter(2, 1, actvt_GrnLed, ("Green led activated first",))
scheduler.enter(5, 1, actvt_RedLed, ("Red led is activated second",))
#
scheduler.run() # start the program

Listing 8-11A Python Scheduled Event Program

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
from tkinter import *
import time

class StopWatch(Frame):
    """ Implements a stop watch frame widget. """
    def __init__(self, parent=None, **kw):
        Frame.__init__(self, parent, kw)
        self._start = 0.0
        self._elapsedtime = 0.0
        self._running = 0
        self.timestr = StringVar()
        self.makeWidgets()

    def makeWidgets(self):
        """ Make the time label. """
        l = Label(self, textvariable=self.timestr)
        self._setTime(self._elapsedtime)
        l.pack(fill=X, expand=NO, pady=2, padx=2)

    def _update(self):
        """ Update the label with elapsed time. """
        self._elapsedtime = time.time() - self._start
        self._setTime(self._elapsedtime)
        self._timer = self.after(50, self._update)

    def _setTime(self, elap):
        """ Set the time string to Minutes:Seconds:Hundreths """
        minutes = int(elap/60)
        seconds = int(elap - minutes*60.0)
        hseconds = int((elap - minutes*60.0 - seconds)*100)
        self.timestr.set('%02d:%02d:%02d' % (minutes, seconds, hseconds))

    def Start(self):
        """ Start the stopwatch, ignore if running. """
        if not self._running:
            self._start = time.time() - self._elapsedtime
            self._update()
            self._running = 1

    def Stop(self):
        """ Stop the stopwatch, ignore if stopped. """
        if self._running:
            self.after_cancel(self._timer)
            self._elapsedtime = time.time() - self._start

            self._setTime(self._elapsedtime)
            self._running = 0

    def Reset(self):
        """ Reset the stopwatch. """
        self._start = time.time()
        self._elapsedtime = 0.0
        self._setTime(self._elapsedtime)

def main():
    root = Tk()
    sw = StopWatch(root)
    sw.pack(side=TOP)

    Button(root, text='Start', command=sw.Start).pack(side=LEFT)
    Button(root, text='Stop', command=sw.Stop).pack(side=LEFT)
    Button(root, text='Reset', command=sw.Reset).pack(side=LEFT)

    root.mainloop()

if __name__ == '__main__':
    main()

Listing 8-10A RPi Three-Button Stopwatch Timer GUI

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

摘要

  • 基于具有充当定时时钟的晶体调节振荡器的“锁存器”的集成电路能够以微秒的分辨率计数和确定事件之间的时间。

  • 自 1970 年 1 月 1 日以来,时间测量基于“滴答”计数,并允许通过 SCADA GUI 确定白天时间、定时协调和安排未来事件。

  • 秒表计时可通过商用和组件装配的 SCADA 系统进行配置。

  • 提供了几种解决方案,用于在实验会话期间监视事件并补偿事件检测器的错误或错误触发。

  • 在第九章中,介绍了图形数据记录的优势,在某些实验中,图形数据记录可以检测事件检测的错误触发。

Footnotes 1

1)供科学家和工程师使用的数字电子学,马尔姆施塔特和科恩,W. A .本杰明公司,纽约州纽约市,ISBN 0-80536899-X

  1. CMOS 食谱第二版 Edn。,兰卡斯特,霍华德·w·萨姆斯&有限公司,国际标准书号 0 672-22459-3

  2. 电子艺术第二版,霍洛维茨和希尔,剑桥大学出版社,ISBN-13 978-0-521-37095-0

2

azeotech.com/dl/labjackguide.pdf

3

https://github.com/j-bellavance/EdgeDebounceLite/blob/master/README.md

https://www.allaboutcircuits.com/technical-articles/switch-bounce-how-to-deal-with-it/

4

  1. 树莓派食谱第二版 Edn。Monk,O’Reilly Media Inc .,ISBN 978-1-491-93910-9

  2. 实用树莓派,霍兰,阿普瑞斯,ISBN 978-1-4302-4971-9

5

HTTP://CODE.ACTIVESTATE.COM/RECIPIES/124894/

6

  1. docspython.org/3/library/sched.html

https://pypi.python.org/pypi/schedule - schedule 0.4.3

7

http://sourceforge.net/p/raspberry-gpio-python/wiki/BasicUsage

九、图形数据记录

一句古老的远东谚语说:“一幅画胜过千言万语。”这句谚语的真实性在化学分析和医学成像中得到了充分的体现,在这些领域中,不仅数值,而且记录数据的形状也传达着信息。医学、物理学和许多其他实验科学中的许多技术都依赖于数据的图形化表示。临床和化学分析传统上使用化学敏感传感器来产生毫伏信号,以响应变化的化学过程值。该小信号被电子放大,并与伺服电机一起使用,以机械方式驱动笔在纸质图表上划过,从而提供被监控的化学过程的视觉记录。尽管 x-y 和 x 对时间绘图系统在制造加工工业、化学分析和其他科学中被广泛使用,但是机电绘图仪器,很像打字机,已经被 PC 取代。

x-y 绘图广泛用于分析光谱和电化学分析,而 x 对时间绘图用于后续滴定、生化动力学以及色谱和光谱分析。

DAQFactory 被用于这个应用程序,因为它具有强大的图形记录和显示功能。《DAQFactory 用户手册》中包含图形显示教程,以及关于 DAQFactory 图形显示功能的详细章节。对于那些使用免费 Express 或完整版 SCADA 软件的研究人员来说,在开始这个练习之前,应该先阅读教程和用户手册。

在本练习中,演示了几个非常重要的概念和电路配置。配置为非稳态多谐振荡器的 555 定时器将用于创建方波、锯齿波和非对称三角波信号波形,作为直观研究脉冲宽度调制(PWM)这一非常重要概念的前奏。将演示电容器充电和放电产生的指数和线性电压波形,并将使用特殊 IC 产生的对称电压波形输出来创建图形数据记录。

在考察的第一个定时器配置中,两个电阻和一个电容将用于在振荡器芯片上形成一个“定时网络”。将选择 RC 元件值,以便定时器芯片产生与我们的记录软件兼容的波形。所选择的电阻元件之一将具有可变的性质,以模拟基于电阻的化学或物理换能器。传感器电阻随某些物理现象的变化,如落在传感器表面的光强度或温度,将导致定时器输出信号的频率和波长发生变化,输出变化将以图形格式显示在 PC 屏幕上。然后,信号变化可以转换为脉冲宽度变化,形成广泛使用的脉冲宽度调制(PWM)概念的基础。

在考察的第二种定时器配置中,将演示如何使用恒流源为定时电容充电,并以图形方式记录“锯齿”和三角输出波形的产生。三角波形或电压斜坡在一些传感器监控和化学分析中有重要用途。组装第三个电路是为了演示一种创建双斜率模拟斜坡的简化方法,该方法常用于电化学、腐蚀和生物物理学研究。

一个简单的 x-y 记录系统构成了本章的最后一部分。

实验:线性图形数据记录

第一部分:硬件和元件选择–方波输出

第八章中之前的工作已经显示了软件开销带来的限制,因此,信号发生时或“实时”显示的信号形状变化率受到计算机性能的限制。处于非稳态模式的双极晶体管 555 定时器可以产生一个输出信号,该信号可以从 70 kHz 变化到大约每分钟四个周期。CMOS 版本的定时器可以产生兆周范围内的频率。大多数 555 定时器制造商都在 IC 的定时网络中包含了电容与电阻的 R1-R2 值之间关系的标准诺模图。图 9-1 是一个扩展图,容纳了能够以更高频率振荡的基于 CMOS 的 ic 的新版本。图 9-1 描述了定时器非稳态配置的近似定时网络值和产生的自由运行输出频率。

用于科研的 Arduino 教程(三)

图 9-1

555 定时网络值的定时器输出频率

为了将定时器芯片的输出信号保持在适合 DAQFactory 图形的低频范围内,电阻值应在兆欧范围内(百万或 10 6 欧姆),电容值应在 0.1–10 uF(微或 1/1,000,000 F)范围内。图 9-1 的图形数据是近似值,选择使用的实际电阻值在某种程度上取决于选择的或可用的电容值。

值为 1–10 uF 的电解电容应适用于此图形显示练习,但为了更精确地工作,可能需要更高质量的低泄漏型电容,如下文所述。

所需的电子元件

  1. 555 定时器集成电路

  2. 可变电阻器和固定电阻器相加得到低兆欧范围,优选地,固定值和可变值处于相同的电阻量级

  3. 1–10 uF 范围内的合适“定时”电容、0.01 uF 旁路电容和 9 V 电池电源

电路原理图

图 9-2 描述了非稳态 555 定时器的电路配置。

用于科研的 Arduino 教程(三)

图 9-2

555 定时器不稳定配置

前面的电路显示了引脚 7 和引脚 2 之间的单个可变电阻。当可变电阻器处于其中间行程位置时,电路将工作,但是当处于其电阻值的低端时,将产生不稳定的结果。为了避免电路故障的任何问题,将固定值电阻器与可变单元串联,以限制第二定时网络电阻的下端值。作者使用 10kω值作为 1.2mωR1+R2 网络的和值。

软件

组装好非稳态振荡器后,将输出连接到 LabJack 上的差分输入通道,并配置一个接收方波输出的通道。然后可以创建图形页面组件。对于长时间的图形显示,确保频道存储容量足够大,以支持所需时间显示的长度。内存中值的数量由通道“历史”框中的值决定。(默认条目是 3600,当在几十分钟或几小时的实验时间范围内工作时,可以很快填满。)

需要页面组件

在新的页面上,从右键弹出的页面组件菜单中选择 2D 图条目,创建一个二维图形屏幕组件,如图 9-3 所示。

用于科研的 Arduino 教程(三)

图 9-3

2D 图形记录器屏幕显示的数据工厂选择

x-y 图形的默认图形屏幕组件配置如图 9-4 所示。

用于科研的 Arduino 教程(三)

图 9-4

默认的 X-Y 图形屏幕显示

通过按 Ctrl 键并将阴影边缘线中心的正方形拖动到页面上的所需位置,图形组件被定位并适合页面。一旦确定了组件的大小,就可以通过右键单击屏幕组件并选择“属性”条目来打开屏幕组件的属性菜单。图形的属性窗口是一个多选项卡显示,具有多个条目表单,用于向图形添加轨迹、定义用于图形显示的轴值、添加标识标题以及选择显示颜色。图 9-5 显示了六选项卡属性窗口的轨迹选项卡,用于定义名称条目。

用于科研的 Arduino 教程(三)

图 9-5

记录器跟踪名称选择

“属性”窗口底部的帮助屏幕解释了图形屏幕组件中的所有数据输入框和选项卡。

对于由 9 伏电池供电的 555 定时器振荡器产生的方波,电压范围被偏移以显示从-1 到 9 伏的值,从而更清楚地描述波形处于 0 伏的时间。

第一部分:观察

使用 392kωR1、900kωR2 和 10kω串联电阻限制单元,从 9 V 电池对 22 uF、25 V 电解电容器充电,在 R2 上以中间设置获得 60 秒内 4 个高时间周期的图形显示。

在图 9-6 和 9-7 所示的两个极端之间,单位时间内产生的信号波形数量发生变化。

用于科研的 Arduino 教程(三)

图 9-7

最小电阻时的定时器输出

用于科研的 Arduino 教程(三)

图 9-6

最大电阻时的定时器输出

如果电路在没有串联电阻来限制 R2 最小值的情况下工作,则可能会产生如图 9-8 所示的波形。

用于科研的 Arduino 教程(三)

图 9-9

输出信号不稳定或“混叠”

用于科研的 Arduino 教程(三)

图 9-8

无最小电阻的波形

实验的

第二部分:硬件和元件选择——三角和“锯齿”输出

除了产生具有可变占空比的方波信号之外,非稳态 555 定时器还可以用来产生“锯齿”和不对称的三角波。基础电子学教导说,当电容器通过固定值电阻器充电或放电时,在电容器的端子上看到增加或减少的指数电压值。当用恒流源给电容充电时,电容两端的电压会线性增加。线性电压变化形成三角波形,该三角波形可用于产生在化学分析和其他实验工作中具有多种应用的电压斜坡。

通过组装图 9-10 所示的电路,可以产生两个额外的波形。

用于科研的 Arduino 教程(三)

图 9-10

恒流充电电源

第二部分:观察

当电容器通过串联电阻充电时,在测试点 1 和 3 之间,观察并记录常见的指数电压变化,如图 9-11 所示。

用于科研的 Arduino 教程(三)

图 9-11

典型 555 定时器“锯齿”输出电压波形

当测量 TP1 和 TP2 之间的电压时,会记录一个三角波形,如图 9-12 所示。

用于科研的 Arduino 教程(三)

图 9-12

555 定时器三角波扩展刻度

用恒定电流对电容器充电会在电容器极板上产生线性电压斜坡,如波形左侧所示。当定时器的放电引脚通过 555 定时器 IC 中的内部 NPN 开关晶体管的发射极接地时,信号的右侧陡峭部分是由电容快速放电引起的。虽然放电轨迹看起来是一条直线,但实际上它是图 9-11 所示的正充电曲率的反指数曲线的初始部分。图 9-12 和 9-13 显示了在电容器和定时器 IC 的放电引脚之间增加一个固定串联电阻的效果。

用于科研的 Arduino 教程(三)

图 9-13

增加放电电阻对定时器输出波形的影响

简单的逻辑表明,要获得线性三角波形,通过恒流源和吸电流对电容进行充电和放电可以实现所需的结果,但使用能够产生各种形状和频率信号的“函数发生器”可以找到更简单的解决方案。

第三部分:硬件和元件选择——双斜率三角波形

要获得对称的三角波形,使用“函数发生器”更容易与 741 和 555 ICs 一样,Exar XR-2209 也是一款非常成功的函数发生器,自 1975 年以来一直采用 8 引脚双列直插式封装(DIP)。集成电路是围绕一个称为压控振荡器(VCO)的电路构建的。XR-2209 VCO 可以从单个 8 引脚 DIP 同时产生方波和三角波电压波形信号。根据当前应用的需要,该芯片可以采用单电压或双电压电源供电。(参见“讨论”)使用单端或双电压电源时,函数发生器芯片需要特别小心,详情见制造商的数据手册。图 9-14 显示了使用双电压电源(在作者的案例中为+/-9 伏电池)的 2209 函数发生器的推荐电路原理图。

用于科研的 Arduino 教程(三)

图 9-14

函数发生器配置示意图

为了产生正负电压斜坡,电路由一对 9 V 电池供电,配置为双极性+/–9V 电源,共地,如图 9-15 所示。

用于科研的 Arduino 教程(三)

图 9-15

一种双电池双极电源

如果电路在试验板上正确组装后无法按预期工作,请查阅制造商的数据手册和“讨论”部分。

第三部分:观察

XR-2209 可以产生如图 9-16 所示的对称三角波形,并通过适当的“上拉”电阻产生如图 9-17 所示的方波。(参见“上拉”电阻选择的设计限制讨论。)

用于科研的 Arduino 教程(三)

图 9-17

带上拉电阻的方波输出

用于科研的 Arduino 教程(三)

图 9-16

XR-2209 函数发生器对称三角波输出

X-Y 数据记录

如图 9-4 所示,二维绘图的默认格式,图形显示屏组件是 x 对 y。图 9-10 的恒流充电电路可用于产生电容器两端电压及其平方的 x-y 绘图,用于测量电容器两端产生的能量。E = CV 2 /2。恒流电路可用于本演示练习,因为恒流充电和器件的指数放电会在电容上产生不对称的电压斜坡。

为了创建所需的显示,可以在为 PWM 数据采集显示创建的通道中记录恒流充电电路的 470 uF 电解电容两端的电压。当定时器芯片将充电的电容器接地时,试验板电子器件使电容器上的电压在电源电压的 1/3 和 2/3 之间线性循环,然后指数放电。因此,循环充电和放电电压的图形显示应该不同。在 x 轴框中输入通道名称,在 y 轴表达式框中计算电压的平方。显示在两个轴上的电压必须根据用于驱动电压变化的电源进行调整,在作者的情况下,图 9-18 、 9-19 和 9-20 中描述的值用于记录图 9-21 中的数据。

用于科研的 Arduino 教程(三)

图 9-20

x-y 图形常规选项卡

用于科研的 Arduino 教程(三)

图 9-19

x-y 图形轴选项卡

用于科研的 Arduino 教程(三)

图 9-18

x-y 图形轨迹选项卡

记下此图形图像显示的数据。如图 9-18 所示,x 轴和 y 轴都不是 PlsWdthVrn555 而是 PlsWdthVrn555[0,20]。因为这是一种循环现象,我们只需要显示通道数据的有限部分,即有限的“视野”或“视觉暂留”

用于科研的 Arduino 教程(三)

图 9-21

电容器电压和电压平方的曲线图

观察:x-y 绘图

图 9-21 中显示的轨迹是一个典型的记录,在记录失真或改变的轨迹之前,它可以保持稳定和可再现几分钟。图 9-22 和 9-23 已经捕捉到两个错误轨迹的实例。

在图 9-22 中,在 5 V 和 25 V 交叉处记录的电压方波放电轨迹已经一分为二。仔细检查图 9-23 会发现,放电轨迹不仅在循环的高压部分一分为二,而且在循环的 3v 和 9 V 低端也是如此。

用于科研的 Arduino 教程(三)

图 9-23

高和低电压轨迹变化

用于科研的 Arduino 教程(三)

图 9-22

更高的电压轨迹变化

讨论

记录数据的图形显示非常有价值,因为它能够显示趋势。实验科学依赖于再现性,数据的图形显示可以用来验证观察结果。

图形显示允许研究者看到隐藏在“实时”观察中的事件或趋势。然而,在检查数据记录的趋势时,在对数据有效性做出判断之前,必须考虑由材料缺陷、自热引起的温度变化、光诱导的变化、实验条件的不良选择以及大量其他误差源引起的偏差。在化学分析过程中,特别是在这项工作中,研究人员必须经常处理“模拟”数据的图形表示,这些数据涉及或需要很长或很短的记录时间。或长或短的时间范围可能需要特殊的部件、特殊的电子电路或配置,以及保护操作电路不受杂散电信号和干扰的影响。超长和超短时间常数可能会接近传统 IC 构建模块原始设计参数的极限,因此在极端工作条件下或接近极端工作条件下使用这些器件时必须格外小心。

从电子来源获得的数据中常见的变化来源包括:

  1. 由于电池或“电源”供电而产生的变化。

  2. 元件的缺陷和变化,如电阻噪声(线绕元件最小,金属薄膜次之,碳元件最大)、电容漏电流和记忆效应(电解元件最大,钽元件次之,塑料薄膜元件最小)。

  3. 由环境变化引起的温度效应和由通过电阻性电子元件的电流引起的内部加热都会导致电信号漂移。

  4. 长电线会积累射频干扰(RFI ),其作用类似于主电源线辐射的天线。电线应尽可能短,如有需要,可装入法拉第笼中。带有长条状金属触点和插入电路板的长元件引线的试验板只能用于实验开发,然后用印刷电路板替换,用于实际的实验服务。

  5. 通道存储的数字采样(或模数转换)中的混叠。这些练习中创建的实验设置的数据由 LabJack 或微控制器转换成数字格式,并由 DAQFactory 软件以输入通道计时值框的通道计时值控制的速率读取。可能由控制计算机电子设备、LabJack 电子设备、实验装置本身或实验可能位于其中的建筑物的干线布线拾取或产生的任何重复或周期性的电信号存在与由被监控的装置产生的真实信号“混淆”的可能性。当以长期图形格式显示时,长时间被监视的信号可能包含叠加在真实或原始信号上的“错误或人为”波形。

x 与时间记录

555 定时器的操作顺序已在第八章中概述,从该总结以及图 9-6 和 9-7 中的信息,我们可以看到在非稳态模式下产生的波形随着定时网络中 R2 电阻值的变化而改变频率。

当以非稳态配置接线时,电容充电时间由 RC 时序网络的总电阻决定,如下所示:

  • t 1 = 0.693(R1 + R2)C(输出高电平时间)

并且放电时间是

  • t 2 = 0.693(R2)C(输出低电平时间)

因此,总信号周期为

t = t1+t2= 0.693(R1+2r 2)C

并且操作的频率是

f = 1/T = 1.44/(R1 + 2R2)C

电容通过两个电阻充电,同时仅通过一个电阻放电。当网络中的 R2 电阻是可变电阻时,输出为低电平的时间与可变电阻值成正比。因此,555 定时网络中变化的模拟电阻可以通过测量输出为低的记录宽度来数字化。

图 9-2 所示电路产生的高电平和低电平时间的相对宽度存在限制。需要特殊的电路来保持振荡器频率相对恒定,而振荡器的高和低时间宽度(占空比)是变化的。

扩大或缩小图形显示的时间刻度可以改变所显示波形的分辨率。

图形显示需要大量的计算机处理资源,并且如前面处理时间和定时的练习中所述,对快速变化的信号的响应能力有限。快速变化的信号最好用硬件数字化,存储在存储器中,然后在收集后,转换成图形格式显示。

对于较慢的信号变化,DAQFactory 能够在其通道中存储图形数据,然后能够将其显示为带状图表记录,这在揭示隐藏信息方面非常有用。如果图 9-12 的三角波形被记录 8 到 10 分钟,然后图形显示的时间刻度被重新配置以显示 8 分钟的数据窗口(即,对于时基,8 分钟的窗口将是 8 分钟× 60 = 480),那么大量的变化变得明显,如图 9-24 和 9-25 所示。

在图 9-24 和 9-25 中,延长显示重复电压周期的时间尺度已经直观地显示了几个普遍存在的实验误差源的影响。

大多数人都熟悉水波在静止水体中的传播。在我们看来,由扔进池塘的石头引起的来自两个源头的水波互相穿过而没有干扰。然而,如果一个物体漂浮在水面上,与波浪在同一点穿过另一点,就会看到该物体剧烈的颠簸。剧烈的纵摇是由叠加原理引起的,叠加原理将穿过彼此的两个水置换波的振幅相加。图 9-24 中 7 . 14 . 30 和 7 . 19 . 00 处可见的失真可能是由幅值为伏特、频率为 4 1/2 分钟一个周期的第二个电压变化波与主信号混合或干扰引起的。

由更复杂的电子问题引起的图形失真的另一个来源是所谓的混叠,该电子问题涉及周期性模拟波形的定时重复数字采样,这在一些电子教科书中有所讨论。 1 (别名是 RPi-Python 编程代码的一个实用概念。)

用于科研的 Arduino 教程(三)

图 9-24

长期信号失真

所记录的三角波形就其出现频率而言是可合理再现的,因为可以看到作者的试验电路在 5 分钟内产生 19 个周期。然而,可以看出电压电平的再现性是漂移和振荡的。电压的下限值从 3.0 到 3.4 不等,而上限值从 5.7 到 5.0 不等。尽管电压的上限值和下限值在变化,但显示有明显的模式,表明系统由于前面讨论的因素而漂移和振荡。

施加到恒流源中左侧和右侧晶体管的手指热量在周期时间内产生膨胀和压缩,如图 9-25 和 9-26 所示。

用于科研的 Arduino 教程(三)

图 9-26

手指加热应用于电流镜的右晶体管

用于科研的 Arduino 教程(三)

图 9-25

手指加热应用于电流镜的左侧晶体管

除了周期时间改变之外,不稳定的振幅也是热效应的结果。

制造电子元件的材料也会产生电子电路中的噪声。线绕电阻的噪声最小,金属薄膜次之,碳基元件对电阻电路噪声的贡献最大。

电解电容价格低廉,可提供更高的值,但几乎所有高值电解单元都有相当大的漏电流。在需要循环或重复再现性的系统中,漏电流会导致问题。传统的低泄漏电容通常没有高电容值,但是当有限的高值单元存在时,它们通常非常昂贵并且物理尺寸很大,如图 9-27 的照片所示。

用于科研的 Arduino 教程(三)

图 9-27

各种类型的定值电容器

利用运算放大器和电容可以产生对称的三角波形,但一种称为压控振荡器的电路被设计用来同时产生方波和对称三角波形。Exar XR-2209 IC 是一个带有外部电容和电阻的模块,可由 4 至+/-13 伏的双电源或单电源供电,以产生所需的信号。图 9-16 和 9-17 是 IC 的典型输出。在作者的试验板设置中,可以看到三角波在所达到的峰值电压中有系统地变化。试验板设置也被证明对用于产生方波的“上拉”电阻值非常敏感。元件灵敏度可能是由于在接近电路设计极限的区域操作电路造成的。

X-Y 记录

当要记录的信号本质上是循环的时,通常使用 x-y 记录。由于信号的循环性质,最好从 x-y 屏幕上清除旧的轨迹,因为新的轨迹会覆盖在旧的数据轨迹上。通过使用[n]通道值符号指定要绘制的数据点数,可以显示信号周期的任何分数或倍数。

在图 9-22 和 9-23 中看到的不可再现信号的影响是由相同的原因引起的,这些原因在图 9-24 、 9-25 和 9-26 中记录的 x 与时间信号的变化中很明显。

微控制器数据绘图

开源、在线社区支持的可编程微控制器不断扩展其基本功能,从版本 1.6.6 开始,Arduino IDE 中增加了数据绘图功能。

在之前的练习中,Arduino 微控制器被用作智能数据采集设备、传感器或显示器的电源以及时钟;在本章中,它将用于提供数据的可视化图形显示。

自 Arduino IDE 版本 1.6.6 和 7 以来,工具菜单中提供了串行绘图仪选项,如图 9-28 所示,最初用于单个绘图,但从版本 7 开始,用于多数据点绘图。

用于科研的 Arduino 教程(三)

图 9-28

Arduino IDE 工具菜单串行绘图仪选择

调用串行绘图仪输出会将串行端口窗口显示转换为 x-y 绘图仪。指向串行端口用于显示打印语句的各个数据点绘制在垂直 y 轴上。x 轴以 500 点移动窗口的形式从左向右自动滚动。x 轴的度量是使用换行符打印指令对代码行的处理。图 9-29 中的第 15 行包含 println 代码,该代码被视为已处理,其总值构成了显示在 x 轴上的数值。

对于多点绘图,用单独的轨迹显示的每个数据值都用打印空白指令或制表符指令与下一个数据值分隔开:(print(” “);或者打印(”/t “);).图 9-29 中的第 10、12 和 14 行形成了图 9-30 中所示的四道图的分离标记。

实验的

图 9-29 中的代码绘制了两条不同频率的直线和两条正弦曲线,如图 9-30 所示。

用于科研的 Arduino 教程(三)

图 9-29

Arduino IDE 典型绘图仪程序

观察

用于科研的 Arduino 教程(三)

图 9-30

Arduino 串行绘图仪输出

对微处理器绘图仪演示代码和显示的正弦波频率的检查验证了正弦波和余弦波之间预期的 20:1 频率比。常数值绘制为预期的直线。

讨论

Arduino 的 IDE 中包含的绘图仪为实验研究者提供了一种非常强大的可视化技术。这个绘图仪既容易使用又有用。由微处理器控制的实验过程产生的图可以被记录,以便利用主机上可用的打印屏幕功能进行存档。实验图归档已用于涉及温度、运动和振动测量的实验工作以及光和光学研究。

虽然绘图仪是一个非常有用的功能,但它在原稿准备时在操作的几个方面受到限制。跟踪的颜色由 IDE 的操作系统决定,有时很难看到。标度是自动调整的,与 DAQFactory 绘图仪不同,它不能独立设置为不同的值。

偶尔在初次启动时,绘图仪会产生虚假图像,如图 9-31 左侧所示,或者不正确地自动缩放 y 轴。

用于科研的 Arduino 教程(三)

图 9-31

Arduino 串行绘图仪启动噪音

如上图所示,绘图仪相当快地进入可再现状态,但有时可能会错误地绘图,直到 500 点窗口自行刷新,自动缩放功能也进入可再现绘图模式。

用 Python 和 Raspberry Pi 记录图形数据

介绍

如上所述,实验数据的图形绘制可以采取两种形式。如果数据是以高速率生成的,那么最好将它保存到内存中进行存储,并在以后以图形方式进行分析。以较低速率生成的实验数据通常可以在“现场”或“实时”显示中显示。Python 和 RPi 使用一个名为 matplotlib 的图形绘图库来显示实时和存储的数据。

本章末尾的清单 9-1 中提供了一个 Python matplotlib 代码示例,该代码绘出了偏置在 GPIO 阵列上的 3.3 伏 RPi 电源与其地之间的 10kω电位计的游标臂电压值。该代码已从带状图表记录器程序修改而来,可在 matplotlib 文档中找到“动画示例代码:strip_chart_demo.py”。该文档包含使用这种类型的动画图形显示的完整开发教程。

虽然 RPi 没有广泛的商业图形显示软件应用程序可供选择,但 matplotlib 可以为开发所需的应用程序提供坚实的基础。本练习中用于监控变化电位计电压的相对较短的程序配备了几个高级实用程序,用于深入检查记录的图形显示。matplotlib 文档中题为“交互式导航”的部分描述了绘图显示左下角的七个按钮的操作,如图 9-32 和 9-34 所示。当使用任何显示操作或存储按钮时,左按钮恢复显示焦点。按钮允许记录轨迹的部分被保存,如图 9-33 所示,并被放大,如图 9-34 、 9-35 和 9-36 所示。除了按钮激活的实用程序之外,库示例还显示鼠标光标的坐标,以便通过将光标指针放在跟踪中感兴趣的点上,并根据显示时间和绘图仪框架右下角显示的数值中的测量数据值读取该点的 x 和 y 坐标,可以识别精确的点。

matplotlib 程序也很容易改变任一标绘轴的比例,但由于之前练习中出现的时间比例不一致,显示的绘图仪时基需要按照以下实验部分所述进行校准。

实验的

为了演示 RPi 提供的绘图功能,可以从 gpiozero 库和 MCP3008 ADC IC 创建一个示例,从偏置电位计的游标读取电压。游标电压由一个 10 位 ADC MCP 3008 数字化,配置如第六章、图 6-17 所述。为了便于 ADC 编程,gpiozero 库通过访问在“pot = MCP3008(0)”行中实例化的对象的“pot.value”属性来提供绘图数据。通过 gpiozero 库创建 pot 对象,程序员可以访问连接到 ADC 芯片第一个通道的游标电压值。通过将要绘制的代码变量设置为等于 pot.value 属性,该值将自动规范化为 0 到 1 之间的无量纲浮点值。

使用 gpiozero 库访问 MCP3008 ADC 的 RPi 配置还允许修改绘图程序,以接受能够提供 3.3 V 或更低电压值的任何传感器或换能器。图 35 和 36 是 555 IC 定时器输出的两条迹线,该定时器连接到数字转换器的第一个或 0 通道。第八章、图 8-8 的右图和电路中说明了 555 IC 的配置。对于本实验,R1 和 R2 为 4.7kω,C1 为 555 定时器 RC 网络中的 100 μF 电解电容。输出电路还包括一个 LED 和限流电阻,以帮助电路组装、电气操作验证,以及通过观察 LED 以 60 秒 59 次的速率连续闪烁来验证记录仪显示。最后两个放大的比例图,图 9-37 和 9-38 ,是通过绘图仪显示左下角选项行的“保存轨迹”按钮制作的。

为了帮助开发已发布的 matplotlib 条形图表记录器代码(使用内部随机数生成器为绘图仪示例输出创建 y 值),作者在正在修改的代码中插入了许多诊断打印语句。print 语句将正在执行的代码中的某些点的某些变量值输出到 Python 控制台,以帮助开发不同的方法,使代码适应不同来源的数据。注释掉诊断打印行将清除控制台显示。流出的变量数据在控制台显示器中显示为图 9-32 至 9-34 中的左侧屏幕。当不再需要时,打印行可以被注释掉。

在 RPi 上使用图形数据显示时,必须考虑几个因素。正如在之前的练习中所提到的,系统的时基不是恒定的,因此绘图仪显示器底部的时间刻度可靠性有限,必须进行半定量校准才能半定量使用(见“讨论”)。

一旦建立了所需的实验时间框架,必须使用秒表来测量系统绘制标称所需窗口时间宽度的数据所需的实际时间。表 9-1 是作者在开发用于校准标称 2 分钟宽绘图窗口的程序时收集的数据示例。

表 9-1

调整绘图仪时基

|

Dt 设置

|

时间宽度(秒)

|
| — | — |
| Zero point zero two | Twenty-five |
| Zero point zero one | Forty-one |
| Zero point zero zero five | One hundred and twenty-seven |
| 0.0055 | One hundred and sixteen |
| 0.00525 | One hundred and twenty-nine |
| Zero point zero zero five | One hundred and twenty-five |

观察

用于科研的 Arduino 教程(三)

图 9-32

电位计游标电压的数据记录

图 9-32 显示了从实验开始 80 到 120 分钟的电压值轨迹,其中作者在显示器未校准的相对时间轴上记录的时间手动转动电位计轴。轨迹的响应速度相对较快,但轴的快速扭转会超出显示器跟上数据值变化的能力。

图 9-33 显示了点击选项行最右侧的“保存图形”图标时调用的操作。图形作为 png 图像保存在 RPi 的文档文件中。

用于科研的 Arduino 教程(三)

图 9-33

“保存图形”选项窗口

在图 9-34 的屏幕截图中,鼠标的光标刚刚经过 17 分钟就被放置在垂直响应线上,然后该点的精确坐标被打印在显示屏的右下角。

图 9-34 显示了将鼠标绘制的框所包围的区域扩展为全屏显示的缩放选项。然后可以如前所述保存扩展的图像,或者可以使用“返回前一视图”图标来恢复或继续正常的绘图动作。

用于科研的 Arduino 教程(三)

图 9-34

“规模扩张”选项

在下面的两个图中,使用“保存数字”选项以扩展的比例记录了详细配置的 555 定时器的输出。图 9-35 和 9-36 显示了软件保存来自外部电压发生源的较短时标绘制数据的能力。

用于科研的 Arduino 教程(三)

图 9-36

555 定时器数据记录的一分钟时间刻度扩展

用于科研的 Arduino 教程(三)

图 9-35

扩展时标 555 定时器数据记录

讨论

使用 Python matplot 库中的带状图记录器程序进行图形数据记录是一个适应性非常强、非常灵活的系统,可用于直接显示来自连接到 GPIO 阵列的传感器或来自 Python 串行端口的数据。

在图 37 中,配置为 R1 = 5.83kω、R2 = 4.7kω和 420 μF C1 定时电容的 555 定时器的输出在 33 秒内产生 10 次 LED 闪烁。计时器由 GPIO 阵列的 3.3 V 电源供电,并针对 4 分钟显示窗口进行校准,详见“实验”部分。

用于科研的 Arduino 教程(三)

图 9-37

校准时基 555 定时器电压输出记录

图 9-38 显示了数据绘图程序显示选项按钮可用的比例扩展功能。

用于科研的 Arduino 教程(三)

图 9-38

时间校准的标绘迹线展开

大量传感器已被编码到 gpiozero 库中,可用于为 matplotlib 绘图程序提供数据。

当矩形脉冲时间宽度的变化以图 9-38 的视觉格式呈现时,图形数据显示的优势之一变得明显。

表 9-1 展示了用于 RPi 图形数据显示的时基限制。Dt 值的逐步递增减半增加了时间测量,但是返回到 0.005 的值与原始测量值产生了 2 秒的差异。这种差异证实了手稿中提到的关于 RPi 操作系统优先级的警告,RPi 操作系统优先级会干扰计算机输入和输出操作的计时。

代码列表

# SCR Plotting of Normalized Potentiometer Voltage Value from an MCP3008 gpiozero used to configure MCP3008 and attributes
# for plotting
#
import matplotlib
import numpy as np
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
from gpiozero import MCP3008
#
pot = MCP3008(0)
#
#
class Scope:
    def __init__(self, ax, maxt=40, dt=0.02):
        """maxt time width of display"""
        self.ax = ax
        self.dt = dt
        self.maxt = maxt
        self.tdata = [0]
        self.ydata = [0]
        self.line = Line2D(self.tdata, self.ydata)
        self.ax.add_line(self.line)
        self.ax.set_ylim(0.0,1.0)  # y axis scale

        self.ax.set_xlim(0, self.maxt)

    def update(self, y):
        lastt = self.tdata[-1]
        if lastt > self.tdata[0] + self.maxt: # reset the arrays
            self.tdata = [self.tdata[-1]]
            self.ydata = [self.ydata[-1]]
            self.ax.set_xlim(self.tdata[0], self.tdata[0] + self.maxt)
            self.ax.figure.canvas.draw()

        t = self.tdata[-1] + self.dt
        self.tdata.append(t)
        self.ydata.append(y)
        self.line.set_data(self.tdata, self.ydata)
        return self.line,
#
#
def rd_data():
   inPutln = pot.value
   #print("inPutln = ", inPutln)
   line = inPutln
   #print(line)
   yield (line)

    fig = plt.figure()
fig.suptitle("Pot Wiper Voltage", fontsize = 12)
ax = fig.add_subplot(111)
ax.set_xlabel("Time")
ax.set_ylabel("Potentiometer Voltage")
scope = Scope(ax)

# uses rd_data() as a generator to produce data for the update func, the MCP3008 value is read by the plotting code in

# 40 minute windows for the animated screen display. 
# Software overhead limits response speed of display.
ani = animation.FuncAnimation(fig, scope.update, rd_data, interval=50,
blit=False)

plt.show()

Listing 9-1Python Code for Live or Real-Time Data Plotting with Raspberry Pi

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

摘要

  • 以 y 对时间或 x 对 y 的图形记录的实验数据可以显示许多电子产生的波形和传感器读数。

  • 图形数据记录可以揭示信号漂移和信号偏差,并显示电气、机械和环境对信号输出的影响,这些影响在数字显示中通常是看不到的。

  • 商业 SCADA 绘图易于配置、强大且非常灵活,而组件组装系统在显示能力方面更受限制,必须手动校准。

  • 在第十章中,介绍了电流控制的各种方法,这是实验设备配置或设计的一个重要方面。

Footnotes 1

电子艺术,霍洛维茨和希尔,剑桥大学出版社,ISBN 0-521-37095-7

十、日常检查

电流控制和监测是许多实验设置和科学测量的重要组成部分。如前一练习所示,可能需要恒流控制来实现特定的结果。传感器测量、扫描仪器中的运动控制、机器人操纵器、电镀或电流分析以及加热控制操作只是需要电流控制的几个例子。led 应该由恒流源供电。已经发现,当来自一个供应商的一批发光二极管由消耗 4 到 39 mA 的恒定电压电源供电并且具有如此宽的电流差时,不能产生相同的发光或色度输出。电流控制可以不同于管理物理或化学变化的传感器,通常需要测量毫微安的 DC 电流,而加热、电沉积和电机控制应用通常涉及控制电流的安培数。

电流控制可以用分立晶体管实现,如第九章所述;为电流调节而配置的通用集成电路,如运算放大器;或者是专门为 DC 或交流电流控制应用而生产的专用集成电路(ASIC)芯片。

本章分为三个部分,涉及恒流 DC 电源、较大电流的控制以及潜在致命的市电交流电源的控制。在控制电流的同时,将演示电机带来的一些限制以及解决这些限制的方法。用于实验装置和这些练习的廉价电机可以从过时的计算机设备中回收,或者如果需要可以从电子供应源获得。我们将演示旋转电机对运动控制的一些限制,并开发为实验装置选择首选电机的过程。

用于电流或功率控制的脉宽调制(PWM)技术将在电机和白炽灯照明应用中进行回顾和演示。

交流电子学,由于它的循环性质,可能比 DC 要复杂得多。为了保持这些练习的简单介绍性质,只考虑无感或完全阻性负载应用。在严格阻性应用中,均方根(rms)、峰峰值或平均交流值可以像大多数电子基本定律中的 DC 值一样使用。高级通信、感应加热或光谱学中遇到的较高频率和相位敏感的交流电子设备不会在这些基础介绍练习中深入讨论。

恒流源

在许多类型的电子电路和许多实验测量仪器中,也可以找到以前使用的恒流源。如前所述,恒流源可以由一对作为“电流镜”的晶体管构成,或者由一个运算放大器(op-amp)和一些电阻构成。虽然前面提到的大部分电子书籍都详细讨论了分立式元件电流镜,但由于设计简单、电路控制范围宽,并且使用容易获得的廉价元件,所以本练习中使用运算放大器。

本练习中使用的运算放大器(如 LM741)由双电压电源供电,必须平衡或适当偏置才能使用。图 10-1 描述了 lm 741–2n 3906 PNP 晶体管接地负载电路的一般原理图,该电路可用于为已知负载提供恒定电流,如各种参考文献中所公布的。图 10-1 和 10-2 中描绘的电路可以组装在典型的原型试验板上,用于测试、电路操作验证和电流控制应用。

下面将针对负载接地、电流感测电阻连接到电源的配置来解释电路工作原理。如果需要相反的情况,则可以使用 NPN 晶体管来调节电流(LF411 可以直接替代 LM741)。

实验的

五金器具

一个+/-双电压电源和一个调整电位计用于为运算放大器供电和平衡。构建和验证恒流源需要一个功率晶体管、三个适当的偏置电阻和一个合适的预期实验负载的可调电阻模拟器。恒流运算放大器电路的典型实现在以下作者组装的测试电路的描述中有详细说明。一节 9 伏电池和 4 节串联的 AA 电池可以提供 15 伏的 DC 电源。串联连接两个 15 伏电池组可用于创建所需的+/-15 伏双极性电源,中间端子接地。双极性电源允许将运算放大器输出驱动至正电压或负电压。(参见 9 章节中的图 9-15 。)

电路原理图

用于科研的 Arduino 教程(三)

图 10-2

运算放大器平衡的典型电路实现

用于科研的 Arduino 教程(三)

图 10-1

典型运算放大器电流控制电路

如果一个特定的化学分析实验(如库仑滴定)有一个代表 20ω负载的滴定容器,并且发现 20 mA 的电流可以产生一个到达分析终点的合理时间,那么就具备了确定组装图 10-1 和 10-2 所示电路所需的电阻值的条件。

根据欧姆定律,通过 20ω负载维持 20 mA 电流需要 0.40 V 的电压,晶体管的 PN 结压降通常为 0.3 V,因此发射极应保持在 0.7 V,要将 15V 转换为 0.7V,需要一个数值为 0.0466 的分压器;因此,R2/(R1 + R2) = 0.046。LM741 可以使用 12 至 18 伏之间的任何双电压电源,因此可以相应地调整分压器网络和限流 R3 的实际电阻值,以保持所需的运算放大器基准电压或设定点,从而获得所需的电池电流。对于 20 mA 的调节电流,根据 I 2 R 的功率关系,我们可以估计电路的调节载流部分中的 1/8 瓦电阻足以满足手头的实验。

作为典型的电化学电池负载模拟,作者使用了一个 25ω、30 W、可调抽头的线绕电阻。调节负载电阻上中心抽头的位置模拟了在实验电化学电池或电阻加热元件中可能遇到的电导率变化。

开始练习时,实验者可以根据前面的原理图组装电路。验证布局后,将运算放大器的反相和同相输入端暂时接地,将调整电位计调整到其中点,并给运算放大器上电。监控放大器输出电压的同时,调整 10kω可变电阻以获得尽可能接近 0 V 的放大器输出,实际平衡运算放大器或将调整电位计游标定位在一个较低的非零电压值点,当实际电路工作期间建立反馈环路时,这将导致系统平衡。

由 R1 和 R2 构成的分压器产生一个参考电压 V Ref ,该电压被提供给运算放大器的同相输入端。现在,通过改变流经 R3 的电流,运算放大器将尝试将两个输入保持在 V Ref 的相同电压。流经负载、晶体管和 R3 的电流由注入 2N3906 晶体管基极的电流控制。流经负载和晶体管的整个电流通过 R3,R3 必须具有足够的瓦特数,以适应恒流配置可能需要的电流变化。如图 10-3 所示,当调节负载模拟电阻器的中心抽头以模拟模拟电池电阻的变化时,电流测量将确认电路通过电池模拟器提供标称 20 mA 电流的能力。

用于科研的 Arduino 教程(三)

图 10-3

大电流试验电路的线绕负载模拟器

上图中的第 1 项是模拟的可变电阻负载,由垂直安装在螺杆上的 25ω30 W 线绕电阻组成。第 2 项是 5 W 电流检测电阻,第 3 项是 LM741 运算放大器塑料 DIP。项目 4 是 2N3906 功率晶体管,项目 5 是正极红色、负极黑色和绿色接地或中性电源引线。第 6 项是用于运算放大器平衡或偏置的调整电阻。

软件

这部分练习不需要页面组件和编程软件。

观察

当中心抽头的位置改变时,线绕电阻器产生非常粗糙的欧姆电阻,但是负载电阻值的改变足以证明所需恒流源的发展。大功率模拟负载在主端子之间测得的标称值 25ω和在裸露线芯匝上重新定位滑动抽头时的约 20 至 10ω之间变化。连接到正电源并向晶体管提供电流的大功率电阻器与可变负载一起决定了可在调节电路中流动的电流。当电路开始通电时,观察到的电流很高。随着电子设备达到大致的热平衡,调节电流稳定在接近所需设定点的最终值。通常电路需要 15-30 分钟达到恒定的热值。表 10-1 列出了通过作者的试验模拟测得的稳定电流。

表 10-1

负载电阻和调节负载电流

|

负载电阻(ω)

|

电流(毫安)

|
| — | — |
| Six point seven | Twenty-one point four |
| Ten point eight | Twenty-one point four |
| Fourteen point three | Twenty-one point one |
| Fifteen point one | Twenty-one point four |
| Seventeen point six | Twenty point nine |
| Nineteen point three | Twenty point nine |
| Twenty point two | Twenty point nine |
| Twenty point three | Twenty-one |

上表中的负载电阻以欧姆为单位,电流以毫安为单位。

讨论

通过回忆运算放大器驱动其输出以均衡反相和同相输入端的电压,可以在反馈配置中解释电路操作,因此 V Sense = V in 。通过感应电阻的电流为 ISense= Vin/RSense,由于通过感应电阻的电流流经晶体管,所以通过负载 I Load 的电流为 V in /R Sense 加上晶体管极小的基极发射极电流。

对于流经 20ω负载的 20 mA 目标电流,该表显示了流经 6.7 至 20.3ω负载的约 21 mA 电流的 0.5 mA 变化。如果需要精确的 20 mA 电流,可以通过实验调整分压器,将基准电压调整到将晶体管电流调节到所需水平的值。

如第九章数据图形显示中所讨论和演示的,以及如前所述,热效应将导致测量信号漂移,直到建立热平衡。如果需要临界电流控制,那么可能需要在实验设置中引入某种形式的热控制或稳定。散热器、冷却气流、绝缘材料或大型金属热物质可以通过辐射或吸收过多的热量来保持或部分稳定温度。

电流调节也可以用专用集成电路来实现,例如美国国家半导体公司的 LM340/78xx 系列集成电路。然而,集成电路在特定的固定电压下工作,并且通常限于 1 安培的总电流。要调节的实际电流由适当阻值的传感电阻决定。具体配置和限制详见制造商数据手册中针对单个器件的应用部分。

由分立元件组装而成的运算放大器功率晶体管电路具有能够在任意电压和负载要求下控制电流的灵活性的优点。运算放大器功率晶体管配置也可以与 PNP“接地负载”配置或“浮动负载”一起使用,其中检测电阻接地,NPN 晶体管连接到电源和浮动负载。

运算放大器的特性和理论可以在前面提到的大多数教科书和许多介绍性的、深入的在线教程中找到。

控制较大的 DC 电流

介绍

无刷直流(BLDC)电机(无换向器或点火刷的电机)

在涉及加热、泵送、机械运动或运动控制的实验装置中,会遇到较大的 DC 电流操纵。对于每一种要控制的运动,通常有几种将电能转换成所需的物理运动或动作的方法。螺线管像在机器人系统中一样线性地来回运动,而马达则扭转或旋转;对于需要电机驱动的简单应用,以及液体混合或泵送、气体冷却或旋转光学扫描操作,我们将重点讨论电机的旋转运动控制。进一步的限制包括使用非常小的分马力电机,该电机设计用于现场或实验室使用,具有容易获得的、坚固的 12 V 铅酸电池系统或 12 V DC 电源,提供所需的更高电流。(电机的物理和机电方面以及更强大的电机控制在机器人和机械、化学或电气工程的文献中有更详细的讨论。)在化学分析和大部分生命科学的实验室工作中,经常使用易燃溶剂,因此,除非经过防爆认证,否则不应在实验操作中使用有刷 DC 电机。

驱动电机所需的较大电流可以由晶体管控制,而晶体管又可以由集成电路产生的小得多的基极电流控制。可变 555 定时器信号可用于控制更高电流的功率晶体管,该晶体管进而调节施加到电机的功率以控制电机速度。在这部分练习中,将使用一个 555 定时器来产生一个方波脉冲序列,该脉冲序列的占空比将以受控方式变化,以改变功率晶体管向风扇电机供电的时间,该风扇电机能够汲取高达 200 mA 的电流。因此,风扇电机的转速将由 555 定时器网络中的电位计控制。风扇盘转速将通过 LabJack 计数器进行光学测量,DAQFactory 程序将计算风扇盘转速并显示在屏幕上。

实验的

五金器具

对于电机控制电路,需要一个试验板来安装一个 555 定时器和将 IC 配置为非稳态模式所需的无源元件。从图 10-4 中可以看出,作者将 100kω电位计的安装支架、TIP-122 功率晶体管的散热器和带无刷直流风扇电机的风扇组件的支架组合到一个定制钻孔的 1 英寸(2.5 厘米)乘 8 英寸(15 厘米)的铝制角钢上,标记为项目 1。散热器安装角用螺栓固定在一个大约 1/16 英寸(1 毫米)厚的 8 英寸乘 6 英寸(20.4 厘米乘 15.2 厘米)的铝板上,标记为项目 1a,试验板用双面胶安装带(地毯带)固定在铝板上。最简单的风扇电机(无刷直流,BLDC)有两条 DC 电源引线。三引线和四引线风扇电机很常见,通常增加了用于监控轴位置的内部霍尔传感器(磁场检测器)的连接。将光电二极管和光电晶体管装配并固定到两个 1 英寸(1.2 厘米)乘 1 英寸(2.5 厘米)的定制钻孔铝板上,铝板上带有室温硫化(RTV)硅酮。编号为 4 的项目是传感器安装标签。标签背面的粘合剂嵌条将传感器二极管牢牢固定,同时不会干扰光学活性表面。如图 10-4 所示,用螺栓和蝶形螺母将调整片安装在风扇电机框架的一角。调整片安装有由光电二极管产生的窄红外光束,该光束指向风扇盘叶片的旋转平面。因此,七叶片风扇盘(项目 2)的旋转在电机每转一圈时将光电二极管和光电晶体管之间产生的红外光束切断七次。

用于科研的 Arduino 教程(三)

图 10-4

实验冷却风扇电流负载测试设置

支撑光束源和检测器的两个板在作者的装置上固定到位,螺栓穿过板和电机框架,用蝶形螺母固定到位。项目 3 是翼形螺母紧固件的臂,其允许光束更容易对准。

作者的设置由一个更大的+/-12V、2 A 电源供电,该电源连接到安装在铝板金属底座上的试验板后部的端子板。

许多从过时或损坏的计算机设备中回收的风扇马达被用来驱动七叶片磁盘。如果用于这些练习的风扇没有七个叶片,在 DAQFactory 变量值表达式框中输入正确的叶片数,如图 10-7 所示。

电路原理图

在图 10-6 中,555 定时器被配置为非稳态模式,以产生连续的方波格式。定时器 IC 周期开始时,电容 C 放电,引脚 2 为低电平,输出引脚 3 为高电平。引脚 3 为高电平时,C 通过 R1 左侧和左侧二极管充电,直到引脚 6(阈值)达到 2/3 V+,此时引脚 3(输出)和引脚 7(放电)变为低电平。引脚 3 为低电平时,电容通过 R1 右侧和右侧二极管放电,直到 C 降至 1/3 V+以下,此时输出引脚 3 和放电引脚 7 变为高电平,循环重复。因此,C 从 R1 的左边充电,从右边放电。通过将充电和放电电阻之和保持在恒定值,输出信号波长也是恒定的,只有占空比改变。根据以下公式,输出频率是固定的

频率= 1.44/(R Varbl * C 定时

图 10-5 用图形显示了占空比的概念及其与频率或波长的关系,如红色箭头所示。对于驱动电机等功率控制应用,根据非常快的脉冲宽度快速打开和关闭电源的能力提供了一种在功率应用范围的高端控制电机速度的方法。然而,如果通过脉冲宽度变化被供电的负载工作在调节范围的低端,则较长的频率将为所施加的功率的控制提供较高程度的分辨率。步进电机中的加热电路和低转速可能需要更长的波长或更低的频率来提供足够的控制调节范围。

用于科研的 Arduino 教程(三)

图 10-6

一种基于 555 定时器 IC 的带光电中断电路的电机控制器

用于科研的 Arduino 教程(三)

图 10-5

占空比概念

软件

图 10-7 描述了用于显示风扇转速的变量值屏幕组件的属性主选项卡。将风扇盘每转的七个光束中断转换为风扇电机转速的计算结果输入到屏幕组件的表达式框中。子窗口的变量值组件选项卡中的各种条目生成弹出属性窗口上方的 RPM 显示框。

用于科研的 Arduino 教程(三)

图 10-7

用于测量风扇电机转速的 DAQFactory 变量值组件配置

不需要任何脚本,因为计数器每秒钟被读取、重置一次并被输入到 RawInputCounts 通道中。作为 RawInputCounts[0]返回的值根据磁盘上的风扇叶片数进行了校正,并规范化为分钟。

观察

当电位计设置在中间位置时,双线风扇电机以大约 2950 rpm 的速度旋转,在电机停止之前,速度可以在 3300 到大约 100–150 rpm 之间变化。

在光学转速表的最初开发阶段,光电二极管-光电晶体管对产生的脉冲序列无法触发 LabJack 计数器,因此需要增加信号强度。使用图 10-6 的原理图中所示的两个分压器,从+12 伏电源中单独提取用于驱动光电二极管-光电晶体管对的功率。光电二极管分压器产生标称 5 V,光电晶体管分压器产生标称 6 V (5.91 V)。图 10-8 显示光束斩波器输出的示波器显示。

用于科研的 Arduino 教程(三)

图 10-8

光束斩波器输出的示波器显示

从大型 CPU 芯片回收的三线冷却风扇电机取代了双线系统,高端风扇转速范围测量为 5,200 rpm。仔细调整后的风扇速度可以降低到 200 转/分的范围内,偶尔在电机停转前降低到 150 转/分的范围内。

芯片冷却风扇上的第三根电线通常是电机内置霍尔效应传感器的输出。霍尔效应传感器检测变化的磁场,第三根导线的输出产生一系列由旋转磁场产生的小尖峰信号,可用于测量电机的转速。

讨论

在本练习中,演示了为电机供电所需的较高电流的脉宽调制控制。基于非稳态配置 555 定时器芯片的有限脉冲宽度调制方案已在第章第八部分中讨论过,相对恒定的频率、可变占空比模式的功率传输现在正通过适当的二极管修改来使用,以扩展占空比范围,同时保持输出方波的频率或波长恒定。

在第八章、图 8-10 和图 10-6 中,可以看到电容器通过 R1 和 R2 的一部分充电,但仅通过 R2 放电,因此循环的充电部分只能降低到 R1 的值,而 R2 的值在循环的放电部分实际上可以降低到零。因此,占空比的可能变化由 R1 的值控制。

简而言之,我们可以看到,我们用于向 BLDC 电机供电的 PWM 技术将占空比从 100%降低到 0%。从 100%时的 12 V 到 50%占空比时的 6 V,再到 0%占空比时的 0 V,总的电压变化是低速旋转时不稳定行为的原因。在占空比较低的部分,12 V 电源没有在足够长的时间内提供平均功率来驱动电机,因此电机“失速”换句话说,在控制电位计的低设置下观察到的控制损失和失速是传递给电机的功率不足的结果。为了更好地控制低速电机运行,需要不同类型的电机和功率控制。

这个 555 PWM,光学转速电路,DAQFactory SCADA 软件显示系统是用一个回收的双线计算机塔冷却风扇开发的。第二个冷却风扇来自较新的大型 CPU 芯片,带有三线控制电路板连接器,被替换到试验板设置中进行比较。第三根电线通常为黄色(见图 10-4 ),用于监控内置于电机转子/定子部分的霍尔效应检测器的输出。霍尔效应传感器对变化的磁场作出响应,可用于指示电动机控制系统中磁铁相对于线圈的位置。

从作者的旧设备中回收的芯片冷却风扇电机是一个 2 1/4 平方英寸(5.7 厘米)的七叶片、12 伏、180 毫安的装置,当通过红/黑电源线供电时,其转速上限为 5200 转/分,转速在 200 到 150 转/分之间停止。

正如我们将在本研究的后面部分看到的,风扇电机的回收和再利用可以廉价地解决一些实验室程序中出现的实际问题。

步进电机

需要对电机功率进行电子控制的 BLDC 电机有两种形式:用于驱动风扇的连续负载型电机和称为步进电机的电机。BLDC 风扇电机在施加满电压的较高速度下产生最大功率,并随着转速降低而停止,因为电压/功率水平降低,而步进电机在不旋转时产生最大功率,并随着转速增加而损耗功率。步进电机的名字和用途源于它们以离散的“步长”移动或旋转的能力。通过控制电机的“步进”动作,可以实现精确的旋转定位和精确的低速旋转速率,以及显著的扭矩。

步进电机有多种形式,并根据用于装配电机的结构类型而具有不同的性能。对于那些需要更多细节的实验设备开发项目,在线(Jones on Stepper Motors)和机器人和工程的文献中都有许多好的教程。 1

出于电流控制练习的目的,我们将讨论和实验限制在称为双极永磁(PM)系统的电机类别。这些电机提供连续的低速旋转,在机器人、简单物理、化学和生物实验室程序中有明确的实际应用。用 555 定时器等 IC 可以相对容易地实现和控制连续旋转。单步执行和往复步进动作中的振荡需要额外的电机绕组知识、稍微高级的编程能力和专业硬件。在接下来的几个练习中提到了实现向下到单步点的受控旋转的方法,但是在这个简单的介绍性部分中不考虑振荡和分数圆周旋转动作。

为了使电机功率控制单元的装配保持简单、廉价和熟悉的形式,本练习中的电子功率控制电路同样基于可调节的、不稳定的 555 定时器电路脉冲产生,但是具有一些相对简单的附加数字逻辑电路。555 定时器 IC 可以由任何能够产生 PWM 控制中使用的低电压、可调占空比、方波脉冲序列的计算机或微控制器代替。

永磁(PM)步进电机的特点是转子轴不能像高速 BLDC 风扇电机那样自由旋转。PM 步进电机轴,当用手转动时,电机不与电源连接,在平衡或静止位置之间“嵌齿”或“步进”。完成一次完整旋转所需的步数表示步进电机旋转或振荡可被控制的“分辨率”或“精细度”。

步进电机的设计使得单个线圈绕组可以单独通电,从而产生内部电磁场,通过转子的旋转,可以与内部永磁磁场建立平衡位置。通过以编程的顺序激励线圈,可以使电机轴以编程确定的任何方式旋转。电磁线圈以顺序方式通电,以使电机轴沿任一方向平稳旋转的程序是这一简化练习的主要焦点。

步进电机的转速比传统的绕线式无刷电机慢得多,在低速时产生的扭矩也大得多。步进电机不会在它们的结构上移动大量的空气,因此会在它们的外部金属外壳周围聚集更多的热量。

实验的

五金器具

步进电机、速度控制、正向/反向开关和电机电源连接需要牢固安装。电机的电源连接必须能够互换单个电机线圈引线与电子控制电路输出功率晶体管的连接。集成电路可以组装在试验板上,以便于构建、原型开发和实验演示。图 10-10 中描述了一个实验性电机和硬件安装架,该安装架由易于获得的材料制成的手动工具组装而成,并在下文中进行了详细描述。

电路原理图

如上所述,为了大多数实验实验室或野外工作的目的,四线圈步进电机的控制电路只需要驱动电机平稳、可控地顺时针或逆时针低速旋转。因此,电源应该能够产生一系列连续的四个可调宽度的电流脉冲,这些电流脉冲具有足够的安培数,以使电机连续步进通过转子的完整旋转。

在将步进电机的电源连接分配给电子电源控制器的输出晶体管时,必须小心谨慎。如果五线电机中的中心抽头或六线电机中的抽头连接到正电源,则“第一”组抽头线圈的末端应连接到功率输出晶体管 1 和 2,第二组线圈末端连接到 3 和 4。如果电机旋转不平稳,对速度控制电位计的响应不符合预期,则依次交换第三个和第四个线圈连接,并重新测试电机。如果交换不能解决问题,则交换第一个和第二个线圈连接,重新测试,如果需要,颠倒第二个和第三个线圈连接。

用于科研的 Arduino 教程(三)

图 10-9

基于 555 定时器 IC 的步进电机控制器

在图 10-9 中,一个由电位计控制的非稳态 555 定时器用于产生一个可调占空比脉冲序列。该脉冲序列用于触发(或供电)一对 D(数据)型触发器,该触发器已被配置为分频器,以产生所需的四个晶体管基极驱动信号序列,从而产生所需的高电流功率脉冲。数据触发器包含在单个 CMOS 4013、14 引脚 DIP 中,与 555 定时器芯片一起可以由更大电流的 12 V 电源供电。

步进电机可以由许多不同的线圈激励序列控制,这些序列可以产生高扭矩的单步或分步旋转、来回步进运动或平滑的连续旋转。低速、高扭矩、平稳的连续旋转是生物/化学实验室工作中应用最多的运动,即搅拌和泵送液体。为了通过四个输出晶体管实现电机线圈的正确排序,线圈的公共中心抽头连接到正电源。因此,线圈的通电包括将绕组端部接地,以使电流从中心抽头流向地面。因此,通过顺序地将绕组的端部接地,可以使电机旋转。用于本练习的电机上的接线颜色代码可能与图 10-9 中显示的不同。典型的电机在绕组末端有四个连接,或者一个公共连接到中心抽头,或者两个连接到中心抽头,从而形成五线和六线电机到电源的连接。

流经单个线圈的电流受到线圈自身电阻的限制。反转流经电机线圈的 DC 电流的方向将反转旋转方向。

电机旋转是通过顺序激励电机的内部绕组以产生磁场来实现的。瞬态电磁场与永久磁场相互作用,导致电机旋转。切断通电线圈的电流会产生反电动势,该反电动势由穿过电机内部绕组的崩溃磁场感应到线圈中。必须保护开关晶体管免受电机线圈高压反电动势的影响,否则它们的 PN 结会被损坏。led 已经放置在图 10-9 的开关装置的收集器中,以保护输出功率装置并提供单个线圈电流通道的视觉确认。

用于科研的 Arduino 教程(三)

图 10-10

一种步进电机测试组件

项目 1 是安装在 1 英寸(1.2 厘米)的铝直角挤压框架上的科帕尔伊莱克特电机,其具有附加的黑色橡胶联轴器以移动和部分抑制共振频率。霍华德电机可以看到右边的安装适配器。项目 2 是用于电机绕组线和试验板接口的端子。第 3 项是 555 定时器芯片,数字 4 标记的是 4013 数据触发器芯片的位置。项目 5 是一排功率晶体管,项目 6 是“速度”控制电位计。项目 7 是旋转方向开关,项目 8 是大电流电源输入线。

软件

需要页面组件

用于切换 4013 D 触发器和驱动晶体管序列的脉冲序列也可用于创建电机转速的转速表显示(参见“讨论”)。作者的实验室有 12 V 永磁 75ω四相(线圈)步进电机,由 Howard Industries 制造,零件号 1-19-4200,每步 3.6 度,还有来自伊莱克特 Copal 的 SP-57B 电机,零件号 85086780,具有 36ω线圈电阻和 7.5 度步进旋转。因此,霍华德汽车公司完成一次完整的旋转需要 100 步,而科帕尔·伊莱克特汽车公司只需要 48 步。与风扇电机一样,转速可以通过 DAQFactory 变量值组件显示在屏幕上。速率的计算方法是,在 1 秒钟内计算施加于触发器逻辑的脉冲数,然后除以完整旋转所需的步数,并归一化为每分钟转数。不需要编写脚本,因为计算可以输入到显示为图 10-7 顶行的变量值屏幕组件的表达式框中。

观察

适度的步进速度导致平稳的旋转,而在低速下,单个的步变得清晰可见。使用发光二极管保护电机线圈免受反电动势的影响,还可以作为电机活动的指示灯。

转子空载的两种步进电机都通过一定的转速,这导致电机和安装结构“共振”3.6 度的霍华德电机在 113 转/分时开始振动,在 100 转/分时产生剧烈振动,在 92 转/分时发出非常大、令人讨厌的嗡嗡声,但在 85 转/分时运行平稳、安静。当来自三件式橡胶“三通”电机驱动连接的 in (0.6 cm)金属轴联轴器被添加到 Howard 电机轴上时,电机在 92 rpm 时显示出强度大大降低但仍然明显的高音调振动,并且在 60 rpm 时还显示出较低强度和较深音调的振动,以及在 30 rpm 时甚至更低音调和较低强度的共振。在共振“峰值”之间的任何转速下,电机都能平稳运转。

科帕尔伊莱克特电机空载转速范围为 60–300 转/分,在 89–90 转/分时会产生共振“震颤”。如果电机轴装有驱动连接器联轴器,共振速度会略微上升至 92–95 rpm 范围,电机会在 250 rpm 时完全停转。

在转子上没有联轴器的情况下,不可能用力挤压轴来停止电机,但是通过联轴器底座提供的额外杠杆作用,转子可以停止;当失速的转子脉动时,RPM 指示器仍然记录了 37 rpm 的等效脉冲率。随着转速的增加,扭矩的损失对于 Howard 马达来说是明显的,但是如果选择了超过 250 转/分的速度设置,则带有附加质量的联轴器的 Copal 伊莱克特会失速。

除了在实验室实验工作中进行低速混合和搅拌之外,步进电机还特别适合控制蠕动泵的输送速度。通过改变 555 非稳态配置中 RC 定时常数的值,利用图 10-9 中的 1.0 uF 电容和 27kω电阻,作者的 Copal 伊莱克特可以降低到 5–6 rpm;通过将电阻和电容都改为 296kω和 1 uF,电机以 1 rpm 的速度连续单步执行 48 次增量。

讨论

步进电机的灵活性和所需的低速性能是以控制电路的复杂性显著增加为代价实现的。可以使用本练习中使用的 D 型触发器或设计为移位寄存器的芯片(如 74LS194 和 CMOS 4035)来产生连续平滑电机旋转所需的连续电流脉冲。使用移位寄存器的详细信息可在网上 2 以及标称 IC 的印刷资料中找到。

步进电机的设计使得转子静止时产生最大扭矩。借助专为该练习设计的系统,转速可降至 1 rpm,在此转速下,电机的每一步只需 1/48 分钟或 1.25 秒。在 1 rpm 的慢速下,练习中使用的科帕伊莱克特电机已接近其最大可用扭矩。离散的、任意的时间步进或保持位置在机器人控制系统中是有用的,并且在动力控制系统中需要比在本部分练习中使用的电位计控制的 555 脉冲发生器所提供的更复杂的编程能力。

共振是步进电机的一个问题,并且电机在共振模式下的持续运行将通过增加旋转部件的机械退化率而大大降低电机的使用寿命。电机应在共振速度下运行,或者如果共振速度很重要,则可能需要在实验装置中内置特殊的机械安装技术、传动装置或旋转质量的变化,以处理系统共振。

电机轴的旋转速度可以通过使用 DAQ factory(lab jack 计数器通道的默认数据收集速率为 1 秒)进行电子测量,应用转子轴旋转一周所需的步数,并将显示的数据值调整为所需的时间单位。在屏幕“变量值”组件中将脉率转换成数字显示所需的公式可以输入到屏幕组件的公式框中,如图 10-7 所示。使用脉冲率来确定电机轴转速使用了电机在旋转时不“打滑”的隐含假设,这可能发生在电机转速范围的较高端,或者如果被驱动的“负载”显著增加。如果滑动是一个问题,或者要监控实验装置的实际旋转,那么应该在移动负载上使用光电断续器转速计方法。

步进电机在低速旋转或作为可旋转的定位代理时最有用,如果需要较低的旋转速度,可以增加 555 非稳态的时间常数,以扩大施加到触发器的脉冲之间的间隔。然而,转速越慢,电机旋转的“步进”作用越明显。

交流电源的控制

介绍

交流电(AC)源通常被称为“电源”在北美,市电或“家用电流”以标称的 120 伏峰峰值或 115 伏均方根(rms)60 赫兹提供,而在欧洲和世界其他地区,50 赫兹为 220 伏(rms)。大量的早期交流电源是由水力发电设备产生的,在水力发电设备中,水轮机旋转发电机,在这些相对较低的频率下产生正向和反向电流脉冲。

低压 DC 电流实际上是无害的,但“电源”电压和电流很容易引发火灾,将建筑物烧毁,造成严重的疼痛烧伤,并产生潜在的致命电击。

与高电压、高电流电能的致命性相一致,固态系统已经被开发出来,用于控制危险的高功率水平并将其与低电压控制电路隔离。

当与控制电路适当隔离时,交流电的优势在于能够直接为电机、照明设备和加热元件供电,而无需在使用前转换成 DC。主电源或交流电源从零到最大正向值循环,然后下降回零,在下降回零值之前上升到其最大反向值,从而完成循环。交流电源通常由晶闸管或四层 P-N-P-N 半导体元件控制,这些元件被制成两种类型的器件:可控硅整流器(SCR ),其导通可以在半个交流周期内进行调节;或者三端双向可控硅开关,可以在整个交流周期内控制导通。SCR 和三端双向可控硅开关的频率响应有限,因此主要用于 50–60Hz,但可用于高达 400 Hz 的交流电源频率。SCR 是具有“门”的多层二极管,该“门”允许二极管在其 AC 波形的正常导通部分的任何点从阻断模式切换到导通模式。通过将两个 SCR 并联但以相反的方向导通来形成硅双向开关或三端双向可控硅开关元件,可以根据施加到公共栅极的信号来控制交流电源波形的正向和反向周期。

如上所述,SCR 和三端双向可控硅开关都是二极管型器件,其栅极允许电路设计者控制交流电源周期通过器件本身以及负载的一个或两个方向。已经开发了使用光耦合到硅双向开关的光电二极管的 IC,以提供光隔离的手段,用于将栅极控制电路与流过硅开关器件的高能 AC 电源分开。光隔离器芯片有两种形式,包括传输控制信号以随机开始导通的器件和能够检测主电源信号过零点的器件。如果交流电源周期被随机“斩波”,可能会产生射频干扰(RFI)或更常见的电磁干扰(EMI),因此必须使用滤波器来抑制不需要的辐射。过零检测电路仅在过零点开启和关闭交流控制器件,可最大限度地减少显著射频干扰的产生。

随机相位或过零、光隔离集成电路由低压 DC 源供电,因此,如果标准数字逻辑电路与市电交流电源的三端双向可控硅开关控制一起使用,则必须提供所需的 DC 电源。可以使用电池或图 10-11 所示的简单专用 5 V 电源。

用于科研的 Arduino 教程(三)

图 10-11

典型的交流至 5 伏 DC 输出电源

使用固态设备控制交流电源为研究人员提供了两种利用能量的方法。在第一种也是最简单的方法中,可以将全交流电压施加于负载,并且允许全电流流动的时间是可变的。第二种控制形式包括改变施加到负载上的电压。交流电压在 0 至 120 伏之间循环,固态开关器件可用于将循环中的任何部分(0 至 120 伏)施加到负载上,每秒 60 次。交流波形是一种正弦现象,其中电压幅度遵循正弦曲线。通过选择波形的一部分向负载施加电压,功率控制被称为“相角控制”电压变化有些复杂,只应在需要时使用。通过向负载施加全交流电压并改变全功率施加的时间,可以控制输送到负载的功率,并且当使用过零开关时,所产生的射频噪声大大降低并最小化。

第七章中介绍的脉冲宽度调制概念以及之前在电机控制练习中应用的概念通常应用于 DC 电力系统,但也可用于对交流电源进行初步粗略控制。

本部分练习中使用的光隔离器是随机和过零单元。

实验的

五金器具

一个 60 到 15 瓦的白炽灯泡是一个很好的交流电源控制练习的视觉演示负载。如图 10-12 所示,灯泡插座和用于固定电位计控制器的安装支架,同时作为三端双向可控硅开关安装的散热器,以及用于安装控制电路的端子板和试验板,都应固定在坚固的木头或金属底座上。回顾与交流电源电压和电流相关的危险,根据当地的电气建筑规范,所有输送电源的线路必须牢固固定、适当绝缘并覆盖。应小心切割输送主电源的电线上的绝缘层,以确保在端子板上的螺丝端子连接拧紧后,没有裸露的电线表面暴露出来。所有暴露的电线表面或承载主电源的焊接连接必须用液体塑料绝缘体、硅酮密封剂或热缩管进行绝缘。千万不要给任何有裸露导体输送电源电流的电路通电。

下文解释了作者实验装置中的数字名称(图 10-12 )。

项目 1 是一个 60 瓦灯泡,装在符合电气规范的插座中,正确安装在 1 英寸(1.8 厘米)高密度纤维板上。项目 2 是一个 250 VAC 端子板,配有批准的电线和插头(注意:为清晰起见,移除了盖子)。第 3 项是一个 400 VAC、6 A、BTA06 意法半导体,其散热器上有 TO-220 标签式三端双向可控硅开关,带有热收缩包裹导体,消除了暴露的导体表面。第 4 项是占空比控制电位计,第 5 项是演示练习中使用的光隔离三端双向可控硅开关控制 IC。数字 6 标记双极 555 定时器的位置,第 7 项是 9 V 电池供电。

最初用作视觉活性实验负载的 60 W 灯泡随后被表面更冷的 15 W 灯泡取代,后者通常用作家用电器的室内灯。

用于科研的 Arduino 教程(三)

图 10-12

一种带白炽灯泡的交流电流控制测试装置

电路原理图

图 10-13 是一个典型的框图,显示了用三端双向可控硅开关和光隔离器控制交流电源的实验设置。

用于科研的 Arduino 教程(三)

图 10-13

三端双向可控硅开关和光隔离器交流电流控制

在本练习中,可通过电位计二极管网络,从一个 555 定时器组装一个手动可控的 DC 脉冲源,该定时器配置为非稳态运行,其占空比由手动控制,如之前用于 90%范围的占空比变化。

图 10-13 中的电路图是在使用飞兆半导体 MOC 3022 的配置中绘制的,当 MOC 3022 内部 LED 照明电路中使用合适的限流电阻时,该 MOC 3022 可以由 5 V 电源或 9 V 电池供电。通过给低压脉冲发生电路通电,然后将交流电源线插入主电源,将受控的交流电源施加到负载电路。

图 10-13 的电路是用 MOC 3022 随机相位光隔离器三端双向可控硅开关驱动器绘制的。MOC 3061 过零装置的使用方法与图 10-14 所示的方法相同。

为了对将脉冲宽度变化技术应用于交流电流控制所产生的效果进行重要的可视化显示,图 10-12 、 10-13 和 10-14 中所示的电路应使用图 10-14 中的元件构建在原型试验板上。

组装并检查了在计时网络中使用 0.1 μF 电容改变 555 定时器的占空比对灯泡灯丝的影响后,应将电容改为 1.0 μF 单位,占空比再次在可用范围内变化。

虽然正在组装的电路仅用于演示,但在计时操作中使用低泄漏塑料薄膜或陶瓷电容是一种良好的做法。

用于科研的 Arduino 教程(三)

图 10-14

一个 5 伏 555 定时器 IC 控制线路电源

软件

本练习不需要屏幕显示页面组件或脚本。

观察

使用能够测量频率(单位为 Hz)的手持式万用表测量 555 定时器电路方波的输出频率,发现 0.1 μF 电容的输出频率约为 75–124Hz,1.0 μF 单元的输出频率约为 8–12Hz。

初始设置组装在计时电路中具有 0.1 μF 的试验板上,并使用 MOC 3022,能够将灯的亮度从大约半功率改变到全开。在接近电位计旋转结束时的半开启功率设置下,灯闪烁,并且发现定时器输出在 75 和 82 Hz 之间不稳定地移动。

用一个大得多的 1.0 μF 单位替换定时电容,大大降低了 555 定时器脉冲频率范围,从 12.6 Hz 降至 7.6 Hz。当电位计完全旋转到 12.6 Hz 位置时,灯完全点亮且不闪烁。将电位计旋转到频率计读数为 7.8 Hz 的点,导致灯的亮度在视觉上平滑地降低,并且伴随着不稳定的灯闪烁的增加,直到在频率范围的低端,灯基本上关闭,但是以不稳定的、非常低水平的亮度闪烁。

虽然通过光隔离器的交流线电压的 PWM 开/关功率应用能够粗略地调节传递给灯的能量,但是该系统不能用作平滑的灯调光器,但是可以用于非照明应用。

讨论

世界上大多数电网输送由水、蒸汽或最近的风力涡轮机驱动的旋转发电机产生的能量。交流电能可以通过变压器转换成高电压形式进行远距离传输,然后再转换成高电流相对较低的电压形式供消费者使用。世界上大多数电网都在 50 或 60 赫兹的交流频率下运行。

对于在白炽灯或荧光灯照明、加热或转动电动机中的消耗性使用,交流电源通常可以在从配电网接收到的情况下进行最小的改变。

演示电路中应用于白炽灯泡负载的三端双向可控硅开关控制电源由电池供电的 555 定时器提供的脉冲速率控制。图 10-14 所示的 555 定时器非稳态运行模式中使用的定时网络能够允许占空比在大约 5%到 95%之间变化。因此,输送给负载的功率在相当大的范围内是可变的,但既不会完全关断也不会完全接通。

对于交流电流的无感或严格阻性使用这一简单目的,可以在基本电气计算公式中使用各种形式的均方根(rms)、峰峰值或平均值来描述交流,但必须一致使用,不能混用。如果欧姆定律中使用 rms,那么电压和电流的所有值都必须以 rms 为单位。

如果将灯替换为封闭绝缘容器内的加热元件,则产生的热量可以通过由电位计控制的开/关比来粗略调节,电位计反过来粗略调节温度。回想图 10-5 的图形数据,可以看出占空比的跨度是使用脉冲宽度变化可获得的控制跨度。

在本练习中,仅检查非常简单的交流电路分析和电磁干扰(EMI)。交流电子设备依赖于频率,随着频率的增加变得非常复杂。在任何涉及更高频率的实验工作中,如通信、感应加热、核磁或电子自旋共振光谱学,必须查阅文献以获得更具体和详细的信息。

如果要防止电路产生或拾取电磁干扰,电路必须完全封闭在接地金属盒中,与辐射完全隔离。如果电路从电网获取电力,那么为了安全起见,接地金属盒及其布线必须符合当地的电气建筑规范。

在迄今为止检查的大多数功率控制应用中,都涉及到 DC 电流,因此不需要考虑频率分量。然而,试图将 PWM 技术与 50 或 60 Hz 的固定频率的交流电力传输一起使用会立即对 PWM 方法的性质造成限制和约束。

在图 10-14 所示的电路图中,使用中心抽头电位计构建了一个电路,该电位计允许大约 50kω的电阻变化。对图 9-1 中展开的诺模图的检查表明,对于 50kω–0.1μF 的组合,实验者应该期望定时器在数百 Hz 范围内振荡。

回想一下,电位计二极管配置用于允许占空比的变化,而振荡频率只有微小的变化。如果功率通过一个三端双向可控硅开关器件输送到负载,该器件允许电流以 50 或 60 Hz 的振荡方式流动,那么在十分之一秒内,负载将经历五或六个功率周期。如果 555 定时器每秒钟开关光隔离器中的红外二极管数百次,三端双向可控硅开关将在相当长的时间内处于开启状态。

如果定时器脉冲序列的频率降低到 10 Hz,则占空比变化可以跨越通过三端双向可控硅开关振荡的电源的五个或六个电源周期。图 10-15 描绘了十分之一秒的时间跨度,其中五个电源周期标有在标称占空比设置下关闭红外二极管的点。

用于科研的 Arduino 教程(三)

图 10-15

50 Hz 交流电源和 10 Hz 555 定时器 IC 输出占空比变化的第二图形表示的十分之一

如前所述,在较高的频率下,灯泡大部分时间都是明亮的,只能稍微变暗并不规则地闪烁。在大约低 10 倍的频率下,灯泡可以在其整个照明范围内变暗,但随着亮度降低到零而闪烁。

交流系统的 PWM 方法的进一步扩展用于功率控制应用,其中开/关切换的频率以秒和分钟来测量。长持续时间 PWM 功率控制通常用于加热控制应用中,在加热控制应用中,大的热物质在向加热元件施加功率和在被加热的物质中观察到温度升高之间表现出大的时滞。可以校准具有大时间延迟的交流供电加热系统,并建立 PWM 控制系统。

PWM 系统可用于精确控制输送给负载的功率,通过使用半导体,在一种称为相角控制的技术中,只将功率周期的一小部分传递给负载。然而,相角控制涉及在功率周期和 PWM 控制信号中建立和协调过零点,这超出了本练习的简单介绍性质。

使用 Raspberry Pi 和 Python 的当前控件

介绍

控制较大的 DC 电流

正如在前面的练习中已经指出的,RPi 从 GPIO 引脚提供任何相当大的电流的能力有限。然而,来自外部源的较高电流可以通过 RPi 阵列上的一些引脚来控制。

在线收集了当前控制硬件和电路的优秀摘要。 3

30–60 A 范围内的大电流 DC 可以用金属氧化物半导体场效应晶体管(MOSFETs)来控制,如 ON Semiconductor 或 Fairchild 的 FQP30N06L。FET 半导体通常需要强信号才能进入导通模式,因此使用 GPIO 阵列作为控制源的实验人员必须确保所选的 FET 晶体管与阵列引脚提供的 3.3 V 兼容。FQP30N06L 中的 L 表示器件的栅极与低压控制信号兼容。

利用图 10-16 中示意性描绘的达林顿对晶体管,可以实现适度的电流处理能力。

用于科研的 Arduino 教程(三)

图 10-16

NPN 达林顿晶体管对

双极结型晶体管(BJT)是电流控制器件。通过器件的主电流在集电极和发射极之间流动。集电极和发射极之间的电流由小得多的基极电流控制。基极电流的放大使 BJT 成为一种敏感设备,能够放大来自太阳能电池和热电偶等传感器的非常微弱的信号。由达林顿晶体管对制造的器件能够与晶体管对的两个放大因子的乘积成比例地放大电流。双晶体管组件对基极电流也比用于制造器件的单晶体管敏感得多。

两个常见的达林顿对晶体管是 TIP 120 和 122,它们是在 TO-220 封装中作为标签式三端器件提供的。这两款器件分别能够在高达 60V 和 100 V 的电压下工作,并且通过适当的散热器,可以在 5 A 电流下工作。

实验的

非感性负载

为了演示 RPi 的 GPIO 阵列的电流控制技术,将使用 Python-tkinter GUI 屏幕滑块控件来管理照明汽车白炽灯的 12 V 电源。白炽灯纯粹是电阻性负载,因此不需要二极管来旁路由电感性负载(如电机线圈绕组)产生的破坏性电压尖峰。

将 TIP 122 达林顿对晶体管和电阻器安装在原型板上,并连接到 12 V 电池电源和汽车灯。电流控制演示电路如图 10-17 所示。

用于科研的 Arduino 教程(三)

图 10-17

白炽灯电流控制电路

发现汽车灯在亮红色热源下从 6 V 电源汲取 1.25 A,对应于 4.80ω的灯丝电阻。因此,采用 12 V 电源时,全功率下的预期电流消耗应约为 2.5 A,完全在制造商为 TO-220 封装推荐的 5 A 容量范围内。

通过清单 10-1 创建的 Python-tkinter GUI 滑块控件如图 10-18 所示。

用于科研的 Arduino 教程(三)

图 10-18

一个用于白炽灯负载的 Python-tkinter GUI 滑动功率控制器,带有 PWM 百分比的控制台值显示

图 10-19 是 tkinter 标尺或滑块功率控制图标的详细视图。作者已将箭头标题和百分比数字量标识符应用于图像,而文本和直接滑块数值由清单 10-1 中的适当条目创建。图 10-19 中增加了更多细节,以帮助描述“讨论”中 tkinter 图标的嵌入特征

用于科研的 Arduino 教程(三)

图 10-19

RPi 的 t 中间刻度或滑动屏幕图标控制器。GPIO PWM 库函数

观察

图 10-19 中描述的滑动标尺微件在滑块位于槽的最左端时,灯丝完全关闭,滑块位于槽的最右端时,显示黄红色白炽度。灯丝强度的变化类似于第七章、图 7-7 和 7-9 中观察到的变化。

必须缓慢移动标尺或滑块控件,以便跟随变化的位置值。图标有一个更好的控制度,详见“讨论”部分。

讨论

承载数百毫安和数百安培电流的所有电路接线应使用焊接接头或紧密的机械连接进行正确连接,并进行绝缘处理以防止短路。即使在低电压下,短路产生的高电流放电也会产生非常高的热电弧,熔化金属,点燃可燃物,造成痛苦的烧伤。

Tkinter 是一个 Python 库,它实现了许多图标,用于为 RPi 组装一个活动的、定制的 SCADA GUI。tkinter 集合中的图标内置了大量功能。 4

在许多关于使用 tkinter 和其他 GUI 创建库的教程中,按钮、滑块、滚动条和其他屏幕图标设备等图标通常被称为“小部件”,并在编程代码中被赋予符号 w。

在清单 10-1 中,一个窗口的 tkinter 实例被创建并被设置为 master 的指示符。mainloop()函数扫描主窗口内部的鼠标激活事件。窗口小部件是在屏幕上创建的,或者在主窗口的主动扫描区域内用代码实例化,以完成手头的任务。如果窗口中的小部件必须与运行 tkinter 窗口的 Python 程序通信,则必须调用“回调”函数来与主窗口活动区域之外的代码通信。

简而言之,可以说每个微件都显示在监视器显示屏上的一个小窗口内。tkinter 程序扫描小窗口内的空间,寻找可能在帧内发生的鼠标点击“事件”。鼠标单击或鼠标按钮单击可用于拖动屏幕对象的边缘来调整它们的大小,激活它们的显示控件,以及最小化、最大化或退出程序。

与运行 tkinter 窗口和小部件的 Python 代码进行通信的能力允许实验者访问 RPi 串行端口,并如第十一章所述,将屏幕小部件连接到机电系统,以进行 SCADA 操作。

图 10-18 描绘了当清单 10-1 在回调函数中的诊断打印语句激活的情况下启动时获得的 RPi 屏幕。print 语句会将出现在滑块按钮索引线上的滑块索引的数字位置打印到 Python 控制台。在验证代码操作之后,或者在错误跟踪诊断不需要时,可以注释掉 scale 或 slider 程序回调函数中包含 print 语句的行。

图 10-19 有箭头标题,表示两个极限值,可以用鼠标光标和点击鼠标左键将指示器滑块拖动到这两个极限值。如果实验者需要从屏幕图标上精细设置 PWM 值,可以将索引按钮拖动到所需的近似位置,然后用光标提示调整到最终所需的位置。如果滑块索引按钮的值要增加一位数,光标尖端放置在滑块按钮和滑块刻度的 100%端之间的滑块槽的顶部边缘,并单击索引按钮位置的每个所需的一位数增量。如果从粗略定位开始,步进值将减少,光标尖端将置于步进滑块按钮和刻度的 0%端之间,并单击至所需的最终位置。

感性负载的功率控制

介绍

如图 10-17 所示的控制尖端 122 的 RPi 可用于控制输送到如图 10-4 所示的无刷 DC 电机的功率,但是电机中的线圈是感性负载,当包围线圈的磁场消失时,会产生电压尖峰形式的反电动势(EMF)。为防止反电动势损坏功率晶体管的 PN 结,应在负载上并联一个大小合适的二极管。

来自之前描述的标尺滑块 GUI 的 RPi PWM 信号可用于取代晶体管的 555 定时器-电位计功率控制,该晶体管用于调节输送至无刷 DC 电机的电流,从而控制电机的速度,如图 10-4 所示。也可以使用第八章中描述的电路设置 Python 断梁 RPM 监控器,以监控电机速度,从而根据 RPi-Python 组合复制 DAQFactory 练习。

然而,可以利用 RPi 和 Python 开发一个非常有用的不使用 PWM 的高电流传输演示,为步进电机供电,而不是从一个系统转换到另一个系统。

实验的

步进电机可以用一个 ULN2803 或 ULN2804、8 个达林顿对阵列 IC(3 CDN)从 RPi 进行廉价控制。ULN280n 由 8 个达林顿对功率晶体管阵列组成,采用 18 引脚双列直插式封装。(DIP)IC 阵列制造时已经安装了旁路二极管,用于驱动感性负载。

每个达林顿阵列晶体管对都是“集电极开路”配置,其中晶体管充当开/关开关。在集电极开路配置中,要供电的器件连接到电源的正极和晶体管的集电极开路。如图 10-20 所示,所有对的发射极共用一个公共连接,连接到 RPi GPIO 阵列的负极或“接地”端子以及 ULN280n IC 上的#9 引脚。在高电平和低电平之间切换 GPIO 引脚可以打开和关闭流经电机线圈和指示灯的电流。

正如之前多次练习中所建议的那样,使用 ULN2803 的电路应从基本的基本原理开始构建、测试和验证,直至完成最终工作的电子电源控制器配置。RPi 程序应开发为运行连接到 ULN280n 的一系列四个 led,然后用于连接到实际的步进电机并为其供电。

ULN280n IC 阵列的标准应用已经进行了修改,在用于控制步进电机的基本电路中增加了四个 led。四个 LED 阵列直观地帮助组装和验证这个复杂系统的逐步实施。

用于科研的 Arduino 教程(三)

图 10-20

ULN2803 步进电机控制原理图

图 10-20 是一个连接的半示意图,其中 RPi GPIO 阵列通过功率控制 ic 连接到一个示例性的固定四线圈多永磁转子步进电机。

如上图所示,使用 Python 代码切换 GPIO 18,使 ULN2803 上的#1 引脚变为高电平,然后变为低电平,这将导致电流脉冲通过 A-E 固定线圈,从而产生磁场并点亮第一个二极管。通过线圈的瞬时电流脉冲将产生局部磁场,该磁场将使转子旋转到一个位置,在该位置,最近的相反符号的永久磁极与静止电机线圈中的瞬时磁极对齐。如果控制 GPIO 阵列的 Python 代码现在延迟一小段时间以允许转子旋转和磁场对准,然后在 GPIO 23 上重复逻辑高/低切换动作以使电流脉冲通过线圈 E-B 并点亮第二个二极管,则转子旋转的第二个“步骤”将发生。对于 GPIO 阵列引脚 24 和 25 来说,交替进行短时间延迟的切换动作的重复将在步进电机轴完成一次旋转时点亮第三和第四二极管。

简而言之,可以说,为了用图 10-20 的电路从 RPi GPIO 阵列控制步进电机,实验者必须汇编一个 Python 程序来顺序点亮 LED 阵列,如第三章以及本章末尾提供的清单 10-2 和 10-3 中所述。

图 10-21 描述了作者在原型板上的一个实验配置。

用于科研的 Arduino 教程(三)

图 10-21

步进电机驱动 Python 程序的实验设置

在图 10-21 中,项目 1 是 3 型 Raspberry Pi,其适当的 GPIO 输入引脚连接到安装在原型板(项目 2)中央的 ULN2803 黑色 DIP 的前四个通道。电源控制 IC 输出引脚依次连接到原型板右上角的步进电机线束的四个输入引脚,同时四根额外的导线为电路板左上角的绿色 LED 阵列供电。箭头指向阵列中亮起的 LED。清单 10-2 显示为点亮指定 LED 的诊断实用程序,但实际上,使用图 10-20 的电路,它“单步执行”步进电机。清单 10-3 实际上是清单 10-2 的连续“单步执行”扩展,提供了 RPi GPIO 阵列对步进电机动作的基本控制。

项目 3 是带有拇指驱动器的 USB 集线器,项目 4 是低功率 28BYJ-48 齿轮步进电机。缓慢移动的电机轴有一个透明的带黑色笔标记线的磁带“标志”,以帮助显示轴的旋转运动。图中还显示了 GPIO 引脚位置和识别辅助,有助于在图 10-21 所示的复杂连接布线过程中进行引脚定位。

图 10-22 显示了一个非常便宜的(19 CDN)板载步进电机和 IC 驱动器。板上的 28BYJ-48 电机(项目 1)被爱好者广泛使用,可用于本练习。这种小型步进电机模块在大多数业余爱好或电子商店和在线供应商处都有售。项目 2 是电机线束,项目 3 是连接到 RPi 上 GPIO 阵列的输入引脚阵列。

用于科研的 Arduino 教程(三)

图 10-22

市场上可买到的 SMT 步进电机驱动模块

虽然以非常简单的方式提出,步进电机控制不是一件小事;为了与这项工作的介绍性质保持一致,研究者可以参考书面和在线文献,以获得解释和计算机代码,用于处理本主题“讨论”部分中列出的步进电机控制的高级主题。

作者最初使用由四个碱性电池充电的四单元 D 电池电池组来提供 6 V 输出和 12,000 mAh 额定值,以便在接线验证和旋转测试期间为更大的步进电机供电。随后,齿轮步进电机(大约。1:64,实际上是 63.6839:1),通常用于机器人领域,可以从许多邮购渠道获得,在本练习的代码清单中,型号 28 byj-48(5 美元)用于开发电机驱动器程序。这款小型步进器可以采用 5–12V 电源供电,据报道,其转速为 15 rpm,DC 线圈电阻为 50ω,在 5 V 电压下,RPi 5 V 输出电流能力为 1/10 A,略低于 1 安培。该电机重 30 克,装在一个金属外壳中,带有两个螺丝安装凸耳,便于在实验装置上定位。

观察

为了与前面提到的原理保持一致,即一个工作的复杂系统是由更简单的、经过测试的和经过操作验证的子组件组装而成的,调用了以下程序。

在根据图 11-20 所示对 ULN2803、电机和 GPIO 阵列物理引脚连接进行初始配置后,列表 10-2 中的 LED 照明程序针对 18、23、24 和 25(阵列物理引脚 12、16、18 和 22;回想一下,数组是跨行计数的,而不是沿行计数的)。当每个 GPIO 连接被枚举时,相应的 LED 照明被目视确认,以验证 RPi GPIO 连接到适当的电机线圈引线。

在使用单个 led 进行系统验证后,使用 while 循环逐步通过四个线圈连接的清单 10-3 的第二个程序启动,与之前使用的 2 s 延迟相同,以验证电机线圈的正确顺序激活并确认步进电机的旋转。

2 秒的时间延迟会在高速齿轮电机中产生一个非常小的步进,但是将时间延迟减少到 1/8 秒会导致一个缓慢但明显的步进动作。

讨论

清单 10-2 和 10-3 是基本代码,旨在向调查人员演示步进电机如何工作和控制。为了扩展电机的应用,实验者可以通过以与旋转程序中相反的方式顺序激活线圈来反转电机的连续旋转。为了将步进电机驱动到位置服务,其中转子以顺时针或逆时针旋转步进固定数量的增量,可以将正确的线圈激励代码包含在 Python do 循环结构中。

除了这里介绍的简单代码之外,还有大量不同的动作可以编程到步进电机中,以实现正向和反向连续旋转和速度变化,这在大量关于步进电机的工程和机器人技术文献中有详细说明,应该针对更复杂的步进电机应用进行研究。

对于较大步进电机的应用或试验,例如从过时设备中回收的步进电机,可能需要单独的电源和较大的电流来实现电机旋转。GPIO 阵列可用于激活达林顿对晶体管或较重的 MOSFET 器件,但这两种类型的晶体管都必须用旁路二极管保护,以免电机线圈的反电动势损坏半导体。较大系统的较大电流消耗也可能需要使用半导体散热器。

交流电流控制

介绍

Python 和 RPi 可用于演示交流电能的有限 PWM 控制,使用与前面列出的 DAQFactory 程序相同的非常便宜的 IC。能够在 400 VAC 以上工作的多安培三端双向可控硅开关器件和光隔离器件可以从邮购处以不到 2 美元的价格买到。如图 10-12 所示,由 110 V 交流线路供电的白炽灯泡可用作 RPi 演示的电力负载,并配有这些便宜的组件。

为了安全和符合法律规定,当按照当地电气布线和建筑规范组装时,所有涉及线路电能的布线必须完全覆盖或绝缘。

实验的

图 10-23 描述了用于控制输送到白炽灯泡负载的交流电源的电路。BTA06 三端双向可控硅开关元件应安装在一个散热器上,该散热器足以让练习所选负载中使用的电流通过。用于家庭烹饪炉内部的小白炽灯可以以低至 15 瓦的小瓦特获得。

用于科研的 Arduino 教程(三)

图 10-23

树莓 Pi 的 110 VAC 线路控制

图 10-23 的电路已经用 RPi 提供的脉宽调制控制功能取代了在 DAQFactory 线路功率控制练习中使用的图 10-13 的 555 定时器和电位器。GPIO 引脚具有足够的功率,不仅可以驱动 triac 栅极,还可以同时驱动可选的 LED“pilot”灯及其限流电阻,该限流电阻连接到 GPIO 21 引脚和地,紧接在保护 MOC 3061 输入的 220ω电阻之前。

如前所述,RPi。GPIO 库包含应用来自 GPIO 阵列的 PWM 信号所需的函数,该信号具有足够的功率来点亮 5 mm 的 LED。MOC 3061 中的内部 LED 用于打开三端双向可控硅开关,从而将功率传递给灯丝以点亮灯泡。

清单 10-1 是该功率控制的 PWM 程序。所列程序生成如图 10-18 和 10-19 所示的标尺或滑块小部件,占空比由标尺或滑块水平位置决定。

RPi。PWM 功率控制操作的 GPIO 库实现涉及许多可变参数的选择和设置。操作员必须选择 PWM 脉冲序列的频率和控制信号的初始占空比,并在下面列出的两行代码中手动插入选择。一旦选择被输入到代码中,程序就可以运行,并且滑动按钮将把定制配置的 PWM 功率控制信号应用到三端双向可控硅开关来控制灯的照明功率:

  • pwm = GPIO。引脚 18 上的 PWM(18,500) # PWM 信号设置为 500Hz

  • pwm.start(0) #占空比的初始初始值

为了演示 DC 和交流电源的 PWM 功率控制之间的差异,滑块或标度程序从 500 Hz 的典型默认 PWM 频率开始运行。当显示滑块图标时,灯应通过其 0–100%的功率循环进行循环,并注明功率控制技术实现的效果。

为了积累更多的数据来评估不同的 PWM 频率对提供给灯的 AC 功率的影响,可以手动将 PWM 信号的频率减半,从大约 64 Hz 的线路频率降低到 8 Hz,并且可以收集在灯泡照明上看到的影响的记录。

观察

表 10-2 列出了在各种标称 PWM 频率下,小型交流电源灯泡照明的半定量效果。

表 10-2

标称 PWM 频率下的 110 VAC 灯泡发光输出

| ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Fvkdoc-ds-zh%2Fraw%2Fmaster%2Fdocs%2Farduino-sci%2Fimg%2F503603_1_En_10_Figa_HTML.jpg&pos_id=img-ve6xUVOa-1724461379172) |

光度是用照相测光表半定量测量的,方法是在离照明灯泡固定距离处测量刻度盘指示器从其零位的位移。

讨论

使用 RPi 和 RPi 可以进行 PWM 频率变化研究。GPIO 库,因为 PWM 频率是软件控制的,而不是硬件控制的。

从表 10-2 中可以看出,PWM 频率和灯泡功率传输之间的最佳相关性出现在 16 至 32 Hz 之间。

当 PWM 信号波长等于或大于输送给负载的功率波长时,将 PWM 控制方法应用于 60 或 50 周期交流电源的尝试仅粗略有效。

如表 10-2 和图 10-15 中所示的数据所示,当 PWM 信号施加到一个波长比控制信号的波长短的交流电源时,PWM 功能可以对输送到负载的功率进行粗略控制。在低 PWM 值下的低强度灯闪烁可能是由控制信号在功率周期的最大点开启功率信号引起的。随着 PWM 信号长度的增加,功率信号能够循环通过一个或多个完整的周期;如实验中观察到的,当 PWM 信号接近 100%占空比时,闪烁或闪光消失。

在几乎所有进行的 PWM 频率变化实验中,研究人员将看到不同强度的光闪烁和从完全关闭到完全打开的明显闪烁。两个信号的相位角之间缺乏协调,这在非常灵敏的低质量灯丝中产生完全随机的闪烁和灯强度的循环脉冲。

如前所述,为了使 PWM 信号用于调制或控制仅一部分 AC 波形(称为相角控制)施加到负载,必须有复杂的附加电路来检测和协调电源波和 PWM 信号的过零点。交流电源的 PWM 控制的变体可以用于加热和其他长期应用,其中多个全功率周期以定时脉冲施加到负载。

代码列表

raspberry Pi–Python 代码

# Illuminate LEDS repeatedly in sequence

import RPi.GPIO as GPIO

import time
#
GPIO.setmode(GPIO.BCM)

GPIO.setwarnings(False)
#
# A while loop repeats the cycle till terminated from the keyboard
#
while True:

    # illuminate the first LED on GPIO 18

    GPIO.setup(18, GPIO.OUT)

    GPIO.output(18, GPIO.HIGH)

    time.sleep(0.125)

    GPIO.output(18, GPIO.LOW)
    #

    # illuminate the second LED on GPIO 23

    GPIO.setup(23, GPIO.OUT)

    GPIO.output(23, GPIO.HIGH)

    time.sleep(0.125)

    GPIO.output(23, GPIO.LOW)
    # illuminate the third LED on GPIO 24

    GPIO.setup(24, GPIO.OUT)

    GPIO.output(24, GPIO.HIGH)

    time.sleep(0.125)

    GPIO.output(24, GPIO.LOW)
    # illuminate the fourth LED on GPIO 25

    GPIO.setup(25, GPIO.OUT)

    GPIO.output(25, GPIO.HIGH)

    time.sleep(0.125)

    GPIO.output(25, GPIO.LOW)

Listing 10-3Continuous Stepper Motor Rotation

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
# Locate Physical Pins and GPIO Designations with LEDs

import RPi.GPIO as GPIO

import time
#
GPIO.setmode(GPIO.BCM)

GPIO.setwarnings(False)
#
GPIO.setup(25, GPIO.OUT)

GPIO.output(25, GPIO.HIGH) # caution open collector - ULM2803

time.sleep(2)

GPIO.output(25, GPIO.LOW)

Listing 10-2RPi GPIO Pin Identification Utility

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
# A Horizontal Sliding Current Control Icon for the Raspberry Pi GPIO Array
# In RPI.GPIO pin 18 in BCM numbering or pin 12 in BOARD numbering has
# a PWM function of 0-100%. A slider is a standard Tkinter icon with a
# call back function to send slider position data 0 to 100% back to the python
# program running the RPI.GPIO library to adjust / alter the PWM values.
#
from tkinter import *
import RPi.GPIO as GPIO
import time
#
# library set up
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(18,GPIO.OUT)
pwm = GPIO.PWM(18, 500) # PWM signal on pin 18 set to 500Hz
pwm.start(0) # initial starting value for the duty cycle
#
# tkinter scale or slider control icon set up
#
# set up call back function to process the slider value. Print statement
# in callback is a development/error diagnostic utility
#
def Val(val):     # callback function definition (outside Tk() window instance)
    val = w.get() # the get function reads the slider value
    print(val)    # diagnostic utility comment out when not in use
    pwm.ChangeDutyCycle(val) # RPI library function to alter the PWM power applied to the load
#
master = Tk()     # window instance
master.title("Arduino in Science")  # a title for the main window that holds the widget
w = Scale(master, from_=0, to=100, orient=HORIZONTAL, label="PWM Controller", command=Val)  # creates widget, scale, text and names callback function
w.pack()          # display scale or slider icon instance

#
mainloop()        # main loop over window construct.
GPIO.cleanup()    # reset GPIO pins to low.

Listing 10-1A Horizontal Sliding Current Control Icon

用于科研的 Arduino 教程(三)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

摘要

  • 许多电子和实验科学操作都需要恒流源。

  • 精确的 DC 电流控制可以用分立电子元件或集成电路以模拟形式实现,也可以用脉宽调制技术以数字形式实现。

  • 正弦交流电流控制使用固态器件作为受控二极管,将正弦波功率分布的选定部分传递给负载,这由器件栅极激活决定。

  • 需要精确的电流控制来调节典型负载,如连续的电机转速或激活离散的感应式步进电机动作。

  • 练习演示了使用基本的 DC 脉宽调制技术作为交流电源控制所固有的问题,作为理解使用 PWM 变量控制市电电源的高级微控制器技术的前奏。

  • 第十一章介绍了微控制器,并展示了其作为“智能”I/O 设备和传感器接口的功能。

Footnotes 1

机电一体化和测量系统介绍,Alciatore 和 Histand,McGraw Hill,466 页,2003 年,ISBN 0-07-240241-5

2

http://www.electronics-tutorials.ws

3

https://elinux.org/RPi_GPIO_Interface_Circuits

4

effbot.org/tkinterbook/

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...