我想为 arduino 创建一个程序,以便能够在我想要的时候添加和删除控制某些引脚的规则,而不是对它们进行硬编码。例如这样的规则:
如果 pin1=HIGH 且 pin2=LOW 则 pin3=HIGH
我想变成这样:
if(pin1 == HIGH && pin2 == LOW){
digitalWrite(pin3, HIGH);
}
假设我们通过命令行将规则作为字符串传递。如何将此字符串转换为规则?这样的事情可能吗?
我想为 arduino 创建一个程序,以便能够在我想要的时候添加和删除控制某些引脚的规则,而不是对它们进行硬编码。例如这样的规则:
如果 pin1=HIGH 且 pin2=LOW 则 pin3=HIGH
我想变成这样:
if(pin1 == HIGH && pin2 == LOW){
digitalWrite(pin3, HIGH);
}
假设我们通过命令行将规则作为字符串传递。如何将此字符串转换为规则?这样的事情可能吗?
您所要求的是可能的,但您需要做很多工作。
方法1(想大局):
您正在寻找的是与 PAL(可编程阵列逻辑)和 CPLD(复杂可编程逻辑器件)的操作方式等效的软件实现。如果你阅读这篇文章,你会得到一些关于这是如何在硬件中完成的想法:
PAL 可以在一组输入和输出之间创建任意组合逻辑规则,即可以对任何可以表示为 AND、OR 和 NOT 的逻辑方程的内容进行编程。它是通过“烧毁”一组将输入连接到逻辑门然后连接到输出的保险丝来编程的。上传到这些设备的只是一组 0 和 1。
您可以在软件中使用 0 和 1 的数组来表示保险丝。硬代码将在数组上运行并计算输出。您需要开发使用正确保险丝加载阵列的方法。
对 PAL 进行编程的常用方法是使用语言 VHDL。该语言的编译器采用与您类似的表达式并将其转换为 PAL 可以使用的 AND、OR 和 NOT 集合。搜索将产生对该语言的无休止讨论,例如:
您必须创建接受文本输入并确定保险丝的编译器。您将执行一些重要任务:
一个特定领域的语言解析器(我可以推荐 ANTLR),
一个 PAL 编译器(我不能推荐任何人自己做这个),和
用于模拟 PAL 的 Arduino 代码。
当您创建自己的 VHDL 和 PAL 等价物时,您可能会认为您可以将 PAL 芯片放在原型板上并完成。
方法2(更实用):
实现相同结果的更简单方法是真值表。真值表相当于一组逻辑表达式。要实现真值表,请将您的逻辑表达式转换为每个输入案例一行的表。以下是驱动输出的两个输入的真值表示例:
IN1 IN2 OUT
0 0 1
0 1 0
1 0 1
1 1 1
这种真值表实现的代码如下所示:
const int IN1 = 6;
const int IN2 = 7;
const int OUTA = 13;
byte table[4] = {1, 0, 1, 1};
void loop() {
int in1;
int in2;
byte outbit;
size_t ix;
//
in1 = digitalRead(IN1);
in2 = digitalRead(IN2);
ix = in2 * 2 + in1;
outbit = table[ix];
digitalWrite(OUTA, outbit);
}
逻辑规则的完整表达式是 4 个字节的数组。要“编程”一个新的输出方程,您只需发送一组新的 4 个值,对于您的特定方程,您发送“0 0 1 0”。您的程序将接收值列表并将它们存储在表数组中。一旦存储了新的值/规则,输出的功能就会改变。
只要您有足够的 RAM 来存储表格,这种类型的可编程逻辑是可行的。对于 4 个输入,您只需要 16 个值,对于 5 个输入,您只需要 32 个。
您的问题在电子设计中提出了一个敏锐的观点:您需要为正确的问题选择正确的设备。代码并不总是更好或更容易。避免锤钉陷阱(当你唯一的工具是锤子时,每个问题看起来都像钉子)。PAL/CPLD 和微控制器是一个强大的组合。
您的第二段代码:
if(pin1 == HIGH && pin2 == LOW){
digitalWrite(pin3, HIGH);
}
由您的 IDE 编译成机器码。然后将该机器代码上传到 Arduino 并执行。
因此,您不能只发送这样的字符串
if pin1=HIGH and pin2=LOW then pin3=HIGH
到 Arduino,因为在您的程序将其转换为所需的形式后,Arduino 端缺少完整的 IDE 和编译器内容。而且一个 C++ 编译器工具链很大——几十兆!在 Arduino 上没有这样的地方。
你可以做什么:为你的规则发明一种简单的语言,并为它开发一个解释器,然后在 Arduino 上运行。
也许您也不需要重新发明轮子 - 谷歌搜索在 AVR CPU 上运行的简单 BASIC 解释器并调整其中之一。
要添加到@jdr5ca 提到的真值表方法,最好了解 arduino 中使用的控制器以及使用 ardiuno 库。
引脚 0 到 7 是端口 D,引脚 8 到 15 是端口 B。每个端口表示为三个单字节寄存器 - PORT_ 是输出/偏置电阻,PIN_ 是输入状态,DDR_ 是方向。当您调用digitalRead(pin)
代码时,会查看引脚所在的范围,读取PIN_
该端口,然后移位并屏蔽该值以仅给出该引脚的状态。这对于一次阅读一个大头针很方便,但不如你阅读几个大头针那么方便。
因此,如果您创建一个包含 256 个条目的真值表,您可以使用单行将输入 0 到 7 的值写入引脚 8 到 15 的输出,而不是将寄存器解码为引脚然后再次对其进行编码:
byte table[256] = {0};
void loop() {
PORTB = table[PIND];
}
然后,您可以添加要从串行读取的内容并将新值动态加载到表中。