1

我想为 arduino 创建一个程序,以便能够在我想要的时候添加和删除控制某些引脚的规则,而不是对它们进行硬编码。例如这样的规则:

如果 pin1=HIGH 且 pin2=LOW 则 pin3=HIGH

我想变成这样:

if(pin1 == HIGH && pin2 == LOW){
   digitalWrite(pin3, HIGH);
}

假设我们通过命令行将规则作为字符串传递。如何将此字符串转换为规则?这样的事情可能吗?

4

3 回答 3

1

您所要求的是可能的,但您需要做很多工作。


方法1(想大局):

您正在寻找的是与 PAL(可编程阵列逻辑)和 CPLD(复杂可编程逻辑器件)的操作方式等效的软件实现。如果你阅读这篇文章,你会得到一些关于这是如何在硬件中完成的想法:

维基百科关于 PLD 的文章

PAL 可以在一组输入和输出之间创建任意组合逻辑规则,即可以对任何可以表示为 AND、OR 和 NOT 的逻辑方程的内容进行编程。它是通过“烧毁”一组将输入连接到逻辑门然后连接到输出的保险丝来编程的。上传到这些设备的只是一组 0 和 1。

您可以在软件中使用 0 和 1 的数组来表示保险丝。硬代码将在数组上运行并计算输出。您需要开发使用正确保险丝加载阵列的方法。

对 PAL 进行编程的常用方法是使用语言 VHDL。该语言的编译器采用与您类似的表达式并将其转换为 PAL 可以使用的 AND、OR 和 NOT 集合。搜索将产生对该语言的无休止讨论,例如:

VHDL教程

您必须创建接受文本输入并确定保险丝的编译器。您将执行一些重要任务:

  • 一个特定领域的语言解析器(我可以推荐 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 和微控制器是一个强大的组合。

于 2013-06-08T05:43:58.097 回答
1

您的第二段代码:

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 解释器并调整其中之一。

于 2013-06-07T19:16:12.963 回答
0

要添加到@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];
}

然后,您可以添加要从串行读取的内容并将新值动态加载到表中。

于 2013-06-11T12:52:44.083 回答