2010年12月31日 星期五

Arduino 筆記 – Lab12 使用兩顆 74HC595 和三支腳位控制 16 顆 LED

實驗目的

練習串接 74HC595 移位暫存器 (Shift Register) 以擴充 Arduino 的 I/O 腳位,使用 Arduino 三支接腳搭配兩顆 74HC595 移位暫存器控制 16 顆 LED 燈。

註:本實驗假設你做過「Lab11 使用 74HC595 和三支腳位控制 8 顆 LED」,已經知道單獨一顆 74HC595 的使用辦法。

74HC595 串接簡介

image_thumb10

(圖片來源: SparkFun)

74HC595 是一顆八位元的移位暫存器,同時可以控制八個輸出,我們可以把多顆移位暫存器串接 (Daisy chain) 在一起以擴充腳位,例如: 如果串接兩顆 74HC595 移位暫存器,便可以同時控制 16 個輸出。

74HC595 總共有 16 支接腳,底下這 16 支接腳的圖表說明:

image_thumb4 

腳位編號 名稱 說明
1-7, 15 Q0 ~ Q7 輸出腳位
8 GND 接地
7 Q7’ 序列輸出 (Serial Out)
10 MR Master Reset, 清除所有資料, 低電位有效 (Active low)
11 SH_CP SHift register clock pin (Clock Pin)
12 ST_CP STorage register clock pin (Latch Pin)
13 OE Output Enable, 允許輸出,低電位有效 (Active low)
14 DS 序列資料輸入 (Serial data input)
16 Vcc 供應電壓

要把兩顆 74HC595 串接起來,方法很簡單,只要把第一顆 74HC595 的 SH_CP (Clock Pin) 和 ST_CP (Latch Pin) 兩支腳位接到第二顆 74HC595 上,接著把第一顆 74HC595 的 Q7’ (序列輸出腳) 接到第二顆的 DS (序列資料輸入) 就可以了。

材料
  • 麵包板 x 1
  • Arduino 主板 x 1
  • 74HC595 x 2
  • LED x 16
  • 220 ohm 電阻 x 16
  • 單心線 x N
接線

步驟一:接上第一顆 74HC595 以及 8 顆 LED

  • 接上 8 顆 LED,將每顆 LED 短腳 (陰極) 直接接到 GND,然後將每顆 LED 的長腳 (陽極) 個別接至 74HC595 的輸出腳位 D0 ~ D7 並串接一顆 220 ohm 電阻
  • 74HC595 接線其一:
    • Vcc (pin 16) 與 MR (pin 10) 接 5V
    • GND (pin 8) 與 OE (pin 13) 接地
  • 74HC595 接線其二:
    • DS (pin 14) 接 Arduino pin 11 (下圖藍線)
    • ST_CP (pin 12, latch pin) 接 Arduino pin 8 (下圖綠線)
    • SH_CP (pin 11, clock pin) 接 Arduino pin 12 (下圖黃線)
  • 假如發現 LED 有震動閃爍的現象,可以在 ST_CP (pin 12, latch pin) 上接一顆 0.1uF 電容以去除閃爍現象

image_thumb21

步驟二:加上第二顆 74HC595,第二顆移位暫存器一樣要接線連到電源與接地

  • Vcc (pin 16) 與 MR (pin 10) 接 5V
  • GND (pin 8) 與 OE (pin 13) 接地

image

步驟三:把兩顆 74HC595 連接起來

只要把第一顆 74HC595 的 SH_CP (Clock Pin) 和 ST_CP (Latch Pin) 兩支腳位接到第二顆 74HC595 上 (下圖中的綠線以及黃線),接著把第一顆 74HC595 的 Q7’ (序列輸出腳) 接到第二顆 74HC595 的 DS (序列資料輸入) 就可以了 (下圖中的藍線)。

image

步驟四:加上第二組 LED

image

電路圖

image

(圖片來源: arduino.cc)

程式碼

底下這支程式 (Shiftout_With_Two_74HC595.pde) 會讓 16 顆 LED 由左往右一顆一顆點亮,實際效果請見範例影片,:

 

因為 shiftOut() 函式一次只能送一個位元組,所以必須將 numberDisplay 拆成兩個位元組分兩次傳送:

再次提醒:在送資料前,記得要先把 latchPin 拉成低電位,緊接著使用 shiftOut() 函式送出資料,送完資料後還要把 latchPin 拉回高電位。

範例照片/影片
動動腦
  1. 範例程式的延遲時間固定為 40 ms,請修改程式,使用亂數產生延遲時間。提示:請參考 randomSeed()random() 兩個函式的用法。
  2. 加上一顆可變電阻,讓使用者可以利用可變電阻調整延遲時間。
  3. 試串接三顆 74HC595 控制 24 顆 LED。
延伸閱讀

73 意見:

小B 提到...
作者已經移除這則留言。
小B 提到...

請問三顆IC串時~程式高位元和低位員怎分配

Cooper Maa 提到...

不太懂你的意思耶
可以說明一下嗎?

小B 提到...

如何讓他跑馬燈

Cooper Maa 提到...

用這個 loop() 函式試試:

void loop() {
for (int led = 0; led < 24; led++) {
int numberToDisplay = 0;
byte upper_Byte = 0;
byte high_Byte = 0;
byte low_Byte = 0;

if (led < 16) {
numberToDisplay = 1 << led;
high_Byte = highByte(numberToDisplay);
low_Byte = lowByte(numberToDisplay);
} else {
upper_Byte = 1 << (led - 16);
}

// 送資料前要先把 latchPin 拉成低電位
digitalWrite(latchPin, LOW);

// 先送高位元組 (Hight Byte), 給離 Arduino 最遠的那顆 74HC595
shiftOut(dataPin, clockPin, MSBFIRST, upper_Byte);
// 接著送高位元組 (Hight Byte), 給離 Arduino 較遠的那顆 74HC595
shiftOut(dataPin, clockPin, MSBFIRST, high_Byte);
// 再送低位元組 (Low Byte), 給離 Arduino 較近的那顆 74HC595
shiftOut(dataPin, clockPin, MSBFIRST, low_Byte);

// 送完資料後要把 latchPin 拉回成高電位
digitalWrite(latchPin, HIGH);

delay(40);
}
}

小B 提到...

麻煩大大講解一下這段語法^^
if (led < 16) {
numberToDisplay = 1 << led;
high_Byte = highByte(numberToDisplay);
low_Byte = lowByte(numberToDisplay);
} else {
upper_Byte = 1 << (led - 16);
}

Cooper Maa 提到...

是這樣,一顆 74HC595 是 8 個位元,兩顆是 16 位元,三顆的話就是 24 位元。我用 upper_Byte, high_Byte 跟 low_Byte 這三個位元組代表三顆 74hc595 的資料。所以 upper_Byte 就是離 Arduino 最遠的那顆 74hc595 的資料。

我在程式上做了一點偷吃步,假如 led < 16,代表跑馬燈現在還在前兩顆 74hc595 的範圍內,假如超過 16,就代表跑馬燈現在跑到第三顆 74hc595,所以要去更新 upper_Byte。

不知道這樣解釋你聽得懂嗎?
BTW, 程式可以動嗎?

小B 提到...

恩恩 解釋非常清楚! 程式可以running 3q

小B 提到...

我想多+顆按鈕0~7固定跑馬燈其餘暗,當按鈕按下 if(led==5){全部閃爍}

Cooper Maa 提到...

嗯,你遇到什麼困難了嗎?

小B 提到...
作者已經移除這則留言。
小B 提到...
作者已經移除這則留言。
小B 提到...

想問一下,1<<led這個意思是?

Cooper Maa 提到...

<< 跟 >> 是 C/C++ 語言的 Bitwise shift operator
<< 是 SHIFT LEFT,而 >> SHIFT RIGHT。
如果 led 是 1,那麼 "1 << 1" 這樣是令 "00000001" 往左移 1 位元變成 "00000010",以此類推

shift operator 的用法可以參考這份資料:

http://www.csie.ntnu.edu.tw/~u91029/BitwiseOperation.html

小B 提到...

又可以學到更多了 謝謝^^

Cooper Maa 提到...

不客氣。
網路真的很方便,我很多知識都是從網路上學到的。
希望哪天也能看到你的分享啊。:)

小B 提到...

要開始努力學習建立基本功!!
在大大這真的學到很多!

Cooper Maa 提到...

你還在唸書嗎?在唸個學校科系?
加油!基本功打得愈紮實,將來學習其它功夫就愈容易。

小B 提到...
作者已經移除這則留言。
Cooper Maa 提到...

你是要從中間點亮一顆 LED,然後分流同時向左向右跑馬燈嗎?
這樣的話,得思考怎麼移動位元比較恰當

小B 提到...
作者已經移除這則留言。
小B 提到...
作者已經移除這則留言。
小B 提到...

int x=0;
for (int led =12; led<24; led++) {
x++;
int numberToDisplay = 0;
byte upper_Byte = 0;
byte high_Byte = 0;
byte low_Byte = 0;

if (led < 16) {
numberToDisplay = 1 <>x;
high_Byte = highByte(numberToDisplay);
low_Byte = lowByte(numberToDisplay);
} else {
upper_Byte = 4096>> (x - 16);
}
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, upper_Byte);
shiftOut(dataPin, clockPin, MSBFIRST, high_Byte);
shiftOut(dataPin, clockPin, MSBFIRST, low_Byte);
digitalWrite(latchPin, HIGH);
delay(500);
}
x=0;
結果:先亮12,11,10,9,當亮第8時~0,16亮起~23(中間的13,14,15沒亮)
我在想是不是跑分流時不能跑在同一顆不然有衝突?

Cooper Maa 提到...

1 <>x; // 這行可能寫錯了,C/C++ 沒有 <> 這個 operator 喔

我的想法是這樣,提供你參考看看:
24 bits, 總共是 3 個 byte 的資料
可以利用 2 個 integer 來移動元位,然後將兩個 integer 的 high byte 做位元運算,當做是給第二顆 74hc595 的資料

一開始只設定 bit 11,所以 2 個 integer 初始值都給 1 << 11
接著迴圈讓 integer1 一次左移一個位元,而 integer2 一次右移一個位元
然後將 2 個 integer 的 high byte 做 OR 運算當成是給第二顆 74hc595 的資料

所以,iteration 1:

00000000 00010000
OR 00000000 00010000
--------------------
00000000 00010000 (取 high byte 給第二顆 74hc595)

iteration 2:

00000000 00100000
OR 00000000 00001000
--------------------
00000000 00101000 (取 high byte 給第二顆 74hc595)

iteration 3:

00000000 01000000
OR 00000000 00000100
--------------------
00000000 01000100 (取 high byte 給第二顆 74hc595)

照這個邏輯做,我想應該是可以達到你的目的。

小B 提到...

乎 終於有嚕!有大大只點變更EASY點

Cooper Maa 提到...

我本來還想上來給你個建議,叫你先試一個 74hc595,先從簡單的開始就好,之後再改成三顆。沒想到你已經突破關卡了。讚!

小B 提到...

哈哈!那也是因為大大清楚的邏輯觀光用想得就可以成功^^''
這沒有像FB一樣可以按讚 不然我一定先按給你

Cooper Maa 提到...

你可以按讚了,哈~

小B 提到...

閃爍要如何表達!
我的想法讓它0~23每次做OR 255;(全亮)
0~23每次做AND 0;(全暗)
只是不知怎丟在一起!!

Cooper Maa 提到...

你是說要讓 24 顆 LED 同時閃爍嗎?
方法不是跟 "Blinking a LED一樣「先開 led,延遲一段時間,再關掉 led,然後再延遲一下,如此反覆」這樣就好了嗎?

小B 提到...

恩恩 沒錯

Cooper Maa 提到...

所以你知道怎麼做了嗎?

有些時候利用 pseudo code 來表達會比較容易理解,例如這題可以這樣表示:

loop() {
LEDOn(); // 打開 24 顆 led
delay(50);
LEDOff(); // 關掉 24 顆 led
delay(50);
}

寫出 pseudo code 後,緊接著就可以實作程式碼。在這邊的話,只需要知道怎麼讓 led 全開跟全關而已,這應該不是問題吧?全開就送 3 個 byte 的 1,全關就送 3 個 byte 的 0,簡單吧!?

小B 提到...

剛好你上次點了一下,然後想到送1和0就成功了^^'' 有大大指點一下就變EASY~

Cooper Maa 提到...

你打通關節了,不錯,不錯!:)

芭蕉葉上聽雨聲 提到...

感謝Cooper maa, 我也成功做出連接3顆74HC595了.
如果我想用模組化的觀念接N顆74HC595(例如10顆), 請問副程式ledOn要如何寫?
int IC;
int ledSum;
void setup() {
IC = 10;
ledSum = IC * 8;
...
}
void loop() {
for (int led = 0; led < ledSum; led++) {
ledOn(led);
delay(40);
}
}

Cooper Maa 提到...

你連接了 3 顆 74hc595? 哇塞! 3 顆 74hc595 就可以控制 24 顆 led,你不會接了 24 顆 led 在玩吧? 這工程不小耶! 哈

ledOn(led); // <-- 這行是讓 ledOn() 把數字傳給 10 顆 74hc595 嗎?

芭蕉葉上聽雨聲 提到...

是啊~~我是接了24顆LED在玩,而ledOn(led)這行的確是讓ledOn()把數字傳給10顆74hc595.
我想再增加到64顆, 這樣的話Arduino主板應該是推不動,得外加電源了. 未來還想增加更多的LED. 在硬體方面我也想把它模組化, 也就是以8顆LED為單位做一個模組, 有需要時把它們的PIN串接在一起.同時在軟體方面我希望只修改模組數量的變數即可.
不知您有沒有看過yutube上面的一段影片,一個日本樂團演唱會, 舞台背後用數百台單眼相機組成一個閃光燈陣列,真是光彩炫目.

Cooper Maa 提到...

你要用到這麼多顆 LED 啊? 那改用 LED Matrix 會不會比較適合?

問你一個問題:

void loop() {
for (int led = 0; led < ledSum; led++) {
ledOn(led);
delay(40);
}

這段迴圈功能是什麼? 是讓 80 顆 led 產生跑馬燈的效果嗎?

Cooper Maa 提到...

假如你串 N 顆 74HC595 也是要玩跑馬燈的話,也許 ledOn() 可以這樣寫:

void loop() {

for (int led = 0; led < ledSum; led++) {
ledOn(led);
delay(40);
}
}

void ledOn(int led) {
byte nullByte = 0;
byte dataByte;
int chipNumber;


chipNumber = led / 8; // 看要亮的 led 落在哪一顆 74hc595 上
dataByte = 1 << chipNumber;

// 送資料前要先把 latchPin 拉成低電位
digitalWrite(latchPin, LOW);

for (int i = 0; i < IC; i++) {
if (i == chipNumber)
shiftOut(dataPin, clockPin, MSBFIRST, dataByte);
else
shiftOut(dataPin, clockPin, MSBFIRST, nullByte);
}

// 送完資料後要把 latchPin 拉回成高電位
digitalWrite(latchPin, HIGH);

}

不曉得 work 不 work,我沒有實測過,你試試看。

芭蕉葉上聽雨聲 提到...

我先玩線性的LED(以後再玩LED MATRIC),例如在雨傘的5根骨架上都裝上LED, 您可以想像一下有舞者拿着這些傘在舞台上配合著音樂跳舞的效果. 當然LED的閃燈效果要配合樂曲才行.

您的程式我稍微修改一下就可以動作了, 謝謝. 程式如下:
// 2011-12-13
// 使用 N 顆 74HC595 控制 LED
//
// 接 74HC595 的 ST_CP (pin 12,latch pin)
int latchPin = 8;
// 接 74HC595 的 SH_CP (pin 11, clock pin)
int clockPin = 12;
// 接 74HC595 的 DS (pin 14)
int dataPin = 11;
// 74HC595 數量
int IC;
// LED總數
int ledSum;

void setup() {
IC = 3;
ledSum = IC * 8;
// 將 latchPin, clockPin, dataPin 設置為輸出
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}

void loop() {
for(int i=0; i < ledSum; i++){
ledOn1(i);
delay(40);
}
for(int i=ledSum-1; i >=0; i--){
ledOn1(i);
delay(40);
}
}

// 計算餘數
int mod(int n1, int n2) {
return n1 - n1 / n2 * n2;
}

void ledOn1(int led) {
byte nullByte = 0;
byte dataByte;
int chipNumber;

chipNumber = led / 8; // 看要亮的 led 落在哪一顆 74hc595 上
dataByte = 1 << mod(led, 8);

// 送資料前要先把 latchPin 拉成低電位
digitalWrite(latchPin, LOW);
// 先從最遠那顆 74HC595 送出資料
for (int i = IC - 1; i >= 0; i--) {
if (i == chipNumber)
shiftOut(dataPin, clockPin, MSBFIRST, dataByte);
else
shiftOut(dataPin, clockPin, MSBFIRST, nullByte);
}
// 送完資料後要把 latchPin 拉回成高電位
digitalWrite(latchPin, HIGH);
}

芭蕉葉上聽雨聲 提到...

上述程式 ledOn1()每次只能點亮一顆LED,
要如何把它改成每次可以點亮很多顆LED?

芭蕉葉上聽雨聲 提到...

呵~~我試出來了, 程式如下:
// 2011-12-14
// 使用3顆 74HC595 和三支腳位控制 24 顆 LED
//
// 接 74HC595 的 ST_CP (pin 12,latch pin)
int latchPin = 8;
// 接 74HC595 的 SH_CP (pin 11, clock pin)
int clockPin = 12;
// 接 74HC595 的 DS (pin 14)
int dataPin = 11;

// 74HC595 數量
int IC = 3;
// LED顯示資料
byte dataArray[13][3];
// 延遲時間
int dTime;

void setup() {
// 將 latchPin, clockPin, dataPin 設置為輸出
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

dTime = 50;
// 顯示資料
dataArray[0][0] = B11111111; dataArray[0][1] = B11111111; dataArray[0][2] = B11111111;
dataArray[1][0] = B11111111; dataArray[1][1] = B11100111; dataArray[1][2] = B11111111;
dataArray[2][0] = B11111111; dataArray[2][1] = B11000011; dataArray[2][2] = B11111111;
dataArray[3][0] = B11111111; dataArray[3][1] = B10000001; dataArray[3][2] = B11111111;
dataArray[4][0] = B11111111; dataArray[4][1] = B00000000; dataArray[4][2] = B11111111;
dataArray[5][0] = B11111110; dataArray[5][1] = B00000000; dataArray[5][2] = B01111111;
dataArray[6][0] = B11111100; dataArray[6][1] = B00000000; dataArray[6][2] = B00111111;
dataArray[7][0] = B11111000; dataArray[7][1] = B00000000; dataArray[7][2] = B00011111;
dataArray[8][0] = B11110000; dataArray[8][1] = B00000000; dataArray[8][2] = B00001111;
dataArray[9][0] = B11100000; dataArray[9][1] = B00000000; dataArray[9][2] = B00000111;
dataArray[10][0]= B11000000; dataArray[10][1]= B00000000; dataArray[10][2]= B00000011;
dataArray[11][0]= B10000000; dataArray[11][1]= B00000000; dataArray[11][2]= B00000001;
dataArray[12][0]= B00000000; dataArray[12][1]= B00000000; dataArray[12][2]= B00000000;
}

void loop() {
for(int i=0; i < 13; i++){
digitalWrite(latchPin, LOW);
for (int j = 0 ; j < IC; j++) {
shiftOut(dataPin, clockPin, MSBFIRST, dataArray[i][j]);
}
digitalWrite(latchPin, HIGH);

delay(dTime);
}
}

Cooper Maa 提到...

我忘了對 dataByte 做位元移位。
你還特地為求餘數寫了一個 mod 函式啊? 其實求餘數不用這麼麻煩,這樣寫就好了:

dataByte = 1 << (led % 8);

在很多 C based 語言裏,% 就是 mod 求餘數的指令。

Cooper Maa 提到...

你講的在雨傘上放 LED,應該屬於穿戴式科技這個領域的應用,也許可以朝 Lilypad 這個方向走:

http://web.media.mit.edu/~leah/LilyPad/build/accelero_shirt.html

不過,我想如果要讓 LED 的閃燈效果配合音樂的律動,可能需要弄成一個網路架構,由主控制器去感測音樂的振盪,然後再傳資料給雨傘上的 LED 節點產生變化。架構有點像你前兩天分享的 LED Matrix 立體拼圖一樣: http://www.saccade.com/writing/projects/Puzzlemation/Puzzlemation.html

提到...

請問,為什麼這樣可以先傳訊息到較遠的595再傳給較近的呢?(而不是兩個一起接收?)
shiftOut(dataPin, clockPin, MSBFIRST, high_Byte);
shiftOut(dataPin, clockPin, MSBFIRST, low_Byte);

那我可以發送這樣的資料嗎?

byte seven_seg_digits[10]={
B11111100, // = 0
B01100000, // = 1
B11011010, // = 2
B11110010, // = 3
B10110110, // = 5
B10111110, // = 6
B11100000, // = 7
B11111110, // = 8
B11100110 // = 9
};

因為我想用595控制8x8點矩陣。
還是您有更好的方法呢?
(我不想要用太多腳)
謝謝您!

Cooper Maa 提到...

當 latchPin 拉回高電位的時候,就代表資料傳送完畢
但是在 latchPin 還沒拉回高電位前,如果資料超過 8 個位元,那 Q1 到 Q6 就會往 Q7 移一個位元,而 Q7 的資料就會被擠到 Q7',有點像是 Queue 先進先出的道理一樣,所以第一個 byte 就會傳到較遠的那顆 595 囉。

用 595 控制 8x8 LED Matrix 當然可以啊
你可以參考一下底下這篇:

http://tronixstuff.wordpress.com/2010/06/06/getting-started-with-arduino-chapter-nine/

提到...
作者已經移除這則留言。
提到...

非常的感謝您有利的資訊,還冒昧的再請問您。
請問:
byte seven_seg_digits[10]={
B11111100, // = 0
B01100000, // = 1
B11011010, // = 2
B11110010, // = 3
B10110110, // = 5
B10111110, // = 6
B11100000, // = 7
B11111110, // = 8
B11100110 // = 9
};
shiftOut(dataPin, clockPin, MSBFIRST, seven_seg_digits[3]);
shiftOut(dataPin, clockPin, MSBFIRST, seven_seg_digits[9]);

這樣,我分別將兩顆595接上兩個七段顯示器,他會顯示28嗎?(程式碼有省略)
還有,請問595做多可以串聯幾顆?因為我想做一個萬年曆,但是七段顯示器都是一位數的,所以需要用到很多顆595。
基本上是YY/mM/dD hH/MM,其中m,d,h只需要一顆595,因為他們都只需要顯示一兩個數字而已(例:m只須顯示0,1 d只須顯示0,1,2,3等,我電路設定好就OK)。
那加上其他(大寫的,還有顯示星期的8x8LED要兩顆)我大概需要10顆595。
請問10顆595可以用Q7'接DS串聯嗎?(會有問題嗎?)
謝謝您!

Cooper Maa 提到...

是可以在七段顯示器上顯示 28,不過有個但書
就是要確定應該用 LSB 或 MSB,因為線路的接法有關。你可以參考一下我這篇,當時我是用 LSB:
http://coopermaa2nd.blogspot.com/2011/01/arduino-lab13-74hc595.html

「595 最多個串幾顆?」好問題!這我也不太懂,剛上網查了一下,得到的答案是: 理論上是沒有限制的。例如底下這篇討論,Archiver 的回答是說想接幾顆就接幾顆,他說他看過實例接過 11,12 顆和 16 顆的例子:

http://forums.parallax.com/showthread.php?69278-74HC595-Shift-Register

提到...

那請問一下,
LSB 和 MSB有何不同? 線路接法各有什麼限制?
接了10顆595傳送訊號的時候會Lag嗎?
謝謝您!

Cooper Maa 提到...

LSB 是 Least Significant Bit First
MSB 是 Most Significant Bit First

LSB 是先傳最低有效位元,而 MSB 則是先傳最高有效位元

會不會 Lag 這我不確定,因為我沒有實際接過這麼多顆喔。:)

你有試過會 Lag 嗎?

提到...

因為我現在還在收集資料當中,所以沒有購買材料。
明天再去購買。
會不會Lag可能要一段時間後才會知道囉:d
謝謝您!

Cooper Maa 提到...

不客氣
希望你順利喔!

提到...

請問您,我有點看不懂http://tronixstuff.wordpress.com/2010/06/06/getting-started-with-arduino-chapter-nine/網頁中的
Here is a circuit diagram for our example (click on it to enlarge):
下方的手稿電路。
他那個右上角的電晶體是怎麼接的捏?
(BC548的意思是指電晶體編號548?)
他電晶體的E極接到哪裡去惹?(接地?)
另外,共陰、共陽,程式電路有差嗎?
謝謝您!

Cooper Maa 提到...

E 極要接到 Ground

BC548 為什麼用 548,這我也不曉得耶。:)
不曉得電晶體有沒有什麼編號規則。

一般電路的接法是 PNP 電晶體 for 共陽,而 NPN 電晶 for 共陰。除了電路外,要注意程式邏輯是相反的喔。這部份的觀念可參考這篇:
http://coopermaa2nd.blogspot.com/2011/05/led-active-low-led.html

提到...

請問您,要怎麼分辨點矩陣是共陰還是共陽呢?
PS:我的8x8點矩陣編號是:CSM88041
謝謝您!

Cooper Maa 提到...

點矩陣跟七段顯示器一樣,從外觀好像看不出是共陰還是共陽的。我想最簡單的方法是用萬用電表去量。

提到...

請問,我覺得共陰還是共陽好像都差不多吧!
個人覺得只是接腳位置不同而已,為什要電晶體要分呢?
(PNP 電晶體 for 共陽,而 NPN 電晶 for 共陰)
還有要怎麼用萬用電表來捏??
謝謝您!

Cooper Maa 提到...

我寫過一篇用電晶體驅動七段顯示器的筆記:
http://coopermaa2nd.blogspot.com/2011/01/arduino-lab15.html

之前在做這個實驗的時,該用 NPN 或 PNP 我也曾困擾。有人說 NPN for 正電,PNP for 負電。我記得當時不管是用 NPN 或 PNP 都是可以的。所以,也許電路是沒差的,只是邏輯會不一樣,可能是這樣。

我記得那時候甚至把 C 極和 E 極對調還可以動,問懂硬體的朋友,他說好像都可以驅動。我還不太懂電子,不曉得為什麼。哈~

GCY 提到...

NPN跟PNP不一樣的地方在於射極跟集極電流方向相反,我也不是電子的不過我猜應該是這樣差別造成的吧XD

GCY 提到...

筆誤更正是基極不是射極。

LCW 提到...

若使用NPN時,工作偏壓用正電
若使用PNP時,工作偏壓用負電

工作偏壓是指從基極進來的電壓源。

真正在討論工作偏壓時,我們還必須配合電晶體的工作區間,將基極上的電阻搭配至使電晶體操作在"飽和區間"(若做為電子式開關)。

集極上的電阻一般在選擇時的依據是由負載裝置的工作電流來決定搭配的電阻大小。

PNP的電流是從射極流向集極
NPN的電流則是從集極流向射極
基極電流我們在討論的時候幾乎都視為0(很小)
根據的是Ie=Ib+Ic,又Ic=B*Ib (B(beta)通常為100~150之間的常數故Ib相對於Ic極小)

在下有修過電子學,沒有學得非常好,如果有錯請各位前輩指正XD

Cooper Maa 提到...

感謝各位熱烈的討論,小弟收獲良多

關於 NPN 與 PNP 的異同,國外 "NPN v.s PNP" 這篇整理的很簡潔,也有參考的價值:
http://www.markallen.com/teaching/ucsd/147a/lectures/lecture3/10.php

Y 提到...

請問,該如何做能達到像下面影片中,貪吃蛇遊戲效果
http://www.youtube.com/watch?v=q0Wz8jydeAo&feature=player_embedded

Cooper Maa 提到...

Hi, 那個影片的程式碼網路上找得到喔,在這邊:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265668103

Y 提到...
作者已經移除這則留言。
芭蕉葉上聽雨聲 提到...

LCW對電晶體的描述已經非常清楚了.
不過我最近瀏覽了不少有關電晶體的文章, 發現Ib電流雖然很小, 但也不能不重視它,如果太大還是會燒毀電晶體的, 是故在基極加上一顆限流電阻應該才是比較妥當的做法.

Cooper Maa 提到...

pizchen, 你說的對,電流太大會燒毀電晶體,加個限流電阻比較妥當。

蝗蟲 提到...

不好意思,想請問一下,我想要以0xFFFFFF控制24顆LED,例如打出0x818181的話,
那LED亮法為10000001 10000001 10000001
請問有辦法做到嗎?

Cooper Maa 提到...

可以的

你可以把 0x818181 放到 long integer 裏或是使用 byte array

其實之前就有網友分享控制 24 顆 LED 的方法了喔
請往上找 "芭蕉葉上聽雨聲" 的留言

蝗蟲 提到...

對不起,上面的程式碼,我試過了,但是很像不是我想要的,可是我可以把我想要的打出來,請你幫我看看並解惑
void loop()
{
color_xyz('r',x);
color_xyz('r',x);
light();
}
void color_xy(char a,char x)
{
if(a=='r')
{
r_remember+=0x01<<x;
}
void light()
{
shiftOut(dataPin, clockPin, MSBFIRST, r_remember);
}
差不多是這樣的程式碼,74595有三顆,led有24顆,在loop那裏輸入color_xyz('r',22);和color_xyz('r',5);,那LED燈的第5顆和22顆會亮,請問有辦法嗎?

Milkshark 提到...

你好:
如果想要控制8組LED霹靂燈,
而每組霹靂燈皆由8顆LED組成,共64顆LED。
且每組各有一顆開關控制,按下對應開關時當組LED才會閃爍。

請問是要使用8顆74HC595進行配置,還是有比較推薦的移位暫存器?

謝謝指教!!

Cooper Maa 提到...

Hi, 要控制這麼多顆 LED,建議改用 MAX7219 系列的 IC:
http://playground.arduino.cc/Main/MAX72XXHardware