2017年4月22日土曜日

ESP8266のHTTP Clientと割り込み(Ticker, Timer)でハマる。

ESPr Developer / ESP8266 / ESP-WROOM-02でThingSpeakにデータ送信。
ThingSpeakは15秒の制限があるので、30秒周期でデータを送ることに。

自然な発想でTimerを仕込むが、何故かうまく通信できない。
UDPならうまく行ったのに何故??

参考にしたのは以下のサイト。
 http://www.esp8266.com/viewtopic.php?p=62981

// ソースはこんな感じ
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Ticker.h>
extern "C" {
  #include "user_interface.h"
}

const char* SSID = "<SSID>", PASS= "<PASS>";
Ticker tic1;
void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  IPAddress myIP = WiFi.localIP();
  tic1.attach_ms(30 * 1000, tic1_loop); // 30秒に1回、tic1_loopを実行
}

void sendMessage(String buf) {
  HTTPClient http;
  String url = "http://api.thingspeak.com/update?key=";
  String key = <ThingSpeak API KEY>;
  http.begin(url + key + buf);
  int httpCode = http.GET();
  if(httpCode) {
      Serial.printf("[HTTP] GET... code: %d\n", httpCode);
      if(httpCode == 200) {
          String payload = http.getString();
          Serial.println(payload);
      }
  } else {
      Serial.printf("[HTTP] GET... failed, error: %d\n", httpCode);
  }
  http.end();
}

void tic1_loop(){
  sendMessage(<センサデータ>);
}
void loop{}


いろいろ試行錯誤して気づいたのだが、HTTPClientも割り込みを使うので割り込みの中では使えない。
検証は以下の通り。
1)sendMessage()を単体で呼ぶ ⇒OK
2)loop内でdelayでsendMessage()を何度も動かす ⇒OK
3)Timer割り込みでsendMessage()を何度も動かす ⇒NG

noInterrupts()なのが問題なのでinterrupts()を明示的に呼び出せばHTTPClientも動くはずだが、今回はシンプルにフラグ処理で逃げることにした。


char flag = 0;void interruptFunc(){
  flag = 1;
}

void loop{
  if(flag){
    sendMessage(<センサデータ>);
    flag = 0;
  }
}

これでOKだった。
ESP8266は1か月以上動かしているけど、元気に温度とドアの開閉を記録してくれている。


0 件のコメント:

コメントを投稿