Podemos comprar algún controlador comercial, con su correspondientes cpu’s, y diversos módulos para sensores y controladores, o bien, podemos probar a construirnos lo nosotros mismos.
Si lo hacemos nosotros hay varias posibilidades, desde raspberry pi , Arduino, pcls, etc..
Como esto es un taller de Arduino, veamos este, ji.ji..
Lo primero es decir que la mayoría de la documentación esta disponible en la Web, tanto de librerías, desarrollos, etc. Tendremos que saber algo de electrónica, pero no en un nivel avanzado...
Lo segundo, aparte de escoger la placa de Arduino con la que vamos ha crear el controlador, es tener claro que queremos hacer y como va ha interactuar el Arduino en ese esquema.
Me explico, el Arduino puede ser autómata, independiente o ser controlado por software por otro dispositivo, véase PC (Windows, Linux), tablet, etc...
El ser autómata requiere más código y más componentes adicionales (Shield), mientras que si es controlado necesitamos el controlador, un PC o una raspberry, el cual tiene que estar encendido todo el día.
Para mi el segundo modo, en el que el Arduino es controlado, es decir, corre un código muy simple, solo lee variables y procesa comandos, es mucho mas cómodo que el autómata, porque muchas de las funciones/servicios ya los aporta el controlador (PC, rasp..), Ej. Si esta controlado no necesitamos un display, ni un reloj, ni una Shield Ethernet o wifi, todo eso ya lo tenemos con el PC.
En su día desarrolle un código basado en Delphi 5 para Windows. Para mi es mas fácil programarlo así, un mini PC, un Arduino Uno y sondas de temperatura, ph y una placa de relés...
El código era este:
//LIBRERIAS
# include <math.h>
# include<Wire.h>
//include # "RTClib.h"
# include <OneWire.h>//temperatura
//variables
float temacu;
float ph ;
float sensorph;
float temc;
int val = 0; // varible pa reles
int valluz=0;
// USO LCD
void posicion(int x, int y)
{ Serial.print(0x7C, BYTE);
Serial.print(24, BYTE);
Serial.print(x, BYTE);
Serial.print(0x7C, BYTE);
Serial.print(25, BYTE);
Serial.print(y, BYTE);
}
void valortemperatura()
{//temperatura
temc = 0.00;
int y = 0;
for(y=0; y<200 ; y++) {temc += analogRead(1); //100 lecturas
delay(2);
}
temc = temc / 250; //media de las lecturas
temacu = (5 * temc * 100) / 1024;
posicion (0,36);
Serial.print("TEMP:");
posicion (45,36);
Serial.print(temacu);
}
void valorph()
{//sensor de ph
sensorph = 0.00;
ph = 0.00;
int x = 0;
for(x=0; x<100 ; x++) {sensorph += analogRead(0); //100 lecturas
delay(5);
}
sensorph = sensorph / 100; //media de las lecturas
ph = (0.0178 * sensorph) - 1.889; //temperatura 25
//ph = 7 - (2.5 - sensorph / 200) / (0.257179 + 0.000941468 * temacu); // temperature variable
posicion (0,28);
Serial.print("PH:");
posicion (45,28);
Serial.print(ph);
}
void sensorluz()
{ // SENSOR DE LUZ
int y = 0;
for(y=0; y<10 ;y++) {valluz += analogRead(2);//10 lecturas lee el sensor de oscuridad conectado en el pin analogico 3
delay(5);
}
valluz = valluz / 10; //media de las lecturas
posicion (0,20);
Serial.print("LUZ:");
posicion (45,20);
Serial.print(valluz);
}
void setup()
{ Wire.begin();
Serial.begin(115200);
pinMode(2,OUTPUT); // declaro the 2 pin as output led- Luz de luna
pinMode(11,OUTPUT); // declaro the 11 pin as output RELE8
pinMode(10,OUTPUT); // declaro the 10 pin as output RELE7
pinMode(9,OUTPUT); // declaro the 9 pin as output RELE6
pinMode(8,OUTPUT); // declaro the 8 pin as output RELE5
pinMode(7,OUTPUT); // declaro the 7 pin as output RELE4
pinMode(6,OUTPUT); // declaro the 6 pin as output RELE3
pinMode(5,OUTPUT); // declaro the 5 pin as output RELE2
pinMode(4,OUTPUT); // declaro the 4 pin as output RELE1
Serial.print(0x7C, BYTE);
Serial.print(0x00, BYTE);
delay(1000);
}
void loop()
{ Serial.print(0x7C, BYTE);
Serial.print(0x00, BYTE);
delay(10);
valortemperatura();
valorph();
sensorluz();
posicion (0,0);
Serial.println("");
delay(1000);
//reles
val = Serial.read(); // read the serial port
if (val !=-1)
{
if (val=='1'){
digitalWrite(2,HIGH); // luna connected to digital pin 2
}
if (val=='A'){
digitalWrite(2,LOW); // luna connected to digital pin 2
}
if (val=='2'){
digitalWrite(3,HIGH); // VEN connected to digital pin 3
}
if (val=='B'){
digitalWrite(3,LOW); // VEN connected to digital pin 3
}
if (val=='4'){
digitalWrite(4,HIGH); // R4 connected to digital pin 4
}
if (val=='D'){
digitalWrite(4,LOW); // R4 connected to digital pin 4
}
if (val=='5'){
digitalWrite(5,HIGH); // R3 connected to digital pin 5
}
if (val=='E'){
digitalWrite(5,LOW); // R3 connected to digital pin 5
}
if (val=='6'){
digitalWrite(6,HIGH); // R2 connected to digital pin 6
}
if (val=='F'){
digitalWrite(6,LOW); // R2 connected to digital pin 6
}
if (val=='7'){
digitalWrite(7,HIGH); // R1 connected to digital pin 7
}
if (val=='G'){
digitalWrite(7,LOW); // R1 connected to digital pin 7
}
if (val=='8'){
digitalWrite(8,HIGH); // R5 connected to digital pin 8
}
if (val=='H'){
digitalWrite(8,LOW); // R5 connected to digital pin 8
}
if (val=='9'){
digitalWrite(9,HIGH); // R6 connected to digital pin 9
}
if (val=='I'){
digitalWrite(9,LOW); // R6 connected to digital pin 9
}
if (val=='10'){
digitalWrite(10,HIGH); // R1 connected to digital pin 10
}
if (val=='J'){
digitalWrite(10,LOW); // R7 connected to digital pin 10
}
if (val=='11'){
digitalWrite(11,HIGH); // R8 connected to digital pin 11
}
if (val=='K'){
digitalWrite(11,LOW); // R8 connected to digital pin 11
}
}
}
Y el resultado fue este, (grabar y pulsar sin ver donde tocas, pues eso ratón al canto…ji,ji)
Os dejo un video..
Este fue un desarrollo , la v.02, pero fue un intento fallido de controlar la densidad (digamos que la lie un poco, ji,ji))

Sobre este volveré cuando lo necesite…Aparque el proyecto con arduino en su día y ahora lo he retomado, así que llevo unos días probando otra configuración, esta vez sin PC, de forma autónoma pero con acceso externo. La ventaja que quería explorar es el servidor Web que se puede montar con la Shield Ethernet, la placa de relés no la he conectado, de momento no voy a controlar nada con ellos, las funcionalidades son muchas menos que con Delphi, pero es posible que si cambio la pantalla de T5 a leds los reprograme para dimearlos, pero de momento no..
Se necesita el siguiente material, he puesto esta tienda pero lo hay en eBay, de segunda mano… esto es lo minimo, caja para arduino, alimentador a pilas, screew shields, etcc. se pueden añadir al gusto de cada uno..
Un Arduino Uno, http://www.bricogeek.com/shop/arduino/3 ... o-uno.html
Una Ethernet Shield, http://www.bricogeek.com/shop/arduino/3 ... ernet.html
Una sonda de Ph, http://www.bricogeek.com/shop/otros/581 ... de-ph.html
Una sonda de Temperatura, http://www.bricogeek.com/shop/sensores- ... tanco.html
Un dispositivo para visualizar, móvil, tablet, PC..
El código a incluir en el Arduino es este, algunas cosas sobran, pero no las he quitado, ji,ji..
# include <SPI.h>
# include <OneWire.h>
# include <EEPROM.h>
# include <U8glib.h>
# include <Ethernet.h> // Ethernet shield attached to pins 10, 11, 12, 13
//variables de librerias
byte mac[] = {0x90, 0xA2, 0xDA, 0x0F, 0x26, 0x4C };
IPAddress ip(192, 168, 1, 150); // esta es la ip de mi lan, la parte interna, para verlo desde fuera hay que redireccionar el Puerto en el ruter desde nuesta ip publica a la interna
unsigned int localPort = 80;
EthernetServer server(80);
EthernetClient client;
unsigned long lastDebounceTime = 0;
unsigned long time; // Para ver los Milisegundos que han transcurrido desde inicio, no lo uso
byte EspRfrIp = 1;
OneWire ds(2);
// buffers para recepcion y envio de datos
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // Instancia Ethernet UDP para enviar y recibir paquetes
//variables propias
double te ; // se iguala a valor celsius;
double ph ; // se iguala a valor de sonda;
double phmax = 8.18;
double phmin = 8.18;
double temax = 26.00;
double temin = 26.00;
//varibles ph // conexion sonda df robotRojo------5 Vcc , Negro ---- GND, Azul --- PIN Analogico A0
SensorPin 0
unsigned long int avgValue;
float b;
int buf[10],temp;
void setup()
{
Serial.begin(9600);
while (!Serial) {;}
Ethernet.begin(mac, ip); //mac 90:A2:DA:0F:26:4C
server.begin();
lastDebounceTime= millis();
pinMode(7, OUTPUT); // led para blink
}
void loop()
{
sensortemperatura();
sensorph();
IncomingConnections();
GestRfIp();
}
void sensorph()
{
for(int i1=0;i1<10;i1++) //valor intermedio
{
buf[i1]=analogRead(0); //sonda de ph conectada a A0
delay(10);
}
for(int i1=0;i1<9;i1++) //sort the analog from small to large
{
for(int j1=i1+1;j1<10;j1++)
{
if(buf[i1]>buf[j1])
{
temp=buf[i1];
buf[i1]=buf[j1];
buf[j1]=temp;
}
}
}
avgValue=0;
for(int i1=2;i1<8;i1++) //hace la media
avgValue+=buf[i1];
float phValue=(float)avgValue*5.0/1024/6; //convierte analogico en milivoltios
phValue=3.5*phValue; //convierte milivoltio en valor pH
ph=phValue;
Serial.print(" pH:");
Serial.print(ph,2);
if (phmin>ph) {
phmin = ph;
};
if (phmax<ph) {
phmax = ph;
};
Serial.print(" Min :");
Serial.print(phmin);
Serial.print(" - ");
Serial.print(" Max :");
Serial.print(phmax);
Serial.println(" ");
delay(800);
}
void sensortemperatura ()
{
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
if ( !ds.search(addr))
{
Serial.print(".");
ds.reset_search();
delay(250);
return;
}
Serial.print("ROM =");
for( i = 0; i < 8; i++)
{
Serial.write(' ');
Serial.print(addr, HEX);
}
if (OneWire::crc8(addr, 7) != addr[7])
{
Serial.print("CRC is not valid!");
return;
}
switch (addr[0])
{
case 0x10:
Serial.print(" Chip = DS18S20");
type_s = 1;
break;
case 0x28:
Serial.print(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.print(" Chip = DS1822");
type_s = 0;
break;
default:
Serial.print("Device is not a DS18x20 family device.");
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // convierte los vatios entre la toma de 5 y el parasito(resistencia..)
delay(1000);
present = ds.reset();
ds.select(addr);
ds.write(0xBE);
Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++)
{
data = ds.read();
Serial.print(data, HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
int16_t raw = (data[1] << 8) | data[0];
if (type_s)
{
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10)
{
raw = (raw & 0xFFF0) + 12 - data[6];
}
}
else
{
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw & ~7;
else if (cfg == 0x20) raw = raw & ~3;
else if (cfg == 0x40) raw = raw & ~1;
}
celsius = (float)raw / 16.0;
te=celsius+0.21; //CORRECCION DE LA SONDA
Serial.print(" Temperatura = ");
Serial.print(te);
Serial.print(" Celsius ");
if (temin>te) {
temin = te;
};
if (temax<te) {
temax = te;
};
Serial.print(" Min :");
Serial.print(temin);
Serial.print(" - ");
Serial.print(" Max :");
Serial.print(temax);
Serial.print(" ");
}
void IncomingConnections()
{
EthernetClient client = server.available();
if (client)
{
Serial.print("WebSite Arduino Equal");
boolean currentLineIsBlank = true;
while (client.connected())
{
if (client.available())
{
char c = client.read();
//Serial.write(c);
if (c == '\n' && currentLineIsBlank)
{
//pagina web
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.println("<DOCTYPE HTML>");
client.println("<html>");
client.println("<head>");
client.println(" <meta http-equiv='refresh' content='5'>");
client.println(" <script type='text/javascript' src='https://www.google.com/jsapi'></script>");
client.println(" <script type='text/javascript'>");
client.println(" google.load('visualization', '1', {packages:['gauge']});");
client.println(" google.setOnLoadCallback(drawChart);");
client.println(" function drawChart() {");
client.println(" var data = google.visualization.arrayToDataTable([");
client.println(" ['Label', 'Value'],");
client.println(" ['Temperatura',");
client.print(te);
client.println(" ],");
client.println(" ['pH', ");
client.print(ph);
client.println(" ]");
client.println(" ]);");
client.println(" var chart = new google.visualization.Gauge(document.getElementById('chart_div'));");
client.println(" var options = {width: 700, height: 300, redFrom: 28, redTo: 30,");
client.println(" yellowFrom:27, yellowTo: 28, minorTicks: 5, min: 7, max: 30};");
client.println(" chart.draw(data, options);");
client.println(" }");
client.println(" </script>");
client.println("</head>");
client.println("");
client.println("<body>");
client.println("<br>");
client.println("<font color=\"#000000\"><div align=\"center\"><FONT SIZE=+4>WebSite Arduino EQUAL REEF(c)</FONT>");
client.println("<br>");
client.println("<td width=\"360\"> <div id='chart_div'></div><td>");
client.println("<font color=\"##707070\"><div align=\"center\">Basado en JajaScript y Google Apps.Developers.");
client.println("<br>");
client.println("Datos Sensores ");
client.println("(Temp. Min: ");
client.print(temin);
client.print(" Temp. Max: " );
client.print(temax);
client.println(") (pH Min: ");
client.print(phmin);
client.print(" pH Max: ");
client.print(phmax);
client.print(") " );
client.println("<br>");
client.println("<br>");
client.println("</body>");
client.println("</html>");
break;
}
if (c == '\n')
{
currentLineIsBlank = true;
}
else
if (c != '\r')
{
currentLineIsBlank = false;
}
}
}
delay(100);
// cerramos la conexion
client.stop();
Serial.println("Actualizada Web");
digitalWrite(7, HIGH); // Encemos un led con cada envio, en este caso el 7
delay(100);
digitalWrite(7, LOW);
}
}
void GestRfIp()
{
unsigned long MillisNow = millis();
if (MillisNow<lastDebounceTime){lastDebounceTime= millis();}
if ((MillisNow - lastDebounceTime) >= 60000) {lastDebounceTime= millis(); if (EspRfrIp<1);EspRfrIp=20;}else{EspRfrIp--;}
}
void RfIp(){
int Reintento;
Reintento=0;
while(true){
if (client.available())
{
client.stop();
client.flush();
return;
}
else
{
Reintento++;
IncomingConnections();
delay(10);
if (Reintento >= 100 )
{
client.stop();
client.flush();
return;
}
}
}
}
Y este el resultado, aunque la web es muy simple es lo que necesitaba en este momento, controlar la temperatura y el pH, aun asi es HTML básico, la página se actualiza cada 5 segundos si hay un cliente conectado, sino no publica..
Se puede generar con Wordpress, con CSS, con Dreamweaver, almacenarla en la SD de la Ethernet y publicarla..

Las posibilidades son infinitas y los modos de plantearlo también. Es lo bueno de esto, es divertido y entretenido, eso si te llevas algún que otro cabreo... ji.ji…
Seguro que tenéis otros planteamientos y configuraciones, seria interesante que las expusieras, ya que serian de ayuda a gente que este empezando o simplemente que quieran probar...