Last active
March 10, 2019 10:56
-
-
Save cthbst/dd7bc771bf40f44df53a47c37ebbe8ca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct { // WindDirection 監測風向 | |
/* 由 23456789 腳, 其中第2腳為正北方 | |
* 換成角度的話 | |
* 2 = 0度 | |
* 3 = 45度 | |
* 4 = 90度 | |
* 5 = 135度 | |
* 6 = 180度 | |
* 7 = 225度 | |
* 8 = 270度 | |
* 9 = 315度 | |
* 兩者同時亮則為在兩個之間的角度 | |
*/ | |
const int p[8] = {2,3,4,5,6,7,8,9}; // 測試風向的腳位 | |
int time_stamp = 0; | |
int wind[60]; // 最近一分鐘的紀錄 | |
int cnt[16]; // cnt[i]: 方向 i 出現的次數 | |
unsigned long last; // 最後一次更新的時間 | |
float wind_dir; | |
void init() { | |
for (int i = 0; i < 8; i++) { | |
pinMode( p[i], INPUT); | |
} | |
for (int i = 0; i < 8; i++) { | |
digitalWrite( p[i], LOW); | |
} | |
} | |
int get_direction() { | |
// 回傳 0, ..., 15 | |
// 回傳 i 表示風向角度為 i * 22.5 | |
int ret = 0; | |
for (int i = 0; i < 8; i++) { | |
if (digitalRead( p[i] ) == HIGH) { | |
ret = 2 * i; | |
} | |
} | |
for (int i = 0; i < 8; i++) { | |
if (digitalRead( p[i] ) == HIGH && | |
digitalRead( p[ (i + 1) % 8 ] ) == HIGH) { | |
ret = 2 * i + 1; | |
} | |
} | |
return ret; | |
} | |
void update_dir() { | |
int t = time_stamp % 60; | |
if (time_stamp >= 60) cnt[wind[t]]--; | |
wind[t] = get_direction(); | |
cnt[wind[t]]++; | |
time_stamp++; | |
} | |
void most_frequent_dir() { | |
int dir = 0; | |
for (int i = 0; i < 16; i++) { | |
if (cnt[dir] < cnt[i]) { | |
dir = i; | |
} | |
} | |
wind_dir = dir * 22.5; | |
} | |
void do_loop() { | |
if ( millis() - last < 1000 ) return; // 每一秒做一次 | |
last = millis(); | |
update_dir(); | |
most_frequent_dir(); | |
} | |
} WindDirection; | |
const int RD_PER_CYCLE = 3; // 幾次算一圈 | |
struct { // WindSpeed 監測風速 | |
const unsigned long time_EPS = 100; // 訊號間隔大於 time_EPS ms | |
int counter = RD_PER_CYCLE-1; | |
unsigned long rot_stamp[RD_PER_CYCLE]; | |
unsigned long last; | |
float rpm; | |
float wind_speed; | |
void init() { | |
pinMode( 10, INPUT); | |
digitalWrite( 10, LOW); | |
} | |
void update_speed() { | |
unsigned long t = millis(); | |
if (digitalRead(10) != HIGH){ | |
// 如果 10 秒都沒接收到 pin 10 = HIGH 就將 rpm 設成 0 | |
if ( millis() - last >= 10000 ) rpm = 0.0; | |
return; | |
} | |
if (t - rot_stamp[(counter - 1) % RD_PER_CYCLE] <= time_EPS){ | |
return; | |
} | |
unsigned long delta = t - rot_stamp[counter % RD_PER_CYCLE]; | |
rot_stamp[counter % RD_PER_CYCLE] = t; | |
counter++; | |
last = t; | |
float r = 60.0 * 1000.0 / delta; | |
rpm = rpm * 0.9 + r * 0.1; | |
wind_speed = 1.0 * rpm; | |
} | |
void do_loop() { | |
update_speed(); | |
} | |
} WindSpeed; | |
#include <SoftwareSerial.h> | |
SoftwareSerial esp8266(10,11); | |
String apiKey = "8QUX6P6Z0CBAI81N"; // ""內輸入ThingSpeak的Write API Key | |
String ssid = "science1"; // ""內輸入wifi基地台的名稱 | |
String password = "astronomy"; // ""內輸入wifi基地台的密碼 | |
boolean DEBUG = true; | |
void showResponse(int waitTime){ | |
long t=millis(); | |
char c; | |
while (t+waitTime>millis()){ | |
if (esp8266.available()){ | |
c=esp8266.read(); | |
if (DEBUG) Serial.print(c); | |
} | |
} | |
} | |
boolean thingSpeakWrite(float value1, float value2){ //自己增加或減少要上傳的數據項目 | |
String cmd = "AT+CIPSTART=\"TCP\",\""; | |
cmd += "184.106.153.149"; | |
cmd += "\",80"; | |
esp8266.println(cmd); | |
if (DEBUG) Serial.println(cmd); | |
if(esp8266.find("Error")){ | |
if (DEBUG) Serial.println("AT+CIPSTART error"); | |
return false; | |
} | |
String getStr = "GET /update?api_key="; | |
getStr += apiKey; | |
getStr +="&field1="; | |
getStr += String(value1); | |
getStr +="&field2="; | |
getStr += String(value2); | |
// getStr +="&field3="; //自己增加或減少要上傳的數據項目 | |
// getStr += String(value3); | |
// ... | |
getStr += "\r\n\r\n"; | |
cmd = "AT+CIPSEND="; | |
cmd += String(getStr.length()); | |
esp8266.println(cmd); | |
if (DEBUG) Serial.println(cmd); | |
delay(100); | |
esp8266.print(getStr); | |
if (DEBUG) Serial.print(getStr); | |
else{ | |
esp8266.println("AT+CIPCLOSE"); | |
if (DEBUG) Serial.println("AT+CIPCLOSE"); | |
return false; | |
} | |
return true; | |
} | |
void setup() { | |
WindDirection.init(); | |
WindSpeed.init(); | |
Serial.begin(9600); | |
while (!Serial); | |
Serial.println("Arduino...OK"); | |
esp8266.begin(115200); | |
esp8266.write("AT+UART_DEF=9600,8,1,0,0\r\n"); | |
delay(1500); | |
esp8266.begin(9600); | |
Serial.println("ESP8266...OK"); | |
esp8266.println("AT+CWMODE=1"); // set esp8266 as client | |
showResponse(1000); | |
esp8266.println("AT+CWJAP=\""+ssid+"\",\""+password+"\""); | |
showResponse(10000); //顯示並等待wifi完成連線 | |
} | |
float& wind_dir = WindDirection.wind_dir; | |
float& rpm = WindSpeed.rpm; | |
float& wind_speed = WindSpeed.wind_speed; | |
void loop() { | |
WindDirection.do_loop(); | |
WindSpeed.do_loop(); | |
unsigned long time_ms = millis(); //紀錄時間 | |
Serial.print("Time = "); | |
Serial.println(time_ms); | |
Serial.print("Direction = "); | |
Serial.println(wind_dir, DEC); | |
Serial.print("rpm = "); | |
Serial.println(rpm, DEC); | |
Serial.print("wind_speed = "); | |
Serial.println(wind_speed, DEC); | |
static unsigned long last_upload_time = 0; | |
if ( last_upload_time - millis() >= 20000 ) { // 秒才做一次 | |
last_upload_time = millis(); | |
thingSpeakWrite(wind_dir, rpm); //自己增加或減少要上傳的數據項目 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment