用于科研的 Arduino 教程(一)

随笔4个月前发布 伊人泪满面
53 0 0

原文:Arduino in Science

协议:CC BY-NC-SA 4.0

一、LED 照明的按钮控制

本章中的练习实际上是最简单的计算机控制形式之一,通过单击主系统显示屏上的按钮图标或运行几行计算机代码来打开和关闭 LED 设备。图形用户界面(GUI)是显示屏,包含按钮图标、滑动控件、仪表、数字显示、图形带状图记录器显示和其他符号,主动/被动和基于文本,可用于监测和控制当前过程。单击屏幕按钮可以打开和关闭 LED,系统的状态由 LED 是否亮起来直观地确定。作为 SCADA 软件与 HMI 和试验板电子设备接口的初始练习,演示了从显示屏或键盘控制简单电子电路供电的能力。

为了将在基于“视窗”的计算机操作系统上运行的面向视觉的数字软件连接到位于工作台上或嵌入在实验环境中的“插入式”快速原型“试验板”,需要数字电气连接。用于将外围设备连接到主计算机的 USB 电缆可以用作将主计算机连接到机器接口的电信号传输线。

机器接口连接可以是多种 USB 兼容的可编程硬件设备中的任何一种,能够接收数字代码的输入,解释或识别代码的意图,并产生所需的数字输出信号。

在图 1-1 中,显示了能够提供所需输入解释并产生适当输出信号的数据采集或 HMI 设备的选择。

项目 1 和 3 来自美国科罗拉多州莱克伍德的 LabJack 公司。该公司生产大约 12 种与 USB、以太网和 Wi-Fi 系统兼容的多功能数据采集(DAQ)设备。LabJacks 是坚固耐用的设备,旨在用于艰苦的工业和实验室应用,带有沉重的塑料保护壳和大型螺丝端子接线连接。所描述的两种设备是成本最低的 U3-HV(115 美元;参见 LabJack 文献,了解所有可用的附加功能和特性)和原始 LabJack 多功能 DAQ 设备(160 美元)。

第 2 项是 Digilent Inc .的 chipKIT Uno32(已退役)Arduino 兼容微控制器。图示设备已被 chipKIT uC32,3.3 伏 Arduino 兼容微控制器(42 CDN)所取代。第 4 项和第 5 项是 SparkFun Inc .的廉价量产 SMT Arduino 兼容微控制器(20-30 美元)。

所示的每个设备都能够接收单个数字开/关信号或编码指令,并产生所需的输出。

用于科研的 Arduino 教程(一)

图 1-1

一些人机界面设备

微控制器目前由十几家公司制造,具有各种各样的功能和各种各样的成本。

实验的

驻留在外部独立供电的原型板上的 LED 的原始控制屏幕按钮照明是在 2007 年使用 LabJack U12 创建和写入的,如图 1-1 第 3 项所示。许多年后,随着低成本微控制器板的出现,图 1-1 中的项目 2、4 和 5 可用于实现相同的接口功能。虽然这个练习描述了 U12 的使用,但是任何微控制器板都可以用来代替图 1-1 中的 LabJacks。第十一章给出了激活 Arduino 以点亮 LED 的 DAQFactory 控制屏幕按钮的详细配置。在“实验下载-向微处理器发送数据”部分,配置了三个按钮来打开和关闭 LED 的电源,并按照编程的顺序进行。

五金器具

图 1-2 显示了本练习中合适电子元件的典型选择,放置在原型“试验板上”

用于科研的 Arduino 教程(一)

图 1-2

原型试验板和各种组件

项目 1 是一个塑料电池盒,能够容纳八节 AA 型电池,以提供 12 伏的标称电压。(八个 1.5 伏的新鲜碱性电池将提供 12 伏,而八个 1.2 伏的镍金属氢化物(NiMH)可充电电池将提供初始的 9.6 伏 DC 电源。锂电池每个可以提供 3.6 伏的额定电压。)

标题 2 旁边的项目是发光二极管。左侧的红色 LED 是一个 3 毫米(1/8 英寸)的微型设备,接下来的四个彩色二极管是 6 毫米(1/4 英寸)的设备,而右侧的透明设备是一个 10 毫米(3/8 英寸)的白光 LED。

第 3 项是 CD4050 同相十六进制缓冲器(见下文)。项目 4 是一个典型的 1/8 瓦限流电阻,而项目 5 是一个 2 英寸(50 毫米)乘 6 1/4 英寸(163 毫米)的原型板。该板在顶面的顶部和底部有两条独立的电源轨,标有红色(+)和蓝色(–)线。每条轨道电力线可以容纳 50 个电源连接和 50 个接地连接。上下电源轨之间是两组独立的 63 列五个连接点。

电路原理图:DAQFactory 和 LabJack 组合

图 1-3 中的电路原理图用于前两个练习。第二章中使用了完整的四个 LED 电路,其中监控各种颜色 LED 的单独功耗。在第一个练习中,仅使用红色 LED 电路中的接线。

用于科研的 Arduino 教程(一)

图 1-3

用于 LED 功率控制的电路

CD4050 芯片中的单个开关是单向的,因为施加到输入端的电压变化会影响输出,但输出端的电压波动不会影响输入引脚。

软件

所需的页面组件:单个按钮

正如“练习路线图”中所讨论的,在进行任何科学训练时,都应该做详细的笔记。在本练习中,应选择用于控制 HMI 的通道名称,或在本例中为 LabJack,并配置软件,将通道输出信号传送至 LabJack 端子板上的第一个输入/输出端子(I/O 0)。(参见 LabJack U12 或 U3-HV 用户指南。)应遵循 DAQFactory 和 LabJack 用户指南中的详细信息,在本练习中,作者使用了一个名为 RedLed 的通道。任何 DAQFactory 项目中使用的通道都应该在放置屏幕组件之前通过 Apply 按钮进行配置和激活。通过在创建屏幕组件之前定义频道,频道名称将出现在弹出菜单中,如图 1-11 所示。(关于使用微控制器代替 LabJacks,参见第十一章“实验下载”。))

与所有编程一样,文档是必需的。不记录软件是一种很差的实践。在放置和配置按钮之前,应该在屏幕上放置一条描述性的文本消息,以记录该按钮的功能。通过选择静态选项,然后选择文本选项,从鼠标右键弹出菜单(人民币-PUM)创建文本组件。显示允许创建屏幕消息的窗口。

图 1-4 、 1-5 和 1-6 描述了静态文本屏幕组件的选择、组件属性子窗口的显示以及活动文本输入面板。

用于科研的 Arduino 教程(一)

图 1-5

简单按钮控件属性

用于科研的 Arduino 教程(一)

图 1-4

简单按钮控制

当消息轮廓框架就位并处于选定模式时,右键单击将显示包含属性选项的菜单。选择菜单中的属性条目将打开属性窗口,允许在文本组件中显示字母条目。

用于科研的 Arduino 教程(一)

图 1-6

文本框配置

在文本框中输入所需的文字并选择对齐、颜色、字体和大小后,可以使用确定按钮关闭主选项卡以放置文本消息。如图 1-7 所示的文本框可能需要扩展/调整大小以显示整个信息。

用于科研的 Arduino 教程(一)

图 1-7

按钮图标的大小

为了与持续文档的哲学保持一致,现在可能是用页面属性框命名页面的好时机,如图 1-8 所示。右键单击页面列表中的当前 page_n 指示符,并选择中间的选项:页面属性,即可显示该框。

用于科研的 Arduino 教程(一)

图 1-8

DAQFactory 页面命名框

按钮组件是从人民币-PUM 中选择的,按下 Ctrl 键,组件可以定位在适当的文本下面。

在屏幕上定位按钮组件后,可以通过完成“组件属性”对话框中的相应选项卡来配置它的实际用途。如图 1-9 所示,右键单击所选图标,调用属性对话框。为了将屏幕显示的按钮连接到实验环境中的一个动作,选择“Do Action”选项,如图 1-9 所示。

用于科研的 Arduino 教程(一)

图 1-9

按钮属性对话框

如图 1-10 所示,按钮组件属性窗口包含两个选项卡,Main 和 Action。

用于科研的 Arduino 教程(一)

图 1-10

“执行操作”按钮选择的主选项卡

默认情况下,主选项卡允许按钮用期望的字体和字符大小以及适当的字体颜色进行标记,这些字体在显示的图标中居中。如图 1-6 和 1-8 所示,在配置屏幕组件时,为了方便参考,在属性窗口下方显示了一个帮助屏幕。可以通过帮助框侧面的滚动控件查看帮助框的文本内容。

按钮组件盒如图 1-10 所示。

顾名思义,组件动作选项卡配置鼠标光标点击按钮图标时调用的动作。如图 1-11 所示,动作选项卡弹出一个动作或选项的下拉列表,从中可以进行所需的选择。可在窗口底部的组件帮助文件中找到下拉操作列表中各条目的详细信息

用于科研的 Arduino 教程(一)

图 1-11

“执行操作”选项中的“操作”弹出列表

对于试验板上 LED 的手动控制,选择下拉列表中的切换选项。选择切换选项需要完成几个对话框,这些对话框精确地指定了要做的事情,如图 1-12 所示。

用于科研的 Arduino 教程(一)

图 1-12

在动作自动填充列表之间切换

当选择了切换选项时,通常是一个通道在两个交变电压之间切换,例如 0 伏和 5 伏。如本软件配置部分开头所述,I/O 通道配置数据的完成和输入现在反映在图 1-12 的智能弹出选择列表中的红色 Led 条目中。双击红色 Led 频道条目将在框中输入频道名称。确保在框中输入的名称是正确的,并且没有无意中在所需名称中添加或删除额外的字符。

“操作”选项卡还有其他几个灰显的选项,可通过操作列表中的各种选项激活。在这种情况下,如图 1-13 所示,有用于输入“切换”值的框,这些框将作为轴出现在通道的图形显示上。

用于科研的 Arduino 教程(一)

图 1-13

DAQFactory 按钮操作屏幕已完成

本练习的目的是将按钮直接耦合到 LED 电源控制器,无需任何脚本。

观察、测试和开发

将数字电压表的正极引线连接到 I/O 0 端子,将黑色引线连接到实验室插孔的 GND 端子。设置仪表刻度,以便能够测量 5 伏电压。打开仪表,确保读数为零。然后点击 LED 开/关按钮,读数应该上升到 5 伏。

如果没有出现 5 伏读数,则首先检查所有部件和表格中的通道名称拼写。红色 Led 区分大小写,在屏幕组件和频道表中出现的所有实例中,必须与拼写完全一致。确保“切换”值在 0 和 5 伏之间。

当在 LabJack 端子处获得 5 伏信号时,可以准备从端子到 CD4050 IC 芯片的接线。将 CD4050 六角同相缓冲芯片沿中央分隔槽插入试验板的方便位置。通常放置芯片时,从顶部看芯片时,1 号引脚位于左下角位置。

将 1 号引脚连接到试验板上的+电源线路,将 8 号引脚连接到试验板上的负电源或–电源,并将 I/O 0 线连接到 3 号引脚。将 LabJack 上的 GND 端子连接到试验板上的–电源。将外部电源连接到试验板的+和-线,将电压表的正极引线连接到 IC 的引脚 2,负极引线连接到试验板的负电源线。单击 LED 开/关按钮,电表电压应升至标称+5 伏。

如果 5 伏信号没有出现在仪表上,首先验证电源,然后按照图 1-3 中红色 Led 示意图所示,重新检查每个有线连接。

当在 CD4050 缓冲器的引脚 2 处获得标称 5 伏信号,并且可以通过屏幕图标循环开/关时,就可以对通过控制屏幕按钮激活的红色 led 进行功率限制计算。使用欧姆定律计算将通过本项目选择的红色 LED 的电流限制在制造商建议的中间范围所需的电阻大小。从数据手册中可以看出,作者的构建所使用的明亮 LED 源的额定最大电流为 30 mA,标称压降为 1.8。欧姆定律的应用表明,213ω的电阻值会将二极管电流限制在规定的最大允许值的一半。任何 220ω或更高的标准电阻都可以保护 LED,实验设置中使用了标称值为 470ω的电阻。

根据电源的标称电压,计算将 LED 电流限制在二极管数据手册中规定的最大值所需的电阻的理论尺寸是一种很好的做法。利用数据手册中的最大电流和电源电压标称值,可以为使用中的 LED 产生一个足以保护二极管的电阻值。如果使用高于“足够”计算值的下一个标准值电阻,二极管将被很好地点亮,并具有额外的电流过载保护裕度,这将进一步延长器件的使用寿命,并有助于将电源负载降至最低。

在确定限流电阻器的正确尺寸,然后将电阻器、二极管和 CD4050 缓冲器组装到电源连接之后,红色 LED 的照明现在应该由控制屏幕上的按钮图标控制。(确保二极管的阴极或短引线接地。)

简单的 DAQFactory 图形用户界面如图 1-14 所示。

用于科研的 Arduino 教程(一)

图 1-14

用于 LED 照明控制的 DAQFactory 按钮

讨论

在本练习中,按钮是用 SCADA 软件创建的。然后,来自按钮状态的逻辑信号被传输到 LabJack 端子板,该端子板进而控制能够处理激活 LED 所需功率的 ic。LED 本身由外部电源供电,因此产生光所需的电流不会从 PC 电源获得。如果检查 CD4050 hex 缓冲器的电路,很明显电压信号正在控制双 CMOS 反相器配置(图 1-15 )。

用于科研的 Arduino 教程(一)

图 1-15

独立 CMOS 缓冲电路

从前面的原理图中可以看出,在集成电路电子学的几篇参考文献 1 中也有详细讨论,内部互补金属氧化物半导体绝缘栅器件实际上阻止了任何 DC 电流流入 CD4050。来自 HMI 的电压变化是控制信号,实际上不会给 USB 系统带来任何电流负载。

Raspberry Pi,Python,屏幕按钮 LED 控件

利用 Raspberry Pi (RPi)单板计算机(SBC ),可以通过多种方法实现屏幕显示的 LED 照明。电源控制可以通过 Pi 的 Linux 操作系统的命令行来实现,也可以通过鼠标点击系统屏幕显示上的按钮图像来实现,该按钮图像是通过名为 easyGUI 的 Python 编程语言库、名为 tkinter 的 Python 图形用户界面库或 RPi 与 led 之间的 Arduino 微控制器板接口来实现的。

所有的 LabJack DAQ 设备都与 Linux 操作系统和 Python 语言兼容。

在第一个练习中,将演示使用 Python 解释器的交互或脚本模式点亮二极管的命令行方法。除了命令行控制之外,easyGUI 库还将创建一个简单的双按钮 LED 控制 GUI。

当模拟信号的数字化需要 10 位模数转换器(ADC)时,使用 Arduino 微控制器接口实现 LED 控制将在第四章中介绍。

基本的 Raspberry Pi 计算机的组装和配置在诸如 Apress 书籍中的 Practical Raspberry Pi 以及 Raspberry Pi Foundation 的在线文档中的最新详细信息中进行了讨论。

通过将图 1-16 中定义的 SBC 引脚直接连接到图 1-17 中描述的试验板,RPi GPIO 的实验可以以最小的复杂度完成。带状电缆可用于将 RPi SBC 上的一排双引脚连接到原型板,如果使用,研究者应确保带状电缆上的白色或红色条带连接到主板上双排引脚的左上引脚(从上方看)。

用于科研的 Arduino 教程(一)

图 1-16

GPIO 引脚识别

实验的

在图 1-17 中,发光二极管(LED)上的长引线是阳极,连接到正电源。发光二极管是固态器件,只能单向传递电流。流经该器件的电流控制照明强度,但过大的电流会损坏二极管,因此在电路中使用限流电阻。

为了确保 Python 和 RPi 硬件引脚数组之间的通信,在 Raspbian 操作软件发行版中包含了一个名为 gpiozero 的库。要创建活动屏幕组件,可以下载一个非常简化的 GUI 创建库,名为 easyGUI,详见下文,并在这些介绍性练习中使用。

在 RPi 终端,输入“sudo apt-get install python 3-easy GUI”。为了获得 Python 3 版本的正确库,需要 3。

在图 1-17 中,描绘了 RPi SBC 早期 26 针模型的连接。

用于科研的 Arduino 教程(一)

图 1-17

GPIO 引脚直接连接到原型板

如图 1-17 所示,阳极通过原型板上的一列连接引脚连接到 GPIO 阵列中的+5 伏引脚。二极管的阴极与接地的限流电阻串联。电阻值由所用 LED 器件的最大电流规格决定。

RPi 的 Linux 操作系统有一个 Python 编程语言解释器,调查人员可以用它来激活 GPIO 总线上的一些引脚或将其通电至+5 伏。Python 命令可以在交互模式下处理,每次处理一行,以响应在终端输入的代码,或者作为脚本编写的一系列自动执行的 Python 命令。

在交互模式中,我们可以认为这是“手动”模式,因为我们每次处理一行从键盘输入的代码。交互模式对于用键盘设置和测试电路非常有用,在交互模式下,我们可以根据需要在 Python shell 中打开和关闭 LED。当实验者只使用外壳和键盘来打开和关闭 LED 时,不会有任何系统之前动作的记录。

当 RPi 与 Python 脚本一起使用时,可以将显式的 print 语句写入代码,以记录所采取的每个操作,从而提供系统状态的历史记录。

观察

用 Python 编写的 easyGUI 库为实验者提供了创建一系列包含典型基本 GUI 应用程序的屏幕所需的代码。图 1-18 是一个“点亮 LED”动作框,它是由 easyGUI 库中的取消/继续对话框示例修改而来。点按“继续”会点亮 LED,点按“取消”会将其关闭。作者已经修改了库代码,以记录图标使用的先前动作或历史。文本记录显示在运行对话框的 Python shell 中。

用于科研的 Arduino 教程(一)

图 1-18

用于 LED 控制的简单 GUI

LED 灯盒上的调整大小按钮可以工作,但停止程序按钮不行。双按钮对话框实际上是在 Python shell 中的一个窗口中运行,如图 1-19 所示,shell 停止程序按钮是有效的。

用于科研的 Arduino 教程(一)

图 1-19

Python Shell 的“Kill”对话框

在本章末尾的代码清单中,有手动和基于 GUI 的清单,可用于激活连接到 GPIO 引脚的 LED。

讨论

DAQFactory 是商用 SCADA 成品软件。购买这种“开箱即用”的“交钥匙”系统,研究者可以连接到受控系统,并从复杂指令集计算(CISC)设备上提供的可配置图标组装所需的 GUI。Raspberry Pi 是一种成本非常低的精简指令集计算(RISC)设备,它使用免费的开源软件,能够进行物理计算。

如前所述,RPi 是一种成本非常低的入门方法,用于控制作为教育项目或实际科学研究调查一部分的实验过程或测量实验。RPi 可以被编程以实现简单或非常复杂的实验设置的管理,但是随着被管理的实验的复杂性增加,需要研究者增加开发时间。

代码列表

用适当的限流电阻(CLR)组装 LED 后,将串联有线设备连接到 GPIO 引脚 2 和地,然后将清单 1-1 中的代码输入 Python shell 或交互终端。

from gpiozero import LED
grnLed = LED(2)
grnLed.on()
grnLed.off()

Listing 1-1Manual LED Control

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这一系列简单的代码将打开 gpiozero 库,并使 LED 对象可分配给 GPIO 引脚 2。grnLed.on()线将 GPIO 引脚 2 设置为高电平或真值,并点亮 Led。下一行 grnLed.off()将 GPIO 引脚 2 设置为低或假,并关闭 Led(清单 1-2 )。

# Exercise with easyGUI to turn a LED on and off
# an adaptation of the continue or cancel dual
# button message box.
#
from easygui import *
import time
from gpiozero import LED
#
redLed = LED(2)
#
# Use a while loop for continuous activation
while 1:
    msg = "Light the LED"
    title = "The Scientyst's Ayde"
    #
    if ccbox(msg, title):  # show a Turn On/Off dialog box
        print("LED is turned ON!")
        redLed.on()
        # LED power turned on

    else:  #user chose cancel
        print("The Led has been turned off!")
        redLed.off()
        # LED power turned off

Listing 1-2A Button GUI LED Control

用于科研的 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

摘要

  • 监视器上的基本按钮图标控制远离主机的电子设备。

  • 计算机实验接口可以在更昂贵的系统中通过配置来实现,或者在不太昂贵的基于组件的系统中根据基本原理来编程。

  • 在第二章中,将开发一个更具交互性的双向控制系统,带有多个按钮和一个实验数据显示。

Footnotes 1

1)CMOS 基础知识指南,电路,&实验,柏林,Howard W. Sams &有限公司,ISBN 0-672-21654-X

  1. CMOS 食谱第二版 Edn。SAMS 兰开斯特和柏林,ISBN 0 672-22459-3

二、电源控制、监控和专用图形用户界面的创建

SCADA 首字母缩略词中的“SC”代表监控,而“DA”代表数据采集。开发完整软件包(如 DAQFactory)的目的是监控真实世界的机电过程并监督或控制其运行。本章及其练习通过创建多个 LED 按钮,然后监控激活这些单独的 LED 所消耗的功率,对单按钮控制进行了扩展。因此,展示了响应于一个或多个单元操作激活的控制系统输入的过程操作值的读取。

led 的各种尺寸、构造方法、预期用途和颜色会导致其半导体结上的不同压降,详见“实验”部分。每个具有固定标称值的限流电阻(CLR)都有自己独特的电阻值,该电阻值在该类型器件的标准值容差范围内(即+/-10、5 或 1%)。当负载电阻变化与二极管压降和 CD4050 缓冲器的导通电阻结合起来考虑时,很明显,流经不同颜色 LED 电路的每个电流都是不同的。

表 2-1

典型 5 毫米 LED 参数

|

二极管颜色

|

典型电压降(V)

|

波长(纳米)

|

电流(毫安)

|
| — | — | — | — |
| 红色 | 1.63–2.03 | 610–760 | Thirty |
| 格林(姓氏);绿色的 | 1.9–4.0 | 500–570 | Twenty-five |
| 柑橘 | 2.03–2.10 | 590–610 | Thirty |
| 黄色 | 2.10–2.18 | 570–590 | Thirty |
| 蓝色 | 2.48–3.7 | 450–500 | Thirty |
| 白色的 | 2.48–3.7 | 450–500 | Thirty |
| 紫罗兰 | 2.76–4.0 | 400–450 | Thirty |
| 紫外线的 | 3.1–4.4 | < 400 | Thirty |

本练习将测量不同颜色的发光二极管点亮所产生的单个电流,并通过监控单个操作和整个系统的功耗来提供关于整体系统性能的信息。

许多电子参考文献和科学中的 Arduino 测量中介绍了几种方法,可用于使用电流表、静电计、感应或霍尔效应设备测量直流电流。然而,在手稿的介绍阶段,为了便于实施,电阻压降测量和欧姆定律计算将用于监控通过被测系统的电流。

实验的

发光二极管(LED)的电流、电压、电阻和发光度特性可以根据欧姆定律和基尔霍夫电压定律更好地理解。

如图 2-1 所示,led 以各种形式制造。

用于科研的 Arduino 教程(一)

图 2-1

各种形式的 LED

图 2-1 所示为一个 10 毫米绿色、一个 5 毫米蓝色和一个 3 毫米红色 LED 通孔装置。(led 有扁平、条形和表面贴装三种配置,如 Arduino 或 Raspberry Pi 电路板的任何照片中所示。为了便于使用第一章、图 1-1 中所示的原型板进行实验设置,最好使用双引线 led。)图 2-1 底部的星形圆盘是一个 3 瓦的照明二极管。顶部的三个指示器型器件可以由计算机或 USB 设备供电,但设计用于照明或照明服务的底部二极管通常消耗足够的电流,以保证用螺栓连接到散热器,因此在使用时通常需要一个特殊的高电流电源,远远超过计算设备的电流能力。

根据发光二极管产生的光的类型,它们通常被分类为指示器或照明器。指示器通常产生从各个角度可见的有色物体的漫射光,而照明器通常具有透明体,产生纵向或直接在装置前方最强的集中光束。LED 亮度以毫坎德拉(mcd)或辐射强度来衡量。一根普通的蜡烛发出大约 1 坎德拉的光。

表 2-2 和 2-3 是 LED 数据表上常见的电气和光学参数的典型列表。

表 2-3

典型 LED 光学参数

| ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](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_2_Figb_HTML.gif&pos_id=img-i6QwkMpv-1724461347833) |

表 2-2

典型 LED 电气参数

| ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](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_2_Figa_HTML.gif&pos_id=img-Xsh2rel1-1724461347833) |

查阅数据手册获取信息时,务必验证所检索的数据是否适合手边的正确封装尺寸。在选择 LED 电路中使用的电流时总是需要折衷,因为电流越高,光越亮,设备的使用寿命越短。数据手册中的列表给出了典型工作电流、短时最大电流和较长使用寿命的工作电流。

数据手册中也给出了二极管的光学特性,包括发射光的频率或波长、二极管压降以及给定二极管电流下的光输出亮度。

为了避免损坏实验应用中使用的二极管,限流电阻(CLR)与 LED 串联。电源的电压必须足够高,以打开 LED,电源电压和二极管电压之间的差值可以通过限流电阻下降,以调节指示器或照明电路中的电流。(基尔霍夫电压定律指出电路周围的总电压降为零,欧姆定律可以用来确定调节 LED 电路中的电流所需的电阻值。)

使用欧姆定律的理论计算和典型 5 mm LED 的数据表明,200ω电阻应足以限制我们电源标称电压的电流。作者的 6 V AA 电池电源和 30 mA 亮源二极管表明,6V/30mA = 200ω电阻足以保护二极管和 CD4050 缓冲器(见图 2-2 )。最接近的较大标准值电阻为 220ω,使用 5%容差元件,我们选择四个元件用于本练习。用数字伏特-欧姆表,我们测量四个电阻的单个值并记录数据。为方便简单起见,电阻以 LED 颜色命名。在作者的开发工作中,红色为 221ω,绿色为 219ω,黄色为 216ω,橙色为 216ω。确保识别单个电阻并记录其实际电阻值,因为计算单个负载电流时需要这些数值。

五金器具

四个各种颜色的明亮发光二极管和四个测量电阻 220ω的标准电阻器,对于预期的电流具有足够的额定瓦数,在练习的开发中使用。(标注的值基于作者的实验设置,使用标称 6 V 电源和 30 mA 二极管。)

在本练习中,CD4050 IC 缓冲芯片上可用的六个门电路中的四个用于将 led 与 USB 隔离,并从辅助电源获取电能。

一个扁平的矩形电池组,能够容纳四个串联的 AA 电池,为安装在原型板上的实验组件提供标称 6 伏电源。(有关使用电池作为辅助电源的更多详细信息,请参见“讨论”)。

图 2-2 显示了本练习的电路图。为了测量流经单个 LED-电阻器串联组合的电流,使用了 LabJack U12 的模拟输出和输入信号端子。

用于科研的 Arduino 教程(一)

图 2-2

四 LED 显示屏的电路

软件

总共需要八个通道。四个配置为输出,以控制 led 的电源开关,四个通道监控单个测量值负载电阻上的电压。

输出通道可以像上一练习中一样标记为红色、绿色等。输入通道标记为 RedLedCurrent、GreenLedCurrent 等。本项目练习的 DAQFactory 通道表如图 2-3 所示。

用于科研的 Arduino 教程(一)

图 2-3

DAQFactory 通道表

需要页面组件

如图 2-4 所示,四个按钮、五个变量值组件(VVC)和两个文本显示被放置在屏幕上,以形成所需控制屏幕用户界面的基本结构。

(DAQFactory 手册提供了有关创建屏幕组件、将它们定位在屏幕上以及创建文本标签和消息的详细信息,这些标签和消息用于识别不同的组件以及输入或显示的值。根据手册,一组独立的屏幕组件可以组合在一起,形成一个单一的单元,便于在屏幕上操作。单独的成组组件可以以独特的背景颜色显示,以向终端用户或操作过程控制器提供视觉上可理解的控制屏幕。将相关的组件组合在一起,并用单独的彩色背景将它们隔离,以吸引眼球,从而增加易用性,同时最大限度地减少操作人员出错的机会,这是一个好的设计。组背景的着色应在应用程序中实际使用之前留给控制屏幕的最终配置,因为背景颜色面板的创建会限制对组中各个组件的访问,从而在系统开发过程中造成不必要的复杂性。)

用于科研的 Arduino 教程(一)

图 2-4

所需 GUI 组件的初步组装

四个按钮中的每一个都根据被激活的 led 的颜色进行标记,并且相应的变量值元件被设置为显示电流的 mA。第五个变量值显示可设置为显示总电流,单位也是毫安。

图 2-5 显示了电源监控面板,图 2-6 显示了彩色按钮电源输入的典型表示。

用于科研的 Arduino 教程(一)

图 2-6

电源监控 GUI 的典型计算表达式

用于科研的 Arduino 教程(一)

图 2-5

GUI 的初步着色

变量值表达式使用以下计算:

(RedLedCurrent [0]/221)*1000

其中,RedLedCurrent [0]是红色二极管限流电阻上的最新电压读数,221 是红色二极管限流电阻的实际 DVM 测得电阻值(单位为欧姆),*1000 乘法器将电流从小数安培转换为整数毫安。

总分量显示中的表达式将所有四个单独的当前表达式计算相加。

观察、测试和开发

一个或多个发光二极管的激活应该指示流过单个二极管的电流和汲取的总电流。显示屏上的值应该每秒更新一次,因为这是频道表中定时条目的默认值。通过在面板上控制按钮的左侧添加 LED 符号,可以创建视觉效果更好的彩色 LED 控制面板。LED 符号可以设置为被激活的 LED 的相应颜色,整个组件组合在一起形成一个连贯的单元,如图 2-7 所示。面板组件用于为分组提供背景(参见 DAQFactory 手册),识别号显示在分组面板上,将面板与显示在主显示屏底部的一组注释/说明联系起来,下面的面板可能是其中的一个组件。

用于科研的 Arduino 教程(一)

图 2-7

电源监控图形用户界面

使用图 2-8 所示的 DAQFactory 线性规组件,可以实现不同的、或许更有效的功耗视觉显示。

用于科研的 Arduino 教程(一)

图 2-8

仪表添加选项

如果线性仪表组件设置为通过将四个单独的彩色 LED 电流相加来显示消耗的总电流,它可以放在按钮控制面板旁边,以更直观全面的格式显示电源消耗的总电流。

讨论

新 AA 碱性电池的额定电流通常为每单位 2890 毫安时。如果所有四个 led 都亮起,则每个 led 消耗约 30 mA,这表明在作者的设置中,6 伏四电池支架的有效使用寿命约为 100 小时。估计 100 小时的使用寿命实际上是理论上的,必须认识到,发光二极管的压降约为 2 伏,电阻的压降约为 2 伏,CD4050、其余的接线以及电池本身的内阻占用了作者的标称 6 伏电源的剩余部分。在估计的 100 小时寿命之前的某个时间点,电池组的电压输出将下降到二极管太暗而看不见或根本不发光的程度。文献表明,原电池碱性化学电池以某种程度上线性的方式放电,随着使用量的增加,电压和电流输送能力都损失了。镍金属氢化物(NiMH)等二次电池化学电池的开路电压(OCV)明显低于一次电池系统(1.2 对 1.5 V),AA 型号的额定容量略低于 2500 mAh。然而,二次电池 NiMH 化学电池倾向于具有低得多的电压损失率,并且不是在其整个放电过程中逐渐失效,而是将所输送的电压保持在相对恒定的值,然后随着其电力耗尽,在非常短的时间内快速且完全地放电。使用电池供电的研究人员应该了解不同电池系统的特性。(碱性 AA 电池的 6 伏电压由 4 个单元提供,但镍氢电池的标称 6 伏电压需要 5 个可充电单元。)

很明显,对于电池组,随着电源上的负载增加,电压下降,并且提供给单个电流消耗负载的电流将减少。无论使用碱性电池还是镍氢电池,当每个二极管导通时,输送到每个二极管的电流都会下降。当绿色、橙色和黄色二极管被激活时,电源监控面板将显示红色 LED 消耗的电流减少。在更关键的现场或实验室操作中,为了最大限度地减少负载增加时的功率下降,可能需要稳压电源、并联电池组或更大的电池形式,如 C 或 D 电池,以维持实验负载下的电流和电压水平。

由面板显示器监控的逐渐减小的电流是从电池组输送的功率的实时指示器,并且逐渐减小的电流可以用于粗略估计电源剩余的使用寿命。

一般来说,可以说新的一次电池或新充电的二次电池将表现出最小的内阻,该内阻随着电池放电逐渐上升到最大值。充电监控可以通过确定开路电压(OCV)和电池单元本身的内阻来完成。OCV 是在空载条件下测量的,但电池组内阻的确定是一个动态过程,需要同时记录消耗的电流和瞬时电路电压。通过图形记录 I 和 V 的同时变化率,可以确定电池的电阻 R。绘制电池的 OCV 和内阻可以用来确定电池组的剩余使用寿命。(参见 Arduino 科学高级技术中的供电实验。)

使用价格低得多的微控制器可以减少功耗问题,该微控制器可用于开发类似于全功能工业级 LabJack DAQ 的实验接口。然而,需要大量的时间和精力来将手头任务的一部分功能实现到内置于市场上可买到的 HMI 设备中的微控制器中。为了用微控制器实现电源控制 GUI 练习,将介绍涉及 DAQFactory 和微控制器程序配置的基本步骤。(详见第十一章。)

与上一次使用 LabJack 的实验一样,从 lab 5%容差电源中选择四个标称值为 220ω的电阻,并用 DVM 测量其实际电阻。为了简化和便于组装,已知值电阻直接安装在原型板上,没有 CD4050 缓冲器,如图 2-9 和图 2-12 所示。

用于科研的 Arduino 教程(一)

图 2-9

一组 led 的 Arduino 控制的 DAQFactory GUI 开发

为了使 DAQFactory 通过串行通信端口识别微控制器并与之通信,必须识别微控制器使用的 com 端口。通过在主机和微控制器之间连接 USB 电缆并启动微控制器集成开发环境(IDE)程序,可以在工具菜单的端口:条目中找到端口标识。识别端口后,通过加载并运行文件/examples/01 中的“Blink”程序来确认连接和板功能。IDE 的基础/闪烁菜单。微控制器的板载 LED 应以每秒一次“闪烁”的速度闪烁,从而确认通信链路。(板载 LED 是“RedBoard”徽标框旁边的发光绿点,如图 2-12 中描绘的红色电路板的左下角所示。)

DAQFactory 程序中的公共控制屏幕可以服务于 LJ DAQ 或微控制器实验接口。然而,图 2-3 中的通道配置使用的是已经为其编写了驱动软件的 LabJack U12 设备。必须在 DAQFactory 环境中创建一个新设备,以便将数据传输到微控制器上的低级通信端口。一个典型的低成本微控制器是“red board”Arduino 兼容设备,见第一章图 1-1 中的第 4 项,以及图 2-12 中的有线配置。DAQFactory com 设备是通过选择端口和协议创建的。(参见第章 11 、图 11-4 、 11-5 和 11-6 。)

在 DAQFactory 程序的通道创建表中出现可识别设备之前,必须先创建该设备。在 DAQFactory 页面上选择快速➤设备配置条目,将弹出设备配置窗口,其中包含可用设备列表和新的串行(RS232/485) /以太网(TCP/IP)设备条目。(参见图 11-4 ,章 11 。)要创建新的串行设备,请单击新的串行(RS232/485) /以太网(TCP/IP)设备条目以将其高亮显示,并单击窗口右上角的选择按钮以调出以太网/串行设备配置窗口。(参见图 11-5 ,章 11 。)在配置窗口中,输入新的设备名称。(数据工厂名称必须以字母开头,并且只能包含字母、数字或下划线。)正在使用的设备被命名为“ardyRb ”,作为 RedBoard 和 Arduino 的助记符。要创建新的串行端口,请单击“新建串行端口”按钮,弹出串行端口配置窗口。(参见图 11-6 ,章节 11 。)

端口的名称部分是通过查询 Arduino 的通信端口号来定义的,该端口号被发现是 com 端口 4,因此诸如 COM4 之类的名称将足以作为新的连接名称。DAQFactory 配置表中的串行端口号条目必须为 4,以与连接的微处理器的串行端口号相对应。(参见第章 11 ,图 11-6 。)串行端口配置窗口的其余默认设置最好按输入的那样接受,并且当单击窗口保存按钮时,复选框“COM4”应该出现在以太网/串行设备窗口的串行端口列表中。必须为正在创建的设备分配一个协议,因为数据流是由 DAQFactory 序列或脚本控制的,所以选择空协议。空或无协议允许使用序列中的低级通信功能。选择协议并选中“COM4”框,当单击以太网/串行设备窗口右上角的 OK 按钮时,可以保存“ardyRb”设备以供需要时使用。

为了开发具有更简单的微控制器接口设备的电源监控设施,同时坚持从简单系统开始并逐步发展到更复杂系统的基本概念,最初将从 DAQFactory 中的控制屏幕控制单个 Arduino 供电的 LED。然后,单个 LED 可以扩展为一组四个 LED。LED 按钮控制的最简单形式是在 DAQFactory 控制屏幕上创建两个按钮,如图 2-10 左上角所示。

用于科研的 Arduino 教程(一)

图 2-10

用于控制 Arduino LEDs 的 DAQFactory GUI

DAQFactory 通常运行在基于 PC 的计算平台上,而 ATmega328 芯片则托管 Arduino 操作系统。这些程序可以通过串行端口软件相互通信,但是一次只有一个程序可以使用串行端口。实际上,DAQFactory 显示中的“屏幕图标”的视觉激活启动了到串行端口的低级命令流。串行端口的另一端是 ATmega328 控制的 Arduino 微控制器,它基本上运行在 C 语言上,可以通过编程来处理串行端口上出现的低级命令。

在图 2-10 中,顶部的两个按钮是“红色 led 开启”和“红色 led 关闭”图标。这两个按钮按照第一章的说明在屏幕上配置,在点击“红色 led on”按钮时可能启动的动作列表中,如第一章的图 1-11 所示,选择“快速序列”。快速序列选择调出如图 2-11 所示的窗口。

用于科研的 Arduino 教程(一)

图 2-11

快速序列窗口

快速序列条目的独特之处在于,只有当它所绑定的按钮被激活时,它才被访问和执行。图 2-11 中的单行代码是将字符 1 写入串行端口的完整序列。

DAQFactory 串行端口通过硬件和软件连接到 USB,USB 也通过硬件和软件连接到 Arduino 的基于 C 的操作系统。这两种软件系统都具有处理低级通信的设施,这些通信是基于比特和字节格式的字符的串行发送和接收。

在图 2-10 和 2-11 的简单例子中,在激活“红色 led on”按钮时,十进制表示数值 1 的 ASCII(美国信息交换标准代码)值 49 被发送到串行监视器。

Arduino 程序被称为草图,用于接收串行端口上的“1”字符和打开数字引脚的代码在清单 2-1 中(本章末尾的“代码清单”部分提供了所有代码清单)。检查清单 2-1 会发现代码将在串行端口上接受一个 0,一个 ASCII 码 48,并关闭 LED。双按钮控制方案简单明了,使用一张草图来管理两种可能的 LED 功率水平。

在控制屏幕的第二行中有一个标记为“切换红色 led”的按钮,该按钮在第一次点击时打开 led,在第二次点击时关闭。清单 2-2 中的 Arduino 草图包含标志变量“oofR”形式的“切换动作”逻辑,记录 LED 的状态为开或关,从而使代码能够切换或改变设备的当前电源状态。

控制屏幕左下角的四个彩色按钮将电源控制功能扩展到四个按钮,Arduino 代码如清单 2-3 所示。

控制屏幕上的每个彩色按钮都与一个快速序列动作相关联,该动作将 R、G、O 或 Y 字符写入串行监视器。在连接的 Arduino 端,代码将到达串行端口的新字符与称为“case”结构的四个字符的集合进行比较。当找到匹配时,执行与所识别的“案例”相关联的代码。在清单 2-3 中,动作包括打开或关闭对应于 DAQFactory 控制屏幕按钮颜色的彩色 LED。

图 2-10 中的控制屏幕包含七个屏幕图标,称为变量值组件,可用于提供过程值的可视化数字显示或读数。

该练习旨在演示设备的远程激活,并测量活动设备消耗的电流形式的过程变量。清单 2-4 、 2-5 和 2-6 列出了可用于单向传递动作发起请求并传回结果效果的快速序列代码。清单 2-6 是一个较短的快速序列 DAQFactory 端方法,用于声明电流已经停止。

Arduino 微控制器配备了一个 6 通道、10 位模数转换器(ADC),能够将 0–5 伏信号转换为 0 到 1023 之间的数字值(2 10 或 1024)。当 5 伏特被分成 1024 个单位时,每个数字计数单位产生 4.8828 毫伏。如图 2-9 所示,四个二极管压降中的每一个都由 ADC 的模拟输入测量。电压降测量完成后,使用 Arduino 的“serial . println(iRed);”将计算出的二极管电流写入串行端口将回车换行(CR-LF) ASCII 字符附加到发送到串行端口的二极管电流值字符的格式。1310 用作描述或识别字符结尾的标记,向 DAQFactory 快速序列数据解析逻辑提供测得的二极管电流数值。

清单 2-9 和 2-10 是 DAQFactory 快速脚本,当图 2-10 左下角的四个面板中的一个或多个彩色按钮被激活时运行。每个按钮都有一个快速序列脚本,可清除串行输入缓冲区,并将代表按钮颜色的大写字母和相应的 LED 发送到 DAQFactory 入口或串行端口的内存位置。Arduino 微处理器 C 代码检查从 DAQFactory 控制屏幕发送的字符,并执行所需的操作,将返回数据参数发送到串行端口。清单 2-7 和 2-8 是支持 DAQFactory 动作请求的 Arduino 代码。快速序列在发送激活请求后开始延迟,然后开始处理出现在串行端口上的字符。

清单 2-9 仅处理活动 LED 消耗的电流,而清单 2-10 处理任何活动 LED 消耗的单个电流和所有活动 LED 消耗的总电流。

这些简单的系统展示了 SCADA 系统的巨大优势之一,即两个计算平台之间的串行通信不需要错误检查或错误处理能力。发送和接收的字符在软件中是固定的,只需要激活屏幕图标即可实现所需的活动和测量。控制屏幕的操作者需要最少的动作,因为不需要数据输入,只需要点击控制屏幕上的正确图标。在电噪声工业或实验环境中,这些简单的程序可能需要错误检查和错误处理能力。

双按钮开/关控制面板尽可能简单,操作员有两种选择来打开和关闭 LED。如图 2-12 所示,安装在原型板上的任何二极管的照明提醒操作者系统的状态,以及哪个按钮在改变系统的状态时处于活动状态。

用于科研的 Arduino 教程(一)

图 2-12

Arduino 控制的四 led 阵列

电流的测量已经自动化,并且在实际实验应用中进行额外的工作,可以验证该过程以确定电流测量的准确性和再现性。

Arduino 和 DAQFactory 程序都有丰富的功能来帮助开发串行通信。串行通信系统非常简单,广泛应用于工业制造和实验研发项目。本练习中使用的两个软件系统都有串行端口窗口,这些窗口允许可视化驻留在串行监视器接口上的数据,并允许研究人员从主机程序接收串行数据或向主机程序发送串行数据。

除了程序之间的串行端口通信之外,Arduino 串行端口还用于许多应用,并且可以从连接到微控制器的多种类型的传感器传输数据。各种可能的测量方法的详细信息可在科学杂志的 Arduino 测量中找到。

在图 2-13 中,DAQFactory 串行端口已经扩展到测试和监控串行端口上发生的动作。

用于科研的 Arduino 教程(一)

图 2-13

DAQFactory 串行端口监视器

为了查看运行中的 DAQFactory 串行端口监视器,主机必须运行与所用控制屏幕兼容的微控制器程序。当微控制器程序在最小化或后台配置中运行时,包含控制屏幕的 DAQFactory 程序可以在前台运行,如图 2-13 中标记的 1。从“快捷”菜单中选择“设备配置”,出现如图第十一章图 11-4 所示的设备配置窗口。从设备配置窗口的条目中,选择“ardyRb ”;点击窗口右上角的选择按钮,出现“以太网/串行设备”窗口,即图 2-13 中的面板 2。输入正确的名称和通信端口后,可激活“监视器”按钮,调出 COM4 的串行端口监视器,在图 2-13 中标为面板 3。

激活后,COM4 的串行端口监控器现在控制进出串行端口的数据流。在面板 1 的底层控制屏幕上仍然可见的两个按钮不再响应,并且只有通过将二极管颜色的正确的大写首字母发送到串行端口,才能激活 Arduino 阵列上的相应二极管。从面板 3 的活动记录中可以看出,记录为“Tx R”的 R 的传输之后是脚本 Rx 10.69131010.691310。Rx 是“接收到一个传输”的符号,10.69 是一个数字序列,附加了 ASCII 码 013(回车)和 010(换行符)。紧接在换行符号之后的是一个数字序列,它再次附加了一对打印指令。

如前所述,Arduino 代码已识别 R 并激活红色二极管,发回单个二极管电流和总电流,两个数值后跟 CR-LF 组合。如果一个大写的 O 被发送到端口,预期的动作发生;如果在大写字母 O 仍位于发送区间时使用 Enter 键,Arduino 代码将触发橙色二极管,如面板 3 所示。

如前所述,用非常便宜的微控制器板代替工业研究级接口是一种实践,可以利用显著增加的开发时间作为实践学习的优势。

使用 Raspberry Pi 进行电源监控和控制

对于不熟悉 Raspberry Pi (RPi)教育计算机及其通过通用输入和输出(GPIO)引脚阵列在物理计算中的使用的研究人员、实验人员或教育工作者,有几个文本可供参考。 2 当前信息和软件可从树莓派基金会在线获得,在尝试以下练习之前应先阅读这些信息和软件。

虽然 Raspberry Pi 单板计算机(SBC)最初是作为一种非常便宜的教学辅助工具,但它可以作为 SCADA 应用程序的物理计算平台使用,但有一些限制。RPi SBC 不具备模数转换功能,但有几种方法可以解决这一电压测量限制。实验传感器的电压可以通过外部 ADC 芯片或与 Arduino 微控制器板的 USB 连接来测量,并通过使用 Python 库和 RPi 来测量已知值电阻-电容串联的时间常数。为 gpiozero Python 库编写的文档指出,RPi 操作系统本身并不完全兼容物理计算的“实时”要求。注意,在诸如 led 之类的设备上使用 GPIO 引脚进行编程脉宽调制(PWM)的尝试可能遭受“抖动”,因为 Pi 操作系统可能涉及减损或干扰脉宽的定时处理的内部过程。

RPi 和 Arduino 微控制器之间的 USB 连接非常类似于前面的 DAQFactory-LabJack 练习中演示的易用性和组装。Arduino 板的成本与 RPi 相当,Arduino 集成开发环境(IDE)可从 Arduino 和 RPi 基金会下载,与 Linux 兼容。通过使用 Arduino 微控制器板作为 RPi 和实验仪器或装置之间的智能接口,可以实现显著的可重复和可预测的物理计算。然而,将 Arduino 微控制器作为 RPi 的智能 I/O 外设的实施涉及到大量的脚本来连接两个系统,这将在下一章的脚本练习中探讨。

在利用 RPi 测量电压并计算电流的各种选项中,最便宜的选项是使用独立的模数转换器(ADC ),如微芯片 MCP3008 集成电路(IC)。IC 芯片成本约为 5 美元(CDN ),是一款 10 位逐次逼近型寄存器(SAR)器件。LabJack、Arduino 和 MCP3008 中使用的 10 位分辨率将输入电压划分为 1024 个量化单位。IC 连接到 RPi GPIO 引脚,如图 2-14 所示,并使用 py-spidev Python 库实现的 Python 串行外设接口(SPI)协议。见拉斯伯里皮。org/documentation/hardware/raspberrypi/spi/README了解在 GPIO 引脚阵列上实现 SPI 协议的 RPi 设置说明。

用于科研的 Arduino 教程(一)

图 2-14

用于 led 电源监控的 RPi 电路

实验的

如前所述,RPi 的廉价电压测量能力可以用微芯片技术 MCP3008 来实现。该芯片是一个 16 引脚、塑料双列直插式封装(PDIP)、集成电路、10 位模数转换器。该 IC 有 8 个输入通道,可以用来对电路中相对于公共地的最多 8 个不同点的电压进行数字化处理,或者测量电路中 8 个点之间的最多 4 个差分电压降。(有关数字概念和 10 位或 12 位 ADC 的详细信息,请参见第章 4 、章 5 和章 6 ,10 bit = 2 10 或 1024,12 bit = 2 12 或 4096。)

图 2-14 是从 RPi GPIO 阵列到 MCP3008 的连接示意图,以及可用于测量流经彩色二极管的电流的四个通道的示意图。

为了简化图 2-14 的图形,GPIO 引脚和 MCP3008 引脚之间的连接线没有画出来。GPIO 阵列左上角引脚上 RPi 的 3.3 V 电源连接到 IC 上的引脚 16 和 14。其余的连接以相同的方式指定和连接。

清单 2-11 中列出了用于选通(激活)ADC 芯片进行转换,然后读取并显示 10 位电压值的 Python 代码。

与所有复杂的实验系统一样,研究人员从简单的组件开始,测试每个组件并验证其作为独立实体的单独性能。一个复杂的系统是通过一次增加一个部件来组装的,如果可能的话,每次增加一个部件都要对组件进行测试,直到完成一个完整的操作装置。

据报道,RPi 的早期型号设计为在 3.3 V 逻辑电平下提供 3 mA 的输出电流,因此可用的总功耗为 17 引脚× 3 mA = 51 mA。微小的 3 毫米指示灯 led 的最大电流限制为 20 毫安,应在 16–18 毫安范围内工作。5 毫米和 10 毫米 led 汲取 20-40 毫安范围内的电流,为了获得更长的使用寿命,应在低于其最大短期电流处理能力 15-20%的情况下工作。

LED 辐射与流经二极管的电流成正比。数据手册中的电流建议是针对以最大亮度或接近最大亮度工作的器件给出的,实验工作并不总是需要这种亮度。5–10mA 的 LED 电流通常为实验工作提供充足的亮度,可用于避免 GPIO 引脚上的 RPi 电源连接过载。

为了适应 RPi GPIO 引脚提供的有限电流,图 2-14 的电路可以用现成的 5 mm 发光二极管、合适的 clr 和单独的手动电源控制开关组装,所有这些在组装期间都设置在打开位置。电源监控练习的初始测试中使用的配置是一组打开的开关。

阵列中的四个 led 应单独测试,然后一起测试,以确认电源供电时它们的亮度。(有关手动激活 LED 的命令行终端方法,请参见第一章。)一旦所有 LED 二极管都成功点亮,然后关闭电源,二极管及其 CLR 的连接点连接到 ADC 的适当输入通道。ADC 正确连接到 LED 阵列后,就可以连接 MCP3008 和 RPi GPIO 引脚,并运行 Python 程序。系统的初始输出应该显示每个通道没有输出电流,总和也没有。系统的简单性需要手动操作模式来查看从 LED 照明系统的功率加载和分配得到的数据。由于每个 LED 都是手动打开和点亮的,因此应运行电源监控程序来计算和显示汲取的单个电流及其总和。

通过将流经 led 的电流保持在 12–16mA 范围内,RPi 应该可以轻松地完全点亮三个 led,并能够在短时间内点亮第四个二极管,同时电源监控程序会收集并显示更高的功耗数据。对于使用比 GPIO 引脚更多功率的实验,可以使用一个辅助电源和几个 CMOS 4050 缓冲芯片。

观察

本练习的目的之一是向使用 RPi GPIO 引脚为实验装置供电的研究人员传授一种绕过系统限制安全工作的方法。

图 2-15 描述了电源监控程序在 Python shell 中的典型输出。

用于科研的 Arduino 教程(一)

图 2-15

电源监控程序输出的 RPi 显示

检查图 2-14 的原理图部分可以发现,限流电阻器(CLR)的测量电阻上的电压降是由流过二极管-电阻器组合的电流引起的。MCP3008 通道用于直接测量接地电阻上的压降,从而间接测量整个电路中的恒定电流。

讨论

作为一台教育计算机,Raspberry Pi 不仅能够以信息处理模式运行,还能够作为一个物理计算平台。然而,当用于物理计算模式时,必须认识到紧凑、廉价系统的局限性。简而言之,RPi 操作系统是进程驱动的,如果处理器内核中正在运行更高优先级的进程,它可能不会立即响应 GPIO 引脚上的事件。图形处理是计算资源的一个非常大的消费者,因此当在物理计算模式中使用时,RPi 应该尽可能使用最实用或最小的屏幕显示。

Raspberry Pi Foundation 编写并提供了几个 Python 库,允许计算机与各种硬件设备接口,以扩展与外部设备和传感器的通信,如 MCP 系列模数转换器。

代码列表

print("RPi 4 Led Array Power Monitoring Program")
print() # a blank line for output screen spacing
print("ADC reading of LED voltage value is normalized from 0 to 1 by gpiozero library.")
print("The true value of the monitored voltage is the product of the normalized ADC value and the reference voltage.")
print()
# a single normalized value is printed each time the module is run

from gpiozero import MCP3008
# create an object representing the device and assign the input channels
ADC_vlu = MCP3008(0)   # the number in brackets is the channel on the device
ADC_vlu1 = MCP3008(1)
ADC_vlu2 = MCP3008(2)
ADC_vlu3 = MCP3008(3)
#
print("ADC Channel 1")
print('Normalized ADC value = %.3f'%ADC_vlu.value,' Volts') # the blue LED in the author' circuit
#
# convert object, value into a numerical parameter
ledVltg = float(ADC_vlu.value) * 3.3
print('LED CLR voltage value = %.3f'%ledVltg, ' Volts')
# calculate the LED current from Ohms law
blue = (float((ADC_vlu.value) *3.3) / 329) * 1000
print('Blue LED current = %.3f'%blue,' mA')
#
print()
#
print("ADC Channel 2")
print('Normalized ADC value = %.3f'%ADC_vlu1.value) # the yellow LED in the author's circuit
#
# convert object, value into a numerical parameter
led1Vltg = float(ADC_vlu1.value) * 3.3
print('LED1 CLR voltage value = %.3f'%led1Vltg)
# calculate the LED1 current from Ohms law
yellow = (float((ADC_vlu1.value) *3.3) / 220) * 1000

print('Yellow LED current = %.3f'%yellow,' mA')
#
print()
#
print("ADC Channel 3")
print('Normalized ADC value = %.3f'%ADC_vlu2.value) # the red LED in the author's circuit
#
# convert object, value into a numerical parameter
led2Vltg = float(ADC_vlu2.value) * 3.3
print('LED2 CLR voltage value = %.3f'%led2Vltg)
# calculate the LED2 current from Ohms law
red = (float((ADC_vlu2.value) *3.3) / 220) * 1000
print('Red LED current = %.3f'%red,' mA')
#
print()
#
print("ADC Channel 4")
print('Normalized ADC value = %.3f'%ADC_vlu3.value) # the green LED in the author's circuit
#
# convert object, value into a numerical parameter
led3Vltg = float(ADC_vlu3.value) * 3.3
print('LED3 CLR voltage value = %.3f'%led3Vltg)
# calculate the LED3 current from Ohms law
green = (float((ADC_vlu3.value) *3.3) / 219) * 1000
print('Green LED current = %.3f'%green,' mA')
#
print()
#
ttl_Currnt_drw = blue + yellow + red + green

print('Total current draw = %.3f'%ttl_Currnt_drw, ' mA')

Listing 2-11Python Code for the Raspberry Pi Monitoring the Power Draw of a Four-LED Array

用于科研的 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
device.ardyRb.Purge()           // clear the serial buffer
device.ardyRb.Write('R')        // send R to serial port for repeat activation
delay(0.1)                      // allow for code execution
global iRed                     // declare diode current as global variable
global iTotal                   // declare total current as global variable
private string datain1          // declare private variable for 1st data value
private string datain2          // declare private variable for 2nd data value
datain1 = device.ardyRb.ReadUntil(13)     // parse out 1st value
datain2 = device.ardyRb.ReadUntil(13)     // parse out 2nd value
iRed = strToDouble(datain1)          // convert characters to numerical values
iTotal = strToDouble(datain2)        // and assign to declared variables

Listing 2-10Toggle Red LED DAQFactory Quick Sequence with Diode Power Draw

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
device.ardyRb.Purge()      // clear serial buffer
device.ardyRb.Write('R')   // initiate repeat activation
delay(0.1)                 // allow code to execute
global ldCurrnt            // declare global variable in DAQFactory code
private string datain    // define local variable in DAQFactory code
datain = device.ardyRb.readUntil(13)  // parse out character codes for numeric value
ldCurrnt = strToDouble(datain)        // convert character codes to numeric value

Listing 2-9Toggle Red LED DAQFactory Quick Sequence

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
// Toggle leds on/off from DAQFctry button icons on COM4
// The DAQF QS sends an R, G, O or Y to the serial port on com // 4. On the
 arduino side the status of the appropriate led dp is // determined and
 toggled as required through a switch construct.
//
// power drawn calculations, each led has a CLR and the voltage // on the
 junction of the resistor and led is measured and used to // calculate diode
// current by A0 to A3 respectively. Current calcln only done // when diode activated.
//
const int RedLedPin = 3;            // red led is on dig pin 3
const int GreenLedPin = 4;          // green led on dp 4
const int OrangeLedPin = 5;         // orange led on dp 5
const int YellowLedPin = 6;         // yellow led on d pin 6
//
int oofR = 0;                       // on off flags initialized
int oofG = 0;
int oofO = 0;
int oofY = 0;                      // on off flags initialized
//
char incomingByte = ' ';           // define incoming character
//
float iRed = 0;                    // red led current in decimal float format

float iGreen = 0;
float iOrange = 0;
float iYellow = 0;
float itotal = 0;
//
void setup() {
 Serial.begin(9600);                  // start the serial port
 }
//
void loop()
{
  if (Serial.available())            // check for incoming data
  {
  char incomingByte = Serial.read();   // set char value for switch branching
// Serial.print(incomingByte);         // diagnostic
  switch(incomingByte)                 // branch to desired location/option
  {
  case 'R':                            // Red Led Activation
  if (oofR == 0 ) {
  pinMode(RedLedPin, OUTPUT);          // set pin I/O
  digitalWrite(RedLedPin, HIGH);       // turn led on
  oofR = 1;                            // set flag
  iRed = ((analogRead(A0)* 4.8828)/216);      // calc i when led on
  //Serial.print(analogRead(A0));             // diagnostics
  //Serial.print("iRed = ");                  // diagnostics
  Serial.println(iRed);                       // add CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;     // calculate total power consumption
  //Serial.print("itotal = ");                 // diagnostics

  Serial.println(itotal);                      // add CR-LF
  }
  else {                        // flag is set to 1 so led is on
    pinMode(RedLedPin, OUTPUT); // set pin mode to output
    digitalWrite(RedLedPin, LOW);        // turn led off
    oofR = 0;                            // re-set flag to off
    iRed = 0;                   // turn iRed contribution to itotal off
    Serial.println(iRed);       // send data to DAQFtry
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current draw
    //Serial.print("itotal = ");                // diagnostics
    Serial.println(itotal);   // send to serial port with CR-LF
    }
break;
//
case 'G':                              // Green Led Activation
  if (oofG == 0 ) {                    // check status flag
  pinMode(GreenLedPin, OUTPUT);        // set pin I/O
  digitalWrite(GreenLedPin, HIGH);     // turn led on
  oofG = 1;                            // reset status flag
  iGreen = ((analogRead(A1)*4.8828)/215);  // calc diodecurrent
  //Serial.print("iGreen = ");             // diagnostics
  Serial.println(iGreen);              // send data with CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;  // calculate total current draw
  //Serial.print("itotal = ");             // diagnostics
  Serial.println(itotal);                  // send with CR-LF
  }
  else {
    pinMode(GreenLedPin, OUTPUT);      // set pin I/O mode
    digitalWrite(GreenLedPin, LOW);    // turn green led off
    oofG = 0;                          // set green status flag
    iGreen = 0;                        // turn green contributionto total off
    Serial.println(iGreen);         // send green current value with CR-LF
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current draw
    //Serial.print("itotal = ");                 // diagnostic
    Serial.println(itotal);   // send total current with CR-LF
  }
break;
//
case 'O':                            // Orange Led Activation

  if (oofO == 0 ) {                  // check status flag
  pinMode(OrangeLedPin, OUTPUT);     // set pin I/O
  digitalWrite(OrangeLedPin, HIGH);  // set pin I/O
  oofO = 1;                        // set orange flag to led on
  iOrange = ((analogRead(A2)*4.8828)/215);  // calculate orange led current draw
  //Serial.print("iOrange = ");             // diagnostic
  Serial.println(iOrange);    // send to serial port with CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;  // calculate total current draw
  //Serial.print("itotal = ");               // diagnostic
  Serial.println(itotal);                    // send total to serial port with CR-LF
  }
  else {                                 // orange led is on
    pinMode(OrangeLedPin, OUTPUT);       // set pin I/O
    digitalWrite(OrangeLedPin, LOW);     // turn orange led off
    oofO = 0;                            // reset orange status flag to off
    iOrange = 0;                    // turn orange contribution to total off
    Serial.println(iOrange);        // send out orange current with CR-LF
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current draw
    //Serial.print("itotal = ");      // diagnostics
    Serial.println(itotal);  // send out total current draw with CR-LF
  }
break;
case 'Y':                             // Yellow Led Activation
  if (oofY == 0 ) {                   // led is off
  pinMode(YellowLedPin, OUTPUT);      // set pin I/O
  digitalWrite(YellowLedPin, HIGH);   // turn yellow led on
  oofY = 1;                           // re-set lag to led on
  iYellow = ((analogRead(A3)*4.8828)/217);        // calculate yellow led current
  //Serial.print("iYellow = ");       // diagnostic
  Serial.println(iYellow);            // yellow led value to serial port with CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;     // calculate total current draw
  //Serial.print("itotal = ");                    // diagnostic
  Serial.println(itotal);     // send to serial port with CR-LF
  }
  else {                            // yellow led on
    pinMode(YellowLedPin, OUTPUT);  // set pin I/O mode
    digitalWrite(YellowLedPin, LOW);   // turn yellow led off
    oofY = 0;                  // re-set flag to yellow led off
    iYellow = 0;               // set yellow led current to 0
    Serial.println(iYellow);  // send value to serial port with CR-LF
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current and send with CR-LF
    //Serial.print("itotal = ");                  // diagnostic

    Serial.println(itotal);    // send total current with CR-LF
  }
break;
  }
 }
}

Listing 2-8Arduino Sketch for a DAQFactory Four-Button Control Screen and Power Consumption Indicators

用于科研的 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
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
// Toggle an led on/off from one DAQFctry button icon on COM4
// The DAQF QS sends an R to the serial port on com 4. On the
// arduino side the status of the RedLed dp is determined and
// toggled as required.
//
const int RedLedPin = 3;            // red led is on dig pin 3
int oofR = 0;                       // power state of red diode
char incomingByte = ' ';            // declare incoming byte
float iRed = 0;                     // red led current
//
void setup() {
  Serial.begin(9600);              // start the serial port
  pinMode(RedLedPin, INPUT);       // must initially read the dig. pin
}
//
void loop() {
  if (Serial.available()) {          // check for incoming data
    char incomingByte = Serial.read();
    //Serial.print(incomingByte);    // diagnostic for code de-bugging
    if (incomingByte == 'R' && oofR == 0) {  // check action required and status
      pinMode(RedLedPin, OUTPUT);      // set pin I/O mode
      digitalWrite(RedLedPin, HIGH);   // turn diode current on
      iRed = ((analogRead(A0) * 4.8828)/216 );  // calculate diode current
      Serial.println(iRed);    // send value to serial port with LF-CR
      oofR = 1;                // set status flag to "diode on"
    }
    else {
      if (incomingByte == 'R' && oofR == 1){   // alternate action toggle to off

      pinMode(RedLedPin, OUTPUT);          // set pin I/O mode
      digitalWrite(RedLedPin, LOW);        // turn power off
      iRed = 0;                   // set red diode current to 0
      Serial.println(iRed);
      oofR = 0;
      }
    }
  }
}

Listing 2-7Arduino Code for Single Button Icon Toggling LED On/Off with Power Measurement

用于科研的 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
device.ardyRb.Purge()        // clear old data from the serial port buffer
device.ardyRb.Write('0')     // write a zero to the serial port to switch led off
delay(0.1)                   // allow code to be processed
global ldCurrnt              // declare individual diode current to be global
ldCurrnt = 0                 // set individual diode current to 0

Listing 2-6Quick Sequence Alternate Code for Off Button

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
device.ardyRb.Purge()     // clear residual data from input buffer
device.ardyRb.Write('1')     // write to serial port
delay(0.1)                   // delay to allow processing
global ldCurrnt              // declare variable to be visible throughout
                             // DAQFactory program
private string datain        // declare datain variable
datain = device.ardyRb.readUntil(13)    // parse data up to line feed and carriage return
ldCurrnt = strToDouble(datain)       // convert character to numeric value

Listing 2-5Quick Sequence Code for On Button

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
// Arduino code for a single led illumination on the red board // Arduino
 the pgm waits for an incoming character on com port 4 // if a 1 the led is turned on
// if a 0 it is turned off.
// A0 is wired to Rd led junction and the Arduino calculates // the led current and
 prints the value to the serial port.
//
const int RedPin = 3;  // red board dig. pin with red led and clr
int incomingByte;     // a variable to hold incoming byte
float iRed = 0;       // the led current through the CLR
//
void setup() {
  Serial.begin(9600);                  // start the serial port
  pinMode(RedPin, OUTPUT);             // set the pin function
}
void loop() {
  if(Serial.available()> 0) {     // check port for last data byte
  incomingByte = Serial.read();   // read serial port value
  if (incomingByte == '1') {      // if is 1, turn the led on
    digitalWrite(RedPin, HIGH);   // set I/O of pin
  // calculate led current and print to the serial port
  iRed = ((analogRead(A0) * 4.8828 )/216);
  Serial.println(iRed);    // note the line feed indication to append 01310
// to the transmitted character to aid in the DAQFactory parsing of the incoming code

.
  }
  //
  if (incomingByte == '0') {
    digitalWrite(RedPin, LOW);        // if 0, turn the led off
  // calculate led current and print to the serial port
  iRed = ((analogRead(A0) * 4.8828 )/216);  // ensures the LED is off
  Serial.println(iRed);   // 1310 for DAQFactory parsing code
  }
  }
}

Listing 2-4Arduino Sketch to Turn Red LED On or Off and Measure the Diode Current Draw for Display on the DAQFactory Control Screen

用于科研的 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
// Toggle leds on/off from DAQFctry button icons on COM4
// The DAQF QS sends an R, G, O or Y to the serial port on com 4. // On the
arduino side the status of the appropriate led // dp is determined and
toggled as required through a switch construct.
//
const int RedLedPin = 3;           // red led is on dig pin 3
const int GreenLedPin = 4;         // green led on dp 4
const int OrangeLedPin = 5;        // orange led on dp 5
const int YellowLedPin = 6;        // yellow led on d pin 6
//
int oofR = 0;                      // on off flags initialized
int oofG = 0;
int oofO = 0;
int oofY = 0;                      // on off flags initialized
//
char incomingByte = ' ';           // define incoming character
//
void setup() {
 Serial.begin(9600);               // start the serial port

 }
//
void loop()
{
  if (Serial.available())          // check for incoming data
  {
  char incomingByte = Serial.read();  // set char value for switch branching
  Serial.print(incomingByte);   // diagnostic for use in debugging code
  switch(incomingByte)       // branch to desired location/option
  {
  case 'R':                     // Red Led Activation
  if (oofR == 0 ) {             // check status flag
  pinMode(RedLedPin, OUTPUT);   // set pin I/O
  digitalWrite(RedLedPin, HIGH);            // turn led on
  oofR = 1;                                 // re-set flag
  }
  else {                       // flag is set to 1 so led is on
    pinMode(RedLedPin, OUTPUT);       // set pin mode to output
    digitalWrite(RedLedPin, LOW);     // turn led off
    oofR = 0;                         // re-set flag to off
  }
break;
//
case 'G':                             // Green Led Activation
  if (oofG == 0 ) {                   // check status flag
  pinMode(GreenLedPin, OUTPUT);       // set pin I/O
  digitalWrite(GreenLedPin, HIGH);    // turn led on
  oofG = 1;                           // reset status flag

  }
  else {
    pinMode(GreenLedPin, OUTPUT);
    digitalWrite(GreenLedPin, LOW);
    oofG = 0;
  }
break;
//
case 'O':                              // Orange Led Activation
  if (oofO == 0 ) {
  pinMode(OrangeLedPin, OUTPUT);       // set pin I/O
  digitalWrite(OrangeLedPin, HIGH);
  oofO = 1;
  }
  else {
    pinMode(OrangeLedPin, OUTPUT);
    digitalWrite(OrangeLedPin, LOW);
    oofO = 0;
  }
break;
case 'Y':                              // Yellow Led Activation
  if (oofY == 0 ) {
  pinMode(YellowLedPin, OUTPUT);       // set pin I/O
  digitalWrite(YellowLedPin, HIGH);
  oofY = 1;
  }
  else {

    pinMode(YellowLedPin, OUTPUT);
    digitalWrite(YellowLedPin, LOW);
    oofY = 0;
  }
break;
 }
  }
  }

Listing 2-3Arduino Sketch to Toggle Multiple Colored LEDs from a DAQFactory Control Screen

用于科研的 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
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
// Toggle an led on/off from one DAQFctry button icon on COM4
// The DAQF QS sends an R to the serial port on com 4. On the
// arduino side the status of the RedLed dp is determined and
// toggled as required.
//
const int RedLedPin = 3;      // red led is on dig pin 3
int oofR = 0;                 // power state of red diode
char incomingByte = ' ';      // declare incoming byte
//
void setup() {
  Serial.begin(9600);         // start the serial port
  pinMode(RedLedPin, INPUT);    // must initially read the dig. pin
}
//
void loop() {
  if (Serial.available()) {          // check for incoming data
    char incomingByte = Serial.read();       // read the port
    //Serial.print(incomingByte);            // diagnostic
    if (incomingByte == 'R' && oofR == 0) {  // check flag for led status
      pinMode(RedLedPin, OUTPUT);         // set pin for output
      digitalWrite(RedLedPin, HIGH);      // if off turn on
      oofR = 1;                           // set status flag

    }
    else {
      if (incomingByte == 'R' && oofR == 1){ // check flag for led status
      pinMode(RedLedPin, OUTPUT);            // set pin mode
      digitalWrite(RedLedPin, LOW);          // turn led off
      oofR = 0;                              // set status flag
      }
    }
  }
}

Listing 2-2Arduino Sketch for Toggling the Red LED on the Arduino RedBoard from the DAQFactory Single-Button Control Screen

用于科研的 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
// Arduino code for a single led illumination on the red board // Arduino
 the pgm waits for an incoming character on com port 4, // if a 1 the led is turned on
if a 0 it is turned off.
const int RedPin = 3;    // red board dig. pin with red led and clr
int incomingByte;      // a variable to hold incoming byte
//
void setup() {
  Serial.begin(9600);            // start the serial port
  pinMode(RedPin, OUTPUT);       // set the pin function
}
void loop() {
  if(Serial.available()> 0) {      // check port for last data byte

  incomingByte = Serial.read();  //
  if (incomingByte == '1') {     // if is H (ASCII 72), turn the led on
    digitalWrite(RedPin, HIGH);
  }
  if (incomingByte == '0') {
    digitalWrite(RedPin, LOW);   //if L (ASCII, 76), turn the led off
  }
  }
}

Listing 2-1Arduino Code for a Two-Button On and Off Control Screen

用于科研的 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

摘要

  • 开发了能够在外部实验中激活多个组件并显示来自该实验的数据的交互式控制面板 GUI。

  • 微控制器可以与强大的工业预配置 SCADA 系统一起使用,或者与容易获得的廉价元件和适当的编程一起使用。

  • 在第三章,将会介绍更详细的脚本和编程技术。

Footnotes 1

  1. 建筑科学仪器第四版。,Moore,Davis 和 Coplan,剑桥大学出版社,ISBN 978-0-521-87858-6 精装本

  2. 电子艺术第二版 Edn。,Horowitz 和 Hill,剑桥大学出版社,ISBN 13 978-0-521-37095-0 精装本

  3. 发明家实用电子学第三版 Edn。,谐谑曲与蒙克,麦格劳希尔,ISBN 978-0-07-177133-7

2

  1. 树莓派用户指南,厄普顿和哈尔法克里,约翰威利父子公司,ISBN 978-1-11846446-5

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

  3. 用 Linux 学习 Raspberry Pi,Membrey and Hows,Apress,ISBN 978-1-4302-4821-7

三、脚本简介

SCADA 是一个工业概念,其中收集关于活动过程的信息,然后用于监视和控制该操作。在工业规模的应用和这些科学测量实验中,脚本允许过程控制或数据采集的自动化。在本章中,在 DAQFactory (DF)软件中汇编成称为序列的小程序的代码将用于控制和监控在前面练习中装配在试验板上的 led 电路。

DF 用户手册指出,用于创建序列的脚本语言语法类似于大多数标准语言,如 C、Python、Visual Basic、Pascal 和其他语言(如 Fortran)的变体。

前面关于通道命名的符号也适用于 DF 中使用的脚本语言。该语言区分大小写,因此在命名通道、变量、脚本和页面时避免键入错误和拼写不匹配非常重要。建议使用 C 风格的命名或变体,如这些 MySpecialName、My_Special_Name、My_Spcl_Nm 和 MySpclNm 示例中所示。选择有表现力和有意义的名字以减少错误。

强烈建议使用注释和代码段缩进形式的文档,以使脚本代码清晰易懂。当 Tab 键被按下时,用于创建序列的 DAQFactory 代码编辑器缩进,一条垂直虚线描述代码块。其他研究人员必须能够遵循代码脚本和复制任何科学工作。

可用于脚本序列的数学运算在 DAQFactory 软件手册的“表达式”一节中有所描述表达式是从一些初始值计算结果的公式。在之前的练习中,变量值屏幕组件中使用了表达式来计算单个彩色 LED 电流和汲取的总电流。

与大多数语言一样,变量或数组在序列脚本中使用之前,必须用声明语句声明,有适当的名称,并创建实例。

对于大多数研究人员来说,创建和运行编程或脚本代码所需的技能最好通过实践来培养。几乎所有当今广泛使用的流行编程语言都可以通过大量的在线教程来学习。教程和语言文档可以以研究者感到舒适的速度复习和练习。DAQFactory 手册有一个介绍性的教程和一个详细的文档,当研究人员开发 DAQFactory 序列代码的脚本时,应该将它们放在手边作为参考。

实验的

一旦机电系统配置完成,硬件在试验板上得到验证,请不要犹豫,在全新的 DAQFactory 页面上尝试脚本代码。科学本质上是实验性的,这篇手稿有望帮助掌握物理计算的基础知识,并尽快应用它们进行实验测量。

五金器具

使用之前练习中的多色 LED 电路作为过程操作,其控制将从直接手动屏幕控制转移到编码脚本或序列。

电路原理图见第章 2 ,图 2-2 。

软件

需要页面组件

对于所需的基本屏幕配置,文本消息应该放在按钮控件上。文本内容应该表明该按钮控制一个脚本的开始和停止,该脚本在四个彩色 led 上产生一个简短的“灯光秀”。

在前面使用频道的练习中,频道必须已经创建并输入到频道表中,才能出现在弹出的键入帮助列表中。对于必须命名并输入到序列汇总表中的脚本序列也是如此。一旦命名并输入汇总表,在按钮配置期间可从列表中选择合适的序列,如图 3-1 和 3-2 所示。

用于科研的 Arduino 教程(一)

图 3-2

命名序列条目列表

用于科研的 Arduino 教程(一)

图 3-1

按钮操作标签条目

脚本

DAQFactory 有一个脚本输入和编辑程序,用于汇编代码,如图 3-3 所示。

用于科研的 Arduino 教程(一)

图 3-3

LED 灯光秀脚本

灯光表演的脚本使用一组编码语句,将各个彩色 led 的通道输出电压值切换到 5 伏,然后将其重置为 0 伏。通过在光激活线之间嵌入延迟语句,并在迭代“for 循环”中封装代码块,可以创建“光表演”。图 3-3 代码中的文档有望一目了然。作者的二极管从左起依次为红色、绿色、橙色和黄色。因此,2 和 4 的偶数二极管是绿色和黄色,而奇数二极管是红色和橙色。

开始显示按钮可以与描述性文本组件组合在一起,形成一个面板,如图 3-4 所示。

用于科研的 Arduino 教程(一)

图 3-4

脚本激活按钮

观察

当鼠标点击启动显示按钮时,四个 LED 灯组上出现灯光显示。

当灯光秀序列在一台 CPU 运行频率为 1.48 GHz、内存为 736 MB 且配有高分辨率显卡的旧台式机上运行时,在之前的练习中创建的电源监控面板只能跟上半秒延迟的灯光秀计时,而图形显示则不能。

讨论

本练习演示了 SCADA 软件通过软件编程和 HMI 设备控制电子电路激活的能力。

用户手册中的详细信息描述了描述性文本屏幕组件与其他几个组件的使用,这些组件具有选项卡式属性窗口,允许设置某些属性和选择操作。描述性文本组件能够显示运行/停止消息,指示附加到屏幕组件的选定序列的状态。

脚本化的代码序列实际上以计算机的时钟速度运行,因此比屏幕显示快速变化的能力、HMI 的速度或人类视觉能够跟随的速度快得多。

图形电源监视器显示无法跟上 LED 电流的脚本顺序切换,这表明了系统的局限性。DAQFactory 程序是一个视频显示密集型软件,如果没有足够的时间来绘制屏幕,显示就会滞后甚至不更新。在极少数情况下,就像旧的台式电脑一样,降低屏幕分辨率可以让反应迟钝的屏幕正常工作。

高速数据传输是光谱学、反应动力学和物理学中经常需要的专业领域。目前的工作重点是开发使用以秒或更长时间计量的时间尺度的方法。在适当的硬件或软件用户手册以及本文后面的章节中,将讨论更高速度的“数据流”以获得更快的捕获速率。

DAQFactory 序列:Arduino LED 阵列

在第二章中,一个廉价的微控制器板被用来代替一个稳定的工业级接口,以响应 SCADA 系统中设置的控制屏幕。如果实验者能够花时间重新编写串行通信代码,以监控安装 Arduino 的 LED 阵列的功耗,从而适应脚本化的灯光表演,那么使用 Arduino 的低成本优势就可以在这个脚本练习中实现。

实验的

Arduino 微控制器配有四个不同颜色的二极管,如第二章、图 2-9 所示。Arduino 保存清单 3-1 的 C 程序,提供所需的 LED 照明,而以下程序清单 3-2 中的常规或快速序列 DAQFactory 代码将适当的字符写入串行端口(本章末尾的“代码清单”部分提供了所有代码清单)。

DAQFactory 控制面板的设置如图 3-5 所示。

用于科研的 Arduino 教程(一)

图 3-5

双按钮脚本激活屏幕

虽然快速序列码和常规序列码相同,但快速序列码仅通过快速序列选择可见。常规序列可以在 DAQFactory 的任何地方使用,并且可以在所有序列选择列表中看到。

讨论

图 3-3 中描述的 DAQFactory 代码列表利用通道在 5v 和地之间改变 LabJack 输出连接。发送到串行端口的大写或小写序列码由 Arduino 逻辑收集,并直接为连接到相应 LED 的数字引脚供电,而无需使用复杂的通道。

树莓派

RPi 使用 Python 以及 gpio 和 gpiozero Python 库与 GPIO 阵列的各个引脚进行通信,并直接控制这些引脚。RPi 只能在输出模式下将引脚设置为高电压或低电压,或者在输入模式下读取引脚状态为高电压或低电压。

通过仔细的设计和精心的编程,可以组装一个“灯光秀”,直接从 GPIO 引脚运行,而不需要任何中间硬件。如第章第一部分图 1-16 中所述,GPIO 阵列有两个版本:早期型号有 26 个引脚,而新型号有 40 个。第一个 26 针阵列为所有型号所共有,而较新版本的 RPi 有额外的 14 针,如图 1-16 所示。总之,40 针阵列由 26 个 GPIO 针、2 个 3.3 伏和 2 个 5 伏电源针、8 个接地针和 2 个串行输入输出针组成,其分配和位置详见表 3-1 。

表 3-1

RPi GPIO 引脚阵列的分配和定位

| ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](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_3_Figa_HTML.jpg&pos_id=img-XyfRs4Wl-1724461347836) |

清单 3-3 中是一个用 Python 代码编写的简单的四 LED“灯光秀”程序。

在第二章中,RPi 能够短时间为四个 led 供电,而 Python 程序读取 ADC 电压并计算 GPIO 阵列的总功耗。在本练习中,脚本创建照明的定时序列,以产生简单的“灯光秀”如果原型板上增加更多光源,以增加显示器的视觉吸引力,引脚输出应进行缓冲,以避免 RPi 的电流供应能力过载。

第一章中使用的 CD4050 六路同相集成电路等高输入阻抗缓冲芯片可以用来缓冲 GPIO 引脚,以处理许多小电流负载,而 ULN2803 达林顿晶体管阵列等芯片可以处理 8 个缓冲 GPIO 引脚中每个引脚的最高 500 mA 电流。(CMOS 4050 高阻缓冲芯片 0.50 CDN,ULN2803 芯片 2.50 CDN。)

表 3-1 显示了 SBC 上 0.1 英寸(2.45 毫米)间距阵列中的 GPIO 引脚名称及其位置。(从 RPi 板的顶部看,阵列在右侧,1 号引脚在顶部,而左右两列的 20 号引脚在底部,与 USB 连接器相邻。)

借助足够强大的辅助电源和 RPi 引脚的 CMOS 或达林顿对缓冲,脚本应该能够控制多达 26 个 led。

代码列表

列表 3-1 到 3-3 提供了本章的完整程序。

# Led "Light Show" Ex. 3 Scripting on Raspberry Pi
# Pins are numbered sequentially from the top down in the right
# and left columns for ease of assignment and counting when
# wiring jumpers
from gpiozero import LED
from time import sleep
# Define and assign the leds
redLed = LED(2) # left column pin 2
grnLed = LED(3) # left column pin 3
orngLed = LED(4) # left column pin 4
yelLed = LED(5) # left column pin 15
# repeat code for flashing 4 times
for i in range(4):
    redLed.on()
    grnLed.on()
    orngLed.on()
    yelLed.on()
    sleep(1)
    redLed.off()
    grnLed.off()
    orngLed.off()
    yelLed.off()
    sleep(1)
# reoeat code for streaming to left 4 times
for i in range(4):
    redLed.on()
    sleep(0.1)
    redLed.off()
    grnLed.on()
    sleep(0.1)
    grnLed.off()
    orngLed.on()
    sleep(0.1)
    orngLed.off()
    yelLed.on()
    sleep(0.1)
    yelLed.off()
# repeat code for streaming to the right 4 times

for i in range(4):
    yelLed.on()
    sleep(0.1)
    yelLed.off()
    orngLed.on()
    sleep(0.1)
    orngLed.off()
    grnLed.on()
    sleep(0.1)
    grnLed.off()
    redLed.on()
    sleep(0.1)
    redLed.off()
# repeat code for alternate pair flashing 4 times
for i in range(4):
    redLed.on()
    orngLed.on()
    sleep(1)
    redLed.off()
    orngLed.off()
    grnLed.on()
    yelLed.on()
    sleep(1)
    grnLed.off()

    yelLed.off()

Listing 3-3Raspberry Pi Scripted “Light Show”

用于科研的 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
// Scripted Control of 4 Leds on an Arduino MC for a Simple
// Light Show DAQFactory script uses serial port transmission
// to control MC. Buttons on a DAQFactory control screen
// activate a quick sequence or regular sequence scripting, to
// transmit the led activation codes to the serial port where
// the Arduino resident C code parses the commands and
// activates the appropriate diode.
// Main loop iterates four times. May 21, 2019
//
for (Private.Counter = 0, Counter < 4, Counter ++)
   // even diodes lit
   device.ardyRb.Write('G')             // light the green led
   device.ardyRb.Write('Y')             // light the yellow led
   delay(0.5)               // leave the lights on for 1/2 sec.
   device.ardyRb.Write('g')      // green led off
   device.ardyRb.Write('y')      // yellow led off
   delay(0.5)                    // keep lights off for 1/2 sec
   // odd numbered diodes lit
   device.ardyRb.Write('R')                 // red on
   device.ardyRb.Write('O')                 // orange on
   delay(0.5)                               // time delay
   device.ardyRb.Write('r')                 // red off
   device.ardyRb.Write('o')                 // orange off
   delay(0.5)                               // time delay
endfor
// run lights to right
for (Private.Counter = 0, Counter < 4, Counter ++)
   device.ardyRb.Write('R')                 // red on

   delay(0.1)                               // on for 1/10 sec
   device.ardyRb.Write('r')                 // red off
   device.ardyRb.Write('G')                 // green on
   delay(0.1)                               // on for 1/10 sec
   device.ardyRb.Write('g')                 // green off
   device.ardyRb.Write('O')                 // orange on
   delay(0.1)                               // on for 1/10 sec
   device.ardyRb.Write('o')                 // orange off
   device.ardyRb.Write('Y')                 // yellow on
   delay(0.1)                               // on for 1/10 sec
   device.ardyRb.Write('y')                 // yellow off
endfor
//
delay (0.5)
// run lights to left
for (Private.Counter = 0, Counter < 4,Counter ++)
   device.ardyRb.Write('Y')                  // yellow on
   delay(0.1)                                // on for 1/10 sec
   device.ardyRb.Write('y')                  // yellow off
   device.ardyRb.Write('O')                  // orange on
   delay(0.1)                                // on for 1/10 sec
   device.ardyRb.Write('o')                  // orange off
   device.ardyRb.Write('G')                  // green on
   delay(0.1)                                // on for 1/10 sec
   device.ardyRb.Write('g')                  // green off

   device.ardyRb.Write('R')                  // red on
   delay(0.1)                                // on for 1/10 sec
   device.ardyRb.Write('r')                  // red off
   endfor

Listing 3-2DAQFactory Regular Sequence Code for Light Show

用于科研的 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
// Arduino code for multiple led illumination on the red board
// Arduino the prgrm waits for an incoming character on com
// port 4 and then processes the data to identify which led is
// to be turned on or off. R, G, O and Y turn the diode ON and
// r, g, o, and y turn the diode OFF.
//
int RedPin = 3;                 // red board dig. pin with red led and clr
const int GreenPin = 4;         // red board dig. pin with green led and clr
const int OrangePin = 5;        // red board dig. pin with red led and clr
const int YellowPin = 6;        // red board dig. pin with yellow led and clr
char incomingByte = ' ';        // variable to hold incoming byte
//
void setup() {
  Serial.begin(9600);                  // start the serial port
  pinMode(RedPin, OUTPUT);             // set the pin function
  pinMode(GreenPin, OUTPUT);
  pinMode(OrangePin, OUTPUT);
  pinMode(YellowPin, OUTPUT);
}
void loop() {
  //
  while (Serial.available() == 0)       // wait for a character
  {

                               // do nothing until data arrives
  }
  if (Serial.available() > 0)             // a char has arrived
  {
    char incomingByte = Serial.read();   // set character comparison variable to new char
  //Serial.print(incomingByte);              //diagnostic
  if (incomingByte == 'R' ) {        // R sets the red led power to high
    // Serial.print("logic OK");     // logic diagnostic
    digitalWrite(RedPin, HIGH);      // turn red led on
    }
  if (incomingByte == 'r' ) {        // turn red led off
    //Serial.print(incomingByte);    // diagnostic
    digitalWrite(RedPin, LOW);       // r sets the red led power to low
  }
  if (incomingByte == 'G') {         // G sets the green led power to high
    digitalWrite(GreenPin, HIGH);
  }
  if (incomingByte == 'g') {
    digitalWrite(GreenPin, LOW);   // g sets the green led power to low
  }
  if (incomingByte == 'O') {        // O sets the orange led power to high
    digitalWrite(OrangePin, HIGH);
  }
  if (incomingByte == 'o') {
    digitalWrite(OrangePin, LOW);    // o sets the orange led power to low

  }
  if (incomingByte == 'Y') {          // Y sets the yellow led power to high
    digitalWrite(YellowPin, HIGH);
  }
  if (incomingByte == 'y') {
    digitalWrite(YellowPin, LOW);     // y sets the yellow led power to low
  }
 }
}

Listing 3-1Arduino LED Illumination 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
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

摘要

  • 商业 SCADA 软件有一个脚本工具来增强内置的控制功能,并实现与远程过程或实验装置的通信。

  • 由廉价易得的组件组装的 SCADA 系统需要使用计算平台的编程语言进行更详细的程序开发。

  • 当主机屏幕用于输入和显示数据时,将在第四章中进一步开发脚本或编程技术。

四、从屏幕输入数据

控制系统必须包括从屏幕输入数据的能力,以便能够修改或改变序列或过程的操作。在本章中,从键盘输入的数值用于修改程序代码的脚本序列,该程序代码使 led 在预定的周期数内开关。此外,为功率控制模式创建了两个选项,其中二极管的照明从全开到全关循环,并且二极管输出强度从关到全亮度递增,以创建“渐变”或“渐隐”效果。LED 亮度由流经器件的电流决定。通过 LED 的最大电流由与二极管、电源和地串联的限流电阻(CLR)设置。通过 LED 的电流可以通过改变电源电压来调节。然而,通过电压变化控制二极管强度只能在器件导通所需的电压水平以上有效,通常为 1.8-3 伏。

在本章中,通过输入数据值的屏幕确认,创建了一个 DAQFactory 序列码,该序列码以固定数量的电压增量增加施加到二极管上的功率。本练习还展示了软件在通常称为“线程化”应用程序中同时运行两个序列的能力。

然后,各种控制和监测选项被组合在一个简单的图形用户界面(GUI)数据输入、过程控制面板中。

使用一种称为脉宽调制(PWM)的技术可以更有效地控制二极管强度。在 PWM 控制操作中,全功率被施加到被驱动的负载,作为一系列方波电压脉冲,其时间宽度以受控方式改变或者相对于增加或减少的时间周期被调制。方波电源的频率和功率应用的脉冲宽度都可以数字控制或从屏幕输入值调制。(有关 PWM 的应用和实施的更多详细信息,请参见第七章。)

已经开发了使用便宜得多的微控制器的替代屏幕数据输入练习。微控制器练习与之前的练习一样,对实现该练习所需的更复杂代码的解释很少。微控制器使用的细节将在手稿的后面介绍,在这一点上,这些相对便宜的设备的一些优点和缺点可以得到充分的理解。

五金器具

如第一章图 1-3 所示,为先前练习接线的红色 LED 电子电路将用于本次练习的一部分;绿色 LED 连接到 LabJack 端子板上的第一个模拟输出通道(A0)。根据图 4-1 中的示意图,AO 0 信号连接到 2N3904 晶体管的基极。

用于科研的 Arduino 教程(一)

图 4-1

带数据输入设备的 DAQFactory 控制屏的原型电路

晶体管的集电极和发射极相连,因此基极电压通过限流电阻控制从+5 V 电源流向红色 LED 的电流大小。回想一下,晶体管是电流控制器件。进入晶体管的基极电流的大小由施加在基极电路中串联电阻上的电压决定。施加的电压由 LabJack HMI 的脚本控制 AO 0 输出设置。

如果修改了图 4-1 中所示的电路,实验者应确保限流电阻不允许电流超过所用二极管的最大规定值。

软件

需要页面组件

如图 4-5 所示的 DAQFactory 数据输入面板由总共八行组成,包括四个文本组件、两个用于数据输入的编辑框、两个用于启动序列的按钮和两个描述性文本组件。

为了组装控制面板,可以使用之前用于创建、定位和配置屏幕组件的技术,必要时,可以参考 DAQFactory 用户手册来放置和配置本练习中使用的新屏幕图标。

下表列出了组成成品控制面板的页面组件,如图 4-5 所示:

用于科研的 Arduino 教程(一)

图 4-7

按钮组件多动作选择面板

用于科研的 Arduino 教程(一)

图 4-6

描述性文本组件的配置面板

用于科研的 Arduino 教程(一)

图 4-5

控制面板可改变 LED 照明重复次数

用于科研的 Arduino 教程(一)

图 4-4

编辑框准备调整大小

用于科研的 Arduino 教程(一)

图 4-3

编辑框主选项卡已完成

用于科研的 Arduino 教程(一)

图 4-2

编辑框主选项卡,用于设置通道或变量值

  1. 文本信息用于识别面板/分组及其功能(顶行,黄色背景,黑色字体;从组件配置窗口的框中选择的文本和背景颜色;参见第章 1 ,图 1-6 。

  2. 配置一个编辑框(见图 4-2 和 4-3 )并贴上标签以识别和接收要输入面板的数据。“闪烁 led 重复次数”是图 4-1 中红色 LED 的闪烁次数。DAQFactory 中保存闪存编号索引的变量定义为 flsh_Rpts,并声明为自动启动序列中的全局变量(清单 4-1;本章末尾的“代码清单”部分提供的所有代码清单)。为了使正确的变量名自动出现在下拉列表中,如图 4-2 所示,突出显示“cycles”条目,变量名必须用一个短序列声明为全局变量,该序列在页面加载时自动运行(参见第三章中的图 3-1 )。面板中的第 2 行完全通过标题框和勾选“设置按钮按下时设置”复选框进行配置,如图 4-3 所示。“设置按钮标题”被输入到适当的框中,以出现在面板第二行的按钮上。当配置和编辑编辑框组件时,确保光标尖端在编辑框活动区域内,并且在单击鼠标左键之前按下 Ctrl 键,然后用图 4-4 所示的粗阴影边框突出显示编辑框本身。在编辑框高亮显示的情况下,点击鼠标右键可以调出图 4-2 和 4-3 的属性对话框。编辑框中输入的值将根据需要放入通道或变量中。

  3. 创建第二个编辑框以接收可变数值,该数值将使图 4-1 中绿色 LED 的强度或亮度从关闭循环至全亮度,然后返回关闭。保存衰落周期数的变量被声明为 fd_Rpts,其自动启动序列与 flash 索引相同。

  4. 在面板的第四行,数据输入框下面的静态文本标识输入的变量。为了增强对比度,黑色文本在绿色背景下书写。(参见章节 1 中的选项,图 1-6 )。

  5. 描述性文本组件构成了面板的第五行,用于直观地确认编辑框中输入的值,该值已被设置为脚本代码使用的脚本变量“flsh_Rpts”的值。图 4-6 显示了描述性文本组件的属性窗口。描述性文本组件需要标题、表达式和比较表。对照表中的条目在左栏中是一个数值,在右栏中是一个文本串。添加和删除按钮用于组装所需的表。组装和配置完成后,如果在单击 Enter 按钮时在编辑框中输入 0,描述性文本组件将查找变量 flsh_Rpts 的值,并在文本列中打印相应的条目“未输入值”在编辑框中输入 4 将导致在标题“闪光重复”后打印消息“四次”,本质上,比较表具有手边变量的数值范围,并且当变量落在定义的范围内时显示相应的文本消息。

  6. 第六行由左边的描述性文本和右边的按钮组成。一个贴有适当标签的按钮用于启动脚本控制的“n”次重复,红色二极管开/关闪烁。在图 4-5 中,DAQFactory 控制屏幕被配置为运行清单 4-2 中列出的常规序列码。LED 的电源由 RedLed 通道控制,其输出可在 LabJack I/O 0 引脚上找到。

  7. 在控制面板的第七行中是第二描述性文本组件,其被配置为报告绿色 LED 重复淡入/淡出振荡的次数。

  8. 描述性文本和第二个按钮构成了控制面板的第八行,也是最后一行。该按钮控制一对序列,第一个是红色 LED 闪烁序列,而第二个,在清单 4-3 中,是绿色 LED 的淡入/淡出代码。在图 4-7 中,显示了按钮组件的动作选项卡。下拉编辑框动作列表将显示一长串单项选择。如果在点击按钮时需要一个以上的动作,那么可以使用添加/删除上/下箭头来添加当点击按钮时要调用的动作。在本演示练习中,闪烁和淡入淡出序列同时运行。

为了视觉上的清晰,面板组件可用于为构成特定操作控制屏幕的各组活动屏幕组件创建背景。位于面板底部的粗体数字可用于关联主控制屏幕上注释和说明表中的条目。

脚本

清单 4-1 是使用屏幕组件改变变量内容时要采用的一个重要程序。清单 4-2 和 4-3 中详细说明了红色和绿色 led 的闪烁和渐变顺序,而在最小开启电压和最大电源电压之间改变绿色 LED 电压的 27 步过程可在清单 4-4 中找到。清单 4-3 通过调用 AnalogUp()和 AnalogDwn()函数,根据淡入/淡出效果的需要,逐步增加二极管的电压电平,从而改变绿色二极管的亮度。该序列用于从低到高的转换,第二个例程用于从高到低的转换,使系统能够在 1.3 秒内增加和降低 LED 亮度。

观察

红色二极管的开关周期是决定性的,因为灯处于最大亮度或关闭。施加于 2N3904 基极的电压或电流以一系列增量步进,会在半导体照明中产生“噪声”增加和减少。(参见“讨论”)

描述性文本组件应用程序是图标用法的一个非常简单的说明,但是提供了如何组装和操作比较表的概述。

变量循环索引中的数据输入是该技术的一个简单说明,两个不同脚本从一个按钮的双重启动说明了 DAQFactory 编程演示“线程”的能力,其中两个程序似乎同时执行。(线程是一个高级编程主题,如果实验控件需要,可以从 Python 编程的文献中详细研究。)

讨论

正如在打开和关闭红色 LED 电源的脚本代码中可以看到的,变量“flsh_Rpts”被声明为一个全局实体。当脚本被键入并且“应用和编译”按钮被成功点击时,全局变量“flsh_Rpts”出现在弹出的通道、变量和序列脚本的键入帮助列表中。

晶体管是电流的放大器。 1 任何由 DAQFactory 软件产生并最终表示为施加在 LabJack 的 AO 0 端子上的电压电平的信号都含有噪声。该噪声叠加在 DAQFactory 脚本产生的外加 DC 信号电平之上,通过保护晶体管基极免受过大电流影响的 10kω电阻放大。施加在 2N3904 基极上的信号噪声被晶体管的增益或放大系数 h fe 放大,通常值在 35 到 100 之间,以产生容易看到的闪烁和不规则的淡入或淡出过渡。

虽然在练习中使用了 PNP 晶体管,但是经过图 4-8 所示的改变,也可以使用 NPN(2n 3904 和 2N2222 是合适的 NPN 器件)。

用于科研的 Arduino 教程(一)

图 4-8

NPN 和 PNP 功率控制

二极管开关的脚本代码包含在一个循环中,该循环的索引声明为全局类型变量,其值在屏幕编辑框中设置。相同的代码可用于标有 AnalogUp()和 AnalogDwn()的两个函数,在简单的开/关循环中,调用这两个函数来代替将模拟输出通道 A0 设置为 5v 或 0 的赋值语句。通过电压调节使照明强度上下步进的功能是改变输送给绿色二极管的功率的非常简单的方法。可能有许多更好的代码序列可以用来控制照明强度。(注:如果 PNP 和 NPN 晶体管互换,模拟向上和模拟向下将改变功能。)

U12 LabJacks 可以配置为 PWM 输出,以提供平滑的功率控制应用,而不是本练习中使用的粗略演示方法。如第七章所述,较新的数据采集和接口设备通常配有内置 PWM 设备。

使用 Arduino 微控制器进行屏幕数据输入

数据的屏幕输入也可以采取从 DAQFactory 中的控制面板生成的一系列数字控制值的形式。来自在主机上形成控制屏幕的一组 DAQFactory 图标的数值可以通过串行端口传递给微控制器,以将输入的数据转换成过程变化或实验控制动作。数据必须在低级位和字节或开/关通信级别通过两个不同计算系统之间的串行端口入口。尽管开/关识别能力在两个系统中都是以 ASCII(美国信息交换标准码)字符的形式组织的,但信息必须被转换成用于数学运算的数字整数或数字浮点值,或用于识别目的的字母字符。

正如前面的练习所介绍的,Arduino 微控制器可以通过串行端口进行控制。除了微控制器板的成本低得多之外,微控制器还有许多更新的特性,例如可编程硬件定时器,可以用来改变 5 V 电脉冲的时间宽度,以实现脉宽调制。(详见第七章。)

Arduino 通常有 14 个数字 I/O 引脚,其中 6 个可以提供 PWM 电源控制。

通过串行端口将 SCADA 软件连接到 Arduino 微控制器会限制电子设备一次处理一个信号。无论有多少数据流在传输到串行端口之前被多路复用或混合,然后在微控制器端被解析回各自的数据流,一次只有一位通过串行连接。

第十一章介绍了串行连接及其使用的更多细节。

实验的

为了实现使用 Arduino 微控制器代替 LabJack U12 来演示用于控制和接收来自微处理器的显示数据的控制屏幕数值输入,可以使用第二章图 2-9 中描述的数字引脚和 ADC 输入。

在所有 DAQFactory-Arduino 编程中,只有一个程序可以控制串口。作者通常的做法是开发手头任务所需的 Arduino 代码,然后通过启动 Arduino 的串行监视器并将 DAQFactory 控制屏幕发送的字符串发送到微控制器代码来测试代码。一旦确认了正确的 Arduino 响应,Arduino 上的串行端口将被关闭,Arduino IDE 窗口将被最小化以在后台运行。一旦接收正确 DAQFactory 字符串以调用所需动作的 Arduino 代码在后台运行,就可以启动 DAQFactory 程序来开始控制会话,该 DAQ factory 程序包含要投入使用的控制屏幕页面。在本练习中,图中所示的 DAQFactory 屏幕驻留在 SCADA 软件中,该软件可以访问和控制串行端口,通过该端口可以发送字符,以便从连接到 Arduino I/O 连接的设备启动所需的操作。

创建了如图 4-9 所示的初始 DAQFactory 屏幕,以开始串行通信的渐进开发。

红色 led 开和红色 led 关按钮耦合到列表 4-5 的快速序列码,该快速序列码向串行端口发送 1 或 0,列表 4-6 的 Arduino 代码根据需要激活/禁用红色 led。Arduino 代码还读取测量的已知值限流电阻上的电压降,并将电流数据发送回串行端口,DAQFactory 快速序列码解析出电流数据,显示在控制屏幕上。

用于科研的 Arduino 教程(一)

图 4-9

DAQFactory 控制屏幕,用于指导 Arduino 微控制器板上的操作

DAQFactory 控制屏幕左上角的第二个按钮耦合到第二个快速序列,该序列激活 Arduino 板上红色 led 的更复杂和更有效的切换。清单 4-7 和 4-8 的程序是管理切换效果的快速序列码和 Arduino 码。

图 4-10 描述了当 Arduino 板上的绿色和橙色 led 被 DAQFactory 控制屏幕上的相应按钮激活时获得的 DAQFactory 控制屏幕显示。COM4 监视器上串行端口动作的传输历史记录在图框的左下方。清单 4-9 和 4-10 控制控制面板的彩色按钮。

用于科研的 Arduino 教程(一)

图 4-10

DAQFactory 控制屏幕,用于指导 Arduino 微控制器板上的多个操作

清单 4-9 和 4-10 包含通过点击彩色按钮激活的 DAQFactory 快速序列码,以及控制屏幕彩色按钮和变量值读数的响应 Arduino 码,如图 4-10 所示。

在图 4-5 中,使用 LabJack 设备和自动启动序列开发了 DAQFactory 屏幕数据输入面板,以声明保存要输入的弧线步进值所需的变量。DAQFactory 中的自动启动序列也会在加载包含数据输入面板的页面以供 Arduino 微控制器使用时激活。除了线程演示按钮之外,前面讨论的关于 DAQFactory 的所有功能在微控制器上都是活动的。(参见“讨论”)

如清单 4-11 所示,“带可变索引的 Tst 脚本”按钮与快速序列程序相连。快速序列依靠一个“for 循环”,执行“flsh_Rpts”次,向运行清单 4-6 中所列代码的 Arduino 发送开/关或“1”/“0”串行端口传输,以打开或关闭红色二极管。或者,清单 4-12 、 4-13 和 4-14 可用于操作 Arduino 的 PWM 功能,使微控制器板上的橙色二极管变暗和闪烁。(参见“讨论”)

观察

当屏幕数据输入使用带有 LabJack 的编辑框屏幕组件时,可以在闪烁和渐变编辑框中输入两个不同的值,当底部按钮“同步脚本”被激活时,两个二极管上的闪烁和渐变动作同时运行。(参见“讨论”)

LabJack 和 Arduino 屏幕和功能的其余部分按预期工作。

讨论

除了 DAQFactory 脚本语言,Python 是一种能够适应“线程化”的编程语言。线程的细节和应用是比这篇介绍性文章更高级的主题,要了解更多信息,可以参考 Python 的文献。

检查清单 4-8 中的 Arduino 代码会发现,为简单起见,用于确定红色 LED 状态的逻辑已经完全写入微控制器系统。如果微控制器位于远程位置,DAQFactory 控制屏幕的操作员需要了解红色 LED 或连接到数字引脚的设备的状态,则可以通过串行端口将一个标志连同当前提取的数据一起传回控制屏幕。

实验人员在 Arduino 上使用数字和 PWM 引脚时必须小心,因为 14 个数字 I/O 引脚中只有 6 个支持 PWM(即 Arduino 引脚 3、5、6、9、10 和 11 支持 PWM)。)

当使用 DAQFactory 串行端口时,如果 Arduino 代码要使用它来标记字符传输的结束,实验人员必须在每次传输的结尾手动添加一个换行 ASCII 标记。Arduino 串行监视器在视野的右下角有一个选择框,用于为当前的终端会话选择所需的行尾。

通过在 DAQFactory 序列脚本中计算时序和功率要求,并仅在需要时发送功率激活命令,使用 0–255 整数功率电平的 PWM 激活码可用于 LED 激活的渐变和闪烁模式。

Raspberry Pi:数据的屏幕输入

RPi 使用的 Python 语言的数据输入是通过 input 语句完成的。Python 中的 input 语句接受一个字符串值参数,然后可能需要将其转换为适当的整数或浮点数形式的数值。典型的屏幕输入代码如下(#标记注释行):

input_str = input("Enter the desired input characters", )
variable = int(input_str)   # can only be used for non-floating point conversion of numbers
variable = float(input_str) # can only be used for floating point numeric strings

  • 1
  • 2
  • 3
  • 4

使用 Python 语言控制 led 可以使用名为 RPi 的基本库。GPIO 或更高级的功能库 gpiozero。这两个库的文档都可以在线获得。

由于 GPIO 阵列是一个数字输入/输出系统,如果不借助 PWM 和电容平滑,就不容易实现电压控制。(PWM 在第七章中介绍。)

演示使用 Python 和 RPi 在屏幕上输入数据的简单练习可以通过使 LED 闪烁来创建,闪烁长度根据屏幕输入值设置,重复次数也由屏幕输入设置。清单 4-15 中的 Python 程序产生图 4-11 的输出,并按照记录闪烁标称 LED。

用于科研的 Arduino 教程(一)

图 4-11

数据程序 Python 屏幕输入的输出

有时,当外设连接到 GPIO 阵列时,打开 RPi 电源时,一些阵列引脚可能处于高电平或通电状态。清单 4-16 中列出了两个能够重置零或关闭活动引脚的实用程序。一个实用程序使用通道列表函数,第二个实用程序使用 Python 循环来处理 GPIO 阵列的各个引脚。

代码列表

# Clear, Turn Off or Reset the RPi GPIO array
#
import RPi.GPIO as GPIO
# set the pin identity mode
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# Reset the array pins to off/false/0
chan_list = (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
GPIO.setup(chan_list, GPIO.OUT)
GPIO.output(chan_list, GPIO.LOW)

Listing 4-16Python Code to Reset the GPIO Array

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
# Input of data from the control screen
#
import RPi.GPIO as GPIO
import time
# set the pin identity mode
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# Reset the array pins to off/false/0
chan_list = (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
GPIO.setup(chan_list, GPIO.OUT)
GPIO.output(chan_list, GPIO.LOW)
#
# Enter the number of the GPIO array pin connected to the LED to be activated
input_str = input("Input the GPIO pin number for the LED control exercise " , )
arry_pn_no = int(input_str)
#
# Input the number of times to repeat the flashing of the LED
input_str = input("Input the number of times to flash the LED ", )
rpts = int(input_str)
#
# Input the number of times to flash the LED in a second
input_str = input("Input the on time in seconds for the LED flash ", )
flsh_rt = int(input_str)
print("Array pin number = ",arry_pn_no, "Repeats = ", rpts, "Flash rate = ", flsh_rt)
#
print("Lighting the LED on GPIO pin ", arry_pn_no, "to flash ", rpts, "times for", flsh_rt, " seconds per flash")
#
for i in range(1, rpts + 1):
    GPIO.output(arry_pn_no, GPIO.HIGH)
    time.sleep(flsh_rt)
    GPIO.output(arry_pn_no, GPIO.LOW)
    time.sleep(flsh_rt)
# Clear the GPIO array
Print("GPIO array cleared")
GPIO.cleanup()

Listing 4-15Python Data Input from the Host Computer Screen

用于科研的 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
  /* DAQFtry ardyRb PWM Led Control through serial port
Quick Sequence control of Orange led fade with arduino PWM
Arduino PWM requires a 0 - 255 integer to set the PWM DC.
This pgm uses the string to int function to convert a digit
based number into an integer to set the PMW value.
*/
String inString =  " ";
byte pinOut = 5;              // dig pin for orange led
int pwr_Vlu = 0;
//
void setup() {
  Serial.begin(9600);         // start serial port
  pinMode(pinOut, OUTPUT);    // set output pin
}
//
void loop() {
  while (Serial.available() > 0) {
  int inChar = Serial.read();
  if (isDigit(inChar)) {
  // cnvrt incoming byte to char and add to strng

  inString += (char)inChar;
  }
  // if nuline convert accumulated to integer
  if (inChar == '
') {
    pwr_Vlu = (inString.toInt());
    Serial.print(pwr_Vlu);
    //int twotimes = pwr_Vlu * 2;
    //Serial.print(twotimes);
    pinMode(pinOut, OUTPUT);
    analogWrite(pinOut, pwr_Vlu);
    // clear the string for new input
    inString = " ";
  }
 }
}

Listing 4-14Arduino Code to Accept Digits from 0 to 255 to Be Used as PWM Power Application Requests 

用于科研的 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
// Orng led flashed on/off with 255 and 0 PWM Arduino power level applications
global flsh_Rpts
//
for (Private.Counter = 0, Counter < flsh_Rpts, Counter ++)
//
device.ardyRb.Write("255" + Chr(10))     // turn led full on
delay (0.5)                              // delay 1/2 sec
device.ardyRb.Write("0" + Chr(10))       // turn led off
delay(0.5)                               // delay 1/2 sec
endfor

Listing 4-13DAQFactory Regular Sequence to Use the “flsh_Rpts” Screen-Entered Loop Index Counter

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
// Green Led on Arduino pin 5 to be cycled from full power to
// off from a DAQFctry script using the serial port and the
// edit box entry of the requested number of repeats, fd_Rpts.
// Start illumination decrease cycle

device.ardyRb.Write("255" + Chr(10))
delay(0.25)
device.ardyRb.Write("192" + Chr(10))
delay(0.25)
device.ardyRb.Write("128" + Chr(10))
delay(0.25)
device.ardyRb.Write("96" + Chr(10))
delay(0.25)
device.ardyRb.Write("64" + Chr(10))
delay(0.25)
device.ardyRb.Write("48" + Chr(10))
delay(0.25)
device.ardyRb.Write("32" + Chr(10))
delay(0.25)
device.ardyRb.Write("24" + Chr(10))
delay(0.25)
device.ardyRb.Write("16" + Chr(10))
delay(0.25)
device.ardyRb.Write("12" + Chr(10))
delay(0.25)
device.ardyRb.Write("8" + Chr(10))
delay(0.25)
device.ardyRb.Write("6" + Chr(10))
delay(0.25)
device.ardyRb.Write("4" + Chr(10))
delay(0.25)
device.ardyRb.Write("3" + Chr(10))
delay(0.25)
device.ardyRb.Write("2" + Chr(10))
delay(0.25)

device.ardyRb.Write("0" + Chr(10))

Listing 4-12DAQFactory Regular Sequence Code for Fading the Green LED on the Arduino Board

用于科研的 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
for (Private.Counter = 0, Counter < flsh_Rpts, Counter ++)
   device.ardyRb.Write('1')
   delay(0.5)
   device.ardyRb.Write('0')
   delay(0.5)
   endfor.

Listing 4-11DAQFactory Quick Sequence for Flashing the Arduino-Mounted LED for the Number of Cycles Requested Through the Screen Data Entry Edit Box

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
// Toggle leds on/off from DAQFctry button icons on COM4
// The DAQF QS sends an R, G, O or Y to the serial port on com
// 4. On the arduino side the status of the appropriate led
// digpin is determined and toggled as required through a
// switch construct.
//
// power drawn calculations, each led has a CLR and the voltage
// on the junction of the resistor and led is measured and used
// to calculate diode current by A0 to A3 respectively. Current
// calcln only done when diode activated.
//
const int RedLedPin = 3;           // red led is on dig pin 3
const int GreenLedPin = 4;         // green led on dp 4
const int OrangeLedPin = 5;        // orange led on dp 5
const int YellowLedPin = 6;        // yellow led on d pin 6
//
int oofR = 0;                      // on off flags initialized
int oofG = 0;
int oofO = 0;
int oofY = 0;                      // on off flags initialized
//
char incomingByte = ' ';           // define incoming character
//
float iRed = 0;                    // red led current in decimal float format

float iGreen = 0;
float iOrange = 0;
float iYellow = 0;
float itotal = 0;
//
void setup() {
 Serial.begin(9600);                // start the serial port
 }
//
void loop()
{
  if (Serial.available())            // check for incoming data
  {
  char incomingByte = Serial.read();   // set char value for switch branching
// Serial.print(incomingByte);          // diagnostic
  switch(incomingByte)                  // branch to desired location/option
  {
  case 'R':                             // Red Led Activation
  if (oofR == 0 ) {
  pinMode(RedLedPin, OUTPUT);           // set pin I/O
  digitalWrite(RedLedPin, HIGH);        // turn led on
  oofR = 1;                             // set flag
  iRed = ((analogRead(A0)* 4.8828)/216);  // calc i when led on

  //Serial.print(analogRead(A0));         // diagnostics
  //Serial.print("iRed = ");              // diagnostics
  Serial.println(iRed);                           // add CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;     // calculate total power consumption
  //Serial.print("itotal = ");                   // diagnostics
  Serial.println(itotal);                        // add CR-LF
  }
  else {                       // flag is set to 1 so led is on
    pinMode(RedLedPin, OUTPUT);       // set pin mode to output
    digitalWrite(RedLedPin, LOW);     // turn led off
    oofR = 0;                         // re-set flag to off
    iRed = 0;                     // turn iRed current contribution to itotal off
    Serial.println(iRed);             // send data to DAQFtry
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current draw
    //Serial.print("itotal = ");      // diagnostics
    Serial.println(itotal);   // send to serial port with CR-LF
    }
break;
//
case 'G':                             // Green Led Activation
  if (oofG == 0 ) {                   // check status flag
  pinMode(GreenLedPin, OUTPUT);       // set pin I/O
  digitalWrite(GreenLedPin, HIGH);    // turn led on
  oofG = 1;                           // reset status flag
  iGreen = ((analogRead(A1)*4.8828)/215); // calc diodecurrent
  //Serial.print("iGreen = ");            // diagnostics
  Serial.println(iGreen);               // send data with CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;  // calculate total current draw
  //Serial.print("itotal = ");                  // diagnostics
  Serial.println(itotal);                    // send with CR-LF
  }
  else {
    pinMode(GreenLedPin, OUTPUT);      // set pin I/O mode
    digitalWrite(GreenLedPin, LOW);    // turn green led off

    oofG = 0;                          // set green status flag
    iGreen = 0;   // turn green contribution to total current off
    Serial.println(iGreen);   // send green current value with CR-LF
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current draw
    //Serial.print("itotal = ");          // diagnostic
    Serial.println(itotal);    // send total current with CR-LF
  }
break;
//
case 'O':                             // Orange Led Activation
  if (oofO == 0 ) {                   // check status flag
  pinMode(OrangeLedPin, OUTPUT);      // set pin I/O
  digitalWrite(OrangeLedPin, HIGH);   // set pin I/O
  oofO = 1;                        // set orange flag to led on
  iOrange = ((analogRead(A2)*4.8828)/215);        // calculate orange led current draw
  //Serial.print("iOrange = ");                   // diagnostic
  Serial.println(iOrange);   // send to serial port with CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;     // calculate total current draw
  //Serial.print("itotal = ");                    // diagnostic
  Serial.println(itotal);          // send total current to serial port with CR-LF
  }
  else {                           // orange led is on
    pinMode(OrangeLedPin, OUTPUT);       // set pin I/O
    digitalWrite(OrangeLedPin, LOW);    // turn orange led off
    oofO = 0;                // reset orange status flag to off
    iOrange = 0;              // turn orange contribution to total off
    Serial.println(iOrange);  // send out orange current with CR-LF
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current draw
    //Serial.print("itotal = ");       // diagnostics
    Serial.println(itotal);  // send out total current draw with CR-LF
  }
break;
case 'Y':                             // Yellow Led Activation
  if (oofY == 0 ) {                     // led is off
  pinMode(YellowLedPin, OUTPUT);        // set pin I/O
  digitalWrite(YellowLedPin, HIGH);     // turn yellow led on
  oofY = 1;                             // re-set lag to led on

  iYellow = ((analogRead(A3)*4.8828)/217);        // calculate yellow led current
  //Serial.print("iYellow = ");                   // diagnostic
  Serial.println(iYellow);        // yellow led current value to serial port wth CR-LF
  itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current draw
  //Serial.print("itotal = ");                    // diagnostic
  Serial.println(itotal);     // send to serial port with CR-LF
  }
  else {                                 // yellow led on
    pinMode(YellowLedPin, OUTPUT);       // set pin I/O mode
    digitalWrite(YellowLedPin, LOW);     // turn yellow led off
    oofY = 0;                            // re-set flag to yellow led off
    iYellow = 0;                 // set yellow led current to 0
    Serial.println(iYellow);     // send value to serial port with CR-LF
    itotal = iRed + iGreen + iOrange + iYellow;   // calculate total current and send wth CR-LF
    //Serial.print("itotal = ");    // diagnostic
    Serial.println(itotal);    // send total current with CR-LF
  }
break;
  }
 }
}

Listing 4-10Arduino Code Supporting DAQFactory Multiple-Button Colored Diode Selection with Power Consumption

用于科研的 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
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
device.ardyRb.Purge()
device.ardyRb.Write('R')
delay(0.1)
global iRed
global iTotal
private string datain1
private string datain2
datain1 = device.ardyRb.ReadUntil(13)
datain2 = device.ardyRb.ReadUntil(13)
iRed = strToDouble(datain1)
iTotal = strToDouble(datain2)

Listing 4-9DAQFactory Quick Sequence Code for Multiple-Button Control of Arduino LEDs

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
// Toggle an led on/off from one DAQFctry button icon on COM4
// The DAQF QS sends an R to the serial port on com 4. On the
// arduino side the status of the RedLed digpin is determined
// and toggled as required. Led current calculated and written to
// Ser prt where DAQFtry parses out floating point current value.
//
const int RedLedPin = 3;      // red led is on dig pin 3
int oofR = 0;                 // power state of red diode
char incomingByte = ' ';      // declare incoming byte
float iRed = 0;               // red led current
//
void setup() {
  Serial.begin(9600);         // start the serial port
  pinMode(RedLedPin, INPUT);  // must initially read the dig. pin
}
//
void loop() {
  if (Serial.available()) {         // check for incoming data
    char incomingByte = Serial.read();
    //Serial.print(incomingByte);              // diagnostic
    if (incomingByte == 'R' && oofR == 0) {
      pinMode(RedLedPin, OUTPUT);
      digitalWrite(RedLedPin, HIGH);
      iRed = ((analogRead(A0) * 4.8828)/216 );
      Serial.println(iRed);
      oofR = 1;
    }
    else {
      if (incomingByte == 'R' && oofR == 1){
      pinMode(RedLedPin, OUTPUT);
      digitalWrite(RedLedPin, LOW);
      iRed = 0;
      Serial.println(iRed);
      oofR = 0;
      }
    }
  }
}

Listing 4-8Arduino Code for Receiving the DAQFactory Control Screen Button Request to Toggle Red LED Illumination

用于科研的 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
device.ardyRb.Purge()
device.ardyRb.Write('R')
delay(0.1)
global ldCurrnt
private string datain
datain = device.ardyRb.readUntil(13)
ldCurrnt = strToDouble(datain)

Listing 4-7DAQFactory Quick Sequence Code to Toggle Red LED and Read the Power Consumption

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
// Arduino code for a single led illumination on the red board
// Arduino the pgm waits for an incoming character on com
// port 4 if a 1 the led is turned on if a 0 it is turned off.
// A0 is wired to Rd led junction and the Arduino calculates
// the led current and prints the value to the serial port.
//
const int RedPin = 3;      // red board dig. pin with red led and clr
int incomingByte;          // a variable to hold incoming byte
float iRed = 0;            // the led current through the CLR
//
void setup() {
  Serial.begin(9600);             // start the serial port
  pinMode(RedPin, OUTPUT);        // set the pin function
}
void loop() {
  if(Serial.available()> 0) {     // check port for last data byte
  incomingByte = Serial.read();   //
  if (incomingByte == '1') {      // if is 1, turn the led on
    digitalWrite(RedPin, HIGH);
  // calculate led current and print to the serial port

  iRed = ((analogRead(A0) * 4.8828 )/216);
  Serial.println(iRed);
  }
  //
  if (incomingByte == '0') {
    digitalWrite(RedPin, LOW);       // if 0, turn the led off
  // calculate led current and print to the serial port
  iRed = ((analogRead(A0) * 4.8828 )/216);  // ensures the LED is off
  Serial.println(iRed);
  }
  }
}

Listing 4-6Arduino Code for DAQFactory Code of Listing 4-5

用于科研的 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
device.ardyRb.Purge()
device.ardyRb.Write('1')
delay(0.1)
global ldCurrnt
private string datain
datain = device.ardyRb.readUntil(13)
ldCurrnt = strToDouble(datain)

Listing 4-5DAQFactory Quick Sequence to Turn the Red LED On from the Button and Read the LED Current

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
//Analog Voltage is raised from 2.4 volts to 5.0
// in steps of 0.2v with a delay of 0.05 sec
// between increments. Rvn. Jan4/10
AnalogOut = 2.2
delay (0.05)
AnalogOut = 2.4
delay (0.05)
AnalogOut = 2.6
delay (0.05)
AnalogOut = 2.8
delay (0.05)
AnalogOut = 3.0
delay (0.05)
AnalogOut = 3.2
delay (0.05)
AnalogOut = 3.4
delay (0.05)
AnalogOut = 3.6
delay (0.05)
AnalogOut = 3.8
delay (0.05)
AnalogOut = 4.0
delay (0.05)
AnalogOut = 4.2
delay (0.05)
AnalogOut = 4.4

delay (0.05)
AnalogOut = 4.6
delay (0.05)
AnalogOut = 4.8
delay (0.05)
AnalogOut = 5.0
return()

Listing 4-4DAQFactory Regular Sequence for LED Illumination Intensity Variation

用于科研的 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
//Variable Intensity Flash varies the voltage of the
//AO 0 channel to raise and lower the intensity of the
//green LED
//Nov. 16/09
//
global fd_Rpts
AnalogOut = 0
for (Private.Counter = 0, Counter < fd_Rpts, Counter ++)
AnalogUp ()
AnalogDwn ()
endfor
AnalogOut = 0

Listing 4-3DAQFactory Code to Fade In and Out the Green LED Brightness

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
// Sequence Name --: TstSqncForLoopVariableReps
//Screen Entry of Alph-Numeric Values
//Oct9/09 and Nov. 13/09
//A screen Edit Box accepts entered values as a variable called
//flsh_Rps. The variable is declared as a global type with an
//auto-run sequence and is used as the loop counter value to
//vary the number of times the loop iterates.
//
global flsh_Rpts
//
for (Private.Counter = 0, Counter < flsh_Rpts, Counter ++)
   //
    RedLed = 5
    delay(0.5)
    RedLed = 0
    delay(0.5)
   //
endfor

Listing 4-2DAQFactory Code to Flash the Red LED a Variable Number of Times as Entered from the Control Screen

用于科研的 Arduino 教程(一)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
// Auto declare variables is a sequence that runs when the Main
// Screen page is run. Two variables are declared globally,
// flsh_Rpts and fd_Rpts representing the number of times to
// flash the red led and fade the green.
//
global flsh_Rpts
//
global fd_Rpts

Listing 4-1DAQFactory Auto-start Sequence Code to Declare Variables

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

摘要

  • 在商业 SCADA 系统中需要脚本来输入从配置的主机屏幕 GUI 控制面板初始化和控制手边的过程所需的过程变量。

  • 屏幕输入的过程或实验变量也可以输入到 SCADA 系统中,该系统由较便宜的组件和计算平台组装而成。

Footnotes 1

电子烹饪书,蒙克,奥莱利媒体公司,ISBN 978-1-49195340-2

© 版权声明

相关文章

暂无评论

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