ラベル ESP8266 の投稿を表示しています。 すべての投稿を表示
ラベル ESP8266 の投稿を表示しています。 すべての投稿を表示

2021年9月9日木曜日

Stepper Motor Driver の問題解決

2~3年前秋月にコパルのSPG27-1101が安価で出ていたので、使い道も考えずに纏め買いして、ジャンクボックスの肥しになっていました。 で、バタフライバリコンでこれを使ってリモートで、と当然考え、これのドライバをESP8266とDRV8835で作ってみました。

SPG27のスペックシートを見ると12Vでの動作が出ていたので、つい「12Vで動かす必要がある」と思い込んでいましたが、DRV8835のVMmaxが12Vです。 気にしないで、12V加えていましたが、 突然動かなくなって、ESP8266もUSB入力を受け付けなくなってしまうものが幾つか出てきました(壊れている!)。

回路はいたって簡単で、外部からDC電源を供給して、内部で3.3VのVccをICに供給、モーターには外部からのDCを供給するようになっています。

壊れそうなところは無いので、最初原因が分からず色々考えていましたが、DRV8835のVM maxが一番怪しい!という事で、電圧を5V位まで落としてみましたが、StepperMotorはちゃんと動いてくれます(トルクが少し落ちているかもしれませんが)。 また、動かなくなることも今のところないようなので、結論として、12Vが拙かった!  

ちょっとした勘違いで、可愛そうなESP8288とDRV8835を幾つかお見送りしてしまいました。Amen...

SPG27-1101は基本ステップ角度3°で、これに5:1のギアでMLAのバタフライバリコンを動かしています(0.6°/step)が、100pF程度のバタフライバリコンだと、まだ粗い感じがあります。 

マルチバンドのMLAの場合は、多分、固定コンデンサと小容量のバタフライバリコンの組み合わせ、等を考える必要があるのでしょうね。 この時、固定コンデンサの切り替えをリレーで行うとすると数十Aの高周波電流を許容するリレーをどうするか?が問題になりそう。

備忘録としてfritzingのBreadboardとPCBのコピー、それにsketchを添付しておきます。

 

 

 

 

 

 

 

 

 

 

 

 

 //  For use of DRV8835+SPG27-1101
//  Author  Ken Yamada, JA2IYJ
//  WeMos D1 mini
//  Date:  2019 July 3rd. V0.5 Initial version.
//              July 11th V1.0 Zero_sensor added and bandled to the workable protype hardware.
//         2020 Nov. 11 v2.0  MAX_sensor added.  
//         2021 Apr. 23 Modified for Butterfly Capacitor ... No need of Max/Min Stopper.
//         2021 May. 19  EEPROM.write/read/commit added to set initial and current Position.
//         2021 Sept. 3  Changed Up/Dwn/Init pin to reflect PCB alignment.  Motor runs at 5V.
//                       Above 11V, DRV8835 might die and kills ESP8266 too.
//

#include <Stepper.h>
#include <EEPROM.h>
#include <ESP8266WiFi.h>

#define EEPROM_SIZE 2  // sizeof(int)=2 byte.
#define TRUE 1
#define FALSE 0
#define MOTOR_1 16 //15  DRV8825のピン配置に合わせて変更 5/22
#define MOTOR_2 14 //12
#define MOTOR_3 12 //13
#define MOTOR_4 13 //14
// digital address それぞれをボタンにアサイン
#define UP_BUTTON 0 // 黄色
#define DOWN_BUTTON 4 // 白
#define INIT_BUTTON 2 // Position 0 setting (GPIO16 has a built-in pull-down resistor.)
#define STEPS_PER_REV 120  // SPG27-1101 specification
#define MAX_POS 155 // 90deg/3deg step, 5:1 gear = 30 x 5 + α

// stepPerRotate は素のモーターの一回転当たりのstep数の様です(ギアの事汎用では顧慮できないもんね)
//const int stepsPerRotate = 20;// SPG20-1332ス テップ数 = 480 ギア比1:24 hence 20
const int stepsPerRotate = 12;// SPG27-1101 ステップ数 = 120 ギア比1:5 hence 24 でも12でないと動かない! 何故?
int curPosition;
int initPosition;
boolean toggle1 = FALSE;
boolean toggle2 = FALSE;

Stepper myStepper(stepsPerRotate, MOTOR_1, MOTOR_2, MOTOR_3, MOTOR_4);

void setup(){
  Serial.begin(115200);
  Serial.println("\n Setup ...");
  // WiFiを使用しないので、省電力化の為に下の3行
  WiFi.mode(WIFI_OFF);
  WiFi.forceSleepBegin();
  delay(1);
 
 //EPROM.begin(EEPROM_SIZE);
//initPosition = EEPROM.read(0);
//curPosition = initPosition;
  Serial.print("\n curPosition = ");
  Serial.println( curPosition );
  pinMode(UP_BUTTON, INPUT_PULLUP); // 手動制御用のUp/Down ボタン High
  pinMode(DOWN_BUTTON, INPUT_PULLUP); // 手動制御用のUp/Down ボタン High
  pinMode(INIT_BUTTON, INPUT_PULLUP);  // One time.
  myStepper.setSpeed(2000); // 2500位まではOKの様です。
  //myStepper.setSpeed(50); // make it slow

  Serial.println("\n  End of Setup ...");
}

void loop(){
  Serial.println(" Start Loop ---");
  //  初期設定の時に容量最大値の位置を0に設定する。
  #if 0
  if( digitalRead(INIT_BUTTON) == LOW) {
    EEPROM.begin(EEPROM_SIZE);
    EEPROM.write(0, 0);
    EEPROM.commit();
    Serial.println( " Wrote EEPROM -> 0 ");
    delay(500);
  }
  #endif
  // Up button
  if( digitalRead(UP_BUTTON) == LOW ){
    Serial.println("Up button 1");
//  while( digitalRead(UP_BUTTON) == LOW && toggle1 == TRUE && curPosition < MAX_POS){
    while( digitalRead(UP_BUTTON) == LOW ){
      myStepper.step(1);
      curPosition++;
      yield();    // Soft WDT reset が出ない様にするため。
      delay(50);
    }
  }
  // Down button
  if ( digitalRead(DOWN_BUTTON) == LOW ){
    Serial.println("Down button 1");
//  while( digitalRead(DOWN_BUTTON) == LOW && toggle2 == TRUE && curPosition > 0 ){
    while( digitalRead(DOWN_BUTTON) == LOW ){
      myStepper.step(-1);
      curPosition--;
      yield();    // Soft WDT reset が出ない様にするため。
      delay(50);
    }
  }

  stopMotor();
  #if 0
  if (curPosition != initPosition ){
     EEPROM.write(0, curPosition);
     EEPROM.commit();
     initPosition = curPosition;
     Serial.print( "Save curPosition = ");
     Serial.println( curPosition );
  }
  delay(10);
  #endif
  Serial.println("  End of Main loop ...");  
  delay(10);
}
void stopMotor() {
  digitalWrite(MOTOR_1, LOW);
  digitalWrite(MOTOR_2, LOW);
  digitalWrite(MOTOR_3, LOW);
  digitalWrite(MOTOR_4, LOW);
}  
#if 0
int moveAbsPos2(long pos){
  if (pos < maxPosition) {
    myStepper.step(currentPosition - pos);
    currentPosition = pos;
  } else {
    return -1;
  }
 
}
int incrementPosBy(long pos){
  if (currentPosition + pos < maxPosition) {
    myStepper.step(pos);
    currentPosition = currentPosition+pos;
  } else {
    return -1;
  }
}
int decrementPosby(long pos){
  if (currentPosition - pos > 0 ){
    myStepper.step(-pos);
    currentPosition = currentPosition - pos;
  } else {
    return -1;
  }
}
#endif



 

 

 

2020年4月24日金曜日

温湿度モニター(センサーをSHTに変更)

センサーをDHTからSHTに変更して、センサー部分の構造をむき出しから、アクリルパイプ(16φ 10cm)の中に入れる方法にしてみました。 
また、SHTだけですが供給電圧を計測時にonして終了すればoffするようにして、省電力化をさらに進めてみました。 
また、計測時間間隔を凡そ10分にしています。 (何故か、一つの計測点のDHTがうまく動作しなくなってしまったので、この際2つ共にSHTに変更しました。)
 また、実験中にhttpd-access.logに408が記録され、データがちゃんと受信できていなかった時があったので、Li電池を新しいものに交換してみました。
回路図を添付するほどの物ではないので、以下結線の記述;
SHT VIN -> D6(GPIO12)
      G     -> Ground
      SCL -> D1(GPIO5)
      SDA -> D2(GPIO4)
ESP-WROOM-32
     RST -> D0(GPIO16)  deepsleep wakeup の為、

>> 408のエラーを調べてみると、Headerが送られて来てから中身が送られて来るまでの間隔が長いと、攻撃とみなして、Timeoutさせる、仕様になっているようなので、外部にexposeするサーバーでは無いので、取り敢えず、/usr/local/etc/apache24/httpd.confのmod_reqtimeout.soをコメントアウトして様子を見ることにしました。
また、SHTの電源のoffは、サーバーとのコネクションを切ってからにしました。
>> これも解決には至っていない! 何が原因だろう?
何故か、手こずるなー、、、。
>> deepsleep で4時間半(10分毎なので、25,6回)位で止まってしまうので、別の8266に替えてみると、問題なく動いています。 結局は原因が良くわからず、8266自身が不良品だったのかもしれません。 
色々弄っているときにESP8285でもやってみましたが、此方はdeepsleepから立ち上がりませんでした。 ググるとdeepsleepが動かない、と言う書き込みがあったので、8266と同じものとして扱うことは出来なさそうです。
>>使用していた1000mAhのLi電池の出力が3.7V位に下がってしまう(劣化?)とNJU7223が3.3V作ってくれなくて起動できなくなっている物があることに気が付きました。NJUは入力電圧が0.6V以上高い必要がある為に、Liが3V台に落ちてしまうとアウト!




/*
    This sketch establishes a TCP connection to a "quote of the day" service.
    It sends a "hello" message, and then prints received data.
*/
#include "ESP8266WiFi.h"


#ifndef STASSID
#define STASSID "Buffalo-G-4CC0"
#define STAPSK  "65rhwrit3nnee"
//#define IDENTIFIER "GardenCenter"
#define IDENTIFIER "GardenEast"
//#define IDENTIFIER "GardenWest"
#endif
#define SHT 12  //  D6=GPIO12 set to SHT power. DTH11 was broken and replaced to SHT10 2020/04/21
#define DHTpin 14

#ifdef DHT  
  #include "DHTesp.h"
  DHTesp dht;
#else
  #include "SHTSensor.h"
  #include "Wire.h" 
  SHTSensor sht;

#endif
const char* ssid     = STASSID;
const char* password = STAPSK;
const char* Identifier = IDENTIFIER;
const char* host = "192.168.1.3";
const uint16_t port = 80;

void setup() {
  Serial.begin(115200);
  delay(1000);  //let sercial console settle.
  pinMode(SHT,OUTPUT); // Control SHT power to minimize the consumption.  
  // We start by connecting to a WiFi network
  /* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
     would try to act as both a client and an access-point and could cause
     network-issues with your other WiFi-devices on your WiFi-network. */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
#ifdef SHT  
  digitalWrite(SHT, HIGH);
  delay(100);  // need to wait a while ...
  Wire.begin();
  if (sht.init()) {
    Serial.print("init(): success\n");
  } else {
    Serial.print("init(): failed\n");
  }
#endif
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
#ifdef DHT
  dht.setup(DHTpin, DHTesp::DHT11);  //Connect DHT sensor to GPIO 14
#else
  sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); // only supported by SHT3x
#endif
}
void loop() {

  WiFiClient client;
  if (!client.connect(host, port)) {
    Serial.println("connection failed");
    delay(5000);
    return;
  }
#ifdef DHT
  delay(dht.getMinimumSamplingPeriod());
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.getHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.getTemperature();
  // Check if any reads failed and exit early (to try again).
#else
  float h = sht.getHumidity();
  float t = sht.getTemperature();

#endif

  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT/SHT sensor!");
    delay(100);
    return;
  } 

  // WEB serverにデータをアップロードする。
  String url = "/weather/weather_log.php";
        url += "?location=" + String(Identifier); // ID to identify location
        url += "&temperature="+String(t);
        url += "&humidity=" +String(h);
        url += "&pressure=" +String("-----");     
  Serial.print("Requesting URL: ");
  Serial.println("GET "+ url);
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
                "Connection: close\r\n\r\n");
  delay(50); 
  // Read all the lines of the reply from server and print them to Serial
  Serial.println("Returned message from server: ");
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  client.stop();  
  
  digitalWrite(SHT, LOW);  // turn off SHT power.

  // 15分deepsleepする。
  ESP.deepSleep(10*60*1000*1000, WAKE_RF_DEFAULT); // 60*1000*1000 = 1min, 10 min
  delay(1000); // execute once every 5 minutes, don't flood remote service
}

2019年11月18日月曜日

ESP8266 温湿度モニターの筐体の検討

取り敢えず、100均でPPの小さな容器を買ってきて、これに断熱テープを張り付けて、内部に基板を入れて、窓際に置いて、数日間温湿度を計測してみました。 また、対照として、卓上にブレッドボード上に同じものを作り、これも計測データをサーバーに送らせて、比較してみました。

結果はOMG! 何を測っているのか分からなーい! 断熱テープで太陽光を遮っても、容器内に暖められた空気がこもり、この温度を測ってしまっていますね。 
太陽電池に太陽光を当てて、且つ周りの雰囲気温度を計測するのは思ったより難しそうです。 
今度は、100均で台所で使う少し大きめの網目のPP籠で実験してみることにします。  雨が当たらないように、配置を考える必要があります。 
電子的にはあまり問題はありませんが、筐体には結構頭を使わないといけませんね。これは難しい。





2019年11月13日水曜日

ESP8266 WiFi 温度湿度モニター

そもそも太陽電池、LiPo、充電モジュールを興味本位でAmazonで買ってしまったので、昔考えていたWiFi温度湿度モニターが復活してしまいました。 で、deepsleep(60分は出来なかったので、15分)を使ってこの組み合わせでどの位使えるのか、実証してみようと、100均でPPの容器を買ってきて、取り敢えずバージョンを作ってみました。
取り敢えずのブレッドボードでdeepSleepを確認してみましたが、30分程度にしかならない(60x60x1000x1000と引数に書くと、符号付と解釈される?)ので、15分毎にアップデートすることとしました(3,600,000,000って書くとちゃんと60分になるのかは未確認)。

> 数字を直接入れると60分位になることを確認しましたが、 3600000000を入れても、実際には11:50:21 - 12:45:50 = 55:29と正確ではありませんね。 
ま、esp8266のタイマーに精度を求めるのには無理があるので、もう少し細かい間隔で記録を取って、平均したほうが良いと思います


秋月の46X72の基盤を46X36に2分して、JRCのNJU7223DL1-33を電池からの電源に噛まして、47μFをパラにして安定化を図り、RSTとD0をショートピンでショート出来るようにしただけの超簡単基板ですが、まともに動きますねー。

さて、消費電流ですが、microUSBでPCと繋いでいると常時13mA位流れていますが、プログラムの書き込み後、自走させると、アップロード時に64mA、それ以外は0.01mA或いはそれ以下(使った電流計が0.01mA以下が読めなかった)で、アップロードは数秒で終わりますので、これだとかなり行けそうです。


「さー、これでいけるぞ!」とPPの容器に、断熱テープ(Amazonで購入した、ガラスウールとアルミのラミネート)を張り付け、容器の上に太陽電池、下は解放という形状にしてみました。 
断熱テープって、アルミなので電波シールドになっちゃうんじゃ?とESP8266の基板を取り付けた方は断熱材を剥がしています(こちら側に太陽光が当たらないように設置する必要があります)。 ケース内の取り付けは、両面テープでちょこっと張り付けただけの、超いい加減バージョン!

1週間ほど、室内の窓際に置いて、問題が無ければ、実際に庭に設置して計測を開始することにする予定。
あ、電源のon/offスイッチ付けるの忘れてる!!

使用しているコード














2019年11月9日土曜日

ESP8266 Arduino、、、、

太陽電池、リチウム電池、充電モジュールが手に入ったので、屋外で温度湿度をリポートしてくれるモジュールを作ってみたくなり、昔購入して余っていたESP8266を引っ張り出してきて実験してみましたが、色々と躓いています。
1)3~4年はこの世界では世界が違う!
左が新しいもの、右が昔のWROOM-02
スイッチサイエンスの昔のモジュールにスケッチを書き込もうとすると、エラーが出ます。 あ、Arduino IDEの設定が膨れ上がっていて、色々事前に設定することがあるようです。

 

2)ESP8266にも色々ある
  昔のESP8266って、裸でしたが、最近のは色々周辺がくっ付いていて、プログラム書き込みモードを手動でしなくても良い、Serial port(CH340)が付いていていきなりUSBが繋げる、など随分と進歩していますが、この分IDEの事前設定が必要なのですね。
取り敢えず、ESP8266関連の物が見えるようにする為に、ファイルー>環境設定ー>「追加のボードマネージャのURL」に"https://arduino.esp8266.com/stable/package_esp8266com_index.json"を入れて「ツール」のボードの選択肢にESP8266関連が出てくるようにし、更にボードの仕様に応じてReset等の細かい設定をすることが必要になっています。

3)Arduino IDEのシリアルモニターが文字化けしてうまく動かない!
  色々躓きながら、何とかスケッチの書き込みまでは出来るようになりましたが、シリアルモニタの出力が文字化けして、どうしても治りません! 転送スピードを弄ったら何とかなるかと、9600位まで落としてみましたが変化無し! 化け方が何とはなく、昔見たことがあるような気がするのですが(8bit,Non-parity,1 stop bitが違っている?)、弄るところもないので???

お手上げで、今日は店じまい。





参考にさせて頂いた記事; 
 WeMos D1(ESP8266)を動かす
 ESP-WROOM-02
 ESP-WROOM-02の開発キットを使ってみる




2019年11月6日水曜日

太陽電池、LiPo、、、、

昔、ESP8266で温度、湿度、気圧を測定して定期的に室内のWeb serverにデータを飛ばしてくるモジュールを作りましたが、電源の確保が心配だった(時折電池を取り替えなければならない?)ので、室内にぶら下げていますが、やはり屋外の温度等が測定してみた
い、とずっと思っていました。
時々?入ってくるAmazonのAdで小さな太陽電池や、リチウム電池の充電保護回路などが安く売られているので、ちょっと、意欲が湧いてきて、屋外の温度もWeb serverに取り込む物を再度作ってみようと、少し始めてみました。
取り敢えず、太陽電池と充電保護回路を繋いで室内の日の当たるところで、動作確認してみると、「おー、動く!」。 当たり前か。 
昔のBlog見ながら、温度湿度レポーターを作ることにしますが、もう4年ほど前の事なので、結構忘れていてSketchの見直しから! できれば、ついでに風速計も作ってみたいなー。

今回購入したもの;
 HiLetgo 10個セット 5V 1A 18650 リチウムバッテリー チャージボード Micro USB チャージモジュール プロテクト [並行輸入品] 

 NUZAMAS 4組 5V 30ma ソーラーパネル専門屋出品 超薄型軽量 携帯型 多結晶フレキシブル ソーラーパネル DIY モジュール 

 4個 リチウムイオンバッテリ、3.7V 1000mAhリチウムバッテリ、リチウム 充電式 充電池、保護ボードと絶縁テープ付き、ESP 32開発ボードと互換性あり、Micro JST 1.25


2017年1月4日水曜日

ESP8266の利用 続き

土壌水分のリモート測定装置を作ろうとしていましたが、センサーの部分について少々問題があり挫折中。 で、取りあえずESP8266のADCを利用してデータを取得、基板上のLCDに表示して、更にデータをWiFi経由でサーバーに送る部分は使えるレベルのようなので公開することにします。
ESP8266のADCで0~1Vを1024の分解能で計測する事が出来ます。 ルーターのアドレス、パスワードやホストのURL等を後から変更できるようにSDカードで管理できるようにしてみました(セキュリティ上の問題がありますので、注意する必要があります) 。
ユニバーサル基板上に組んでいますが、専用の基板を起こせば、この半分くらいのサイズには出来ると思います。

疑問点;
 ESP8266のDeep Sleep modeで最大1時間程度のインターバルが出来るはずなのですが、うまく行きませんでした。 30分位が限界のようですが、何故?
  SD cardは最近の容量の大きいものは使用できません。大容量のSDカードに対応した(ファイル形式の異なる)スケッチが見つかりませんでした。 もっとも、この場合、大容量は要らないので、問題ではありませんが。

/* Sketch */

/*
 *
 *
 */
#include
extern "C" {
  #include "user_interface.h"
}
#include
#include
#include
#include

Sd2Card card;
ST7032 lcd;
const int chipSelect = 2;
// router情報、接続情報などのdefault値 port番号が固定(80)にしてあるので注意
char ssid[30]     = "?????";
char password[30] = "**********";
char Id[13] = "********";
char host[20] = "192.168.1.3";
const int httpPort = 80; 
boolean WiFiFlag = false;

// ESPのADCの生データを取得 データ変換は後で、、、 
uint tout_get(){
  uint ADC_Value = 0.0;
 count = 5;  // 5回計測して平均値を返す
  uint temp = 0;
  for(int i = 0; i < count; i++ ){
    ADC_Value = system_adc_read();
    Serial.println("===> " + String(ADC_Value));
    temp = temp+ADC_Value;
    delay(30); 
  }
  temp = temp/count;
  // Serial.println("ADC_Value = " + String(temp));
  return temp;
}
//  SSIDの指定されたファイル名のファイルの内容(文字列)を返す
char *read_sd(char* file) {
   // open the file for reading:
  File myFile = SD.open(file, FILE_READ);
  char *s0, *s1;
  s0 = s1;
  if (myFile) {
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *s1++ = myFile.read();
    }
    *s1 = '\0';
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening " + file);
  }
  return *s0;
}

void setup() {
  Serial.begin(115200);
  delay(10);
#if 0
  // 自分のMAC addressの取得と表示
  byte mac_addr[6];
  WiFi.macAddress(mac_addr);
  char buff[20];
  Serial.print("Mac address: ");
  sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(buff);
#endfi
  // SDカード読み取りの初期化(設定)
  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
     // SD card無しでdefaultで動かすのなら、ここのコメントを取る
    // return; 
  }
  Serial.println("initialization done.");
  Serial.println("");
  Serial.println("Started");

 // SDカードの情報の読み込み
  ssid = read_sd("ssid.txt"); // WiFiルーターの名前
  password = read_sd("pass.txt"); // WiFi接続のためのpassword
  Id = read_sd("Id.txt");  // 本情報の識別のための任意の名前文字列
  host = read_sd("host.txt"); // HostのIPアドレス或いはURL
  delay(500); //Why?, but need this, otherwise WiFi cannot connect to

  // SSIDから取得した情報でWiFiと接続
  char *s = ssid;
  if(*s != '?' ){ 
    WiFi.begin(ssid, password);
    Serial.println("connecting to " + String(ssid) + " pass: " + String(password) );
    int i=0;
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
      i++;
    }
    WiFiFlag = true;  // When connection being made, then transmit data to WiFi, otherwise only to LCD.
    Serial.println("");
    Serial.println("WiFi connected"); 
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
  } else {
    WiFiFlag = false;
  }
  // LCDの初期化
  lcd.begin(8,2);
  lcd.setContrast(25);
  delay(40);
}
void loop() {
  String s1;
  int xx;
  // データ計測
  xx = tout_get();
  s1 =  String(xx) + " C"; //仮に温度だとして
  // LCDへの表示
  lcd.clear();
  lcd.setCursor(2,0);
  lcd.print(s1);
  Serial.println(" ====  Temp = " + s1 );
  // WiFiでHostに接続してデータ送出
  if (WiFiFlag){
    // Use WiFiClient class to create TCP connections 
    Serial.print("connecting to ");
    Serial.println(host);

    WiFiClient client;
    if (!client.connect(host, httpPort)) {
      Serial.println("connection failed");
    }
    // URIを生成  Host側がIdentifier,data1,data2,data3,data4,data5,data6を受け取るようにしているので使っていなくても数だけ""を入れる
    String url = "/data/data_logger.php";
           url += "?Identifier=" + String(Id);
           url += "&data1="+String(xx);
           url += "&data2=" +String("");
           url += "&data3=" +String("");
           url += "&data4="+String("");
           url += "&data5=" +String("");
           url += "&data6=" +String("");                    
    // Serial.print("Requesting URL: ");
    // Serial.println("GET "+url);
    // Hostにデータを送出
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                    "Host: " + host + "\r\n" +
                    "Connection: close\r\n\r\n"); 
    delay(50);
    // Hostからの応答を読み込み、serialに表示
    while(client.available()){
      String line = client.readStringUntil('\r');
      Serial.print(line);
    }
    Serial.println();
    Serial.println("closing connection");

  }

  //DEEP SLEEPモード突入命令
  Serial.println("DEEP SLEEP START!!");
  //1:μ秒での復帰までのタイマー時間設定  2:復帰するきっかけの設定(モード設定)
  //ESP.deepSleep( (30*1000*1000), WAKE_RF_DEFAULT); // 1 min
  ESP.deepSleep( (60*1000*1000) * 30, WAKE_RF_DEFAULT); // uint32 = 4294967296micro sec, 4295 sec, 1.1 hour.  でも30分位が限界?
  //deepsleepモード移行までのダミー命令
  delay(1000);
}

2016年4月5日火曜日

土壌水分計 続き microSD, WiFi

SDカードのソケットではちょっと図体が大きすぎるのでmicroSDに変更してみたが、SPIモードですんなり動いた。 WiFiの接続が不安定で、今朝は問題なく繋がったがdeep sleep modeの試験をすると、繋がっていない。 バッファローのルータのログの意味が良く分からずに頓挫していたが、ググっていると「ログの意味は何ですか」というのを見つけました。それによれば
reason 15 = "4 way handshake timeout"で「ノイズやその他の理由によりWPA2/WPAなどの認証時、またはKey(鍵)更新時に行われる鍵交換通信がうまく行かず、タイムアウトしてしまったことが考えられます。この場合は認証が失敗するため、無線の切断が発生します。無線子機では、通信が切断されると、再び無線接続動作をやり直します」
ー>要するに波の送受信がうまくいっていない(弱い)。 
だったら、中継器を部屋につけてやってみたらどうだろう? ということで、実験台の直ぐそばに中継器を置いてみたら、すんなり接続できました。

ちょっと不安だったSDカードから接続情報を取得する方法も問題なく使えることが確認できました。
後は、回路を完成させて、動作試験と、土壌湿度の校正データの構築。 折角、風乾土壌を準備し始めたのに昨日の雨で振出しに戻りました(研究室と違い、自宅は土を広げる屋根のある場所などありませんので、、、)。 

>> ESP.deepSleepの受け取る引数のサイズを意識せずに、指定していたところ何か動作がおかしいので、ググってみたらuint32だと!! これだとmicro sec単位での指定なので1時間がMaxということになりなります。 取りあえず30分毎に起きるようにすることにします。 ただ、これで単4電池2本でどのくらい持つのか、、、。


 SoilMoistureMeasurement


/*
 *  This sketch sends data via HTTP GET requests to data.sparkfun.com service.
 *
 *  You need to get streamId and privateKey at data.sparkfun.com and paste them
 *  below. Or just customize this script to talk to other HTTP servers.
 *
 */
#include
extern "C" {
  #include "user_interface.h"
}
#include
#include
#include
#include
#define SWITCH 15 // use pin 15 as the switch to temp/moist - Low: moist, High:temp

Sd2Card card;
ST7032 lcd;
const int chipSelect = 2;


char ssid[30]     = "Buffalo-G-4CC0";
char password[30] = "**********";
char Id[30] = "*************************";
char host[20] = "192.168.1.3";
const char* streamId   = "Baffalo-G-4CC0";
const char* privateKey = "";
const float vref = 1.00;  // ESP8266 ADC(Tout) reference is 1.00, declare globally
char conversionTable[100];  // Convert voltage to moisture (0 - 100) %

int measure_temp(){
  float offset = 0.424; // volts at 0 degree
  float v = 0.0;
  float vc = 0.00625;  // delta volts per degree
  uint ADC_Value = 0;
  float temp = 0.0;
  int i;
  for(i = 0;i < 30; i++){
    ADC_Value = system_adc_read();
    v = float(ADC_Value)/1024.0 * vref;
    temp = temp + (v-offset) / vc;
    delay(30);
  }
  return (int)temp/30;
}

void read_ssid(){
   // open the file for reading:
  File myFile = SD.open("ssid.txt", FILE_READ);
  char *s = ssid;
  if (myFile) {
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *s++ = myFile.read();
    }
    *s = '\0';
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening ssid.txt");
  }
}
void read_password(){
  File myFile = SD.open("password.txt");
  if (myFile) {
    char *p = password;
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *p++ = myFile.read();
    }
    *p = '\0';
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening password.txt");
  }
}
void read_Id(){
  File myFile = SD.open("Id.txt");
  char *p = Id;
  if (myFile) {

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *p++ = myFile.read();
    }
    *p = '\0';
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening Id.txt");
  }
}  
void read_host(){
  File myFile = SD.open("host.txt");
  char *p = Id;
  if (myFile) {
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *p++ = myFile.read();
    }
    *p = '\0';
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening host.txt");
  }
}
void setup_conv_table(){
  File myFile = SD.open("conv.dat");
  if (myFile){
    for(int i=0, j=0; i < 100; i++, j++){
      conversionTable[i] = myFile.read();  // put one byte into the table.  tobe binary 0 to 255 (8 bit)
    }
    myFile.close();
  }else{ // If no data available, make one to one fake one.
    for(int i=0, j=0; i < 100; i++, j++){
      conversionTable[i] = j;
    }
  }
}
int measure_moist(){
  float v = 0.0;
  uint ADC_Value = 0;
  float temp = 0.0;
  int i;
 
  for(i = 0;i < 30; i++){
    ADC_Value = system_adc_read();
    v = float(ADC_Value)/1024.0 * vref; // milli volts
    temp = temp + v;
    delay(30);
  }
  return (int)temp/30*1000; // rounded milli volts in decimal
  // return (int)conversionTable[(int)temp/30*1000)]; // In future, % moisture.
}

void setup() {
  Serial.begin(115200);
  delay(10);
  pinMode(SWITCH, OUTPUT);  // set SWITCH(IO15) pin as an output
 
  byte mac_addr[6];
  WiFi.macAddress(mac_addr);
  char buff[20];
  Serial.print("Mac address: ");
  sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(buff);
 
  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  Serial.println("");
  Serial.println("Started");

 // Read ssid, password, Id from SD card and put 'em to global variables
  read_ssid();
  read_password();
  read_Id();
  read_host();
  delay(500); //Why?, but need this, otherwise WiFi cannot connect to

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected"); 
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
 
  // Set up LCD display
  lcd.begin(8,2);
  lcd.setContrast(25);
  delay(40);
}
void loop() {
  // Display data to LCD first
  String s1;
  String s2;
  int temp;
  int moist;

  digitalWrite(SWITCH, HIGH);
  temp = measure_temp();
  digitalWrite(SWITCH, LOW);
  moist = measure_moist();
  digitalWrite(SWITCH, HIGH);
  s1 =  String(temp) + " C";
  s2 = String(moist) + " %";
  lcd.clear();
  lcd.setCursor(2,0);
  lcd.print(s1);
  lcd.setCursor(2,1);
  lcd.print(s2);
  Serial.println(" ====  Temp = " + s1 );
  Serial.println(" ==== Moisture = " + s2);
  /*
// Use WiFiClient class to create TCP connections 
  Serial.print("connecting to ");
  Serial.println(host);

  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
 
  // We now create a URI for the request
  String url = "/data/data_logger.php";
         url += "?Identifier=" + Id;
         url += "&data1="+String(temp);
         url += "&data2=" +String(moist);
         url += "&data3=" +String("");
         url += "&data4="+String("");
         url += "&data5=" +String("");
         url += "&data6=" +String("");                    
  Serial.print("Requesting URL: ");
  Serial.println("GET "+url);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                  "Host: " + server + "\r\n" +
                  "Connection: close\r\n\r\n"); 
  delay(50);

  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
 
  Serial.println();
  Serial.println("closing connection");
  */
  //DEEP SLEEPモード突入命令
  Serial.println("DEEP SLEEP START!!");
  //1:μ秒での復帰までのタイマー時間設定  2:復帰するきっかけの設定(モード設定)
  ESP.deepSleep( 60 * 1000 * 1000 * 60 * 3 , WAKE_RF_DEFAULT); // 3 hours
  //deepsleepモード移行までのダミー命令
  delay(1000);
  /*
  //  QRX
  for(int i=0; i < 60 ; i++){
    delay(1000);
  }
  */
}

2016年4月4日月曜日

土壌水分計の制作 続き

ESP8266は使い勝手が良く、結構思ったことが簡単に実現できるので気に入ってます。
今回は、測定値を表示するためのI2CDisplayとWiFiのアドレスやデータの校正情報を個別に保存できるようにSDカードの接続を実験してみました。
I2CもSDカードも実にすんなり使うことが出来るようになりましたが、肝心のBaffaloの無線LanのルーターがDHCPを出してくれないので、ここでとん挫。  Failed status 37って何ですか? reason code とかstatus codeがLogに吐き出されますが、これらのコードの説明が見つからないために中断です。
I2CとSPIを使い、尚且つToutを使ったADCに、更に温度計と水分計の切り替えの為の1ポートと、目いっぱいの利用で、左のような接続で実験していますが、問題はないようです。
SDカードの読み出しは
myfile = SD.open()
myfile.read()
しかないようなので、一文字ずつバッファに書き出してゆくまどろっこしいコードになりますね。
コメントアウトした部分(未完成)も含めて、備忘録としてアップしておくことにします。

 I2CDisplay_update.ino



/*
 *  The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
    Pin 4 used here for consistency with other Arduino examples

 */
#include
extern "C" {
  #include "user_interface.h"
}
#include
#include
#include
#include
Sd2Card card;
const int chipSelect = 2; // IO2 not IO4

ST7032 lcd;

char ssid[30] = "*********************";
char password[30] = "#####################";
char Id[20] = "$$$$$$$$$$$$$$$$$$$";
char host[20] = "?????????????"; // host address ie. 192.168.100.100
File myFile;

float offset = 0.424;
float v = 0.0;
float temp = 0.0;
float vc = 0.00625;
float vref = 1.0;

void setup() {
  Serial.begin(115200);
  delay(10);

  byte mac_addr[6];
  WiFi.macAddress(mac_addr);
  char buff[20];
  Serial.print("Mac address: ");
  sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(buff);  // Check MAC address

  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  Serial.println("");
  Serial.println("Started");

  // Read ssid, password, Id from SD card and put 'em to global variables
  read_ssid();
  read_password();
  read_Id();
  read_host();
  /*

  // First connect to WiFi

  Serial.print("Connecting to ");

  Serial.println(ssid); 

  WiFi.begin(ssid, password );

//  WiFi.begin("Baffalo-G-4CC0","65rhwri3nnee" );

  while (WiFi.status() != WL_CONNECTED) {

    delay(500);

    Serial.print(".");

  }

  Serial.println("");

  Serial.println("WiFi connected");

  Serial.println("IP address: ");

  Serial.println(WiFi.localIP());

*/
  // Set up LCD display
  lcd.begin(8,2);
  lcd.setContrast(25);
  delay(40);
}


void loop() {
  // put your main code here, to run repeatedly:
  /*

  Serial.print("connecting to ");

  Serial.println(host);

  WiFiClient client;

  const int httpPort = 80;

  if (!client.connect(host, httpPort)){

    Serial.println("connection failed");

    return;

  }

  String url = "/weather/weather_log.php";

         url += "?location=" + String(Identifier); // ID to identify location

         url += "&temperature="+String(t);

         url += "&humidity=" +String(h);

         url += "&pressure=" +String(p);

  Serial.print("Requesting URL: ");

  Serial.println("GET "+url);



  client.print(String("GET ") + url + " HTTP/1.1\r\n" +

                "Host: " + host + "\r\n" +

                "Connection: close\r\n\r\n");

  delay(50);

  // Read all the lines of the reply from server and print them to Serial

  Serial.println("Returned message from server: ");

  while(client.available()){

    String line = client.readStringUntil('\r');

    Serial.print(line);

  }



  Serial.println();

  Serial.println("closing connection");

  */
  String s1;
  String s2 = "*******";
  int temp;
  temp = measure_temp();
  s1 =  String(temp) + " C";
  lcd.clear();
  lcd.setCursor(2,0);
  lcd.print(s1);
  lcd.setCursor(0,1);
  lcd.print(s2);
  Serial.println(" ====  Temp = " + s1 );
  delay(1000);
}


int measure_temp(){
  uint ADC_Value = 0;
  float temp = 0.0;
  int i;
  for(i = 0;i < 30; i++){
    ADC_Value = system_adc_read();
    v = float(ADC_Value)/1024.0 * vref;
    temp = temp + (v-offset) / vc;
    delay(30);
  }
  return (int)temp/30;
}
void read_ssid(){
   // open the file for reading:
  myFile = SD.open("ssid.txt", FILE_READ);
  char *s = ssid;
  if (myFile) {
    Serial.println("ssid.txt");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *s++ = myFile.read();
    }
    *s = '\0';
    // close the file:
    myFile.close();
    Serial.println(ssid );
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening ssid.txt");
  }
}
void read_password(){
  myFile = SD.open("password.txt");
  if (myFile) {
    Serial.println("password.txt");
    char *p = password;
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *p++ = myFile.read();
    }
    *p = '\0';
    // close the file:
    myFile.close();
    Serial.println(password);
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening password.txt");
  }
}
void read_Id(){
  myFile = SD.open("Id.txt");
  char *p = Id;
  if (myFile) {
    Serial.println("id.txt");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *p++ = myFile.read();
    }
    *p = '\0';
    // close the file:
    myFile.close();
    Serial.println(Id);
  } else {I2c
    // if the file didn't open, print an error:
    Serial.println("error opening Id.txt");
  }
}  
void read_host(){
  myFile = SD.open("host.txt");
  char *p = Id;
  if (myFile) {
    Serial.println("host.txt");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      *p++ = myFile.read();
    }
    *p = '\0';
    // close the file:
    myFile.close();
    Serial.println(host);
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening host.txt");
  }
}

WSJT-x Super F/H

 WSJT-x使い始めてから随分経ちます(JT65しかなかった頃から)が、FT8のF/Hの使いがっ手の悪さ、MSHVの方が利用されている実態、F/HでFoxがマルチで返答すると信号が弱くなる、などからSuperF/Hが実装されましたね。  そこまでは、問題なく理解していたのですが...