https://tomo3i.hatenablog.com/entry/2018/11/21/082245
そこそこ順調に動いてくれていたものの、たまに固まっていることに気がついた。特にログも出していないし何が問題なのかはまったくわからない。そこでとりあえずの対策としてwatchdog timerを導入することにした。
Arduinoっていろんな種類のMCUがあって、ボードによって同じコードが動いたり動かなかったりするというのは、前回HIDで学んだことだけど、watchdog timerも似たような状況っぽい。発見したソースコードをコンパイルしたらエラーなく通ったのでTinyduinoでも動かしてみることにした。
#include <avr/wdt.h> void setup () { Serial.begin (115200); Serial.println ("Restarted."); wdt_enable (WDTO_8S); // reset after one second, if no "pat the dog" received } // end of setup void loop () { Serial.println ("Entered loop ..."); wdt_reset (); // give me another second to do stuff (pat the dog) while (true) ; // oops, went into a loop } // end of loop
これで、8秒後にリセットがかかるようになった。Tinyduinoはavr/wdt.hでウォッチドッグタイマーが使えます。
あと、単に点灯し続けるのはつまらないので勝手にON/OFFさせてみることにした。
unsigned long nextOnTime = 0; unsigned long nextOffTime = 0; unsigned long currentTime = 0; void blinkOnOff() { if (lastCommand == 1) { currentTime = millis(); if (currentTime > nextOnTime) { modulate_out(on); nextOffTime = currentTime + 2000; nextOnTime = currentTime + 3000; } if (currentTime > nextOffTime) { modulate_out(off); nextOffTime = currentTime + 10000; } } else { nextOnTime = nextOffTime = 0; } }
millis()というのは50日ぐらいでオーバーフローするらしい。今のところ3日ぐらいで固まっているから問題ないことにする。ということで、ONしたら次にOFFするタイミングとONするタイミングを決めておくことにした。このタイミング情報は、本来なら決め打ちじゃなくてHTTPでもってくるJSONのパラメーターとして実装したいところだけど、とりあえずの実装としてはこれでOKということにする。
ということで、全ソースコード。
/* Modified Repeating WiFi Web Client http://arduino.cc/en/Tutorial/WiFiWebClientRepeating */ #include <SPI.h> #include <WiFi101.h> #include <avr/wdt.h> #include "arduino_secrets.h" char ssid[] = SECRET_SSID; // your network SSID (name) char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) int keyIndex = 0; // your network key Index number (needed only for WEP) int status = WL_IDLE_STATUS; // Initialize the WiFi client library WiFiClient client; // server address: char server[] = SECRET_SERVER; unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds const unsigned long postingInterval = 1L * 1000L; // delay between updates, in milliseconds #define O 4 // control signal output pin #define SHORT 390 -20 // target - adjustment us #define LONG 990 -10 // target - adjustment us #define INTER 9930 -1000 // us #define NUM 5 // repeat the same command String inputString = ""; // a String to hold incoming data bool stringComplete = false; // whether the string is complete String on = "0001010100010101010101110"; String off = "0001010100010101010101000"; void short_out() { digitalWrite(O, HIGH); delayMicroseconds(SHORT); digitalWrite(O, LOW); delayMicroseconds(LONG); } void long_out() { digitalWrite(O, HIGH); delayMicroseconds(LONG); digitalWrite(O, LOW); delayMicroseconds(SHORT); } void modulate_out(String s) { int l = s.length(); //Serial.println(l); int i, j; short_out(); for (j = 0; j < NUM; j++) { delayMicroseconds(INTER); for (i = 0; i < l; i++) { char c = s.charAt(i); if (c == '0') { short_out(); } else { long_out(); } } } } void setup() { wdt_enable (WDTO_8S); // reset after one second, if no "pat the dog" received //Initialize serial and wait for port to open: Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } pinMode(O, OUTPUT); digitalWrite(O, LOW); WiFi.setPins(8, 2, A3, -1); // check for the presence of the shield: if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi shield not present"); // don't continue: while (true); } int wait = 5; // attempt to connect to WiFi network: while ( status != WL_CONNECTED) { wdt_reset (); Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 5 seconds for connection: delay(5000); wait--; if (wait == 0) { break; } } // you're connected now, so print out the status: printWiFiStatus(); } int countDown = 0; int checkNF = 0; int lastCommand = 0; int thisCommand = 0; void checkCommand() { char c = client.read(); //Serial.write(c); if (checkNF == 1) { checkNF = 0; if (c == 'n') { // command is on thisCommand = 1; } else if (c == 'f') { // command is off thisCommand = 0; } } if (countDown > 0) { countDown--; if (countDown == 0) { //Serial.println("check if it is o"); if (c == 'o') { checkNF = 1; } } } if (c == '{') { //Serial.println("in JSON"); countDown = 7;; } } void sendCommand() { Serial.println("command changed"); Serial.println(thisCommand); if (thisCommand == 1) { modulate_out(on); } else { modulate_out(off); } } unsigned long nextOnTime = 0; unsigned long nextOffTime = 0; unsigned long currentTime = 0; void blinkOnOff() { if (lastCommand == 1) { currentTime = millis(); if (currentTime > nextOnTime) { modulate_out(on); nextOffTime = currentTime + 2000; nextOnTime = currentTime + 3000; } if (currentTime > nextOffTime) { modulate_out(off); nextOffTime = currentTime + 10000; } } else { nextOnTime = nextOffTime = 0; } } void loop() { wdt_reset (); while (client.available()) { checkCommand(); } if (lastCommand != thisCommand) { sendCommand(); lastCommand = thisCommand; } blinkOnOff(); // if postingInterval seconds have passed since your last connection, // then connect again and send data: if (millis() - lastConnectionTime > postingInterval) { httpRequest(); } } // this method makes a HTTP connection to the server: void httpRequest() { // close any connection before send a new request. // This will free the socket on the WiFi shield client.stop(); // if there's a successful connection: if (client.connect(server, 80)) { client.println(SECRET_HTTP_GET); client.println(SECRET_HTTP_HOST); client.println("Connection: close"); client.println(); // note the time that the connection was made: lastConnectionTime = millis(); } else { // if you couldn't make a connection: Serial.println("connection failed"); } } void printWiFiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }