loading

Ever wanted to monitor your city's Current Weather Conditions, Carbon Footprint, Noise and Pollution levels? Do you want be a Climate Change Crusader or set-up your own Tweeting Weather Station and share your local weather conditions with the world?

Meet Tweeting Weather IoT Station aka TWIST - a DIY, Open-Source Environmental Monitoring and Meteorological Data Acquisition Platform. The purpose of TWIST is so that individuals and communities can collect data of what's actually happening in their environment and share this data on social media such as Twitter.

  • TWIST is an Internet of Things (IoT) powered platform.
  • The brain of TWIST is an Intel Edison Board.
  • TWIST is compatible with a variety of sensors.
  • All code, design files(schematics & PCB layout) are Open-Source. This means that anyone can contribute to the TWIST platform by sharing code and schematics for different sensors.

TWIST consists of three technological layers:

The first layer is a hardware board that contains all the weather and environmental sensors known as the 'Sensor Board'. As the name suggests, it carries sensors that measureair composition, temperature, humidity,rain. Additional sensors likeseismic activity, UV index, barometric pressure, altitude, lux(luminosity), sound levels, wind speed & direction,etc can also be added. Once it’s set up, the Sensor Board is able to stream data measured by the sensors to the second layer. The second layer is the Intel Edison Board that receives data from the Sensor Board, processes it and sends it to the next layer. The third layer connects your Edison Board to the Internet over Wi-Fi using the wireless module on the Edison board and Tweet's the Current Weather & Environmental conditions.

Power to the device can be provided by a solar panel or an AC Adapter.

Version controlled repositories

All three technological layers of TWIST are Open-Source, and thus all the files we use for code, PCB development, mechanical design,etc are readily available on our Github repository.

Contest Entries

Intel IoT Invitational

I would like to thank Intel+Instructables for providing me with the Intel Edison Board. I plan on making many more IoT related Instructables using the Edison board.

#iotweatherstn

If you make TWIST, don't forget to tweet the weather using #iotweatherstn. #iotweatherstn can be a hashtag used by all IoT powered Tweeting Weather Stations.

Step 1: Parts and Materials

Quantity Part Details
1Intel Edisonwith Arduino Breakout Board
1MQ2Combustible Gas Sensor
1YL-83Rain Sensor
1SL-HS-220Temperature & Humidity Sensor
1Resistor32K
1Resistor4.7K
2Wood SheetA4 Size(Can later be cut into size)
3Metal Standoff1inch

Step 2: Electrical Design

Power

The entire system is powered from a 5V 1A power supply. The sensors(Temperature,Humidity,Rain,Gas) draws approximately 200 mA, the Edison around 500 mA, Since the total current required is less than 1amp, a 1 amp supply should work just fine. The inbuilt green LED on digital pin 13 of the Edison Board is used to show the power status.

Control
An Intel Edison runs the show for TWIST. The Edison is mounted on an Arduino breakout board, which makes it easy to read the digital & analog signals from the sensors. The Edison is connected to the 5V rail via a micro usb cable. The Edison has a built-in Wi-Fi radio, which allows it to connect to the Twitter without the need for any additional hardware.

Real Time Clock(RTC)

Since the time-stamping automatically carried out by Twitter for each tweet has a resolution limited to the number of total days since the time of Tweeting, a real time clock is used to accurately time stamp the date and time in the Hour-Minute-Second format. The real time clock used in the TWIST platform is the DS-1307 RTC module.

Sensors
The most basic setup of this system has four sensors(Temperature,Humidity,Rain,Gas) that connect to the Edison. Additional sensors can be added such as Noise, Wind,etc. Each sensor is directly powered from the 5V rail and has its signal pin connected respectively to analog pins A0 through A2 and digital pin 2 on the Edison breakout board. The sensors also each have a sensitivity adjustment potentiometer mounted on each sensor board; The MQ-2 is a combustible gas sensor (liquified petroleum gas, propane, hydrogen, and methane) that outputs an analog voltage proportional to the concentration of gases in parts per million. The SL-HS-220 has a thermistor that gives the temperature value. Since the output of the thermistor is non-linear, the corresponding temperature table is given in the sensor repository. The thermistor requires a voltage divider circuit when connected to the Edison Board as shown in the circuit diagram. The SL-HS-220 also has an inbuilt hygrometer which measures humidity and outputs an analog voltage that corresponds to a fixed humidity value. The humidity-voltage table is also given in the sensors repository. A common substitute to the SL-HS-220 is the DHT11 sensor. The rain sensor/water sensor has a potentiometer which is adjusted to give a digital output for a certain amount of rain whose sensitivity can be adjusted by the user.

Pressly.fzzWeather Station.fzz

Step 3: Mechanical Design

The body of the TWIST is made out of two plates of wooden sheets. Although I used 1/4" plywood , the design can be assembled out of any sheet material as the spacing (maintained by 1" aluminum standoffs) is the only critical element. I've attached the vector files for download above.

Laser Cutting

For all those who wish to laser cut the two plates, I have attached the laser cutter files for download below. It also includes an additional air quality sensor in its design. So you can either use an MQ2 sensor module or air quality sensor module depending on your choice.

Step 4: Frame Assembly: Face & Base


Faceplate

The Sensors fit into their matching holes and cut-outs and can be fixed using screws or glue.

Baseplate

The standoffs of the Edison board are screwed on to the Baseplate. The analog-to-digital-converter(ADC) which is connected to the rain sensor can also be screwed on to the Baseplate.

Additional components like buzzers or the voltage regulator circuit for the solar input can also be screwed on to the Baseplate.

The Baseplate and the Faceplate are both separated by 1" standoffs.

Step 5: Electronics & Sensor Assembly

Power

The power for the system is provided by a wall adapter with a standard barrel jack which is connected directly to the Edison's Barrel connector. The system can also be powered through the USB port on the Edison board. You can also power the board from an external Solar panel.

Sensors

The sensors are attached to breakout boards with male headers and hence they can be directly connected to the Edison via male-to-female jumper wires.

Step 6: Twitter Configuration

Inorder to Tweet, we are using a third-party app developed by NeoCat that gets the Twitter token you will need to Tweet with your Edison board. Tokens can also be sourced from Twitter's Developers webpage.

So, to get started, visit NeoCat's website, follow his/her tutorial to get the twitter library and your twitter token. As NeoCat mentioned on their site, please don't abuse the service. Keep your tweets sparse. If you need something that tweets every 6 seconds, you should set up your own server and twitter app and hence the code that I wrote ensures that NeoCat's server doesn't overload(TWIST tweets every 6 hours).

The library uses this NeoCat's website as a proxy server for OAuth stuff. Your tweet may not be applied during maintenance of this NeoCat's website. Twitter seems to reject repeated tweets with the same content (returns error 403).

Twitter Token

Arduino Tweet Library

Step 7: Software & Configuration

Follow Intel's setup guide for the Intel Edsion before you start coding.

The program is an Arduino sketch running on the Edison. I have explained each of the main blocks of code below.

The code includes some predefined constants, pin declarations and a couple of serial print statements that help in troubleshooting.

Tweet Delay

Since Twitter filters out tweets that have the same content and are tweeted within short periods of time between each of them, a standard 3 hour (10800000 milli second) delay between each tweet has been set.

tweetMessage();
delay(10800000);

Type Casting

A lot of the readings we get from the sensors are in the 'int' or 'float' datatype. But since we are tweeting these values, we need to convert them into a 'String' datatype. For this we use a special Type-casting technique.

char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
  char fmt[100];
  sprintf(fmt, "%%%d.%df", width, prec);
  sprintf(sout, fmt, val);
  return sout;
}

Twitter Token

The twitter token is created on NeoCat's website and should be pasted into the token space here.

void tweetMessage() {  
Twitter twitter("     ENTER TWITTER TOKEN HERE   ");

Tweeting Sensor Values

In order to tweet the sensor value we first include the Sensor type; Example: "Humidity". This followed by a character declaration and a line of code required for typecasting. Next we add a statement for the unit of measurement; Example: "%RH". We can keep on adding values of other sensors too in a similar manner.

humidity();  float humid;
  //Twitter message
  String stringMsg = "Humidity:";
  char tmp[10];
  dtostrf(humid, 1, 2, tmp);
  stringMsg += tmp;
  stringMsg += "%RH";

Weather Station Location & Tagging

Next we tag the location(City,Locality,etc) and other tags like #iotweatherstn .

stringMsg += " #Mumbai #Bandra #iotweatherstn ";

Real Time Clock (RTC)

As explained earlier TWIST can also Tweet the Real Time Clock Data. Below is an example of the 'day' parameter block of code of the RTC. The Real Time Clock feature is optional in the TWIST platform since the module comes separately. Hence there is a separate branch created in the TWIST repository for the code and schematics of the Real Time Clock branch.

  TwistDateTime();<br>  DateTime now = rtc.now();
  int twistday, twistmonth, twistyear, twisthour, twistmin, twistsec;
  String stringMsg = "";
  char ds1307day[10];
  dtostrf(twistday,1,0ds1307day);
  stringMsg += ds1307day;
  stringMsg += "/";

140 Character Limit

This block of code coverts the string array to 140 character array ready to tweet.

char msg[140];
stringMsg.toCharArray(msg, 140);

Message & Connection Troubleshooting

This block of code prints out a couple of lines of text in the Serial Monitor to help the user check the message and tweet status.

//Tweet that sucker!

  if (twitter.post(msg)) 
  {
    int status = twitter.wait();
    if (status == 200) 
    {
      Serial.println("OK.");
      Serial.println("Message Tweeted");
    }
    else 
    {                                  //Connection Test
      Serial.print("failed : code ");
      Serial.println("Message not  Tweeted");
      Serial.println(status);
    }
  }
  else 
  {
    Serial.println("connection failed.");
    Serial.println("Message not  Tweeted");
  }

All the other blocks of code simply converts the analog or digital reading from the sensors into usable data.

The code can be dowloaded from here or from the main repository:

Wather Station.inoWeather Station.ino

Step 8: Contributing to the Sensor Repository

TWIST currently supports the sensors listed below. Follow the instructions below to learn how you can contribute and add more sensors to the TWIST platform. You can also find the Real Time Clock and other features repository status in the table below.

Sensor Type Sensor Model Repository Status
Temperature & Humidity SL-HS-220 Completed
Gas MQ2 Completed
Rain YL-83 Completed
Temperature & Humidity DHT11 Completed
Digital Luminosity/Lux/Light TSL2561 Completed
UV/IR/Visible Light SI1145 Completed
Sound Level LMV324 Completed
Barometric Pressure & Altitude MPL3115A2 Completed
Wind Speed Anemometer Completed
Real Time Clock (RTC) DS1307 Completed

The TWIST sensor Repository is Open Source meaning anyone can contribute to the code of existing sensors which are in the repository. Additional sensors can also be added to the repository.

For now the three basic sensors(SL-HS-220,MQ2,YL-83) are in the same repository since they are the basic sensors.

If you have a sensor in mind that is not already in the repository, you can write the code and schematics for it and contribute to the repository. Or else you can simply leave the name and model along with a link to the sensor in the comments section below and I will surely check it out and try my best to add it to the repository.

TWIST Sensor Repository

HTML tutorialHTML tutorialHTML tutorial

As more people suggest and contribute to the TWIST sensor repository I will update the above table. Completed- indicates that the code and schematics for that particular sensor is fully ready for use and can be implemented into the TWIST system. Beta- indicates that work has been started by either me or another contributor on the code and schematics for that particular sensor. Proposed- indicates that someone has proposed a sensor to be added to the repository & that work hasn't yet been started on the sensors code or schematics.

Code

If you are contributing towards a particular sensors repository by writing code, ensure that you write it the Arduino IDE or Intel Edison IDE and attach the respective file. The code must include the following features:

Pin Declarations,Libraries, Reading Sensor Values, Serial Printing Sensor Values, Tweeting code for Sensor.

Also include the links to all the additional Libraries used in the code.

Ensure that each block of code has the necessary comments for ease of use.

Also include a possible link to the sensors datasheet for further reference for other contributors.

Schematics

If you are contributing towards a particular sensors repository by drawing schematics, ensure that you do this in either the Fritzing or Eagle PCB design softwares. A Breadboard view will be really helpful for people who have beginner level electronic skills. You can also include a PCB view for those wishing to make their custom sensor breakout boards or PCB's. Also include a possible link to the sensors datasheet for further reference for other contributors.

Mechanical Design

You can also contribute to the vector files and laser cutter files for a particular sensor and add those files to the sensors repository. Standard file formats should be used for this purpose.

<p>Have you made your own <strong>TWIST/Tweeting Weather Station</strong>? I want to see it!</p><p>Share a picture of your version of this project in the comments below and be awarded a <strong>3-month Pro Membership</strong> on Instructables.com &amp; a <strong>digital patch.</strong></p><p>3-month Pro Memberships remaining: <strong>10/10</strong></p>
<p>Alternative for Edison?</p>
<p>Instead of recommending another board, I'll give you a couple of reasons why I used the Edison for this project:</p><p>1. The Edison runs Yocto Linux with development support for Arduino IDE, Eclipse (C, C++, Python). In other words it has a broad range of compatible programming languages.</p><p>2. The Intel Edison XDK has also support for HTML5 and NodeJS. This means that you can create a website/web base app that can display the weather from your TWIST. It increases the functionality and adaptablility of TWIST by integrating it with other websites apart from Twitter.</p><p>3. The availability of multiple programming languages &amp; web based functionality makes easier to create API's for TWIST and other projects too.</p><p>4. In the future I plan on using the XDK to develop and API for TWIST.</p><p>5. The Intel Edison Dashboard also allows you ti display the sensor data in the form graphs and charts.</p><p>6. You can incorporate the tiny Edison module(excluding the breakout board) on your custom PCB's without loosing the WiFi or Bluetooth functionalities. This also helps large scale manufacturing or mass producing</p>
<p>Of course, You could use a Raspi for this purpose. But the code in this Instructable will not be compatible with the Raspi.</p>
is it possible to substitute this project with arduino uno or Any other arduino board instead of Intel Edison?pls help?
<p>The Raspberry Pi or a Particle Photon should do well.</p>
<p>Hi jonathan may i have your help. I am also doing a project using edison board, now i use example ReadAnalogVolatge to test out but I have a problem that when i send the voltage to twitter it only show one time and only display 0 V.</p>
You should store the analog value of the sensor's output in a variable. And then send the value of that variable to Twitter.<br>For example:<br>float X= analogRead();
Are there any other errors?
<p>Why wont this compile? I'm trying to incorporate the DHL11 sensor:</p><p>#include &lt;Twitter.h&gt;</p><p>#include &lt;SPI.h&gt;</p><p>#include &quot;DHT.h&quot;</p><p>#include &lt;Ethernet.h&gt;</p><p>#undef int() //inorder to make the stdlib.h work</p><p>#include &lt;Stdlib.h&gt;</p><p>float thermsen = A0;</p><p>float humidsen = A1;</p><p>int rainsen = 2;</p><p>int indicator = 13;</p><p>#define Humidity </p><p>#define DHTPIN 3 </p><p>#define DHTTYPE DHT11 </p><p>DHT dht(DHTPIN, DHTTYPE);</p><p>#define MQ_PIN (2) //define which analog input channel you are going to use</p><p>#define RL_VALUE (4.7) //define the load resistance on the board, in kilo ohms</p><p>#define RO_CLEAN_AIR_FACTOR (9.83) //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,</p><p>//which is derived from the chart in datasheet</p><p>/***********************Software Related Macros************************************/</p><p>#define CALIBARAION_SAMPLE_TIMES (50) //define how many samples you are going to take in the calibration phase</p><p>#define CALIBRATION_SAMPLE_INTERVAL (500) //define the time interal(in milisecond) between each samples in the</p><p>//cablibration phase</p><p>#define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation</p><p>#define READ_SAMPLE_TIMES (5) //define the time interal(in milisecond) between each samples in </p><p>//normal operation</p><p>/**********************Application Related Macros**********************************/</p><p>#define GAS_LPG (0)</p><p>#define GAS_CO (1)</p><p>#define GAS_SMOKE (2)</p><p>/*****************************Globals***********************************************/</p><p>float LPGCurve[3] = {2.3, 0.21, -0.47}; //two points are taken from the curve.</p><p>//with these two points, a line is formed which is &quot;approximately equivalent&quot;</p><p>//to the original curve.</p><p>//data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)</p><p>float COCurve[3] = {2.3, 0.72, -0.34}; //two points are taken from the curve.</p><p>//with these two points, a line is formed which is &quot;approximately equivalent&quot;</p><p>//to the original curve.</p><p>//data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15)</p><p>float SmokeCurve[3] = {2.3, 0.53, -0.44}; //two points are taken from the curve.</p><p>//with these two points, a line is formed which is &quot;approximately equivalent&quot;</p><p>//to the original curve.</p><p>//data format:{ x, y, slope}; point1: (lg200, 0.53), point2: (lg10000, -0.22)</p><p>float Ro = 10; //Ro is initialized to 10 kilo ohms</p><p>char stringMsg;</p><p>void setup() {</p><p> Serial.begin(115200);</p><p> pinMode(A0, INPUT);</p><p> pinMode(A1, INPUT);</p><p> pinMode(2, INPUT);</p><p> pinMode(13, OUTPUT);</p><p> /**********************************************************/</p><p> Serial.print(&quot;Calibrating...\n&quot;);</p><p> Ro = MQCalibration(MQ_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air</p><p> //when you perform the calibration</p><p> Serial.print(&quot;Calibration is done...\n&quot;);</p><p> Serial.print(&quot;Ro=&quot;);</p><p> Serial.print(Ro);</p><p> Serial.print(&quot;kohm&quot;);</p><p> Serial.print(&quot;\n&quot;);</p><p> dht.begin();</p><p>}</p><p>void loop()</p><p>{ dht11();</p><p> float h;</p><p> float t;</p><p> float f;</p><p> //Humidity</p><p> stringMsg += &quot;Humidity:&quot;;</p><p> char dht11humidity[10];</p><p> dtostrf(h,1,2,dht11humidity);</p><p> stringMsg += dht11humidity;</p><p> stringMsg += &quot;%RH&quot;;</p><p> //Temperature Celsius</p><p> stringMsg += &quot; Temperature:&quot;;</p><p> char dht11celsius[10];</p><p> dtostrf(t,1,2,dht11celsius);</p><p> stringMsg += dht11celsius;</p><p> stringMsg += &quot;&deg;C&quot;;</p><p> //Temperature Celsius</p><p> stringMsg += &quot; Temperature:&quot;;</p><p> char dht11farhen[10];</p><p> dtostrf(f,1,2,dht11farhen);</p><p> stringMsg += dht11farhen;</p><p> stringMsg += &quot;&deg;F&quot;;}</p><p>//Manual Type-casting for sensor readings</p><p>char *dtostrf (double val, signed char width, unsigned char prec, char *sout)</p><p>{</p><p> char fmt[100];</p><p> sprintf(fmt, &quot;%%%d.%df&quot;, width, prec);</p><p> sprintf(sout, fmt, val);</p><p> return sout;</p><p>}</p><p>{</p><p> tweetMessage();</p><p> delay(3000);</p><p>}</p><p>//Manual Type-casting for sensor readings</p><p>char *dtostrf (double val, signed char width, unsigned char prec, char *sout)</p><p>{</p><p> char fmt[100];</p><p> sprintf(fmt, &quot;%%%d.%df&quot;, width, prec);</p><p> sprintf(sout, fmt, val);</p><p> return sout;</p><p>}</p><p>//Twitter Message</p><p>void tweetMessage() {</p><p> Twitter twitter(&quot;4310592022-mfWjQTbSIQy9lFni7EZxcp93d1JRzyR4vtWrmno&quot;); //Twitter Token</p><p> humidity();</p><p> float humid;</p><p> //Twitter message</p><p> String stringMsg = &quot;Humidity:&quot;;</p><p> char tmp[10];</p><p> dtostrf(humid, 1, 2, tmp);</p><p> stringMsg += tmp;</p><p> stringMsg += &quot;%RH&quot;;</p><p> temp_now();</p><p> int Temperature;</p><p> //Twitter message</p><p> stringMsg += &quot; Temperature:&quot;;</p><p> char nowtemp[10];</p><p> dtostrf(Temperature, 1, 0, nowtemp);</p><p> stringMsg += nowtemp;</p><p> stringMsg += &quot;&Acirc;&deg;C&quot;;</p><p> MQ2printval();</p><p> float MQ2tweet;</p><p> //Twitter message</p><p> stringMsg += &quot; CO level:&quot;;</p><p> char nowMQ2[10];</p><p> dtostrf(MQ2tweet, 1, 2, nowMQ2);</p><p> stringMsg += nowMQ2;</p><p> stringMsg += &quot;ppm&quot;;</p><p> if (digitalRead(2) == HIGH)</p><p> {</p><p> stringMsg += &quot; Rain Alert&quot;;</p><p> }</p><p> stringMsg += &quot; #Betatesting #raintest #IOTweatherstation #Mumbai #Bandra #CarterRoad &quot;;</p><p> //Convert our message to a character array //Twiiter Character Limit. Converts/limits message to 140 characters.</p><p> char msg[140];</p><p> stringMsg.toCharArray(msg, 140);</p><p> //Tweet that sucker!</p><p> if (twitter.post(msg))</p><p> {</p><p> int status = twitter.wait();</p><p> if (status == 200)</p><p> {</p><p> Serial.println(&quot;OK.&quot;);</p><p> Serial.println(&quot;Message Tweeted&quot;);</p><p> }</p><p> else</p><p> { //Connection Test</p><p> Serial.print(&quot;failed : code &quot;);</p><p> Serial.println(&quot;Message not Tweeted&quot;);</p><p> Serial.println(status);</p><p> }</p><p> }</p><p> else</p><p> {</p><p> Serial.println(&quot;connection failed.&quot;);</p><p> Serial.println(&quot;Message not Tweeted&quot;);</p><p> }</p><p> digitalWrite(13, HIGH); // LED Indicator Feedback Code Working.</p><p>}</p><p>/********Serial print MQ2 Value****************/</p><p>void MQ2printval()</p><p>{</p><p> float MQ2tweet = (MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_LPG));</p><p> Serial.print(&quot;LPG:&quot;);</p><p> Serial.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_LPG) );</p><p> Serial.print( &quot;ppm&quot; );</p><p> Serial.print(&quot; &quot;);</p><p> Serial.print(&quot;CO:&quot;);</p><p> Serial.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_CO) );</p><p> Serial.print( &quot;ppm&quot; );</p><p> Serial.print(&quot; &quot;);</p><p> Serial.print(&quot;SMOKE:&quot;);</p><p> Serial.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_SMOKE) );</p><p> Serial.print( &quot;ppm&quot; );</p><p> Serial.print(&quot;\n&quot;);</p><p>}</p><p>/****************** MQResistanceCalculation ****************************************</p><p>Input: raw_adc - raw value read from adc, which represents the voltage</p><p>Output: the calculated sensor resistance</p><p>Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage</p><p> across the load resistor and its resistance, the resistance of the sensor</p><p> could be derived.</p><p>************************************************************************************/</p><p>float MQResistanceCalculation(int raw_adc)</p><p>{</p><p> return ( ((float)RL_VALUE * (1023 - raw_adc) / raw_adc));</p><p>}</p><p>/***************************** MQCalibration ****************************************</p><p>Input: mq_pin - analog channel</p><p>Output: Ro of the sensor</p><p>Remarks: This function assumes that the sensor is in clean air. It use</p><p> MQResistanceCalculation to calculates the sensor resistance in clean air</p><p> and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about</p><p> 10, which differs slightly between different sensors.</p><p>************************************************************************************/</p><p>float MQCalibration(int mq_pin)</p><p>{</p><p> int i;</p><p> float val = 0;</p><p> for (i = 0; i &lt; CALIBARAION_SAMPLE_TIMES; i++) { //take multiple samples</p><p> val += MQResistanceCalculation(analogRead(mq_pin));</p><p> delay(CALIBRATION_SAMPLE_INTERVAL);</p><p> }</p><p> val = val / CALIBARAION_SAMPLE_TIMES; //calculate the average value</p><p> val = val / RO_CLEAN_AIR_FACTOR; //divided by RO_CLEAN_AIR_FACTOR yields the Ro</p><p> //according to the chart in the datasheet</p><p> return val;</p><p>}</p><p>/***************************** MQRead *********************************************</p><p>Input: mq_pin - analog channel</p><p>Output: Rs of the sensor</p><p>Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).</p><p> The Rs changes as the sensor is in the different consentration of the target</p><p> gas. The sample times and the time interval between samples could be configured</p><p> by changing the definition of the macros.</p><p>************************************************************************************/</p><p>float MQRead(int mq_pin)</p><p>{</p><p> int i;</p><p> float rs = 0;</p><p> for (i = 0; i &lt; READ_SAMPLE_TIMES; i++) {</p><p> rs += MQResistanceCalculation(analogRead(mq_pin));</p><p> delay(READ_SAMPLE_INTERVAL);</p><p> }</p><p> rs = rs / READ_SAMPLE_TIMES;</p><p> return rs;</p><p>}</p><p>/***************************** MQGetGasPercentage **********************************</p><p>Input: rs_ro_ratio - Rs divided by Ro</p><p> gas_id - target gas type</p><p>Output: ppm of the target gas</p><p>Remarks: This function passes different curves to the MQGetPercentage function which</p><p> calculates the ppm (parts per million) of the target gas.</p><p>************************************************************************************/</p><p>int MQGetGasPercentage(float rs_ro_ratio, int gas_id)</p><p>{</p><p> if ( gas_id == GAS_LPG ) {</p><p> return MQGetPercentage(rs_ro_ratio, LPGCurve);</p><p> } else if ( gas_id == GAS_CO ) {</p><p> return MQGetPercentage(rs_ro_ratio, COCurve);</p><p> } else if ( gas_id == GAS_SMOKE ) {</p><p> return MQGetPercentage(rs_ro_ratio, SmokeCurve);</p><p> }</p><p> return 0;</p><p>}</p><p>/***************************** MQGetPercentage **********************************</p><p>Input: rs_ro_ratio - Rs divided by Ro</p><p> pcurve - pointer to the curve of the target gas</p><p>Output: ppm of the target gas</p><p>Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)</p><p> of the line could be derived if y(rs_ro_ratio) is provided. As it is a</p><p> logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic</p><p> value.</p><p>************************************************************************************/</p><p>int MQGetPercentage(float rs_ro_ratio, float *pcurve)</p><p>{</p><p> return (pow(10, ( ((log(rs_ro_ratio) - pcurve[1]) / pcurve[2]) + pcurve[0])));</p><p>}</p><p>/******Humidity***********/</p><p>void humidity()</p><p>{</p><p> int humidSensorValue = analogRead(A1);</p><p> // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):</p><p> // Multiply by 1000 so that map() function can work properly. map() does not count numbers after the decimal.</p><p> float humidvoltage = humidSensorValue * (5.0 / 1023.0) * 1000;</p><p> // When Humidity is 20%RH Voltage is 660mV. When Humidity is 95%RH Voltage is 3135mV.</p><p> float humid = map(humidvoltage, 660, 3135, 20, 95);</p><p> // print out the value of humidity:</p><p> Serial.print(&quot;Humidity:&quot;);</p><p> Serial.print(humid);</p><p> Serial.println();</p><p>}</p><p>/**************Temperature*************/</p><p>void temp_now()</p><p>{</p><p> float tempSensorValue = analogRead(A0);</p><p> // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):</p><p> float voltage = tempSensorValue * (5.0 / 1023.0);</p><p> // print out the value you read:</p><p> //Serial.print(&quot;Voltage(V)= &quot;);</p><p> //Serial.print(voltage);</p><p> //Serial.println();</p><p> int Temperature;</p><p> if ((voltage &gt; 2.521) &amp;&amp; (voltage &lt; 2.585))</p><p> {</p><p> Temperature = 0;</p><p> }</p><p> if ((voltage &gt; 2.585) &amp;&amp; (voltage &lt; 2.648))</p><p> {</p><p> Temperature = 1 ;</p><p> }</p><p> if ((voltage &gt; 2.648) &amp;&amp; (voltage &lt; 2.711))</p><p> {</p><p> Temperature = 2;</p><p> }</p><p> if ((voltage &gt; 2.711) &amp;&amp; (voltage &lt; 2.773))</p><p> {</p><p> Temperature = 3;</p><p> ;</p><p> }</p><p> if ((voltage &gt; 2.773) &amp;&amp; (voltage &lt; 2.834))</p><p> {</p><p> Temperature = 4;</p><p> }</p><p> if ((voltage &gt; 2.834) &amp;&amp; (voltage &lt; 2.894))</p><p> {</p><p> Temperature = 5;</p><p> }</p><p> if ((voltage &gt; 2.894) &amp;&amp; (voltage &lt; 2.95))</p><p> {</p><p> Temperature = 6;</p><p> }</p><p> if ((voltage &gt; 2.95) &amp;&amp; (voltage &lt; 3.01))</p><p> {</p><p> Temperature = 7;</p><p> }</p><p> if ((voltage &gt; 3.01) &amp;&amp; (voltage &lt; 3.07))</p><p> {</p><p> Temperature = 8;</p><p> }</p><p> if ((voltage &gt; 3.07) &amp;&amp; (voltage &lt; 3.13))</p><p> {</p><p> Temperature = 9;</p><p> }</p><p> if ((voltage &gt; 3.13) &amp;&amp; (voltage &lt; 3.18))</p><p> {</p><p> Temperature = 10;</p><p> }</p><p> if ((voltage &gt; 3.18) &amp;&amp; (voltage &lt; 3.24))</p><p> {</p><p> Temperature = 11;</p><p> }</p><p> if ((voltage &gt; 3.24) &amp;&amp; (voltage &lt; 3.29))</p><p> {</p><p> Temperature = 12;</p><p> }</p><p> if ((voltage &gt; 3.29) &amp;&amp; (voltage &lt; 3.34))</p><p> {</p><p> Temperature = 13;</p><p> }</p><p> if ((voltage &gt; 3.34) &amp;&amp; (voltage &lt; 3.40))</p><p> {</p><p> Temperature = 14;</p><p> }</p><p> if ((voltage &gt; 3.40) &amp;&amp; (voltage &lt; 3.45))</p><p> {</p><p> Temperature = 15;</p><p> }</p><p> if ((voltage &gt; 3.45) &amp;&amp; (voltage &lt; 3.5))</p><p> {</p><p> Temperature = 16;</p><p> }</p><p> if ((voltage &gt; 3.5) &amp;&amp; (voltage &lt; 3.54))</p><p> {</p><p> Temperature = 17;</p><p> }</p><p> if ((voltage &gt; 3.54) &amp;&amp; (voltage &lt; 3.59))</p><p> {</p><p> Temperature = 18;</p><p> }</p><p> if ((voltage &gt; 3.59) &amp;&amp; (voltage &lt; 3.64))</p><p> {</p><p> Temperature = 19;</p><p> }</p><p> if ((voltage &gt; 3.64) &amp;&amp; (voltage &lt; 3.68))</p><p> {</p><p> Temperature = 20;</p><p> }</p><p> if ((voltage &gt; 3.68) &amp;&amp; (voltage &lt; 3.72))</p><p> {</p><p> Temperature = 21;</p><p> }</p><p> if ((voltage &gt; 3.72) &amp;&amp; (voltage &lt; 3.76))</p><p> {</p><p> Temperature = 22;</p><p> }</p><p> if ((voltage &gt; 3.76) &amp;&amp; (voltage &lt; 3.81))</p><p> {</p><p> Temperature = 23;</p><p> }</p><p> if ((voltage &gt; 3.81) &amp;&amp; (voltage &lt; 3.85))</p><p> {</p><p> Temperature = 24;</p><p> }</p><p> if ((voltage &gt; 3.85) &amp;&amp; (voltage &lt; 3.88))</p><p> {</p><p> Temperature = 25;</p><p> }</p><p> if ((voltage &gt; 3.88) &amp;&amp; (voltage &lt; 3.92))</p><p> {</p><p> Temperature = 26;</p><p> }</p><p> if ((voltage &gt; 3.92) &amp;&amp; (voltage &lt; 3.96))</p><p> {</p><p> Temperature = 27;</p><p> }</p><p> if ((voltage &gt; 3.96) &amp;&amp; (voltage &lt; 3.99))</p><p> {</p><p> Temperature = 28;</p><p> }</p><p> if ((voltage &gt; 3.99) &amp;&amp; (voltage &lt; 4.03))</p><p> {</p><p> Temperature = 29;</p><p> }</p><p> if ((voltage &gt; 4.03) &amp;&amp; (voltage &lt; 4.06))</p><p> {</p><p> Temperature = 30;</p><p> }</p><p> if ((voltage &gt; 4.06) &amp;&amp; (voltage &lt; 4.09))</p><p> {</p><p> Temperature = 31;</p><p> }</p><p> if ((voltage &gt; 4.09) &amp;&amp; (voltage &lt; 4.12))</p><p> {</p><p> Temperature = 32;</p><p> }</p><p> if ((voltage &gt; 4.12) &amp;&amp; (voltage &lt; 4.15))</p><p> {</p><p> Temperature = 33;</p><p> }</p><p> if ((voltage &gt; 4.15) &amp;&amp; (voltage &lt; 4.18))</p><p> {</p><p> Temperature = 34;</p><p> }</p><p> if ((voltage &gt; 4.18) &amp;&amp; (voltage &lt; 4.21))</p><p> {</p><p> Temperature = 35;</p><p> }</p><p> if ((voltage &gt; 4.21) &amp;&amp; (voltage &lt; 4.24))</p><p> {</p><p> Temperature = 36;</p><p> }</p><p> if ((voltage &gt; 4.24) &amp;&amp; (voltage &lt; 4.26))</p><p> {</p><p> Temperature = 37;</p><p> }</p><p> if ((voltage &gt; 4.26) &amp;&amp; (voltage &lt; 4.29))</p><p> {</p><p> Temperature = 38;</p><p> }</p><p> if ((voltage &gt; 4.29) &amp;&amp; (voltage &lt; 4.31))</p><p> {</p><p> Temperature = 39;</p><p> }</p><p> if ((voltage &gt; 4.31) &amp;&amp; (voltage &lt; 4.34))</p><p> {</p><p> Temperature = 40;</p><p> }</p><p> if ((voltage &gt; 4.34) &amp;&amp; (voltage &lt; 4.36))</p><p> {</p><p> Temperature = 41;</p><p> }</p><p> if ((voltage &gt; 4.36) &amp;&amp; (voltage &lt; 4.38))</p><p> {</p><p> Temperature = 42;</p><p> }</p><p> if ((voltage &gt; 4.38) &amp;&amp; (voltage &lt; 4.4))</p><p> {</p><p> Temperature = 43;</p><p> }</p><p> if ((voltage &gt; 4.4) &amp;&amp; (voltage &lt; 4.42))</p><p> {</p><p> Temperature = 44;</p><p> }</p><p> if ((voltage &gt; 4.42) &amp;&amp; (voltage &lt; 4.44))</p><p> {</p><p> Temperature = 45;</p><p> }</p><p> if ((voltage &gt; 4.44) &amp;&amp; (voltage &lt; 4.46))</p><p> {</p><p> Temperature = 46;</p><p> }</p><p> if ((voltage &gt; 4.46) &amp;&amp; (voltage &lt; 4.48))</p><p> {</p><p> Temperature = 47;</p><p> }</p><p> if ((voltage &gt; 4.48) &amp;&amp; (voltage &lt; 4.5))</p><p> {</p><p> Temperature = 48;</p><p> }</p><p> if ((voltage &gt; 4.5) &amp;&amp; (voltage &lt; 4.51))</p><p> {</p><p> Temperature = 49;</p><p> }</p><p> if ((voltage &gt; 4.51) &amp;&amp; (voltage &lt; 4.52))</p><p> {</p><p> Temperature = 50;</p><p> }</p><p> Serial.print(&quot;Temperature:&quot;);</p><p> Serial.print(Temperature);</p><p> Serial.println();</p><p>}</p><p>void dht11() {</p><p> // Wait a few seconds between measurements.</p><p> delay(2000);</p><p> // Reading temperature or humidity takes about 250 milliseconds!</p><p> // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)</p><p> float h = dht.readHumidity();</p><p> // Read temperature as Celsius (the default)</p><p> float t = dht.readTemperature();</p><p> // Read temperature as Fahrenheit (isFahrenheit = true)</p><p> float f = dht.readTemperature(true);</p><p> // Check if any reads failed and exit early (to try again).</p><p> if (isnan(h) || isnan(t) || isnan(f)) {</p><p> Serial.println(&quot;Failed to read from DHT sensor!&quot;);</p><p> return;</p><p> }</p><p> // Compute heat index in Fahrenheit (the default)</p><p> float hif = dht.computeHeatIndex(f, h);</p><p> // Compute heat index in Celsius (isFahreheit = false)</p><p> float hic = dht.computeHeatIndex(t, h, false);</p><p>Serial.print(&quot;Humidity: &quot;);</p><p>Serial.print(h);</p><p>Serial.print(&quot; %\t&quot;);</p><p>Serial.print(&quot;Temperature: &quot;);</p><p>Serial.print(t);</p><p>Serial.print(&quot; *C &quot;);</p><p>Serial.print(f);</p><p>Serial.print(&quot; *F\t&quot;);</p><p>Serial.print(&quot;Heat index: &quot;);</p><p>Serial.print(hic);</p><p>Serial.print(&quot; *C &quot;);</p><p>Serial.print(hif);</p><p>Serial.println(&quot; *F&quot;);</p><p>}</p>
<p>What is the error you are getting?</p>
<p>Awesome weather station. And thanks for including the CAD file. </p>
<p>Follow me for more awesome Instructables!</p>
<p>Do contribute the changes you make to the CAD files(if any) to the TWIST repository.</p>
<p>hey, I was just wondering would it be possible to use a DHT11 instead of a sl-hs-220 sensor?</p>
<p>Hey I just completed the code &amp; schematics for the DHT11 sensor and I have added it to the <a>repository</a>. You can check it out on step 8 by clicking on its<strong><a> Completed</a></strong> status. If you have any queries let me know.</p>
<p>TWIST is an open source platform with a public-repository. This means anyone contribute and add code and schematics for different sensors.</p><p><strong>The DHT11 is compatible and can be used instead of the SL-HS-220.</strong>I have added this to the Sensor Repository &amp; it's current status is <strong>Proposed.</strong> I will start working on the code and schematics for the DHT11 sensor. You can also contribute you code/schematics(if any) to the sensor repository. Step 8 will show you the repository status of the sensor.</p>
Hmmm. Waterproof? <br>Or before the first rain ? Rain sensor for assembly, from which probably will drain water and to detect =)
<p>I used Silicon glue as a sealant around all the sensors. I applied the glue from the bottom of the faceplate so that it doesn't ruin the aesthetics of the faceplate. The silicon glue should prevent water or rain from contact with any of the other electronics including the Edison.</p>
<p>Awesome GIF and great use of HTML!! =D</p>
<p>Here's a sweet Instructable by Nodcah which helped me with the GIF, table and all the other HTML in my Instructable: <a>https://www.instructables.com/id/How-to-Enhance-Your-Instructables-Using-HTML/</a></p>
<p>good idea</p>
<p>Thanks.</p>
Spectacular project! I really like your pictures and your detailed documentation.
<p>Thanks.</p>

About This Instructable

12,419views

128favorites

License:

Bio: I'm Jonathan Pereira, a novice Electronics Engineer. I like to make Almighty Brainy Buttons, Tweeting Fart Detectors, Electronic Doohickey's, Lumen Powered Thingamajigs and ... More »
More by Jonathanrjpereira:Adruino Serial Plotter 8 Twittering Thingamajigs Tweeting Weather Station 
Add instructable to: