Project tutorial
MetOnline

MetOnline © GPL3+

Control relays trought internet and get sensor values. Controla relés pela internet e obtem dados de sensor.

  • 1,239 views
  • 0 comments
  • 6 respects

Components and supplies

Apps and online services

About this project

This project allows you to control 4 relays, also get methereology info throught internet. Localy you can see the same info in the LCD, with an pushbutton you can alternate the LCD info of the sensor and the relays states.

You can easily addapt to one or another application, relays or sensors.

You'll need:

  • 1x Arduino Uno
  • 1x W5100 Ethernet
  • 1x DHT11 Sensor
  • 1x 16x2 LCD display with I2C
  • 1x Pushbutton
  • 1x 10k Resistor
  • some wires to connect
  • pc with Apache installed (you can easily find a tutorial on Youtube)

Optcionaly this project also requires fixed IP to controll from "outside".

Se vc mora em Araçatuba ou região não deixe de conferir: http://grassicomponentes.com.br

Comprei meus componentes aqui!

Aditional Info:

For outside conection you'll have to set DMZ in your router to the host computer IP.

This project is for experimental (or improve your own with this functional example), doesnt include any user access control. Remember to disable DMZ after tests.

Comments are in Brazilian Portuguese but I can translate if needed.

Instrucions:

arduino.html -> line 12 change to your arduino IP on your network

MetOnline.ino -> change accordly to your network this variables:

IPAddress ip(192, 168, 0, 105); // your arduino IP againIPAddress gateway(192, 168, 0, 1); IPAddress subnet(255, 255, 255, 0);

To find the gateway and subnet in windows just run in CMD this command: ipconfig

Remember to atribute your arduino IP to an address that not already in use. To check if its in use some IP open CMD again and ping it. Like this: ping 192.168.0.105

If you have no answer this IP is good.

Techinical Info:

When the webpage access the Arduino url (ex. http://192.168.0.105) makes the Arduino answer an JSON with current status. Like this: {"temperature":29.36, "humidity":66,...} The relays are operated with an argument in URL like ?r1=0 The arduino recognize this "r" and do the request.

The JQuery takes care of everything sending this argument to update the relay, also updates the page each 2 secconds.

I opted to use JQuery to avoid refresh the webpage also to syncronize the relays status if we have more than one person acessing the page. So if one person turns any relay on, that will update in the others device. The update time is set to 2s to avoid overcharge requests on Arduino.

Also I opted JSON format cause you can make use in almost everything.

This project dont include any power supply but you'll need it if you wish to run it. I think 12V with 2A will be enought (need confirmation). Also you may want an independent power supply on relays to isolate your circuit, just remove the jumper and connect your source. If you just want to test just the USB power will be enough but more relays are on, less current you'll get for the LCD.

I started the project thinking in control everything just with the Arduino but the hard way to write html "inside" Arduino and the constant bugs with large strings makes me re-think in implement this very nice solution.

Any questions or suggestions please make yourself confortable.

Cheers!!

Code

Main CodeArduino
// NAO USAR PINOS 10, 11, 12 e 13 - utilizados pelo ETHERNET
// DESLIGAR SD: pin 4 output high. W500: pin 10 output.
// W5100 problema do restart: colocar um capacitor de 47nF entreo o RESET e o GND

#include <DHT.h>
#include <LiquidCrystal_I2C.h> // biblioteca by Frank Brabander 1.1.2 https://github.com/johnrickman/LiquidCrystal_I2C
#include <SPI.h>
#include <Ethernet.h>

float umidade;
float temperatura;
float indice;

bool opcaoDisplay = true; //variavel para alternar no LCD entre sensores e estado dos reles
int botaoAlterna = 9;

//variaveis para controlar debounce do pushbutton e taxa de atualizacoes
unsigned long tempoAnterior = 0;
unsigned long debounceDelay = 350;
unsigned long tempoLCD = 0;
unsigned long delayLCD = 2000;

String dados;
int reles[4] = { 5, 6, 7, 8 };

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 105);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
EthernetServer server(80);

DHT dht(2, DHT11);
LiquidCrystal_I2C lcd(0x27, 20, 4); // seta endereco LCD para 0x27 com DISPLAY de 16 char e 2 linhas

String HTTP_req; // armazena requisicao HTTP

void setup() {

	Serial.begin(9600);

	//desligando modulo SD do W5100
	pinMode(4, OUTPUT);
	digitalWrite(4, HIGH);

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

	//iniciando sensor DHT11
	dht.begin();

	//iniciando LCD
	lcd.init();
	lcd.setBacklight(HIGH);

	pinMode(botaoAlterna, INPUT);

	//definindo e iniciando os reles
	for (int i = 0; i < 4; i++) {
		pinMode(reles[i], OUTPUT);
		digitalWrite(reles[i], HIGH);
	}
}

void loop() {

	//atualizando dados e estado dos reles
	if (millis() > (tempoLCD + delayLCD)) { // so atualiza se "chegou a hora"
		tempoLCD = millis();
		atualizaDados();
		escreveLCD();
	}

	//altera entre leitura local e da internet
	if ((digitalRead(botaoAlterna) == HIGH)
			&& (millis() > (tempoAnterior + debounceDelay))) { // controlando debounce
		tempoAnterior = millis();
		if (opcaoDisplay) {
			opcaoDisplay = false;
			lcd.clear();
		} else {
			opcaoDisplay = true;
		}
		//atualizaDados();
		escreveLCD();
	}

	//Aguarda conexao do browser
	EthernetClient client = server.available();
	if (client) {
		Serial.println("new client");
		// requisicao http termina com linha em branco
		boolean currentLineIsBlank = true;
		while (client.connected()) {
			/*if (millis() > (tempoRequisicao + delayRequisicao)) {
			 tempoRequisicao = millis();
			 }*/
			if (client.available()) {
				char c = client.read();
				HTTP_req += c;
				// 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) {
					// enviando header JSON
					client.println("HTTP/1.1 200 OK");
					//client.println("Content-Type: text/html"); // header de retorno padro
					client.println("Content-Type: application/json"); // header para JSON
					client.println("Access-Control-Allow-Origin: http://192.168.0.100"); //permitir acesso do jquery do servidor
					client.println("Connection: close");
					client.println();
					processaReles();
					client.print(dados);
					Serial.print(HTTP_req);
					HTTP_req = "";    // requisicao completa, esvaziando string
					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;
				}
			}
		}
		// delay pro browser receber os dados
		delay(1);
		// termina a conexao
		client.stop();
	}
	delay(1);
}

//atualiza dados no programa e prepara JSON
void atualizaDados() {
	umidade = dht.readHumidity();
	temperatura = dht.readTemperature();
	indice = (dht.computeHeatIndex(dht.readTemperature(),dht.readHumidity(), false));
	dados = ("{\"temperatura\":" + String(temperatura) + ",\"umidade\":" + String(umidade) + ",\"indice\":" + String(indice) + ",\"reles\":{");
	dados = dados + "\"0\":" + !digitalRead(reles[0]);
	dados = dados + ",\"1\":" + !digitalRead(reles[1]);
	dados = dados + ",\"2\":" + !digitalRead(reles[2]);
	dados = dados + ",\"3\":" + !digitalRead(reles[3]) + "}}";
}

// mostra dados do sensor ou estado dos rels
void escreveLCD() {
	if (opcaoDisplay) {
		lcd.setCursor(0, 0);
		lcd.print("T ");
		lcd.print(temperatura, 1);
		lcd.write(byte(223));
		lcd.print("C ");
		lcd.write(byte(165));
		lcd.print(" U ");
		lcd.print(round(umidade));
		lcd.print("%");
		lcd.setCursor(0, 1);
		lcd.print("I ");
		lcd.print(indice, 1);
		lcd.write(byte(223));
		lcd.print("C ");
		lcd.write(byte(165));
		lcd.print(" DHT11");
	} else {
		lcd.setCursor(0, 0);
		lcd.print("R0 ");
		if (digitalRead(reles[0]) == LOW) {
			lcd.print("ON  ");
		} else {
			lcd.print("OFF ");
		}
		lcd.write(byte(165));
		lcd.print(" R1 ");
		if (digitalRead(reles[1]) == LOW) {
			lcd.print("ON  ");
		} else {
			lcd.print("OFF ");
		}
		lcd.setCursor(0, 1);
		lcd.print("R2 ");
		if (digitalRead(reles[2]) == LOW) {
			lcd.print("ON  ");
		} else {
			lcd.print("OFF ");
		}
		lcd.write(byte(165));
		lcd.print(" R3 ");
		if (digitalRead(reles[3]) == LOW) {
			lcd.print("ON  ");
		} else {
			lcd.print("OFF ");
		}
	}
}

//requisicao de alteracao de rele
void processaReles() {
	if (HTTP_req.indexOf("r") > -1) {
		//tem pedido de rele pegando o numero dele
		int posicaoRele = (HTTP_req.indexOf("r") + 1);
		int numeroRele = ((int)(HTTP_req.charAt(posicaoRele))) - 48;
		//pegando solicitacao
		int posicaoAcao = (HTTP_req.indexOf("r") + 3);
		int numeroAcao = ((int)(HTTP_req.charAt(posicaoAcao))) - 48;
		//se for valor valido modifica rele
		if ((numeroRele >= 0 && numeroRele <= 3) && (numeroAcao >= 0 && numeroAcao <= 1)) {
			digitalWrite(reles[numeroRele], !numeroAcao);
			//atualiza antes de enviar
			atualizaDados();
		}
	}
}
Main HTMLHTML
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
	<title>Controle Arduino</title>
	<link href="https://fonts.googleapis.com/css?family=Ropa+Sans" rel="stylesheet">
	<link rel="icon" href="http://www.arduino.cc/favicon.ico">
	<link rel="stylesheet" type="text/css" href="style.css">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>	
	<script>
		//definindo variaveis
		var urlArduino = "http://192.168.0.105"; //trocar para o ip do seu arduino
		var urlConsulta = "";
		var stringRele = "";

		//atualiza valores na pagina
		function updateValues () {
			//verifica se houve clique nos "botoes" e prepara url
			if (stringRele != "") {
				urlConsulta = (urlArduino + stringRele);
			} else {
				urlConsulta = urlArduino;
			}
			stringRele = ""; //
			
			//faz a consulta, se houver link do rele atualiza o estado dele no arduino qd chama o getJSON
			$.getJSON(urlConsulta, function(json) {
				//atualiza valores
				$('#temperatura').text((json.temperatura).toFixed(1));
				$('#indice').text((json.indice).toFixed(1));
				$('#umidade').text(json.umidade);
				
				//atualiza botoes
				Object.keys(json.reles).forEach(function(key) {
					var meuLink = "#r" + key;
					if (json.reles[key] == 0) {
						$(meuLink).removeClass("on").addClass("off");
						$(meuLink).attr('value',0);
					} else {
						$(meuLink).removeClass("off").addClass("on");
						$(meuLink).attr('value',1);
					}
				})
			});
		}

		//executa qd entra na pagina
		updateValues();
		
		//intervalor para chamar a funo automaticamente a cada 2s
		window.setInterval(function(){
			updateValues();
		}, 2000);
		
		//funo para click em link dos reles descartando outros links
		$(function(){
			$("a").click(function(){
				var meuId = $(this).attr("id");
				// verifica se o link tem um id
				if (typeof meuId !== typeof undefined && meuId !== false) {
					// se tem "r" no id do link  poque  um boto (nao colocar ids com "r" em outros links)
					if ((($(this).attr("id")).indexOf("r")) != -1) {         
						//pega o valor atual do boto e prepara o complemento com o inverso para a url de consulta
						if ($(this).attr("value") == 0) {
							stringRele = ("?" + $(this).attr("id") + "=1");
						} else {
							stringRele = ("?" + $(this).attr("id") + "=0");
						}
						//realiza a consulta
						updateValues(stringRele);
					}
				}
			});
		});
	</script>	
</head>
<body>
	<div>
		<div id="inicio">
			<div class="logo"></div>
			<div class="titulo"><h1>Controle Arduino</h1></div>
		</div>
		<div>
			<table>
				<tr>
					<th>Temperatura (&deg;C)</th>
					<th>ndice de Calor (&deg;C)</th>
					<th>Umidade (%)</th>
				</tr>
				<tr>
					<td></td>
					<td></td>
				</tr>
				<tr>
					<td id="temperatura"></td>
					<td id="indice"></td>
					<td id="umidade"></td>
				</tr>
			</table>
		</div>
		<div id="buttons">
			<a href="#" class="button off" id="r0" value="0">Rel 0</a>
			<a href="#" class="button off" id="r1" value="0">Rel 1</a>
			<a href="#" class="button off" id="r2" value="0">Rel 2</a>
			<a href="#" class="button off" id="r3" value="0">Rel 3</a>
		</div>
	</div>
	<div>
		<p>&sup1; Preciso do sensor <a href="https://www.mouser.com/ds/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf" target=_BLANK>DHT11</a> de +/-5% para umidade e +/-2 graus Celsius para temperatura.</p>
	</div>
</body>
</html>
StylesheetCSS
body {
	font-family: 'Ropa Sans', sans-serif;
	margin: 0px;
}
h1 {
	margin:0px;
}		
table {
	width: 100%;
	border-collapse: collapse;
}
th, td {
	font-size:3em;
	text-align:center;
	width:33%;
}

#inicio {
	margin: 0px 0px 10px 0px;
	text-align: center;
	background-color: #00979d;
	line-height: 120px;
	height: 120px;
	color: #ffffff;
}
.logo {
	background-image: url(https://content.arduino.cc/brand/arduino-white.svg),url(https://content.arduino.cc/brand/arduino_compressed-white.svg);
	background-position: 30px 10px,30px 120px;
	background-repeat: no-repeat,no-repeat;
	background-size: 134px 100px,58px 32px;
	box-sizing: content-box;
	display: block;
	height: 100px;
	float:left;
	padding: 10px 30px;
	position: relative;
	width: 134px;
}
.titulo {
	float:left;
	width: 80%;
	text-align:center;
}

#buttons {
	text-align:center;
}

.button {
	color:#ffffff;
	font-size:3em;
	height:120px;
	line-height:120px;
	text-decoration: none;
	padding: 18px 8px 18px 8px;
	border-top: 1px solid #CCCCCC;
	border-right: 1px solid #333333;
	border-bottom: 1px solid #333333;
	border-left: 1px solid #CCCCCC;			
}
.on {
	background-color: #00979d;
}
.off {
	background-color: #e67e22;
}

Schematics

http://fritzing.org/projects/metonline

Comments

Similar projects you might like

Color Sensor Prototype: Detect Color Name from Objects

Project tutorial by moretticb

  • 6,227 views
  • 7 comments
  • 32 respects

Arduino Kitchen Timer

Project tutorial by Team I and myself

  • 65,449 views
  • 42 comments
  • 87 respects

Portable Temperature Station V2: IOT Edition

Project tutorial by Isaac100

  • 3,471 views
  • 0 comments
  • 8 respects

Electronic Piano Keyboard With Preset Songs

Project tutorial by Lindsay Fox

  • 88,347 views
  • 67 comments
  • 176 respects

Smart Garden

Project showcase by patel Dipen

  • 36,466 views
  • 17 comments
  • 82 respects

Creating a Datalogger with Arduino - Part II

Project in progress by PCBWay and Silícios Lab

  • 2,971 views
  • 0 comments
  • 13 respects
Add projectSign up / Login