Arduino weather station

This post is the first part in a series that will walk you through connecting several sensors to an Arduino microcontroller board. Of course you could buy a weather shield that has all the sensors included, but where is the fun in doing that? In addition to that, I already had some components laying around just taking up space so why not put them to good use.

Components

  • 1x Arduino Mega 2560.
  • 1x Sparkfun TSL2561 luminosity sensor breakout board.
  • 1x TMP36 temperature sensor.
  • 1x Breadboard
  • ~10x jumper wires, M/M and F/F (if the M/M ones are too short).
  • 1x USB cable A-male to B-male for powering up the Arduino and connecting to it.

Arduino Mega 2560

The Arduino Mega 2560 is a microcontroller board based on Atmel’s ATmega2560 . It has 54 digital input/output pins (of which 15 can be used as PWM outputs), 16 analog inputs, 4 UARTs (hardware serial ports), a 16 MHz crystal oscillator, a USB connection, a power jack, an ICSP header, and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started.

Arduino Mega 2560
Arduino Mega 2560

You can view a large pinout diagram here or download the PDF version.

Sparkfun TSL2561 luminosity sensor

The TSL2561 is an inexpensive, yet sophisticated, light sensor. Unlike simpler sensors, like photoresistors and photodiodes, the TSL2561 incorporates both infrared and visible light sensors to better approximate the response of the human eye. Because the TSL2561 is an integrating sensor (it soaks up light for a predetermined amount of time), it is capable of measuring both very small and very large amounts of light.

Sparkfun TSL2561 luminosity sensor
Sparkfun TSL2561 luminosity sensor

Pins

The breakout board has five pins:

  1. INT is an optional interrupt signal which the TSL2561 can use to “interrupt” your microcontroller. You can set up the TSL2561 to automatically send an interrupt when it completes a measurement, or if a measurement goes above or below a certain level for a certain amount of time.
  2. 3.3V in.
  3. GND is ground.
  4. SCL is the I2C clock line.
  5. SDA is the I2C data line.

Datasheet

You should read the TSL2561 datasheet for more info.

TMP36 temperature sensor

The TMP36 is an analogue sensor, that needs to be read using the Arduino’s analogue input. The sensor outputs a voltage that is proportional to the temperature and is packaged in a transistor like TO92 format. The sensor can operate at either 5 volts or 3 volts, but will produce greater accuracy when operated at 3 volts.

TMP36 temperature sensor
TMP36 temperature sensor

Pins

The sensor has three pins:

  1. Vin left, 2.7-5.5V in.
  2. GND right, ground.
  3. Vout middle is analog voltage out.

Datasheet

You should read the TMP36 datasheet for more info.

Note

Since we are powering the sensor via Arduino’s 3.3V line we need to connect the new reference voltage to the AREF pin, because by default the ADC in the Arduino uses an internal reference voltage of 5V.

Connections

Weather Station schematic
Weather Station schematic
  • 3.3V pin from Arduino goes to the breadboard voltage rail.
  • GND pin from Arduino goes to the breadboard ground rail.
  • A15 (ANALOG) pin from Arduino goes to the middle pin of the TMP36 sensor via breadboard.
  • AREF pin from Arduino goes to the breadboard voltage rail (3.3V).
  • SCL pin from Arduino goes to the TSL2561’s SCL pin.
  • SDA pin from Arduino goes to the TSL2561’s SDA pin.
  • additionally, TSL2561 and TMP36 get wired to the breadboard GND and 3.3V rails.

Code

Note

The code depends on the Sparkfun TSL2561 Arduino library (link or local mirror) so make sure you install it first. Obviously you should have the Arduino IDE installed too.

Open the Arduino IDE, go to File -> New and paste the code below (or download the sketch in .ino format). Go to Tools -> Board and select Arduino Mega or Mega 2560, also select the USB port the board is connected from Tools -> Port. Don’t forget to connect the Arduino board to power (be it an USB cable to your laptop/computer or a battery).

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <SparkFunTSL2561.h>
#include <Wire.h>

#define aref_voltage 3.3 

SFE_TSL2561 light;

/*
 * If gain = false (0), device is set to low gain (1X)
 * If gain = high (1), device is set to high gain (16X)
 */
boolean gain = 0;

/* Integration ("shutter") time in milliseconds */
unsigned int ms;

/* The analog pin where the TMP36 middle pin gets connected to. */
int sensorPin = 15;

boolean debug = true;

/*
 * If time = 0, integration will be 13.7ms
 * If time = 1, integration will be 101ms
 * If time = 2, integration will be 402ms
 * If time = 3, use manual start / stop to perform your own integration
 */
unsigned char time = 2;

/*
 * The setup() function will only run once, after each powerup or reset
 * of the Arduino board.
 */
void setup () {
	analogReference(EXTERNAL);
	Serial.begin(9600);
	light.begin();
	Serial.println("light sensor setting timing");
	light.setTiming(gain, time, ms);
	Serial.println("light sensor powering up");
	light.setPowerUp();
}

String read_sensor_light (double *luxVal) {
	delay(ms);
	unsigned int data0, data1;
	if (light.getData(data0, data1)) {
		double lux;
		boolean good;
		good = light.getLux(gain, ms, data0, data1, lux);
		*luxVal = lux;
		return "data0=" + (String)data0 + ", data1=" + data1 + ", lux=" + lux +
			", valid=" + (good ? "yes" : "no");
	} else {
		byte error = light.getError();
		printError(error);
		return "";
	}
}

String read_sensor_temp (double *tempVal) {
	int reading = analogRead(sensorPin);  
	float voltage = (reading * aref_voltage) / 1024.0;
	float tempC = (voltage - 0.5) * 100;
	float tempF = (tempC * 9.0 / 5.0) + 32.0;
	*tempVal = tempC;
	return "reading=" + (String)(reading * aref_voltage) + ", voltage=" + voltage +
		"V, temp=" + tempC + "°C, temp=" + tempF + "°F";
}

/* 
 * This function loops consecutively, allowing your program to change and respond.
 */
void loop () {
	double luxVal;
	double tempVal;
	String data;
	data = read_sensor_light(&luxVal);
	if (debug) {
		Serial.println("light sensor RAW DATA: " + data);
	} else {
		Serial.println("lux=" + (String)luxVal);
	}
	data = read_sensor_temp(&tempVal);
	if (debug) {
		Serial.println("temp sensor RAW DATA: " + read_sensor_temp(&luxVal));
	} else {
		Serial.println("temp=" + (String)tempVal);
	}
}

/*
 * Dump any I2C errors.
 */
void printError (byte error) {
	Serial.print("I2C error: ");
	Serial.print(error, DEC);
	Serial.print(", ");
	switch(error) {
		case 0:
			Serial.println("success");
			break;
		case 1:
			Serial.println("data too long for transmit buffer");
			break;
		case 2:
			Serial.println("received NACK on address (disconnected?)");
			break;
		case 3:
			Serial.println("received NACK on data");
			break;
		case 4:
			Serial.println("other error");
			break;
		default:
			Serial.println("unknown error");
	}
}

Press ⌘+R (or CTRL+R for Windows) and the sketch should compile. If everything is ok, press ⌘+U (or CTRL+U for Windows) to upload the compiled sketch into the Arduino Mega. Open the Serial Monitor from the Tools menu and you should see output from the sensors.

light sensor setting timing
light sensor powering up
light sensor RAW DATA: data0=32, data1=9, lux=10.19, valid=yes
temp sensor RAW DATA: reading=792.00, voltage=0.77V, temp=27.34°C, temp=81.22°F
light sensor RAW DATA: data0=3, data1=1, lux=0.82, valid=yes
temp sensor RAW DATA: reading=755.70, voltage=0.74V, temp=23.80°C, temp=74.84°F

For the next part we’ll be adding some more sensors and data processing. Stay tuned!