2 Ocak 2021 Cumartesi

Arduino tabanlı hava gözlem istasyonu

 Bu sefer diğerlerinden farklı olarak amatör telsiz harici bir proje ile karşınızdayım.

Kullanacağınız aletlere göre kodda bazı ayarlamalar yapmak gerekebilir. 


Aşağıdaki projeyi bir çok farklı kodu bir araya getirerek yaptım aslında.


Bir yerden rüzgar hızı hesaplayan bir kod bulup kendi cihazıma göre modifiye ettim.

İlave bir tane ethernet shield ekledim. 

Orjinal kodta sadece seri porttan data okumak varken hem LCD hem Web arayüzüne bu sonuçları koydum.

Kesmedi bir de ısı sensörü ilave ettim.

O da kesmedi bir tane de rüzgar gülü ekledim.


Şimdi, neler lazım?


1 adet Arduino Uno

1 adet Anemometre (rüzgar hız ölçer) bendeki dönüş başına belirli bir pulse üretiyor. Kodtaki kısım bu pulse a karşılık dönüş hızını km cinsinden hesaplıyor. 

1 adet rüzgar gülü. Rüzgarın esişine göre içindeki potansiyometre ile 0-5V arası çıkış veriyor. Bu sayede de yön bilgisi okunuyor

1 adet Texas Instruments 18b20 ısı sensörü.

Burada çizimde göstermediğim bir ethernet shield ta var. Onu bağladıktan sonra pin dizilimlerine tekrar bakabilirsiniz.

Arduino Uno da SDA/SCL yani I2C pinleri A4 ve A5 te takılı olduğundan bağlantılar oraya yapıldı. Başka arduino modüllerinde ona göre bir düzenleme yapmak gerekebilir.



Cihazda ethernet shield kullanmamın sebebi, verileri aynı zamanda web sunucu üzerinden alabilmek,
ilave çalışan bir linux sunucu vasıtası ile hem bu verileri cacti üzerinde grafiğe dökebilmek hem de ilave olarak windy.com wunderground.com sitelerine bu bilgileri anlık paylaşarak hava durumu için bir kişisel sensör oluşturabilmek.

İlave olarak kullandığım anten rotator programı (pstrotator) wunderground üzerinden rüzgar hız ve yön bilgisini alıp, rüzgar hızı belirli bir hızın üzerine çıktığında, antenleri rüzgar yönüne çevirebiliyor. Bu da şiddetli rüzgarlarda antenlerin zarar görmesini engelliyor.

blogger üzerinde defaultta kod ekleme olmadığı için kodu buraya direkt paste ediyorum.
Kusura bakmayın.
Ileride aynı kodun içine barometre , nem, yağmur miktar ölçüm kısımlarını ve cihazlarını da eklemeyi planlıyorum.








//*****************Arduino anemometer sketch******************************
#include <Wire.h> // Library for I2C communication
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
EthernetServer server(80);
//onewire port
#define ONE_WIRE_BUS 2 
OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature sensors(&oneWire);

#include <LiquidCrystal_I2C.h> // Library for LCD
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
static byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
static byte ip[] = { 192, 168, 1, 33 };                    //IP Address for Arduino Ethernet Shield
static byte gateway[] = { 192, 168, 1, 1 };
static byte subnet[] = { 255, 255, 255, 0 };
int VaneValue;// raw analog value from wind vane
int Direction;// translated 0 - 360 direction
int CalDirection;// converted value with offset applied
int CompassDir;//Compass 
int LastValue;
#define Offset 0;



const byte interruptPin = 3; //anemomter input to digital pin
volatile unsigned long sTime = 0; //stores start time for wind speed calculation
unsigned long dataTimer = 0; //used to track how often to communicate data
volatile float pulseTime = 0; //stores time between one anemomter relay closing and the next
volatile float culPulseTime = 0; //stores cumulative pulsetimes for averaging
volatile bool start = true; //tracks when a new anemometer measurement starts
volatile unsigned int avgWindCount = 0; //stores anemometer relay counts for doing average wind speed
float aSetting = 60.0; //wind speed setting to signal alarm



 

void setup() {
  //winddir
  LastValue = 1;
  //onewire start
  sensors.begin(); 
  // Initiate the LCD: OGUZ
  lcd.init();
  lcd.backlight();
  
  pinMode(13, OUTPUT); //setup LED pin to signal high wind alarm condition
  pinMode(interruptPin, INPUT_PULLUP); //set interrupt pin to input pullup
  attachInterrupt(interruptPin, anemometerISR, RISING); //setup interrupt on anemometer input pin, interrupt will occur whenever falling edge is detected
  dataTimer = millis(); //reset loop timer

  Ethernet.begin(mac, ip,  gateway, subnet);
  server.begin();

  Serial.println(Ethernet.localIP());
  delay(1000);
}

void loop() {
 //winddir
 VaneValue = analogRead(A0);
 Direction = map(VaneValue, 0, 1023, 0, 360);
CalDirection = Direction + Offset;

if(CalDirection > 360)
CalDirection = CalDirection - 360;

if(CalDirection < 0)
CalDirection = CalDirection + 360;

// Only update the display if change greater than 2 degrees.
if(abs(CalDirection - LastValue) > 5)
{
Serial.print(VaneValue); Serial.print("\t\t");
Serial.print(CalDirection); Serial.print("\t\t");
getHeading(CalDirection);
LastValue = CalDirection;
}
 //winddir-end
  unsigned long rTime = millis();
  if((rTime - sTime) > 2500) pulseTime = 0; //if the wind speed has dropped below 1MPH than set it to zero
     
  if((rTime - dataTimer) > 3000){ //See if it is time to transmit
   
    detachInterrupt(interruptPin); //shut off wind speed measurement interrupt until done communication
    float aWSpeed = getAvgWindSpeed(culPulseTime,avgWindCount); //calculate average wind speed
    if(aWSpeed >= aSetting) digitalWrite(13, HIGH);   // high speed wind detected so turn the LED on
    else digitalWrite(13, LOW);   //no alarm so ensure LED is off
    culPulseTime = 0; //reset cumulative pulse counter
    avgWindCount = 0; //reset average wind count

    float aFreq = 0; //set to zero initially
    if(pulseTime > 0.0) aFreq = getAnemometerFreq(pulseTime); //calculate frequency in Hz of anemometer, only if pulsetime is non-zero
    float wSpeedMPH = getWindMPH(aFreq); //calculate wind speed in MPH
//OGUZ
//web
// listen for incoming clients
  EthernetClient client = server.available();
 if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
  
      client.print("Wind Speed ");
          client.print(wSpeedMPH);
          client.print(" km/h");
          client.print(" Average ");
          client.print(aWSpeed);
          client.print(" Temp ");
          client.print(sensors.getTempCByIndex(0));
          client.print(" Direction ");
          client.print(CalDirection);
          client.print(" ");
          client.println("<br />");
          break;
        }
   
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
//web-end
sensors.requestTemperatures();
lcd.setCursor(0, 0); // Set the cursor on the first column and first row.
   lcd.print("Wnd");
   lcd.setCursor(6, 0);
   lcd.print("Tmp");
   lcd.setCursor(12, 0);
   lcd.print("Dir");
   lcd.setCursor(0, 1);
   lcd.print("                  ");
   lcd.setCursor(0, 1);
   lcd.print(aWSpeed,1); 
   lcd.setCursor(6, 1);
   lcd.print(sensors.getTempCByIndex(0),1);
   lcd.setCursor(12, 1);
   lcd.print(CalDirection,1); 
  //OGUZ
    Serial.begin(57600); //start serial monitor to communicate wind data
    Serial.println();
    Serial.println("...................................");
    Serial.print("Dönüs Hz ");
    Serial.println(aFreq);
    Serial.print("Temperature is: ");
    Serial.println(sensors.getTempCByIndex(0));
    Serial.print("Anlık Ruzgar Hizi (Km) ");
    Serial.println(wSpeedMPH);
    Serial.print("Ortalama Ruzgar Hizi(Km) ");
    Serial.println(aWSpeed);
    Serial.print("Ruzgar Yonu ");
    Serial.println(CalDirection);
    Serial.end(); //serial uses interrupts 
   
    start = true; //reset start variable in case we missed wind data
    attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, RISING); //turn interrupt back on
    dataTimer = millis(); //reset loop timer
  }
}

//using time between anemometer pulses calculate frequency of anemometer
float getAnemometerFreq(float pTime) { return (1/pTime); }
//Use anemometer frequency to calculate wind speed in MPH
float getWindMPH(float freq) { return (freq*0.36); }
//uses wind MPH value to calculate KPH
float getWindKPH(float wMPH) { return (wMPH*1.61); }
//Calculates average wind speed over given time period
float getAvgWindSpeed(float cPulse,int per) {
  if(per) return getWindMPH(getAnemometerFreq((float)(cPulse/per)));
  else return 0; //average wind speed is zero and we can't divide by zero
  }

//This is the interrupt service routine (ISR) for the anemometer input pin
//it is called whenever a falling edge is detected
void anemometerISR() {
  unsigned long cTime = millis(); //get current time
  if(!start) { // calculate time between pulses
   // test = cTime - sTime;
    pulseTime = (float)(cTime - sTime)/1000;
    culPulseTime += pulseTime; //add up pulse time measurements for averaging
    avgWindCount++; //calculating average wind speed
  }
  sTime = cTime; //store current time for next pulse time calculation
  start = false; //we have our starting point for a wind speed measurement
}
//winddir
void getHeading(int direction) {
if(direction < 22)
CompassDir = "N" ;
else if (direction < 67)
CompassDir = "NE" ;
else if (direction < 112)
CompassDir = "E" ;
else if (direction < 157)
CompassDir = "SE" ;
else if (direction < 212)
CompassDir = "S" ;
else if (direction < 247)
CompassDir = "SW" ;
else if (direction < 292)
CompassDir = "W" ;
else if (direction < 337)
CompassDir = "NW" ;
else
CompassDir = "N" ;
}


Hiç yorum yok:

Yorum Gönder

Yeni(Çok ta değil) bir dijital Mod.. Q65

 Selamlar, HF dünyasından insanlar önce jt65 ile tanıştı, sonrasında FT8 ve FT4 ile zayıf propagasyon şartlarının olduğu zamanlarda düşük gü...