我可以在Arduino上使用14个以上的输出引脚吗?我正在一个项目中,我需要单独点亮几个LED。我只有一个Arduino Uno,我不想买一个Mega。
我可以在Arduino上使用14个以上的输出引脚吗?我正在一个项目中,我需要单独点亮几个LED。我只有一个Arduino Uno,我不想买一个Mega。
Answers:
扩展Arduino上可用输出引脚集的一种常见方法是使用移位寄存器,例如74HC595 IC(链接到数据表)。
您需要3个引脚来控制这些芯片:
在程序中,您可以使用shiftOut()命令一次将数据一次传递给移位寄存器,如下所示:
shiftOut(dataPin, clockPin, data);
使用该命令,可以使用data
变量中的8位设置595 IC上的8个输出中的每个输出。
使用一个595,您将获得5个引脚(IC上有8个引脚,但要花费3个与之对话)。要获得更多输出,您可以通过将595的串行输出引脚连接到下一个595的数据引脚,以菊花链的方式将它们串联在一起。您还必须将所有595 IC的时钟和锁存引脚连接在一起。
生成的电路(使用一个595)如下所示:
上图取自此codeproject.com网页:
锁存引脚用于在将数据移出时使595输出保持稳定,如下所示:
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, data);
digitalWrite(latchPin, HIGH);
您可以通过两种方式从arduino中获取更多的引脚。
第一种方法是将模拟引脚用作数字输出引脚,这确实很容易做到。您需要做的只是将A0-A5用作引脚14,15,16,17,18,19。例如,要向引脚A0写入高电平,只需使用digitalWrite(14,HIGH)。
从Arduino获得更多引脚的另一种方法是使用移位寄存器。为此,我建议使用EZ-Expander Shield,它允许您在导入EZ-Expander库时使用digitalWrite([20-35],HIGH)。但是,该屏蔽仅允许将引脚用作输出,并使用引脚8,12和13来控制移位寄存器。
很棒的是,您可以同时使用上述两种方法,而不会出现任何问题。
A0
- A5
标识符,而不是使用数字14-19。例如,digitalWrite(A0, HIGH)
。
digitalWrite(A0)
要正确得多digitalWrite(14)
。在另一块板上,pin 14
实际上可能不是A0
,例如pin 14
在MEGA上为Serial3,TX
并且不会影响您要使用的模拟引脚。即,如果digitalWrite
在模拟引脚上使用,请使用A0
- A5
参考。
如果要驱动LED,那么还可以使用MAX7219,它可以驱动64个LED,而无需额外的电路(不需要晶体管来放大信号)。
驱动MAX7219在Arduino上仅需要3个输出引脚。另外,您可以找到一些Arduino库。
如果需要为64个以上的LED供电,则还可以将其中的几个链接起来。
我已成功将其用于多个7段LED显示器。
缺点:价格昂贵(约10美元)。
您可以使用Charlieplexing。使用这种技术,您可以直接n*(n-1)
从n个引脚驱动LED。因此,使用3针可以驱动6个LED,4针-12个LED,5针-20个LED等。
范例:
3个引脚上的六个LED
PINS LEDS
0 1 2 1 2 3 4 5 6
0 0 0 0 0 0 0 0 0
0 1 Z 1 0 0 0 0 0
1 0 Z 0 1 0 0 0 0
Z 0 1 0 0 1 0 0 0
Z 1 0 0 0 0 1 0 0
0 Z 1 0 0 0 0 1 0
1 Z 0 0 0 0 0 0 1
0 0 1 0 0 1 0 1 0
0 1 0 1 0 0 1 0 0
0 1 1 1 0 0 0 1 0
1 0 0 0 1 0 0 0 1
1 0 1 0 1 1 0 0 0
1 1 0 0 0 0 1 0 1
1 1 1 0 0 0 0 0 0
您可以在这里看到更好的教程。
您可以使用I 2 C协议(Wire库)连接到其他设备,例如端口扩展器。例如,MCP23017。
我用其中一种芯片连接到LCD板上。MCP23017具有16个端口,可以配置为输入或输出。如果需要,它们可以作为中断输入。
将这16个中的13个连接到LCD的示例:
现在,我们仅使用两根电线(SDA / SCL)加上电源和地线即可连接到Arduino:
一些第三方制造商制造的板上带有4个MCP23017,这为您提供了64个输入/输出:
您可以使用诸如74HC4051(8个端口)或74HC4067(16个端口)之类的模拟多路复用器将一个引脚连接到8/16端口之一(但在给定时间只能连接一个),如下所示:
它们是双向的,因此可以用作输入或输出扩展器。
使用SPI可以将快速串行数据发送到移位寄存器,例如74HC595。这些可以菊花链在一起。在此示例中,我仅用3个I / O引脚(MOSI / MISO / SCK)加上电源和地来控制32个LED。
我在一个商业LED标识中发现72个LED由74HC595芯片驱动。
它具有9个芯片来驱动列(9 x 8 = 72个LED)和一个芯片来驱动行,采用多路复用配置。
如果您只想驱动LED,通常可以多路复用它们。MAX7219设计用于驱动LED矩阵,例如7段显示器,从而简化了这一过程:
或64个LED矩阵:
在这两种情况下,都可以通过菊花链方式链接在一起,例如:
所有这些示例仅使用Arduino的3个引脚(MOSI / MISO / SCK)加上电源和地。
前面提到的16端口端口扩展器(MCP23017)也带有SPI变体(MCP23S17),其功能几乎相同。它使用多一根电线,但是会更快。
LED灯条(如NeoPixel的灯条)有自己的协议。Josh Levine在Youtube上发布了一篇帖子,作者使用Duemilanove驾驶了1000多个像素!
移位寄存器已在其他答案中提到,它们绝对是许多项目的绝佳选择。它们便宜,简单,速度适中,通常可以链接在一起以增加更多输出。但是,它们有一个缺点,它们通常需要排他地使用几个引脚(2到4之间,具体取决于您如何设置它们)。
另一种选择是使用更高级的端口扩展器,例如16位MCP23017和MCP23S17。它们分别支持I2C和SPI,这意味着您可以将它们与其他几个设备(可能是不同类型)放置在总线上。总线上的每个设备都可以单独寻址,这意味着您只需要2或3个引脚即可与所有这些设备进行通信。更新速度通常非常快,因此您不太可能在Arduino项目中遇到显着的延迟(即传输延迟)。
在低水平上,使用I2C或SPI比简单的移位寄存器要复杂得多。但是,有Arduino的库代码可以帮助您解决这一问题。例如,请参见以下问题:如何在Arduino上使用I2C设备?
移位寄存器最常见的用途之一是在串行和并行接口之间进行转换。当需要更多的通用输入/输出引脚时,SIPO寄存器通常连接到微处理器的输出。这允许仅使用两个或三个引脚来控制多个二进制设备,但比并行I / O慢。
在链接的文章里卡多中,您可以看到移位寄存器的图。
这里发生的是,您将8个引脚的数据按顺序放置,并且对于每个时钟周期,移位寄存器将移位(将二进制数据从每个锁存器移至下一个锁存器),直到其“绕圈”,即第一位到达最后一针。移位寄存器还有一个输入,您可以在其中打开/关闭移位,以便在将数据移位到该位置后可以保持状态。有关简单的演示,请参见以下动画。
在这里,红灯是串行输入,而绿灯则表示此简化的SIPO移位寄存器中的锁存器状态。数据移到位置后,可以关闭移位,然后可以读取引脚。在这个例子中我移出了10101011
。
从这些示例中,您可以意识到串行传输比并行传输要慢,因为您必须等待移位寄存器将这些位移位到它们的位置。您将不得不等待与要加载的位相同数量的时钟滴答。这是您不能无限期地链接它们的众多原因之一,因为加载将花费很长时间。
正如您已经写过的,您可以将所有引脚(包括TX和RX)用作数字输出。我前一阵子做了一个演示,并录制了这个相当荒谬的项目的视频-20个20个LED的针脚。
如由彼得R.布龙菲尔德 在这里,你必须断开TX和RX上传。此外,您没有足够的引脚来读取传感器的可能的交互性,并且必须确保未达到总电流限制。不要忘记,如果直接用Arduino驱动它们,则限于5V led。
因此,强烈建议使用里卡多描述的通用移位寄存器和595 。
不久前,当我意识到更新引擎艺术家Dominik Jais的Kawaii我的焊接和编程部分(链接的文本为德语)时,我就使用了它们。
在这里,只有一堆595用于驱动8x11 led的显示。由于LED灯是从12V SMD LED 灯带上切下的,因此需要一个额外的电源和一些连接到移位寄存器输出引脚上的UDN2803A Darlington阵列。
其他通用方法包括使用PCF8574(A)8位端口扩展器,该扩展器通过I2C总线进行控制。
无论如何,我会先尝试一下595移位寄存器。
但是,如果需要控制几个RGB LED,则可能需要寻找更专业的解决方案。某些RGB led 灯带有自己的WS2812。这些细小片段可以级联(1-Wire总线),并通过它们在链中的位置进行寻址。
如果全部涉及LED,那么WS2812B LED灯带又或者驱动芯片本身呢?您仅需一根针即可控制几乎无限数量的LED!
尽管人们习惯于条状显示,但它们可以作为独立的LED使用(在Adafruit上称为neo像素)。或者,如果您仅驱动单色,则每个WS2811芯片可以通过将每个RGB输出用于单个LED来控制3个LED。
我最近刚创建了一个使用5个此类LED的项目:Door1打开/关闭,Door2打开/关闭,motor1激活,motor2激活和电源。“活动” LED是双重用途的,因为我有红色是来自活动电动机的输入,绿色是Arduino内部的活动标志。
只需安装1针和库即可,您可以控制任意数量的LED
我自己没有使用此方法,但是我在网页MUX-DEMUX:CD4051 Parlor Tricks上找到了这个巧妙的技巧
无论您选择使用哪种方法来驱动输出或读取输入(移位寄存器,多路复用器或直接使用Arduino引脚本身),都可以通过巧妙地使用并行电路对来形成双倍的输出或输入数量(以形成双路)。输入或输出 组),在每个并行分支上采用相反方向的二极管,并将输入/输出切换为高电平和低电平。
为了说明输出方法(在这种情况下为LED,请注意,不需要额外的二极管):
如果您在此示例中将一对LED视为“ bank”,并且要点亮LED_0,则需要将PIN 17设置为HIGH,将PIN 18设置为LOW。(引脚号令人困惑,但它们与后面的示例匹配,所以对我来说是光秃秃的)。要点亮LED_1,只需反转PINS。LED的二极管特性可防止电流沿相反方向流动,从而使另一方向保持关闭状态。
为了说明输入方法(在这种情况下为CdS,请注意,需要额外的二极管):
如果要在CdS光传感器上进行模拟读取,这会变得更加复杂。首先,您需要在每个传感器上增加一个二极管来控制流量。其次,由于您正在读取值,因此需要将输入拉高或拉低以防止其浮动。作为一个懒惰的人,我将使用内部上拉电阻将其拉高。要读取CdS_0,请将PIN 17模式设置为OUTPUT并将其设置为LOW。这使其成为地面。然后,将PIN 18模式设置为INPUT并将其设置为HIGH来接合上拉电阻。现在,您可以设置对PIN 18(也称为模拟引脚4)进行读取。要访问另一个传感器,只需切换模式和输出。
因此,如果您有一个CD4051 8端口多路复用器,使用Arduino上的5个引脚(而不是通常的3个),则可以获得16个输入或输出,或两者的混合。
同样,如果您具有4067 16端口多路复用器,则可以获得32个输入或输出,或两者的混合。
一个示例草图是:
/*
* Example of getting 16 i/o from 5 pins using a CD4051
*
* Based on tutorial and code by david c. and tomek n.* for k3 / malmö högskola
* http://www.arduino.cc/playground/Learning/4051?action=sourceblock&ref=1
*/
int selPin[] = { 14, 15, 16 }; // select pins on 4051 (analog A0, A1, A2)
int commonPin[] = { 17, 18}; // common in/out pins (analog A3, A4)
int led[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW }; // stores eight LED states
int CdSVal[] = { 0, 0, 0, 0 }; // store last CdS readings
int cnt = 0; // main loop counter
int persistDelay = 100; // LED ontime in microseconds
void setup(){
Serial.begin(9600); // serial comms for troubleshooting (always)
for(int pin = 0; pin < 3; pin++){ // setup select pins
pinMode(selPin[pin], OUTPUT);
}
}
void loop(){
flashLEDs();
if (cnt == 0){
for(int x; x < 8; x++){
led[x] = random(2);
}
}
cnt++;
if (cnt > 100) { cnt = 0; }
}
void flashLEDs() {
for(int pin = 0; pin < 2; pin++) { // set common pins low
pinMode(commonPin[pin], OUTPUT);
digitalWrite(commonPin[pin], LOW);
}
for (int bank = 0; bank < 4; bank++) {
for(int pin = 0; pin < 3; pin++) { // parse out select pin bits
int signal = (bank >> pin) & 1; // shift & bitwise compare
digitalWrite(selPin[pin], signal);
}
if (led[bank * 2]){ // first LED
digitalWrite(commonPin[0], HIGH); // turn common on
delayMicroseconds(persistDelay); // leave led lit
digitalWrite(commonPin[0], LOW); // turn common off
}
if (led[bank * 2 + 1]){ // repeat for second LED
digitalWrite(commonPin[1], HIGH);
delayMicroseconds(persistDelay);
digitalWrite(commonPin[1], LOW);
}
}
}
就像我在第一行中所说的那样,完整的解释可以在MUX-DEMUX上找到:CD4051 Parlor Tricks
对于一个班级项目,我使用了CD4024和两个Arduino引脚来驱动7段显示器。
这种方法有一些警告。例如,要将一个high
值写入纹波计数器的第一个输出,只需要一个reset
和两次切换时钟引脚即可。但是,如果要写入high
所有n个引脚,则需要切换时钟引脚2 n倍,在此期间所有其他引脚都在不断切换和关闭。
如果您的应用程序可以解决这些限制,并且您的引脚短缺,那么这是另一种选择。
奖金回答:有很多的复用输入的例子在这里,其中有许多也适用于多路输出。
经过一些工作(安装其他引导加载程序),Uno上的ICSP1和JP2接头连接器上就可以使用另外七个I / O线。备用引导加载程序称为HoodLoader2。它允许您在Uno的Atmega328和Atmega16U2上安装草图。使用此方法将使处理多个处理器成为主要困难。
在Uno上,ICSP1和JP2接头连接到Atmega16U2的引脚PB1 ... PB7。此外,Atmega16U2具有大约9个I / O引脚,与电路板没有连接。在显微镜下工作的人也许可以将电线连接到16U2上的总共18个I / O引脚上,而将其他三个I / O引脚保留在其普通连接上。
HoodLoader2也可以在Mega板上使用。