外部のADCを利用せず、スイッチをつけて内部のADCを利用するというアプローチが以下にありました。
TINKERING WITH TECHNOLOGY
WHEN YOU NEED MULTIPLE ANALOG INPUTS FOR YOUR ESP8266 APPLICATION
なるほどーです。FSA3157 というスイッチをつけて、GPIO ピンからデジタルでHigh Low させることによりスイッチを動作させるものです。なんか日本語変ですが。上記ブログと、データシート見たほうがわかりやすいです。
FarChild Semiconductor FSA3157
datasheet
これで、ADCのソースを2つから選べるようになるということですね。
3つのソースを2つのGPIOで制御する場合は、以下のICを。
FSA3357
価格的には、どちらも安いので候補ですね。ハードの世界はいろいろなICがあって、面白いですね。
配置した感じでは、大きさがほとんど変わらないので、8pin の 3チャンネル切り替えられる FSA3357 を導入することに。前回検討していた、ダイオードを挟む方法は、正確に抵抗値を読みたいので、適しませんでした。
AliExpress にて、10個1083円なり。1個110円くらいです。
これを組み込んで、電源電圧他、2つのアナログ値を取れるようにして、1つはCDSの照度に使い、あと1つはPINを出しておく形にしておきます。
抵抗分圧して、3.3v をいったん、0.5VにしてADC で値を読ませた後に、元の値に戻しています。wifi eink のコードにあったやつです。まだ、ものがないのでS1,S2 の切り替えコードは書いていませんが、抵抗分圧して、内臓のADC で1V 以上の抵抗を読めるようにテストしてみました。
/*
ADC Read Sample
Arduino IDE 1.6.5 Hourly Build 2015/06/12 03:13
esp8266 by ESP8266 Community version 1.6.5 Hourly Build 2015/06/12
JunkHack 2015.10.10
--- ex Serial output.
Blink Count: 40
ADC mv: 3319
ADC mv: 3313
Blink Count: 41
ADC mv: 3319
ADC mv: 3313
::
*/
#include <ESP8266WiFi.h>
int ledState = LOW;
unsigned long previousMillis = 0;
const long interval = 1000;
void setup() {
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(115200);
delay(10);
}
int value = 0;
int count = 0;
int adc = 0;
int batteryMeasMv = -1;
void loop()
{
delay(interval);
++value;
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (ledState == LOW){
ledState = HIGH; // Note that this switches the LED *off*
} else {
ledState = LOW; // Note that this switches the LED *on*
digitalWrite(BUILTIN_LED, ledState);
delay(1);
count += 1;
Serial.print("Blink Count: ");
Serial.println(count);
}
}
//Battery voltage is divided by an 5.6K/1K resistor divider.
//ADC: 1024 = 1V
adc = analogRead(A0);
batteryMeasMv=(adc*10020*6.6)/10000;
// ^^^^^To correct an error in the resistance value
Serial.print("ADC mv: ");
delay(1);
Serial.println(batteryMeasMv);
}
テスターで実測値に近くなるよう係数を補正しています。
自分自身の電圧をグラフに投げて、長期DeepSpeel の電圧降下具合を記録できそうです。
手抜きですが、以下のようなコードになる感じですかね。
/*
ADC Read Sample.
Fairchild Semiconductor FSA3357 adc Select.
Arduino IDE 1.6.5 Hourly Build 2015/06/12 03:13
esp8266 by ESP8266 Community version 1.6.5 Hourly Build 2015/06/12
JunkHack 2015.10.10
--- ex Serial output.
Blink Count: 1
>adc1(B0)
ADC mv: 3280
>adc2(B1)
ADC mv: 3273
>adc3(B2)
ADC mv: 3293
>adc off
::
*/
#include <ESP8266WiFi.h>
int ledState = LOW;
unsigned long previousMillis = 0;
const long interval = 1000; //1sec
/******************************************************
* Fairchild Semiconductor FSA3357 adc Select.
* 0 = No Connection
* 1 = B0 to A
* 2 = B1 to A
* 3 = B2 to A
*/
const int S1 = 14; // S1 to GPIO Pin
const int S2 = 16; // S2 to GPIO Pin
void adcset(int port) {
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
switch (port){
case 1:
digitalWrite(S1, HIGH);
digitalWrite(S2, LOW);
Serial.println(">adc1(B0)");
break;
case 2:
digitalWrite(S1, LOW);
digitalWrite(S2, HIGH);
Serial.println(">adc2(B1)");
break;
case 3:
digitalWrite(S1, HIGH);
digitalWrite(S2, HIGH);
Serial.println(">adc3(B2)");
break;
case 0:
digitalWrite(S1, LOW);
digitalWrite(S2, LOW);
Serial.println(">adc off");
break;
}
}
/******************************************************
*
*/
void setup() {
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(115200);
delay(10);
}
int value = 0;
int count = 0;
int adc = 0;
int batteryMeasMv = -1;
/******************************************************
*
*/
void loop()
{
adcset(0);
delay(4000);
delay(interval);
++value;
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (ledState == LOW){
ledState = HIGH; // Note that this switches the LED *off*
} else {
ledState = LOW; // Note that this switches the LED *on*
digitalWrite(BUILTIN_LED, ledState);
delay(1);
count += 1;
Serial.print("Blink Count: ");
Serial.println(count);
}
}
// Select ADC source.
adcset(1);
delay(5000);
//Battery voltage is divided by an 5.6K/1K resistor divider.
//ADC: 1024 = 1V
adc = analogRead(A0);
batteryMeasMv=(adc*10020*6.6)/10000;
// ^^^^^To correct an error in the resistance value
Serial.print("ADC mv: ");
delay(1);
Serial.println(batteryMeasMv);
adcset(2);
delay(5000);
adc = analogRead(A0);
batteryMeasMv=(adc*10020*6.6)/10000;
Serial.print("ADC mv: ");
delay(1);
Serial.println(batteryMeasMv);
adcset(3);
delay(5000);
adc = analogRead(A0);
batteryMeasMv=(adc*10020*6.6)/10000;
Serial.print("ADC mv: ");
delay(1);
Serial.println(batteryMeasMv);
}
さて、ぼちぼちと回路図書いてみます。
書いて、PCB上に配置してみました。あと、温度湿度センサーを載せればOKとします。
リチウムの電池からの電圧と、バックブーストで作られた後の電圧を計測して、あとは照度センサーからのADCを計測したら3チャンネル使い切りました。
で、最後にDHT-22 を裏側に乗せました。前回作ったやつと同じように、ESP8266 の上に載る感じ。

UART のPIN配列は、ブレッドボードに挿したときに上からLEDが見えるに配列を逆にしました。あと、UART からの信号のDTRを一工夫して、リセットを押さなくても、書き込みモードになるように回路を組んでおしまいです。
他、何か忘れているような気もしますが、最後の点検でチェックしていきます。
現時点で、忘れているもの。
・メインスイッチ
・CDS の調整用、半固定抵抗
・WEB アクセスのLEDと、WiFi アクセスのLED (をつけるかどうか)
・EN Pin の配線
最後に少し、プログラムを改良したのをメモ。まれに、ADC値が変なので、10回の平均値を出しています。ESP12でテストしているので、ESP13 だとどういう動きになるかは、実際にモノが着てからテスト。
/*
ADC Read Sample2.
Fairchild Semiconductor FSA3357 adc Select.
Arduino IDE 1.6.5 Hourly Build 2015/06/12 03:13
esp8266 by ESP8266 Community version 1.6.5 Hourly Build 2015/06/12
JunkHack 2015.10.11
--- ex Serial output.
>adc3(B2)
ADC3 mv/10: 0 : 476
1 : 475
2 : 474
3 : 474
4 : 474
5 : 474
6 : 474
7 : 474
8 : 474
9 : 474
3139
>adc off
::
*/
#include <ESP8266WiFi.h>
int ledState = LOW;
unsigned long previousMillis = 0;
const long interval = 200; //1sec
/******************************************************
*
*/
void setup() {
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(115200);
delay(10);
}
int value = 0;
int count = 0;
/******************************************************
*
*/
void loop()
{
// Select ADC source off.
adcset(0);
delay(interval);
++value;
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (ledState == LOW){
ledState = HIGH; // Note that this switches the LED *off*
} else {
ledState = LOW; // Note that this switches the LED *on*
digitalWrite(BUILTIN_LED, ledState);
delay(1);
count += 1;
Serial.print("Blink Count: ");
Serial.println(count);
}
}
// Select ADC source.
adcset(1);
delay(interval);
Serial.print("ADC1 mv/10: ");
Serial.println(getMv());
adcset(2);
delay(interval);
Serial.print("ADC2 mv/10: ");
Serial.println(getMv());
adcset(3);
delay(interval);
Serial.print("ADC3 mv/10: ");
Serial.println(getMv());
}
/******************************************************
* Fairchild Semiconductor FSA3357 adc Select.
* 0 = No Connection
* 1 = B0 to A
* 2 = B1 to A
* 3 = B2 to A
*/
const int S1 = 14; // S1 to GPIO Pin
const int S2 = 16; // S2 to GPIO Pin
void adcset(int port) {
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
switch (port){
case 1:
digitalWrite(S1, HIGH);
delay(10);
digitalWrite(S2, LOW);
Serial.println(">adc1(B0)");
break;
case 2:
digitalWrite(S1, LOW);
delay(10);
digitalWrite(S2, HIGH);
Serial.println(">adc2(B1)");
break;
case 3:
digitalWrite(S1, HIGH);
delay(10);
digitalWrite(S2, HIGH);
Serial.println(">adc3(B2)");
break;
case 0:
digitalWrite(S1, LOW);
delay(10);
digitalWrite(S2, LOW);
Serial.println(">adc off");
break;
}
}
/******************************************************
* It reads the 10 times of the average value.
*/
int getMv(){
// correct an error in the resistance value.
const int CORRECT = 10030;
int mv = -1;
int i;
int adc = 0;
for (i = 0; i<10; i++ ){
adc = 0;
//Battery voltage is divided by an 5.6K/1K resistor divider.
//ADC: 1024 = 1V
adc = analogRead(A0);
//delay(10);
// Serial.print(i);
// Serial.print(" : ");
// Serial.println(adc);
mv += (adc*CORRECT*6.6)/10000;
// ^^^^^To correct an error in the resistance value
}
mv = mv / 10;
return mv;
}

