エレキ素人が何か考える（その５：デジタルポテンショメータ）

# デジタルポテンショメータ
Arduinoを使い、抵抗値をマイコンから制御できるデジタルポテンショメータを試した。スイッチサイエンスで購入できる、[MCP4131デジタルポテンショメータ 10KΩ](https://www.switch-science.com/catalog/1056/)を利用。

## MCP4131-103基本情報
[データシート](http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Components/General%20IC/22060b.pdf)よりいくつかピックアップ。

#### 7bit,10KΩタイプ
用いるデジタルポテンショメータは、7bitかつ10KΩタイプであった。
![Rw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/70f4d896-5cf2-e490-36bb-3b89dc3549a6.png)

0から10KΩを128段階で設定可能（129 Step）、設定情報はRAMにあり、SPIで制御（設定）する。

#### ピン情報および抵抗値
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/a3e9725b-5f89-9f1f-f46d-80ec70fea135.png", width=50%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/ffd46716-17c2-645a-7a96-e148895120e6.png", width=70%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/0aa44a8c-c18b-b401-fdb1-96c954043bb0.png", width=80%>

ピン5-7のRab値が10KΩとなっており、ピン6をマイコンから制御できる。Raw+Rwb=Rabという関係になる。

#### Arduinoとの接続
![SPI Connection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/050824f4-80ea-288b-5195-9d72b8fc3bb7.png)

上側の図、Host ControlがArduinoとなる。LEDを接続したときの回路図例は下記となる。
![DigitalPotentiometer_回路図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/c06e34eb-6bb1-8149-b577-5235de108c95.png)
実際の配線状況の写真。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/96634d8b-7e74-895c-211b-f7ae2cc41959.jpeg", width=70%>

#### ソフトウェア関連
![Command.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/5be29ca9-6f49-2851-0e5e-3e881b085356.png)
![Command2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/e829995f-74f0-15ea-316b-0d74d6bd73cf.png)
WriteおよびReadコマンドにより、Wiper（抵抗設定）データをハンドリング。

## ソースコード
### 参照情報
Arduino本家からは、サンプルとして[これ](https://www.arduino.cc/reference/en/libraries/mcp4131-library/)が見つかるが、ここでは、[このサイト](http://www.learningaboutelectronics.com/Articles/MCP4131-digital-potentiometer-circuit.php)の情報をもとに下記コードを作成。

### 使ったコード
```c++
#include <SPI.h>

#define W_ADDR 0x00  // ①
#define R_ADDR 0x0c  // ①
#define CS 10

//#define LOOP 1  // ②

void setup() {
  pinMode(CS, OUTPUT);
  SPI.begin();
  Serial.begin(9600);
#ifndef LOOP
  digitalPotWrite(95); // 0, 63, 95, 127  ③
  delay(10);
  int val = digitalPotRead();
  Serial.print("Read  "); Serial.println(val);  // ③
#endif
}

void loop() {
#ifdef LOOP  // ④
  int i, val;
  for (i = 0; i < 256; i++) {  // does not work for more than 128
    Serial.print("Write "); Serial.println(i);
    digitalPotWrite(i);
    delay(10);
    val = digitalPotRead();
    Serial.print("Read  "); Serial.println(val);
    delay(110);
  }
#endif  
}

int digitalPotWrite(int value) {  // Writeコマンド
  digitalWrite(CS, LOW);
  SPI.transfer(W_ADDR);  // ①
  SPI.transfer(value);
  digitalWrite(CS, HIGH);
}

int digitalPotRead() {  //　Readコマンド
  int val;
  digitalWrite(CS, LOW);
  SPI.transfer(R_ADDR);  // ①
  val = SPI.transfer(255); // Must be 255, instead of 127  ⑤
  digitalWrite(CS, HIGH);
  return val;
}

```

- ①：データシートより、Addressが「00」、Writeコマンドは「00」、Readコマンドは「11」、よって、SPIにセットするデータはWrite時「0x00」、Read時は「0x0c」となる。
- ②：本ソースコードで、loop()を使うかどうかのフラグ。
- ③：loop()未使用時に、代表的なWiper値（抵抗設定値）を書き込み、書き込まれた値を読み込む。
- ④：loop()使用時は、Wiper値を0から255まで変化させる。（ただし、7bitデバイスのため、値が設定できても、128以上の値はWiper値として機能しないようだ。）
- ⑤：種々トライしたが、Writeした値を正しく読むには、255に設定する必要があった。

## 検証
### loop()未使用時の分圧の様子
③で95を設定したときのRaw間の電圧。Arduinoからは5Vが供給されている。そのおよそ4分の1の値。
![IMG_5738.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/0ab6e216-f82e-796a-bec3-b36f8586a3f0.jpeg)

こちらは、シリアルコンソール表示。
![ReadValue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/0dd724c7-1293-5d3c-90c9-153a729477bf.png)

なお、128以上の値が設定できても、実際には機能していない。下記データ参照。

|③の値|Rawの電圧(v)|Rwbの電圧(v)|
|---|---|---|
|0|4.892|0.0247|
|63|2.489|2.414|
|95|1.28|3.631|
|127|0.0612|4.855|
|191|0.0235|4.896|
|255|0.0235|4.896|

なお、Wiper値はRAMに保存されているため、電源OFF/ONでクリアされる。なお、初期値は「64」となっているようだ。

### loop()使用時のLED点灯の様子
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/24a0f251-d237-90e6-718a-8df8bbc30ecc.jpeg", width=70%>

EOF