2016年11月 9日 (水)

SPIFFS 用のFTPサーバーをSD対応に変更

報告のみです
SPIFFS用のFTPサーバーをSDファイルシステム用に変更について。
SPIFFSとSDファイルシステムは互換性が無いためスケッチで"SPIFFS"を"SD"に変更しても動作しません。
スケッチだけでなくESP8266FtpServerSD.cppなどの以下の項目の対応することによりSDファイルシステムで動作出来ました。

  • 全ての"SPIFFS"を"SD"に変更しインクルードファイルを変更
  • SPIFFSにはディレクトリがないのでCWDコマンドのコード追加
  • LIST,MLSD,MLSTのディレクトリ処理を変更
  • RNTO(Rename To)は未実装

以上でFFFTPで接続しファイルのアップロード、ダウンロードは出来ました。

ただし、SDファイルシステムはファイル名が8.3形式なので長いファイル名のファイルが使えない。
ファイル名を8.3に短くするとHTML内のコードでファイルしてを変更しなければならない。

2016年10月25日 (火)

ESPr Developer(ESP-WROOM-02開発ボード) 購入

スイッチサイエンスさんの以下の基板を購入しました。

この基板はESP8266とUSBシリアル変換のFT231がのっていてATMEGA CPUのARDUINOと同じようにソフトウェアの開発に使う事ができます。
ARDUINO IDEからプログラムを書き込むときESP8266はA0端子をLOWにしてリセットする必要がありますが、この基板ではFT231のDTRとRTSからA0を制御し自動で書き込み出来るようになっています。
ARDUINO IDEは1.6.5にボートマネージャ"esp8266byESP8266 Community version 1.6.5-947-g39819f0"をインストールして使用しています。

2016年10月22日 (土)

ESP8266のアナログ入力とVCCの電圧測定方法

アナログ入力
ESP8266にはTOUT端子がありこの電圧のADC値を読み取ることができます。
TOUT端子の電圧を測定するためには以下のようにA0をanalogReadすれば読み出せます。

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  int v=analogRead(A0);
  Serial.println("VCC="+String(v/1000.0)+"V");
  delay(1000);
}

読み取り値は10ビットの0から1023の値で、TOUT端子が1Vのとき1000となります。

次にVCCの測定方法

以下のようにADC_MODEをADC_VCCに変更するとVCC電圧を測定できます。この値を1/1000すると電圧値になります。

#include <ESP8266WiFi.h>
ADC_MODE(ADC_VCC)

void setup() {
  Serial.begin(115200);
}

void loop() {
  int v=ESP.getVcc();
  Serial.println("VCC="+String(v/1000.0)+"V");
  delay(1000);
}

TOUTピンは何も接続しないでください。チップ内でVCCを1/4し1Vの基準電圧で測定し、ライブライ内で4倍した結果がESP.getVcc()から返ってきます。

ADC_MODEはマクロで以下のように定義されています。

enum ADCMode {
    ADC_TOUT = 33,
    ADC_TOUT_3V3 = 33,
    ADC_VCC = 255
    ADC_VDD = 255
};

#define ADC_MODE(mode) extern "C" int __get_adc_mode() { return (int) (mode); }

マクロで定義されいる__get_adc_mode()は以下のように使用されている

extern int __wrap_register_chipv6_phy(uint8_t* unused) {
    phy_init_data[107] = __get_adc_mode();
    return __real_register_chipv6_phy(phy_init_data);
}

ADC_VCCとADC_VDDを指定したときVCCの値が返ります。それ以外は1023が返ります。
anaroguRead()もESP.getVcc()も同じADCを使っていて、動作中のモード切り替えは出来ないと思われます。

調査には以下を使いました。

2016年10月 7日 (金)

Windows10完全シャットダウンの設定方法

Windows10のシャットダウンは、次の起動時に高速起動するためスタンバイの機能を使用してシャットダウンするよう、デフォルトで設定されいる。
このため、メモリーの追加やハードディスクの取り外しなどで不具合が発生する。
これまでと同じような方法を完全シャットダウンとか呼ばれている。

以下の方法で設定を解除出来る
画面左下の「スタート」ボタン右クリック
「電源オプション(O)」選択
「電源ボタンの動作の選択する」選択
「現在利用可能ではない設定を変更します」を選択
「高速スタートアップを有効にする(推奨)」のチェックを外す
「変更の保存」ボタンクリック

2016年10月 6日 (木)

ROBOCOPYでフォルダとフォルダの時間のみをコピーする

ROBOCOPYでフォルダとフォルダの時間のみをコピーする

robocopy.exeを使ってディレクトリ構造のみコピーする。

ファイルを暗号化(EFS)するとディレクトリのタイムスタンプが更新される。
ディレクトリのタイムスタンプを変えたくない場合一度フォルダツリーのみを
コピーしてそこにタイムスタンプを覚えておく。
暗号化完了後に保存していたディレクトリツリーを元に戻す。

robocopy src det /S /E /DCOPY:T /XF *

"/S"       サブディレクトリもコピー
"/E"       空のサブディレクトリもコピー
"/DCOPY:T" ディレクトリのタイムスタンプをコピー
"/XF *"    全てのファイルを除外する

2016年3月16日 (水)

3ステップ(3行)でExcelのVBAでAdobe PDFを使ってPDFを作成する

ExcelのVBAにてAcrobatでPDFファイルを作成する方法。

条件は以下の通り
・プリンタ名は"Adobe PDF"
・プリンターポートは"Ne03"
・出力フォルダは"C:\tmp"
・ファイル名は"test.ps"および"test.pdf"
・出力するシートは現在選択されているシート

以下のコードはExcel 2007とAdobe Acrobat X Standardで動作確認しました。

Sub makePDF()     Application.ActivePrinter = "Adobe PDF on Ne03:"     ActiveWindow.SelectedSheets.PrintOut _         Copies:=1, _         preview:=False, _         printtofile:=True, _         collate:=True, _         prtofileName:="C:\tmp\test.ps"     CreateObject("PdfDistiller.PdfDistiller.1").FileToPDF _
       "C:\tmp\test.ps", _        "C:\tmp\test.pdf", _        vbNullString End Sub

プリンターのポート番号はレジストリの
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Devices]
に一覧があります。

2015年9月24日 (木)

ESP8266 に SD カードと DS3231 リアルタイムクロックをつなぐ その後

ESP8266 に SD カードと DS3231 リアルタイムクロックをつなぐ

Moo Soft さんよりアドバイスをいただきI2Cインターフェースの DS3231 リアルタイムクロックと microSD カードの同時使用が可能になりました。Moo Soft さんありがとうございます。
ATMEGA328PとSPIでつなぎI/Oとリアルタイムクロックを処理させようとか考えていました。

I2Cインターフェースはソフトウェアで実現しているのでしょうか?C:\Users\xxxx\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\1.6.5-947-g39819f0\libraries\Wire\Wire.cppからライブラリが呼ばれていてライブラリのソースが無いので確認できませんでした。

現状を整理すると

イニシャライズは

    SD.begin(sdCardCS);
    Wire.begin(2, 5);

接続は以下の表でカッコ内はピン番号を示す。

8266 *1接続microSD *2I2CFT232RL *3
(1)3V3 3.3V (4)VDD
(2)EN 3.3V
(3)IO14 (5)CLK
(4)IO12 (7)DAT0
(5)IO13 (3)VMD
(6)IO15 GND
(7)IO2 SDA
(8)IO0 10KΩプルアップ (2)DTR *4
(9)GND GND (6)VSS
(10)IO4 (2)CD
(11)RXD (1)TXD
(12)TXD (5)RXD
(13)GND GND
(14)IO5 SCL
(15)RST (3)RTS *5
(16)TOUT
(17)IO16 LED *6
(18)GND GND

*1 8266のピン番号・名称は "ESP-WROOM-02 WiFi Module" のピン番号とモジュールに印刷されている名称
*2 microSDのピン番号は秋月のK-05488のマイクロSDカードDIP化キットのピン番号
*3 FT232RLのピン番号はFT232RLのLD SSOP Packageのピン番号
*4 SWを経由してIO0に接続。ARDUINO IDEの書き込み開始時にSWを押している。
*5 0.1μFのコンデンサでRSTに接続。
*6 出力1で点灯。
*  電源関係は一部省略

2015年8月19日 (水)

ESP8266 に SD カードと DS3231 リアルタイムクロックをつなぐ

ESP8266 に SD カードと DS3231 リアルタイムクロックをつなぐ

ESP8266 にSDカードインターフェースをつなぎ動作OKとなる。
ESP8266 にDS3231 リアルタイムクロックをつなぎ動作OKとなる。

SDカードとDS3231を両方接続し両方をイニシャライズすると片方が動作しない。

SD.begin(sdCardCS)
Wire.begin(2, 14);

の順にイニシャライズするとSDカードが使用できない。

Wire.begin(2, 14);
SD.begin(sdCardCS)

の順にイニシャライズするとDS3231が使用できない。

先日書いたようにIO14がSDカードのクロック(HSPIのCLK)とDS3231のクロック(I2CのSCL)で共通に使用している。このへんが問題の様なきがします。
動作したという情報が有ったら教えてください。

2015年8月17日 (月)

ESP8266 にリアルタイムクロック DS3231 を接続する

ESP8266 にリアルタイムクロック DS3231 を接続する

Arduino NanoでリアルタイムクロッくとしてDS1307を使用していたが、これは5Vで動作している。ESP8266は3.3Vのためデータをレベル変換しなければならない。しかし、I2Cインターフェースでは双方向の信号をレベル変換しなければならないのでちょっと難しそう。
そこで3.3Vで動作するDS3231を使用したモジュールをアマゾンで購入したのでESP8266に接続してみた。

ESP8266は「ESP8266EX搭載 WiFi-UARTモジュール(技適取得済み)ESP-WROOM-02」を使用している

データ線は以下の2本を接続、GNDとVCCも接続する。

ESP8266PinESP8266PinNameDS3231モジュール
3 IO14(SCL) SCL
7 IO2(SDA) SDA

そして以下のページに同じモジュールを使ったサンプルコードがあるので参照。

http://tronixstuff.com/2014/12/01/tutorial-using-ds1307-and-ds3231-real-time-clock-modules-with-arduino/

ただし、このスケッチのコードは標準のARDUINO UNOなど用のためそのままではESP8266で操作しない。といっても変更は簡単で setup() 内の Wire.begin() に IO ピン番号を指定するだけで良い。

  Wire.begin(2, 14);

以上でサンプルのスケッチが動作した。

現状では以上でDS3231に時間をセットしたり、時間を取り出したり出来ています。
気になるのはI2Cインターフェースの 3 番ピンの SCL は HSPI インターフェースのHSPI_CLK と共通になっている。SD カードはこれを使用しているため SDWebServer スケッチの SD 書き込み時のファイル更新時間に使用できるかこれからテストします。

以上、DS3231モジュールを入手して3時間弱でした。

32BitCPUとWiFiモジュール(680円)とリアルタイムクロックモジュール(600円)が80円違い(2015/8/17時点)CPUが安いのかリアルタイムクロッくモジュールが高いのか・・・

2015年8月12日 (水)

Arduino の ESP8266をwebサーバーでSDカードのファイルを返す

Arduino の ESP8266をwebサーバーでSDカードのファイルを返す

今回の修正はSDカード内のindex.htmをクライアントに返すための修正です。
機能説明を目的として最小限の動作のみのコードのためエラー処理や汎用的な処理はしていません。実際に使用するときはSDWebServerスケッチなどを参考にしてください。

SDカードにアクセスできるように include 追加

#include <SPI.h>
#include <SD.h>

SDの有無を示すstatic変数追加

static bool hasSD = false;

SDからファイルを読み出す関数追加

bool loadFromSdCard(String path) {
  String dataType = "text/html";
  File dataFile = SD.open(path.c_str());
  if (dataFile.isDirectory()) {
    path += "/index.htm";
    dataFile = SD.open(path.c_str());
  }
  if (!dataFile) return false;
  server.sendHeader("Content-Length",String(dataFile.size()));
  server.sendHeader("Connection","close");
  server.sendHeader("Access-Control-Allow-Origin","*");
  server.send(200, dataType.c_str(), "");
  WiFiClient client = server.client();
  size_t totalSize = dataFile.size();
  client.write(dataFile, HTTP_DOWNLOAD_UNIT_SIZE);
  dataFile.close();
  return true;
}

onNotFound_()に1行追加

void onNotFound_() {
  if(hasSD && loadFromSdCard(server.uri())) return;

setup()にSDのイニシャライズ追加

void setup() {

  if (SD.begin(4)) {
    hasSD = true;
  }


setup()のserver.on()のコメントアウト

//  server.on("/",onRoot);
//  server.on("/index.htm",onRoot);
//  server.on("/index.html",onRoot);
  server.onNotFound(onNotFound_);
  server.begin();
}

これでブラウザからhttp://192.168.0.99/にアクセスするとSDカードのルートのindex.htmgが表示される。

以上の追加した全コードは以下の通りです。

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <SPI.h>
#include <SD.h>
#include "myssid.h"

ESP8266WebServer server(80);
static bool hasSD = false;

void onRoot() {
  String msg = "<html><head><title>ESP8266WebSerber</title></head><body><h1>Hello</h1></body></html>";
  server.send(200,"text/html",msg);
}
bool loadFromSdCard(String path) {
  String dataType = "text/html";
  File dataFile = SD.open(path.c_str());
  if (dataFile.isDirectory()) {
    path += "/index.htm";
    dataFile = SD.open(path.c_str());
  }
  if (!dataFile) return false;
  server.sendHeader("Content-Length",String(dataFile.size()));
  server.sendHeader("Connection","close");
  server.sendHeader("Access-Control-Allow-Origin","*");
  server.send(200, dataType.c_str(), "");
  WiFiClient client = server.client();
  size_t totalSize = dataFile.size();
  client.write(dataFile, HTTP_DOWNLOAD_UNIT_SIZE);
  dataFile.close();
  return true;
}
void onNotFound_() {
  if(hasSD && loadFromSdCard(server.uri())) return;
  String message = "Not Detected\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " NAME:" + server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}
void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("");

  pinMode(5, OUTPUT);  // オリジナルは13だがテスト環境の都合で5に変えてある。

  if (SD.begin(4)) {
    hasSD = true;
  }

  WiFi.mode(WIFI_STA);
  WiFi.begin(mySSID, myPASSWORD);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  WiFi.config(IPAddress(192, 168, 0, 99), WiFi.gatewayIP(), WiFi.subnetMask());

  Serial.println("");
  Serial.print(WiFi.localIP());

//  server.on("/",onRoot);
//  server.on("/index.htm",onRoot);
//  server.on("/index.html",onRoot);
  server.onNotFound(onNotFound_);
  server.begin();
}

void loop() {
  server.handleClient();
}

«Arduino の ESP8266をwebサーバーで定義以外のファイルが指定され場合の処理