Skip to content

Instantly share code, notes, and snippets.

@cthbst
Last active March 10, 2019 10:56
Show Gist options
  • Save cthbst/dd7bc771bf40f44df53a47c37ebbe8ca to your computer and use it in GitHub Desktop.
Save cthbst/dd7bc771bf40f44df53a47c37ebbe8ca to your computer and use it in GitHub Desktop.
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