WeMosを使ってみる

PCF8574


WeMos(ESP-12)にはGPIOが少ないので、PCF8574(IOエクスパンダー)を使ってGPIOを拡張してみます。
「PCF8564 arduino」のキーワードでGitHubを検索したらいくつかrepositoryが見つかりました。
それらの中で、このライブラリを 使ってみま した。

PCF8574に は PCF8574P と PCF8574AP があります。
どちらも非常によく似たチップですが、i2cアドレスが違います。
PCF8574P   address map 0x20-0x27
PCF8574AP address map 0x38-0x3f

今回使用したのはPCF8574Pなので、i2cアドレスは0x20となります。
SDAとSCLは10Kの抵抗でPullUpしています。

出力ポートを拡張するスケッチは以下の通りです。
PCF8574を5Vで駆動しても、3.3Vで駆動しても、各ポートの出力は同じで1.7Vぐらいしか出ません。
/*
 * PCF8574 GPIO Port Expand
 *
 * PCF8574    ----- WeMos
 * A0         ----- GND
 * A1         ----- GND
 * A2         ----- GND
 * VSS        ----- GND
 * VDD        ----- 5V/3.3V
 * SDA        ----- GPIO_4(PullUp)
 * SCL        ----- GPIO_5(PullUp)
 *
 * P0     ----------------- LED0
 * P1     ----------------- LED1
 * P2     ----------------- LED2
 * P3     ----------------- LED3
 * P4     ----------------- LED4
 * P5     ----------------- LED5
 * P6     ----------------- LED6
 * P7     ----------------- LED7
 *
 */

#include "Arduino.h"
#include "PCF8574.h"  // https://github.com/xreef/PCF8574_library

// Set i2c address
PCF8574 pcf8574(0x20);

void setup()
{
  Serial.begin(9600);

  // Set pinMode to OUTPUT
  for(int i=0;i<8;i++) {
    pcf8574.pinMode(i, OUTPUT);
  }
  pcf8574.begin();
}

void loop()
{
  static int pin = 0;
  pcf8574.digitalWrite(pin, HIGH);
  delay(1000);
  pcf8574.digitalWrite(pin, LOW);
  delay(1000);
  pin++;
  if (pin > 7) pin = 0;
}


入力ポートを拡張するスケッチは以下の通りです。
PCF8574のP1の値を取り込みます。
MCP23017やMCP23S17の様に入出力の方向を特に指定する必要はありません。
/*
 * PCF8574 GPIO Port Expand
 *
 * PCF8574    ----- WeMos
 * A0         ----- GND
 * A1         ----- GND
 * A2         ----- GND
 * VSS        ----- GND
 * VDD        ----- 5V/3.3V
 * SDA        ----- GPIO_4
 * SCL        ----- GPIO_5
 *
 * P1     ----------------- BUTTON
 *
 */

#include "Arduino.h"
#include "PCF8574.h"  // https://github.com/xreef/PCF8574_library

// Set i2c address
PCF8574 pcf8574(0x20);

void setup()
{
  Serial.begin(9600);
  pcf8574.pinMode(P1, INPUT);
  pcf8574.begin();
}

void loop()
{
  uint8_t val = pcf8574.digitalRead(P1);
  if (val==HIGH) Serial.println("KEY PRESSED");
  delay(50);
}

以下の様に一度に8ポートを一気に読むこともできます。
入力ポートが沢山あるときは便利です。
/*
 * PCF8574 GPIO Port Expand
 *
 * PCF8574    ----- WeMos
 * A0         ----- GND
 * A1         ----- GND
 * A2         ----- GND
 * VSS        ----- GND
 * VDD        ----- 5V/3.3V
 * SDA        ----- GPIO_4
 * SCL        ----- GPIO_5
 *
 * P0     ----------------- BUTTON0
 * P1     ----------------- BUTTON1
 * P2     ----------------- BUTTON2
 * P3     ----------------- BUTTON3
 * P4     ----------------- BUTTON4
 * P5     ----------------- BUTTON5
 * P6     ----------------- BUTTON6
 * P7     ----------------- BUTTON7
 *
 */

#include "Arduino.h"
#include "PCF8574.h"  // https://github.com/xreef/PCF8574_library

// Set i2c address
PCF8574 pcf8574(0x20);

void setup()
{
  Serial.begin(9600);
  for(int i=0;i<8;i++) {
    pcf8574.pinMode(i, INPUT);
  }
  pcf8574.begin();
}

void loop()
{
  PCF8574::DigitalInput val = pcf8574.digitalReadAll();
  if (val.p0==HIGH) Serial.println("KEY0 PRESSED");
  if (val.p1==HIGH) Serial.println("KEY1 PRESSED");
  if (val.p2==HIGH) Serial.println("KEY2 PRESSED");
  if (val.p3==HIGH) Serial.println("KEY3 PRESSED");
  if (val.p4==HIGH) Serial.println("KEY4 PRESSED");
  if (val.p5==HIGH) Serial.println("KEY5 PRESSED");
  if (val.p6==HIGH) Serial.println("KEY6 PRESSED");
  if (val.p7==HIGH) Serial.println("KEY7 PRESSED");
  delay(50);
}

PCF8574は入力があると、INTピンが一瞬LOWに落ちます。
PCF8574のINTピンを監視することで、入力割り込み処理が可能です。
以下のスケッチではGPIO13でINTピンを監視しています。
なお、GPIO16だけは入力割り込み監視に使えません。
/*
 * PCF8574 GPIO Port Expand
 *
 * PCF8574    ----- WeMos
 * A0         ----- GND
 * A1         ----- GND
 * A2         ----- GND
 * VSS        ----- GND
 * VDD        ----- 5V/3.3V
 * SDA        ----- GPIO_4
 * SCL        ----- GPIO_5
 * INT        ----- GPIO_13
 *
 * P0     ----------------- BUTTON0
 * P1     ----------------- BUTTON1
 * P2     ----------------- BUTTON2
 * P3     ----------------- BUTTON3
 * P4     ----------------- BUTTON4
 * P5     ----------------- BUTTON5
 * P6     ----------------- BUTTON6
 * P7     ----------------- BUTTON7
 *
 */

#include "Arduino.h"
#include "PCF8574.h"  // https://github.com/xreef/PCF8574_library

#define ESP8266_INTERRUPTED_PIN 13

// Set i2c address
PCF8574 pcf8574(0x20);

// Function interrupt
bool keyPressed = false;

void keyPressedOnPCF8574(){
//  Serial.println("keyPressedOnPCF8574");
  keyPressed = true;
}

void setup()
{
  Serial.begin(9600);
  pinMode(ESP8266_INTERRUPTED_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ESP8266_INTERRUPTED_PIN), keyPressedOnPCF8574, FALLING);

  for(int i=0;i<8;i++) {
    pcf8574.pinMode(i, INPUT);
  }
  pcf8574.begin();
}

void loop()
{
  if (keyPressed){
    PCF8574::DigitalInput val = pcf8574.digitalReadAll();
    if (val.p0==HIGH) Serial.println("KEY0 PRESSED");
    if (val.p1==HIGH) Serial.println("KEY1 PRESSED");
    if (val.p2==HIGH) Serial.println("KEY2 PRESSED");
    if (val.p3==HIGH) Serial.println("KEY3 PRESSED");
    if (val.p4==HIGH) Serial.println("KEY4 PRESSED");
    if (val.p5==HIGH) Serial.println("KEY5 PRESSED");
    if (val.p6==HIGH) Serial.println("KEY6 PRESSED");
    if (val.p7==HIGH) Serial.println("KEY7 PRESSED");
    keyPressed= false;
  }
}

続く...