今年13回目の芝刈りをしました。8月中旬になって,やや成長が鈍ってきました。我が家の芝は,
高麗芝(多分)とティフトンの二種類が植えてありますが,両方とも成長がやや鈍りました。また,
ティフトンの方は,サッチがたまってきたのか,床とどこと茶色になっています。今年は,サッチ
取りを十分にしませんでしたが,来年度は,しっかりとりたいと思います。
IOT再びーESP32編(14)ーーー静電容量水位計に向けてーーADS1115-
超音波センサーによる水位計は,測定が安定しないので,ひとまず休止して,静電容量測定による水位計をい
じってみたいと思います。それにともなって,ESP32は,ADC機能がいまいちということなので,ADC の基
盤,ADS1115をいじってみることにしました。
この基盤は,分解能が16ビットありますので,結構精密に変換できて,接続もI2Cなので,4本だけ接続す
ればいいので,お手軽です。また,ESP32 用にライブラリーもあるので,お手軽です。ただ,本当に理解す
るには,ライブラリーを使わないで,使われているIC に直接書き込みをした方がいいのでしょうね。ちょっ
と,それは気力がないので,ライブラリー使用です。
例のごとくブレッドボードで,ESP32,ADS1115,SSD1306,レベルシフター,を配線しました。
ADS1115とSSD1306はI2C接続なので,並列につなげればいいので,お手軽です。
それほど時間はかかりませんでしたが,ADS1115 の配線でちょっとはまりました。スケッチ例の注意には記
載があったのですが,測定できるのは,ADS1115の Vdd+0.3Vmax の記載があるのをみおとしてました。
5Vラインを測定しても,約 4.0V の表示かできないので,あれこれやりました。
すぐに原因判明しました。
SSD1306の電源に合わせて 3.3V で動作させてました。急遽,レベルシフターをいれて,5Vで動作させる
と,正しく測定できました。写真は,乾電池を測定してるところです。はっきりしませんが,OLED には,
1.63 Vと表示されてます。
まだ,やっていませんが,差動入力にすると,プラスマイナスを逆につないでも,マイナス何ボルトの表示
が可能です。
今回使ったスケッチですが,このスケッチは,測定に必要ない余分なヘッダーファイルをインクルードしていま
す。
// 必要なライブラリのインクルード
#include <wifi.h>
#include <wire.h>
#include <adafruit_gfx.h>
#include <adafruit_ssd1306.h>
#include <adafruit_ads1x15.h>
//ADS1115 ADS(0x48);
Adafruit_ADS1115 ads;
byte hdr, data_h, data_l, chksum;
String inputString = "";
// ピンの定義
#define wifyOn 4 // wify 接続OK
#define wifyOff 2 // wify 未接続
#define OLED 18 // OLDE 表示・非表示
//OLED
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// WiFi接続情報--固定アドレス用
const char* ssid = "***********";
const char* password = "***********";
const IPAddress ip(192, 168, 2, 30);
const IPAddress gateway(192, 168, 2, 2);
const IPAddress subnet(255, 255, 255, 0);
const IPAddress dns1(192, 168, 2, 2);
// セットアップ関数
void setup() {
//入出力ピン設定
pinMode(wifyOn, OUTPUT);
pinMode(wifyOff, OUTPUT);
pinMode(OLED,INPUT_PULLUP);
digitalWrite(wifyOn, LOW);
digitalWrite(wifyOff, HIGH);
Serial.begin(115200); // シリアル通信の開始
Serial2.begin(9600,SERIAL_8N1,16,17);
ads.begin();
//OLED開始
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
//OLED初期設定
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.print(F("Wify set"));
display.display();
// WiFi接続
if (!WiFi.config(ip,gateway,subnet,dns1)){
Serial.println("Failed to configure!");
}
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
digitalWrite(wifyOn, HIGH);
digitalWrite(wifyOff, LOW);
display.clearDisplay();
display.setCursor(0, 0);
display.print(F("Wify con"));
display.display();
}
// メインループ
void loop() {
digitalWrite(wifyOn, HIGH);
digitalWrite(wifyOff, LOW);
ads.setGain(GAIN_TWOTHIRDS);
int16_t adc0;
float volts0;
adc0 = ads.readADC_SingleEnded(0);
volts0 = ads.computeVolts(adc0);
Serial.print("AIN0: ");
Serial.print(adc0);
Serial.print(" ");
Serial.print(volts0);
Serial.println("v");
display.clearDisplay();
display.setCursor(0, 0);
display.println(adc0);
display.print(volts0);
display.print("v");
display.display();
delay(500);
digitalWrite(wifyOn, LOW);
digitalWrite(wifyOff, HIGH);
delay(500);
}
芝刈りーー今年第12回目
IOT再びーESP32編(14)ーーープログラムの修正(A0221AT)防水超音波センサー
テストを繰り返していますが,なかなか安定した測定結果がえられませんでした。データの変動の幅がおおき
かったり値が変化しなかったりとしたため,あれこれとやりました。夜茶の間いろいろやっていると,比較的
安定した結果になるようでしたが,その原因が分かりました。測定結果が安定してないので,センサー部分を
見ると,水滴がかぶっていました。元々防水なので,水滴は大丈夫なはずですが,水滴が付いているため,測
定に影響があるような気がします。もともと超音波センサーは,超音波を発して,その反射が帰ってくるまで
の時間を計測して,距離を算出してますので,水滴がついていると,超音波の発信,受信に影響があるのかも
しれません。
センサー部分の水滴を拭き取ってみると,ほぼ正確な反応が返るようになりました。あれこれスケッチをいじ
ましたが,平均をとらなくても大丈夫なようですので,平均はとらずに運用してみようと思います。
ただ,英語のマニュアルをみてみると,レスポンスが帰るまで,100~300msとあるので,書き込みをし
てから,300msの休止(delay(300);)をいれました。
float measureDistance_2() {
char m[50];
int Sw;
Serial2.write("S");
delay(300);
if (Serial2.available())
{
hdr = (byte)Serial2.read();
if (hdr == 255){
data_h = (byte)Serial2.read();
data_l = (byte)Serial2.read();
chksum = (byte)Serial2.read();
if (chksum == ((hdr + data_h + data_l)&0x00FF)){
distance = data_h * 256 + data_l;//距離計算
new_distance=distance/10;
dtostrf(new_distance, 6, 1, m);//
Serial.print(m);
Serial.println(" cm");
if(digitalRead(OLED)==HIGH){//OLED表示ONの時
display.clearDisplay();
display.setCursor(0, 0);
display.println("rest= ");
display.print(m);
display.println(" cm");
display.display();
}
}
}
}
delay(100);
return distance/10;//cmを返す
}
超音波センサーなので,明るさは関係ないと思うのですが,検証をするのは,蛍光灯の下が大いのですが,そ
の影響もあるのでしょかね。
茶の間で検証の様子です。水が噴霧機に入ってるので,おっちょこちょいの私は,こぼさないかヒヤヒヤして
ます。
芝刈りーー今年第11回目
IOT再びーESP32編(13)ーーープログラムの修正(A0221ATデータフォーマット)
スケッチを書き換えました。初期値を決定するのに,10回計測して,最大値と最小値を除いたものの平均を
とる関数を作成しました。
//初期値設定用 平均
float sokutei_heikin(int m){
float Value[10];
float Max;
float Min;
float Sum;
for(int Ct=0;Ct<m;Ct++){
Value[Ct]=measureDistance_1();//距離の測定関数を呼び出す。
Serial.print(Ct);
Serial.print(" =");
Serial.println(Value[Ct]);
if(Ct == 0) {//最初の測定値を最大・最小値として保存
Max=Value[0];
Min=Value[0];
}
else {
if(Value[Ct] > Max){//取得したデータを最大値と比較して,大きければ,新たに保存
Max=Value[Ct];
}
if(Value[Ct] < Min){////取得したデータを最小値と比較して,小さければ,新たに保存
Min=Value[Ct];
}
}
Sum+=Value[Ct];/*測定値を加算*///測定値を加算していく
}
Sum=(Sum-(Max+Min))/(m-2);//最大値と最小値を除いて,平均をとる。
Serial.print("AVE");
Serial.print(" =");
Serial.println(Sum);
return Sum;/*最大値・最小値を除いた平均値を返す*/
}
sokutei_heikin(10)ということで,10回の測定の平均をとる(最大・最小を除くので実際は8回)
設定で,動かして見ましたが,一回目の測定値が,きちんと測定されてないようなので,測定に入る
一回ダミーの測定をいれsて,実際は,11回の測定でやってみました。大きな変動もなく結果は良好
でした。
今回,最大・最小値を除いた平均を計算するのに,ちょっとなやみました。測定値を全部保存したうえ
ソートして,最大値と最小値を除こうかとも思いましたが,測定値をその都度一時保存の最大値と最小
値と比較するやり方が,よかったようです。
下記が,超音波センサーから,距離を測定するための関数です。
float measureDistance_1() {
char m[50];
Serial2.write("S");//RX端子をHIGHにするのに一文字書き込む。
if (Serial2.available()){
hdr = (byte)Serial2.read();
if (hdr == 255){
data_h = (byte)Serial2.read();
data_l = (byte)Serial2.read();
chksum = (byte)Serial2.read();
if (chksum == ((hdr + data_h + data_l)&0x00FF)){
distance = data_h * 256 + data_l;//距離計算
}
}
}
delay(100);
return distance;
}
distance = data_h * 256 + data_l の部分が,距離を計算する部分です。計算するといっても,HIGHの
データとLOWのデータが,1バイトずつ送られてくるので,桁数を合わせる計算をしているだけです。
マニュアルには,下記のような記述がありました。
計測が開始されるとその結果が下記のように,4バイトのデータでおくられてきます。
0XFF 0X07 0XA1 0XA7
各データは,
0XFF はヘッダーデータ
0X07 は上位データ
0XA1 は下位データ
0XA7 はチェックサム
のようになってますので,
上位のデータと下位のデータを合わせると,
07A1
という16進数が得られますので,これを10進数に直すと,1953mmというデータが得られるようです。
IOT再びーESP32編(12)ーーープログラムの修正
大きな不具合のなかった配線ですが,赤のLEDが点灯しなかったので,いろいろ調べてみると,LEDの足が断
線してました。また,組み込んでテストしてみると,大きな不都合はなかったものの,原因は分かりません
が,測定値が変動するようなので,その対策で,スケッチを修正することにしました。
オリジナルのスケッチでは,超音波の測定による距離をそのままWEBに渡していましたが,この部分を多少
変更します。
噴霧機満タンの状態での測定値を記憶して,それに基づいて,減り具合を加算するようにしたいと思いま
す。満タンの状態は,何度か測定して,平均をだして,初期値とするにあたって,誤差を抑えるために何回
か測定し,最大値と最小値を除いて,平均をとりたいと思います。
どうしたもんかとネット見ていると,下記のようなプログラムが見つかりました。C のものですが,これを
参考に修正しようと思います。
#include <stdio.h>
#define NumValue 5
int main(){
int Value[NumValue];
int Ct;
int Max;
int Min;
int Sum;
for(Ct = 0; Ct < NumValue; Ct ++) {
printf("Enter #%d → ", Ct + 1);
scanf("%d", &Value[Ct]);
if(Ct == 0) {
Max = Value[0];
Min = Value[0]; }
else {
if(Value[Ct] > Max) {
Max = Value[Ct];
}
if(Value[Ct] < Min) {
Min = Value[Ct];
}
}
}
printf("========\n");
Sum = 0;
for(Ct = 0; Ct < NumValue; Ct ++) {
if(Value[Ct] != Max && Value[Ct] != Min) {
Sum += Value[Ct];
}
}
printf("%d\n", Sum);
}
IOT再びーESP32編(11)ーーーテストーー超音波センサー
芝刈りーー今年第10回目
今年10回目の芝刈りです。一週間で,約5cmほど伸びるようです。今年は,例年になく,状態はいいよう
に思いますがサッチが取り切れてないところがやや茶色く見えます。
芝刈り前
芝刈り後