概述
有几种编程微控制器的方法。有些方法比其他方法困难,这通常取决于人们对编程基础的熟悉程度。
本指南主要供Arduino开发人员通过演示程序的使用来学习使用CircuitPython的来龙去脉。两种语言的代码。这可能是对人们熟悉CircuitPython技能的参考。
同样有效的可能是从未使用过Arduino的Python或CircuitPython程序员。显示Arduino用于各种用途的代码可能有助于使自己更适应Arduino环境。
来源:https://www.xkcd.com/303/(CC BY-NC 2.5)
解释与编译
Arduino从大量使用中的工具中获取了很多东西数十年。这包括已编译代码的概念。代码是在没有调试的情况下在文本编辑器类型的环境中编写的。然后,在被命令时,将其馈送到一系列程序,这些程序将获取代码,最后将其从C或C ++编译为微控制器的机器语言。在市场上有各种各样的微控制器,机器代码是该代码和处理器所独有的。
如果需要在Arduino中更改代码,则必须编辑文本代码并通过编译过程将其提交回去。 。在每次发生的编译和加载过程中,进行更改,修复语法错误,“插入”最佳值可能会花费大量时间。
Python通常和CircuitPython特别是解释的。直到必须将代码转换为机器代码。这有很多优点。该代码可以在运行时给出错误消息。随后的任何更改都不需要重新编译。加载代码就像将代码文本文件复制到闪存驱动器一样简单。 CircuitPython程序开发通常只是Arduino程序所需时间的一小部分。该代码对于其他微控制器也具有高度的可移植性。
解释的代码的缺点是速度。将代码转换为机器代码是即时进行的,因此需要时间。解释器还使用微控制器上的RAM和Flash,而不是等效的Arduino用户代码和库。
材料:MS Word 2010剪贴画
Reality
现代微控制器的速度和存储容量不断提高,其价格通常与较旧的微控制器相似或更低(制造商可能希望在某个时候停产)。在现代芯片中,在微控制器上使用Python不会带来速度上的损失。 Python的灵活性以及在学校中教授的灵活性的优势使Python成为人们关注的焦点。
在这个时代,提供帮助将Arduino编码器迁移到CircuitPython的工具似乎特别合适,因为这无疑是行业发展的方向
您可能会很慢,但仍然会赢。而且乌龟的寿命很长。
计算机Python
那Linux板呢?
Arduino代码通常不能在Raspberry Pi,BeagleBone等小型Linux板上运行。为什么?
Linux是一个完整的操作系统,它可以一次运行许多东西。 Arduino代码必须学会共享资源,而不要使用整个处理器,尤其是在无限循环中。也许有一天会添加此功能,但现在不可用。
Python在Linux板上非常流行。 CircuitPython可以通过Adafruit提供的名为Blinka的帮助程序层在小型Linux板上运行。这提供了CircuitPython在微控制器上可以做什么以及如何在Linux上运行之间所需的映射。它们旨在共同发挥作用(只要您的代码也写得很好。
因此,对于基于Linux的小型单板计算机,CircuitPython是目前的唯一选择。但这是一个不错的选择。
在本指南中,我们将不介绍在Linux上通过CircuitPython使用硬件的详细信息。在此处查看有关Blinka的指南
简单的代码结构
Arduino strong》
上图显示了最简单的Arduino程序,即从菜单中选择文件-》 新建会得到的结果。有两个强制性函数调用:
setup-程序启动时将执行一次的代码
loop-连续的代码一遍又一遍地循环运行
这两个函数都不做任何事情。有些草图仅在setup中执行所有操作,而有些程序根本不使用setup而仅使用loop。但是,即使它们是空的(如上所示),也必须同时定义两者。
CircuitPython
CircuitPython并没有限制像Arduino setup函数这样的开始执行的代码重复的主要代码,例如Arduino loop函数。
也就是说,许多CircuitPython程序的结构与Arduino素描程序的结构非常相似。
一个简单的示例。程序将变量var定义为值5,然后一遍又一遍地打印该值,类似于旧的BASIC Hello World程序。在Arduino中,您可以这样编写:
程序会添加一些代码以打开串行连接并输出输出。
等效的CircuitPython程序为:
任何setup类型语句放在程序顶部附近。
可以在Python中通过loop循环将条件设置为while,因此它永远不会退出True。
串行监视器已“嵌入”到CircuitPython中,用户无需设置任何内容即可使用它,并且将对此进行详细讨论。
没有任何限制,CircuitPython完全必须执行无限循环。一个简单的程序可以读取温度传感器,打印输出并结束。
但是,Arduino和CircuitPython都在微控制器上运行。在课堂上,您可能想要做一次读取和打印温度值之类的操作。如果将这个项目部署到农民的田地中,它可能会一遍又一遍地反复读取温度,可能每分钟或一小时读取一次。在农民的田野里,代码永远都不应停止。
因此执行某些功能的无限循环非常有用,并且在大多数微控制器程序中都使用。这就是Arduino为初学者简化事情的原因,以表明您可能想拥有while和setup。您可以在CircuitPython中执行完全相同的操作,只需构建代码以提供相同的功能即可。
处理数字
照片Nick Hillier在Unsplash上发表的文章
您会认为所有语言中的“数字就是数字”,但事实并非如此。所有数字在内部都以二进制形式在微控制器/计算机内部表示,但是编程语言如何提供数字支持会因语言而异。
数字类型
整数
浮点数
布尔值(true/false)
通常,您需要了解 precision -选择最佳的使用方式,数字的大小可能是多少它在计算机程序中。这使使用数字有些棘手,但学习起来却很容易。
Arduino
在Arduino中,您具有以下类型的变量:
int 表示整数,一个值没有小数点。整数的典型范围是-32,768到零到32,767。例如279、1001、0,-23,-990。
long 是一个大整数,值可以是-2,147,483,648到2,147,483,647。
float (浮点数)(浮点数(带小数点和小数的数字))。例子是3.1415,-22.2、0.0、430000.01。单个字符的数字最大为38 x的3 x 10
char 。例如,读取串行数据可能涉及在接收到数据时提供字符值的接收功能。字符基本上可以是键盘上的任何符号(0到255)。
types.h 库提供了趋于表现的数字的更现代表示形式
函数经常使用无符号短整数 uint8_t ,它的范围也从0到255。
布尔数学通常使用 int 值完成。 0是 false ,而任何非零的值(例如1)都是 true 。
Python/CircuitPython
CircuitPython尝试尽可能接近标准的Python实现(通常称为CPython) 。给定微控制器没有操作系统,某些事情会有所不同,但已记录在案。
以下是CircuitPython中的当前类型:
整数,但不是当前的长整数
浮点数。
字符串
布尔值
布尔值是CircuitPython中的实际类型,可以是值 True 或 False 。
CircuitPython具有专用的 Strings 类型,而不是像Arduino那样使用字符数组(以零/零终止)。请注意,CircuitPython 字符串不是以零/零结尾的,所以使用length属性是您处理字符串长度的方法。
更改数字类型
在Arduino/C中,这称为转换。
下载:文件
复制代码
int a;
float b;
b = (float)a;
a = (int)b; int a;
float b;
b = (float)a;
a = (int)b;
在CircuitPython中,您使用类似于函数的语法:
下载:文件
复制代码
x = 5
y = 3.14
z = float(x)
z = int(y) x = 5
y = 3.14
z = float(x)
z = int(y)
除法,一个斜杠对两个斜杠
两种语言中的单个正斜杠/是浮点除法。
Python中的双斜杠//很特殊。它将除以小数点后的任何值(通常称为下限函数)并进行除法。
示例:
下载:文件
复制代码
# Python code for / and // operators
x = 15
y = 4
# Output: x / y = 3.75
print(‘x / y =’, x/y)
# Output: x // y = 3
print(‘x // y =’, x//y) # Python code for / and // operators
x = 15
y = 4
# Output: x / y = 3.75
print(‘x / y =’, x/y)
# Output: x // y = 3
print(‘x // y =’, x//y)
逻辑运算符
逻辑运算符主要用于if语句和其他块/循环语句中。这些不是用于按位运算符和/或/或仅用于构造逻辑比较的运算符。
AND
OR
不是
Arduino/C
&&
||
!Python/CircuitPython
和
或
不是
下载:文件
复制代码
// Arduino / C Logical Operators
a = 5;
b = 7;
if( a 》 2 && b 《 10) {
Serial.println(“Success”);
} // Arduino / C Logical Operators
a = 5;
b = 7;
if( a 》 2 && b 《 10) {
Serial.println(“Success”);
}
下载:文件
复制代码
# CircuitPython Logical Operators
a = 5
b = 7
if a 》 2 and b 《 10:
print(“Success”) # CircuitPython Logical Operators
a = 5
b = 7
if a 》 2 and b 《 10:
print(“Success”)
变量,类型,范围
从Wikipedia中,没有列出创建者
快速参考
变量
Arduino
int a;
int b = 5;
CircuitPython
b = 5
阵列
Arduino
int a[5];
int a = {1, 2, 3, 4, 5};
CircuitPython
a = [1, 2, 3, 4, 5]
讨论
变量
变量就像计算机内存中的小盒子或信箱,可以在其中保留值。
要在C/C ++中创建变量,必须对其进行声明。这就需要给它一个类型,名称和可选的值。
下载:文件
复制代码
int a;
int b = 5; int a;
int b = 5;
在CircuitPython中,您无需声明变量。第一次分配值时便会分配它们。
下载:文件
复制代码
b = 5 b = 5
您只需使用名称即可在两种语言中使用变量的值。
下载:文件
复制代码
int x = a_number; // in C/C++
x = a_number # in CircuitPython int x = a_number; // in C/C++
x = a_number # in CircuitPython
在两种语言中,使用未知变量都是错误的:尚未声明(在C/C ++中)或未初始化(在CircuitPython中)
在C/C ++中,变量使用类型声明,并被静态类型化。它们仅具有该类型的值。
相反,CircuitPython是动态类型的。变量没有关联的类型,并且可以在不同时间具有不同类型的值。每种方法都有优点和缺点,但是在阅读某人的CircuitPython代码时,您应该记住这一点,以防某人重复使用变量并更改其类型。
集合
两种语言都可以创建和操作值的集合。
“终极”-比其他任何集合都要好。只是不要单击它。
(来自维基百科的图像,已获得合理使用许可)
Arduino
Arduino只有一种创建集合作为语言一部分的方法:数组。由于语言是C ++,因此您可以使用大多数C ++库。具有足够的CPU性能和内存,您甚至可以将Arduino版本的标准C ++和Boost库及其集合类一起使用,但是出于讨论的目的,我们假设您使用的是基本语言功能。 p》
数组是简单的固定大小,固定顺序的值序列。 C数组中的所有值都具有相同的类型。实际上,由于C是静态类型的,所以数组项的类型是数组本身类型的一部分。
例如,如果要创建一个可以容纳5个变量int中的值,您可以将其声明为:
下载:文件
复制代码
a int a[5];
如果在编译时已知初始值,则可以初始化数组创建时,并忽略其大小,因为将从初始值的数量中推断出大小。
下载:文件
复制代码
int a[5]; int a[] = {1, 2, 3, 4, 5};
要访问数组中的特定项目,请使用下标符号。可以用来从数组中获取值,或将其设置为新值。
下载:文件
复制代码
int a[] = {1, 2, 3, 4, 5}; int x = a[0];
a[1] = x + 1;
CircuitPython 》
基本的CircuitPython集合是List,其外观和工作方式与C的数组非常相似。但是,它是一个动态得多的结构:您可以自由地删除和插入项目。它的长度是其中当前有多少个项目的函数,而不是它要保留的内容的函数。由于它们是动态的,因此通常不需要提前分配它们。您可以通过将项目放在方括号中来创建列表。
下载:文件
复制代码
int x = a[0];
a[1] = x + 1; 》》》 a = [1, 2, 3, 4, 5]
与C数组一样,您使用下标符号来访问项目。
下载:文件
复制代码
》》》 a = [1, 2, 3, 4, 5] x = a[0]
a[1] = x + 1
CircuitPython的列表提供了比C数组更多的功能,但这超出了本指南的范围。 CircuitPython还具有其他内置集合:元组和字典。请参阅本指南,了解有关Python的基本数据结构,以及该指南的更多内容,重点是列表和流。
Arduino/C和Python都在0处开始元素/数组组。因此对于3元素项,它是x [0],x [1],x [2],这与某些语言(例如FORTRAN)在数组处开始元素1。
范围
来自Elborgo用户的维基百科
变量的作用域是代码中何时何地可用。 C/C ++和CircuitPython都在词法范围内。这意味着变量的范围由代码的结构定义。如果您在函数中创建变量,则该变量在该函数中可用,但不在外部。
下载:文件
复制代码
x = a[0]
a[1] = x + 1 void f() {
int a = 5;
print(a); // 1
}
print(a); // 2
由于void f() {
int a = 5;
print(a); // 1
}
print(a); // 2为范围。即它在函数a中定义,可以使用。但是,第2行会导致编译错误,因为此时名称f尚不清楚。在CircuitPython中,情况类似:
下载:文件
复制代码
a def f():
a = 5
print(a) # 1
print(a) # 2
Local and Global
上面的代码说明了本地状态。即局部于功能。这就是为什么从函数外部引用变量是一个问题。另一个范围是全局范围。在整个代码中都可以使用具有全局范围的内容。
下载:文件
复制代码
def f():
a = 5
print(a) # 1
print(a) # 2 int b = 1;
void f() {
int a = 5;
print(a + b);
}
print(b);
// prints:
// 6
// 1
这是可行的,因为int b = 1;
void f() {
int a = 5;
print(a + b);
}
print(b);
// prints:
// 6
// 1具有全局作用域,因此可以在。在CircuitPython中也是如此。
下载:文件
复制代码
b f
如果我们具有相同名称但在两个作用域中都有变量,该怎么办。现在事情开始不同了。在C/C ++中没有麻烦。
Download:file
Copy代码
b = 1
def f():
a = 5
print(a + b)
print(b)
# prints:
# 6
# 1 b = 1
def f():
a = 5
print(a + b)
print(b)
# prints:
# 6
# 1
但是,CircuitPython中的工作方式却大不相同。
下载:文件
复制代码
int a = 1;
void f() {
int a = 5;
print(a);
}
print(a);
// prints:
// 5
// 1 int a = 1;
void f() {
int a = 5;
print(a);
}
print(a);
// prints:
// 5
// 1
a = 1
def f():
a = 5 # 1
print(a)
print(a)
# prints:
# 5
# 1的分配可能存在问题。这是因为在本地作用域中没有名为“ a”的变量,因此将创建一个变量,因为这是该作用域中对a = 1
def f():
a = 5 # 1
print(a)
print(a)
# prints:
# 5
# 1的第一个赋值。对于该功能的其余部分,将使用此局部变量a,并且将保持不变(且未使用)全局范围内的变量a。
如果这正是您想要的,很好。但是,您的意图可能是将全局a的值更改为5。如果是这种情况,那么您就有问题了。像pylint这样的工具将提醒您以下事实:外部范围(在本例中为全局范围)的名称“ a”正在重新定义。那至少会引起您的注意。如果确实要使用全局a,则可以使用a语句告诉CircuitPython这是您的意图。
下载:文件
复制代码
a global
现在pylint可能会警告您,您正在使用全局语句。这是因为全局变量通常不被接受。但是用一个简单的脚本就可以了(在作者看来)。在更大,结构更强的程序中,它们使用较少,您有办法避免使用它们。
CircuitPython和C/C ++不能共享的一项有趣功能是能够关闭。
数字输入/输出
格雷厄姆·詹金斯(Grahame Jenkins)提供的UnSplash免费许可证
微控制程序的一部分正在使用I/O。 I/O的最基本形式是数字I/O引脚。这些被称为GPIO引脚( G 通用 P 设置 I 输入 O utput)
快速参考 配置输出引脚
Arduino
pinMode(13, OUTPUT);
CircuitPython
import digitalio
import board
led = digitalio.DigitalInOut(board.D13)
led.direction = digitalio.Direction.OUTPUT
为输入引脚配置而不上拉
Arduino
pinMode(13, INPUT);
CircuitPython
import digitalio
import board
button_a = digitalio.DigitalInOut(board.BUTTON_A)
button_a.direction = digitalio.Direction.INPUT
配置带有上拉的输入引脚
Arduino
pinMode(13, INPUT_PULLUP);
CircuitPython
import digitalio
import board
button_a = digitalio.DigitalInOut(board.BUTTON_A)
button_a.direction = digitalio.Direction.INPUT
button_a.pull = digitalio.Pull.UP
从引脚读取
Arduino
int pinValue = digitalRead(inputPin);
CircuitPython
pinValue = button_a.value
写到别针
Arduino
digitalWrite(13, HIGH);
digitalWrite(13, LOW);
CircuitPython
led.value = True
led.value = False
讨论
配置数字I/O引脚
在使用引脚进行输入或输出之前,必须对其进行配置。这涉及将其设置为输入或输出,以及在需要时附加上拉或下拉。
Arduino
Arduino框架提供了pinMode为此。它带有两个参数:
正在配置的引脚号。您以后可以使用相同的引脚号来使用I/O线
模式:INPUT,OUTPUT或INPUT_PULLUP。
要将标准的插针13板载LED设置为可用,您将使用:
下载:文件
复制代码
pinMode(13, OUTPUT); pinMode(13, OUTPUT);
CircuitPython
在CircuitPython中,还有很多工作要做。您需要创建一个DigitalInOut实例。为此,您必须首先导入digitalio模块。像在Arduino示例中一样,给它提供要使用的引脚号。
在上面的Arduino示例中,我们如何知道要使用的引脚号?简短的答案是我们刚刚做了。在此示例中,一个约定是板载LED位于引脚13上。对于其他GPIO引脚,您需要检查所使用的板,以查看可用的引脚以及将电路连接到的引脚。
在Arduino中,没有编译时检查您选择的引脚是否有效或存在。 CircuitPython只允许您使用板子知道的管脚,这可以防止您输入错误。
(如果您导入板子模块(稍后再介绍),您可以使用它列出可用的管脚。 )
下载:文件
复制代码
》》》 import digitalio
》》》 import board
》》》 led = digitalio.DigitalInOut(board.D13)
》》》 led.direction = digitalio.Direction.OUTPUT 》》》 import digitalio
》》》 import board
》》》 led = digitalio.DigitalInOut(board.D13)
》》》 led.direction = digitalio.Direction.OUTPUT
如果需要输入,可以使用digitalio.Direction.INPUT,如果需要设置上拉,则可以单独进行。
下载:文件
复制代码
》》》 import digitalio
》》》 import board
》》》 button_a = digitalio.DigitalInOut(board.BUTTON_A)
》》》 button_a.direction = digitalio.Direction.INPUT
》》》 button_a.pull = digitalio.Pull.UP 》》》 import digitalio
》》》 import board
》》》 button_a = digitalio.DigitalInOut(board.BUTTON_A)
》》》 button_a.direction = digitalio.Direction.INPUT
》》》 button_a.pull = digitalio.Pull.UP
CircuitPython运行的SAMD板还支持在输入引脚上设置下拉。为此,您将使用
下载:文件
复制代码
》》》 pin.pull = digitalio.Pull.DOWN 》》》 pin.pull = digitalio.Pull.DOWN
使用数字I/O引脚
现在您已经设置了引脚,如何读取和写入值?
Arduino
该框架提供了digitalRead函数,该函数以引脚号作为参数。
下载:文件
复制代码
int pinValue = digitalRead(inputPin); int pinValue = digitalRead(inputPin);
从digitalRead返回的值是int类型,将是常量HIGH或LOW之一。
digitalWrite功能用于设置引脚值。它的参数是引脚号和将其设置为的值:HIGH或LOW。例如,假设已如上所述将其设置为输出,则打开连接到引脚13的LED,您可以使用:
下载:文件
复制代码
digitalWrite(13, HIGH); digitalWrite(13, HIGH);
并关闭它:
下载:文件
复制代码
digitalWrite(13, LOW); digitalWrite(13, LOW);
此处的示例显示了如何使用数字输出引脚来闪烁内置的LED:微控制器编程的事实上的 Hello World 。
下载:文件
复制代码
void setup()
{
pinMode(13, OUTPUT); // sets the digital pin 13 as output
}
void loop()
{
digitalWrite(13, HIGH); // sets the digital pin 13 on
delay(1000); // waits for a second
digitalWrite(13, LOW); // sets the digital pin 13 off
delay(1000); // waits for a second
}
void setup()
{
pinMode(13, OUTPUT); // sets the digital pin 13 as output
}
void loop()
{
digitalWrite(13, HIGH); // sets the digital pin 13 on
delay(1000); // waits for a second
digitalWrite(13, LOW); // sets the digital pin 13 off
delay(1000); // waits for a second
}
将数字输入和输出放在一起,下面是一个示例,该示例从开关读取并控制LED作为响应。
下载:文件
复制代码
int ledPin = 13; // LED connected to digital pin 13
int inPin = 7; // pushbutton connected to digital pin 7
int val = 0; // variable to store the read value
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output
pinMode(inPin, INPUT); // sets the digital pin 7 as input
}
void loop()
{
val = digitalRead(inPin); // read the input pin
digitalWrite(ledPin, val); // sets the LED to the button‘s value
} int ledPin = 13; // LED connected to digital pin 13
int inPin = 7; // pushbutton connected to digital pin 7
int val = 0; // variable to store the read value
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output
pinMode(inPin, INPUT); // sets the digital pin 7 as input
}
void loop()
{
val = digitalRead(inPin); // read the input pin
digitalWrite(ledPin, val); // sets the LED to the button’s value
}
CircuitPython
假设led和switch的设置如上所述。
输入引脚可以通过查询其value属性进行读取:
下载:文件
复制代码
》》》 button_a.value 》》》 button_a.value
我们可以通过设置value属性来打开和关闭led = 1》反对一个布尔值:
下载:文件
复制代码
DigitalInOut 》》》 led.value = True
》》》 led.value = False
要在CircuitPython中实现闪烁的演示,我们将做一些类似的事情:
下载:文件
复制代码
》》》 led.value = True
》》》 led.value = False 》》》 import time
》》》 import digitalio
》》》 import board
》》》 led = digitalio.DigitalInOut(board.D13)
》》》 led.direction = digitalio.Direction.OUTPUT
》》》 while True:
。.. led.value = True
。.. time.sleep(0.5)
。.. led.value = False
。.. time.sleep(0.5)
模拟输入
快速参考
配置模拟输入引脚
Arduino
不需要
CircuitPython
import board
import analogio
adc = analogio.AnalogIn(board.A0)
使用模拟输入引脚
Arduino
int val = analogRead(3);
CircuitPython
adc.value
讨论
配置模拟输入引脚
Arduino
配置模拟输入引脚不需要任何特殊操作。需要以与数字输出引脚相同的方式将模拟输出引脚配置为输出。请注意,仅某些引脚可以用作模拟引脚。查看特定电路板的文档以查找哪些电路板。
CircuitPython
在CircuitPython中使用模拟引脚类似于
像以前一样,使用board模块可以按名称访问正确的引脚。另外,analogio模块为您提供模拟I/O类。
要读取模拟输入,您需要创建AnalogIn的实例:
下载:文件
复制代码
》》》 import board
》》》 import analogio
》》》 adc = analogio.AnalogIn(board.A0) 》》》 import board
》》》 import analogio
》》》 adc = analogio.AnalogIn(board.A0)
要设置模拟输出,请创建一个AnalogOut实例。
下载:文件
复制代码
》》》 import board
》》》 import analogio
》》》 led = analogio.AnalogOut(board.A0) 》》》 import board
》》》 import analogio
》》》 led = analogio.AnalogOut(board.A0)
使用模拟输入引脚
Arduino
模拟I/O与数字类似。不同的板可以具有不同数量和位置的模拟引脚。查看您的文档以获取有关主板功能的详细信息。
下载:文件
复制代码
int val = analogRead(3); int val = analogRead(3);
返回的值是一个介于0和1023之间(包括0和1023)的int。该范围假设一个10位模数转换器。通常,模数转换器中的位数决定范围,范围是0到2 bits -1。例如。一个12位转换器将得出0到4095之间的值。请参考您开发板的文档以找到转换器的大小。
CircuitPython
具有上面所示的AnalogIn对象后,只需获取其value属性:
下载:文件
复制代码
adc.value adc.value
在CircuitPython中,模拟如上所示,您输入的输入值将始终在0到65535之间。这并不意味着总会有一个16位转换器。相反,将从转换器读取的值映射到16位范围。这使您不必担心板上的转换器的详细信息。
AnalogIn对象为您提供了一种方便的方法来查询转换器的参考电压,因此如果您需要了解要测量实际电压,只需使用以下代码即可。请记住,其结果将根据引脚上的电压以及参考电压而有所不同。
下载:文件
复制代码
》》》 adc.value / 65535 * adc.reference_voltage
3.2998 》》》 adc.value / 65535 * adc.reference_voltage
3.2998
模拟和PWM输出
快速参考
配置模拟输出引脚
Arduino
大多数开发板没有真正的模拟输出。
CircuitPython
import board
import analogio
dac = analogio.AnalogOut(board.A1)
使用模拟输出引脚
Arduino
大多数板子都没有真正的模拟输出。
CircuitPython
dac.value = 32767
PWM输出引脚
Arduino
不需要
CircuitPython
import board
import pulseio
led = pulseio.PWMOut(board.A1)
使用PWM输出引脚
Arduino
analogWrite(9, 128);
CircuitPython
led.duty_cycle = 32767
讨论 Arduino
直接写入模拟引脚。从技术上讲,这通常不是真正的模拟值,而是PWM信号。即您正在写入的值将设置PWM信号的占空比。范围是0-255(含)。 analogWrite用于此目的,和digitalWrite一样,用于获取引脚和值。
Arduino DUE具有2个实际的模数转换器,可输出实际的模拟电压,而不是输出
下载:文件
复制代码
analogWrite(pin, val);
analogWrite(pin, val);
将它们放在一起,我们可以从模拟引脚读取并写入另一个引脚。区别在于需要容纳值范围,这就是4的除法。
下载:文件
复制代码
int ledPin = 9; // LED connected to digital pin 9
int analogPin = 3; // potentiometer connected to analog pin 3
int val = 0; // variable to store the read value
void setup()
{
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop()
{
val = analogRead(analogPin); // read the input pin
analogWrite(ledPin, val / 4); // analogRead values go from 0 to 1023, analogWrite values from 0 to 255
} int ledPin = 9; // LED connected to digital pin 9
int analogPin = 3; // potentiometer connected to analog pin 3
int val = 0; // variable to store the read value
void setup()
{
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop()
{
val = analogRead(analogPin); // read the input pin
analogWrite(ledPin, val / 4); // analogRead values go from 0 to 1023, analogWrite values from 0 to 255
}
CircuitPython
》 CircuitPython硬件上有两种类型的模拟输出:真实模拟和PWM(与Arduino一样)。
对于真实模拟输出,AnalogOut对象的value参数设置为a值介于0到65535之间,与AnalogInput的值范围相同:0将输出设置为0v,65535将其设置为参考电压。
下载:文件
复制代码
dac.value = 32767 dac.value = 32767
一个相关的输出功能是PWM(脉冲宽度调制)。它以完全不同的方式完成。代替使用analogio模块,您需要使用pulseio并使用要在其上生成信号的Pin创建一个PWMOut对象。
下载:文件
复制代码
》》》 import board
》》》 import pulseio
》》》 led = pulseio.PWMOut(board.A1) 》》》 import board
》》》 import pulseio
》》》 led = pulseio.PWMOut(board.A1)
一个PWMOut对象,可以将其占空比(输出为高的时间百分比)设置为16位整数(0-65535)。例如:
下载:文件
复制代码
# set the output to 100% (always high)
》》》 led.duty_cycle = 65535
# set the output to 0% (always low)
》》》 led.duty_cycle = 0
# set the output to 50% (high half the time)
》》》 led.duty_cycle = 32767 # set the output to 100% (always high)
》》》 led.duty_cycle = 65535
# set the output to 0% (always low)
》》》 led.duty_cycle = 0
# set the output to 50% (high half the time)
》》》 led.duty_cycle = 32767
时间
苏甘斯摄在Unsplash
快速参考
延迟
Arduino
delay(1500);
CircuitPython
import time
time.sleep(1.5)
》
系统时间
Arduino
unsigned long now = millis();
CircuitPython
import time
now = time.monotonic()
讨论
能够等待特定的时间时间在许多项目中都很重要。
Arduino和CircuitPython的处理方法非常相似。
延迟 Arduino
该函数用于等待特定时间, delay,已内置在Arduino框架中。不需要#include。单个参数是延迟时间,以毫秒为单位。
一个示例是如下所示的简单闪烁LED代码:
下载:文件
复制代码
int ledPin = 13; // LED connected to digital pin 13
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
void loop()
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
} int ledPin = 13; // LED connected to digital pin 13
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
void loop()
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}
每次打开或关闭delay以创建闪烁的灯光时,ledPin函数都会等待一秒钟(1000毫秒)。
CircuitPython
CircuitPython中与delay等效的函数是time.sleep函数。默认情况下不包含time模块,必须将其导入到程序中。
传递给time.sleep的参数是延迟时间(以秒为单位)。 》(不是毫秒)。该值可以是十进制,因此如果要等待一秒钟,请放入1.0,如果要等待50毫秒,则为0.050。
下面的代码重复打印单词Hello。打印件之间的间隔为0.1秒,即100毫秒。
下载:文件
复制代码
import time
while True:
print(“Hello”)
time.sleep(0.1) import time
while True:
print(“Hello”)
time.sleep(0.1)
Djim Loic在Unsplash上拍摄的照片
获取系统时间
通常,微控制器和单板计算机通常缺少实时时钟(RTC)模块来了解时间。每个系统通常具有的功能是对自打开电源以来的时间进行计数。对于完成一段时间的某些工作而言,这仍然很有用。
Arduino
要获取自Arduino开发板以来的时间,常用功能是millis。它没有任何参数,并返回自从上次打开该板电源以来的毫秒数。
以下代码草图显示了每秒从串行端口上电以来的时间(1000毫秒)。
下载:文件
复制代码
unsigned long initial;
void setup(){
Serial.begin(9600);
initial = millis();
}
void loop(){
unsigned long now;
now = millis();
if( now - initial 》 3 ) { // Print done after 3 milliseconds elapses
Serial.print(“done”);
}
else {
initial = now;
}
} unsigned long initial;
void setup(){
Serial.begin(9600);
initial = millis();
}
void loop(){
unsigned long now;
now = millis();
if( now - initial 》 3 ) { // Print done after 3 milliseconds elapses
Serial.print(“done”);
}
else {
initial = now;
}
}
CircuitPython
Python具有许多时间函数。但是许多板卡都遇到了与Arduino发现的相同的问题-没有RTC。
CircuitPython具有与Arduino delay类似的功能,称为time.monotonic。但是它返回的是秒,而不是像delay那样的毫秒。
注意,不建议比较大于一小时的时间,因为该值将开始四舍五入,可能会浪费时间,从而造成准确性。
下载:文件
复制代码
import time
initial = time.monotonic() # Time in seconds since power on
while True:
now = time.monotonic()
if now - initial 》 0.003: # If 3 milliseconds elapses
print(“done”)
else:
initial = now import time
initial = time.monotonic() # Time in seconds since power on
while True:
now = time.monotonic()
if now - initial 》 0.003: # If 3 milliseconds elapses
print(“done”)
else:
initial = now
参考 Arduino
Arduino参考
延迟
millis
CircuitPython
时间-与时间和计时相关的功能
库和模块
长爱尔兰都柏林三一学院室内。来自Wikipedia的用户Diliff,CC BY-SA 4.0
快速参考
Arduino
include
CircuitPython
import time
讨论
Arduino和CircuitPython都提供了一种从正在处理的文件外部提取代码的方法。这可能是您编写的另一个文件,是框架的一部分,或者是传感器支持模块。
Arduino
C和C ++将代码分为代码文件(分别以.c或.cpp结尾)和头文件(以.h结尾)。 Arduino环境为您的草图/程序的主文件收取了少量费用。它以.ino结尾。
头文件通常包含函数和全局变量声明以及宏和类型定义。在C ++中,类定义也位于此处。代码文件包含函数定义。头文件提供了到库的接口,告诉您的代码如何访问/调用库的工具。
要使用头文件(及其包含的库)您包括它:
下载:文件
复制代码
#include #include
现在,您的代码可以使用string.h中定义的函数和类型,该函数和类型是字符串的集合操作功能,例如strcpy()用于复制字符串。
CircuitPython
所有CircuitPython代码文件均具有.py扩展名(结束)。没有定义接口的单独文件。
CircuitPython具有与Arduino/C相似的机制,称为模块。代码创建者为特定目的收集了一组功能并创建了一个模块。
预编译的模块具有.mpy文件扩展名。并非所有模块都必须预先编译,这样只会节省空间。
使用CircuitPython模块,则应将适当的文件(通常是.mpy文件)放置在开发板闪存驱动器上的/lib文件夹中。
“时间”页面上的较早位置, time模块已导入,并提供了两个功能:time.sleep和time.monotonic。
请注意,当您如上所述导入模块时,不能仅引用里面的东西,你必须给它们加上模块名的前缀。即time.monotonic(),而不仅仅是monotonic()。有很多方法可以避免这种情况,但这超出了本指南的范围。
下载:文件
复制代码
import time
while True:
print(“Hello”)
time.sleep(0.1) import time
while True:
print(“Hello”)
time.sleep(0.1)
CircuitPython无法将完整的Python/CPython可用的大型模块导入为微控制器上的内存非常有限。
Adafruit致力于提供大量模块来支持广泛的硬件。这包括传感器,显示器,智能LED(NeoPixel等)等等。正如Adafruit是提供开源Arduino库的领导者一样,Adafruit也在Python世界中努力做到这一点。
Python模块有更多功能,但以上内容基础。有关更多信息,请参见此类Python参考。
有关最新的CircuitPython模块的信息,请参考Adafruit GitHub存储库。
董事会模块
图片作者:Unsplash上的rawpixel
您正在微控制器板上编写嵌入式代码。这几乎总是意味着您正在通过董事会的一些图钉与外界互动。您如何知道哪些代码在做什么,以及在代码中使用哪些代码?
Arduino
在编译之前在Arduino IDE中,选择要使用的板。这基本上告诉了编译器信息,该信息需要专门针对MCU和该特定板的配置进行编译。但是,那无助于知道使用什么引脚。您必须查看电路板的文档并弄清楚。 Arduino硬件平台提供了一些有用的标准。您将始终有一些以“ D”为前缀的引脚。这些用于数字I/O。有些将以“ A”为前缀。这些可以用于模拟信号,但并非全部都支持真实的模拟输出。
将有I2C(SCL和SDA)和SPI(MOSI,MISO和SCK)引脚。在代码中,您将使用适当的管脚编号,尽管某些板具有在Arduino IDE中选择板时可使用的那些管脚的预定义值。
CircuitPython
CircuitPython采用了非常不同的方法来处理各种受支持的电路板。首先,CircuitPython驻留在板上,而Arduino是计算机上的一组工具,该工具会生成一个二进制文件,然后将其保存在板上。
进行此项工作的一部分是制作以下版本的CircuitPython:特定于每个受支持的板。例如,如果您想将CircuitPython与Feather M4 Express一起使用,则可以得到CircuitPython的Feather M4 Express版本,并将其放到Feather M4 Express板上。有关详细信息,请参见本指南。
之所以如此重要,是因为CircuitPython知道其运行在哪个板上,并且知道该板上的功能,以及该板上的引脚是什么。以及他们可以做什么。
要使此功能可用,您可以导入board模块。该模块包含特定板上引脚的常数。 CircuitPython中用于另一块板的board模块将具有特定于该板的不同常量。知道,用户不必告诉CircuitPython它在什么板上运行。
所有这些使使用板模块成为使用板引脚的最安全,最可靠的方法。它使您不必担心板子引脚连接到哪个MCU引脚。对于围绕ARM内核构建的更复杂的MCU(例如SAMD或nRF52系列MCU),这更是一个问题。
例如,可以将I2C信号连接到MCU有多种方式(我们将不介绍),但是使用板卡模块,您可以轻松执行以下操作:
下载:文件
复制代码
import board
import busio
i2c = busio.I2C(board.SCL, board.SDA) import board
import busio
i2c = busio.I2C(board.SCL, board.SDA)
这将在CircuitPython中任何受支持的板上工作。/p》
那么您如何知道板上有哪些引脚可用?他们叫什么?您可以使用CircuitPython的dir函数。这是在Circuit Playground Express上:
下载:文件
复制代码
》》》 import board
》》》 dir(board)
[‘A0’, ‘A1’, ‘A2’, ‘A3’, ‘A4’, ‘A5’, ‘A6’, ‘A7’, ‘A8’, ‘A9’,
‘ACCELEROMETER_INTERRUPT’, ‘ACCELEROMETER_SCL’,
‘ACCELEROMETER_SDA’, ‘BUTTON_A’, ‘BUTTON_B’, ‘D0’, ‘D1’,
‘D10’, ‘D12’, ‘D13’, ‘D2’, ‘D3’, ‘D4’, ‘D5’, ‘D6’, ‘D7’,
‘D8’, ‘D9’, ‘I2C’, ‘IR_PROXIMITY’, ‘IR_RX’, ‘IR_TX’, ‘LIGHT’,
‘MICROPHONE_CLOCK’, ‘MICROPHONE_DATA’, ‘MISO’, ‘MOSI’,
‘NEOPIXEL’, ‘REMOTEIN’, ‘REMOTEOUT’, ‘RX’, ‘SCK’, ‘SCL’,
‘SDA’, ‘SLIDE_SWITCH’, ‘SPEAKER’, ‘SPEAKER_ENABLE’, ‘SPI’,
‘TEMPERATURE’, ‘TX’, ‘UART’]
》》》 》》》 import board
》》》 dir(board)
[‘A0’, ‘A1’, ‘A2’, ‘A3’, ‘A4’, ‘A5’, ‘A6’, ‘A7’, ‘A8’, ‘A9’,
‘ACCELEROMETER_INTERRUPT’, ‘ACCELEROMETER_SCL’,
‘ACCELEROMETER_SDA’, ‘BUTTON_A’, ‘BUTTON_B’, ‘D0’, ‘D1’,
‘D10’, ‘D12’, ‘D13’, ‘D2’, ‘D3’, ‘D4’, ‘D5’, ‘D6’, ‘D7’,
‘D8’, ‘D9’, ‘I2C’, ‘IR_PROXIMITY’, ‘IR_RX’, ‘IR_TX’, ‘LIGHT’,
‘MICROPHONE_CLOCK’, ‘MICROPHONE_DATA’, ‘MISO’, ‘MOSI’,
‘NEOPIXEL’, ‘REMOTEIN’, ‘REMOTEOUT’, ‘RX’, ‘SCK’, ‘SCL’,
‘SDA’, ‘SLIDE_SWITCH’, ‘SPEAKER’, ‘SPEAKER_ENABLE’, ‘SPI’,
‘TEMPERATURE’, ‘TX’, ‘UART’]
》》》
这是在Gemma M0上:
下载:文件
复制代码
》》》 import board
》》》 dir(board)
[‘A0’, ‘A1’, ‘A2’, ‘APA102_MOSI’, ‘APA102_SCK’, ‘D0’,
‘D1’, ‘D13’, ‘D2’, ‘I2C’, ‘L’, ‘RX’, ‘SCL’, ‘SDA’, ‘SPI’,
‘TX’, ‘UART’]
》》》 import board
》》》 dir(board)
[‘A0’, ‘A1’, ‘A2’, ‘APA102_MOSI’, ‘APA102_SCK’, ‘D0’,
‘D1’, ‘D13’, ‘D2’, ‘I2C’, ‘L’, ‘RX’, ‘SCL’, ‘SDA’, ‘SPI’,
‘TX’, ‘UART’]
您可以看到有一些共同的引脚,但也有特定于主板的引脚。
责任编辑:wv
-
编程
+关注
关注
88文章
3578浏览量
93548 -
Arduino
+关注
关注
187文章
6461浏览量
186554
发布评论请先 登录
相关推荐
评论