分類: Arduino Brick

電子積木(2)類比多工器

No Comments

多工器(multiplexer),是統稱。
依訊號源有分類比多工器及數位多工器。
多工器必須由“輸入至輸出的對應關係”來界定,界定出了一對多及多對一。
例如,有兩支輸入腳位(還須有另一支承載訊號的腳位),有四支輸出腳位;兩支腳位的輸入可有 00,01,10,11 四種狀況,因此恰可定位至輸出的每一腳位,00 至輸出腳位一,01 至輸出腳位二,10 至輸出腳位三,11 至輸出腳位四。因此這整個對應關係稱為一對多的解多工器(demultiplexer),也稱為選擇器或解碼器。反之,在輸入至輸出為多對一的情況下,就是稱為編碼器或多工器(multiplexer)。因此,多工器與解多工器是輸出入方向互為相反的邏輯運算器。
本文要介紹的是可承載類比訊號的雙向多工器(訊號雙向)。16-ch analog multiplexer,NXP 的 HC4067。並且既可收送類比訊號,當然也就可收送數位訊號。而我們要用在 GPIO 的擴展上,所以我們將要使用的是將它當成選擇器來使用。原則上用掉 5 pin,就能多出 11 pin。

16 通道類比多工器,參考批發價 2.3 RMB

預備注意事項

  • Y0-Y15 總共 16 通道。S0-S3 共四個位元,對應關係即,(s0, s1, s2, s3)=(0, 0, 0, 0) 對應 Y0,(1, 0, 0, 0) 對應 Y1,(0, 0, 0, 1) 對應 Y8 以此類推。
  • EN 是低電位致能。板上預設就是 10K pull-low。所以該腳位空接就能使用。要有開關功能就是拉 high 就會關掉,這應跟省電相關。
  • Z 腳位就是訊號通道。
  • ESP8266EX 單晶片的類比腳位 ADC/A0,只適用於 0V 至 1V 之間。所以若輸入 3.3V 會燒壞它,必須使用分壓電阻讓它最高只有 1V。不過,開發板大多使用 ESP8266MOD,或板本身,也都已加了分壓電阻了。所以使用 3.3V 無虞。
  • 使用 16 通道的 IC 不代表 16 路皆要用上。考量到我們的 GPIO 數,除了 A0 我們是必要使用外,我們只要耗用二路在選擇器上就有四路通道生出來。但,減三加四,我們只有一路的增益。故建議是至少規劃 8 通道個人覺得 CP 值最高。以本文範例,將用上搖桿,其只有三路訊號(二類比一數位),只須至少 2 pin 用在選擇器上。
  • 想必也已想到,它是類比多工器,故數位訊號從多工器進來,至 A0 接收到,若,我們取中間值為安全值,說,1.65V,電壓大於 1.65V 我們就視為高準位,反之低準位,故數位或類比我們都能透過 A0 來取得。
    但,為何要限於 A0,我們其他的 GPIO 數位輸入腳位同樣可以讀取從多工器進來的數位訊號,只差無法讀類比訊號而已,也因這在我們規劃時早已可安全地確定了。所以這意謂著,若來源只是數位訊號,我們就不要浪費掉 A0。
  • 因此基於 ESP8266 我們可以這樣地運用:一顆 8 路輸出串接到 8 路,用上第一級 3 路去選擇第二級,那麼,第一級若接數位訊號共 5 路可用,第二級若接類比訊號共 8 路可用,單晶片就用掉 3 路及 1 類比 1 數位輸入。故增益了 8 路且要數位要類比皆多路可用。(前提是多工器可 autolatch)
  • 不知在哪看到,多工器的定位後輸出入取樣有 6ns 的延遲。(切換到別的通道,原通道準位會被鎖定)。讓我們算了一下剛好約略 160MHz 的 CPU 跑 1 條指令的時間。故,定位後,保險一點就跑一條 nop 再讀取 A0 的值;輸出後先跑一條 nop 再轉定位。

範例


bool Timeout_1s(){
    static int current_time = millis();
    int new_time = millis();
    if (new_time < (current_time + 1000)) return false;
    current_time = new_time;
    return true;
}

bool NOP(){return true;}

void setup() {
    // put your setup code here, to run once:
    
    Serial.begin(115200);
    pinMode(D1, OUTPUT);
    pinMode(D2, OUTPUT);
    pinMode(D3, OUTPUT);
    pinMode(D4, OUTPUT);
}

void loop() {

    int states[16];

    if (Timeout_1s()){
        for (int i=0; i<16; i++){
            digitalWrite(D1, (i & 1) >> 0); // S0
            digitalWrite(D2, (i & 2) >> 1); // S1
            digitalWrite(D3, (i & 4) >> 2); // S2
            digitalWrite(D4, (i & 8) >> 3); // S3
            NOP();
            states[i] = analogRead(A0);
        }
        
        Serial.printf("A0 values: ( ");
        for (int j=0; j<16; j++){
            Serial.printf("%04d, ", states[j]);
        }
        
        Serial.printf(" )\r\nvoltages: ( ");
        for (int k=0; k<16; k++){
            Serial.printf("%1.2f, ", states[k]/1024.0*3.3);
        }
        Serial.printf(" )\r\n");
    }
}

結論

  • 範例是在每一秒下,將所有通道掃過一次並列印出來。
  • 這顆多工器的 Y8-Y15 八根腳位似乎空接浮動,讀出的數值偏高,Y0-Y7 並沒有此現象。這算是所謂的 cross talk。不過也不像。那八根上過高低準位後,浮動還是回到較高準位,約接近 3V。如下圖所示。
  • 這顆廉價的搖桿是讓人失望了XD,不過還是堪用的。它的電位變化沒有預期的很線性,所以若要分成很多段來運用恐怕要失望了。
  • 但經上述測試及細思後,才領悟,這顆多工器是不能如筆者原意這樣使用的。若用於輸入,則只對應到單晶片 1 pin,且軟體判斷輸入數值,則分時多工 16 pin ,如此是沒有問題的。但若用於輸出,唯有定位到的那一腳位,其準位或訊號才是確定的,其餘的 15 pin 都會是浮動的,這顯然對於輸出是不適用的。因此,在我們運用此晶片時,輸出入是必須先確定的,該輸入就輸入,該輸出就輸出,並且輸出還須另一顆 IC 來輔助,即,latch ic。問題是,latch 也是所有腳位齊步更新變化,故,除非此多工器有自我 latch 的功用(但看 block diagram 應是沒有),不然當前對筆者而言是無解了,筆者再查看的結果,唯有使用 GPIO Expander 或移位暫存器了。
  • https://assets.nexperia.com/documents/data-sheet/74HC_HCT573.pdf
  • pdf.datasheetcatalog.com/datasheet/stmicroelectronics/2047.pdf
  • https://www.nxp.com/docs/en/brochure/75016987.pdf
  • https://www.ti.com/lit/ds/scls041i/scls041i.pdf
  • 至於如此,多工器能怎麼用?即,輸入是沒問題的,一顆就解決問題。而輸出的話就如 datasheet 所述可作異時開關;每根輸出都作 pull high/low。

Categories: Arduino Arduino Brick

Tags:

PHP Code Snippets Powered By : XYZScripts.com