Arduino Based Attic Monitor

September 29th 2011

Expanding on the garage monitor project I decided to monitor a couple of gable fans I installed in my attic. I installed the gable fans after finding out that my attic was 145 degrees one afternoon.

The 4 pin headers connect to the sparkfun opamp breakout boards.

Schematic:
Attic Monitor Schematic

Board:
Attic Monitor Arduino Shield

Code:

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// EtherShield webserver demo
#include "EtherShield.h"
#include <stdlib.h>
#include <OneWire.h>
#include <DallasTemperature.h>
 
// define inputs for fans
int frontfan = 5;
int backfan = 4;
 
#define ONE_WIRE_BUS 6  // Data wire is plugged into pin 6 on the Arduino
OneWire oneWire(ONE_WIRE_BUS);  // Setup a oneWire instance to communicate with any OneWire devices 
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
 
// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {
  0x54,0x55,0x58,0x10,0x00,0x85};
 
static uint8_t myip[4] = {
  192,168,230,21};
 
#define MYWWWPORT 80
#define BUFFER_SIZE 550
static uint8_t buf[BUFFER_SIZE+1];
 
// The ethernet shield
EtherShield es=EtherShield();
 
uint16_t http200ok(void)
{
  return(es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n")));
}
 
// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf)
{
  String Output1;
  float garageTempf = 0.0;
  char garageTempc[7];
  int i=0;
  uint16_t plen;
  plen=http200ok();
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<html><head><title>Jim's Attic</title></head><body>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<center><h1>Welcome to Jim's Attic</h1>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr><h2><font color=\"red\">"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br> The Front Fan is: "));
  ///////  READING CT sensor 10 times and get average reading, fan off == ~600 ADC
  int CTarray[11];
  float IsItOn = 0;
  for (int x = 0; x < 10; x++) {
    CTarray[x]=analogRead(frontfan);
  }
 
  for (int y = 0; y < 10; y++) {
    if (CTarray[y] < 400)
    {
      IsItOn = IsItOn + 10;
    }
    else if (CTarray[y] < 700 && CTarray[y] > 400 )
    {
      IsItOn = IsItOn + 1;
    }
    else
    {
      IsItOn = IsItOn + 10;
    }
  }
  IsItOn = IsItOn / 10;
  Serial.print("IsItOn == ");
  Serial.println(IsItOn);
  //////
  if ( IsItOn > 1 )
  { // The fan is on because the average eq >1
    Output1 = "ON!";
    Serial.println("the font fan is on");
  }
  else
  {
    Output1 = "OFF";
    Serial.println("the front fan is off");
  }
  i=0;
    while (Output1[i]) {
                buf[TCP_CHECKSUM_L_P+3+plen]=Output1[i++];
                plen++;
        }
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br> The Back Fan is: "));
  ///////
  // READ Current sensor 2
  //////
    Output1 = "Not Connected!";
    i=0;
    while (Output1[i]) {
                buf[TCP_CHECKSUM_L_P+3+plen]=Output1[i++];
                plen++;
        }
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br>The Temp is: ") );
  sensors.requestTemperatures(); // Send the command to get temperatures
  garageTempf = DallasTemperature::toFahrenheit(sensors.getTempCByIndex(0));
  dtostrf(garageTempf, 3, 2, garageTempc);
  Serial.println(garageTempf);
  i=0;
  while (garageTempc[i]) {
               buf[TCP_CHECKSUM_L_P+3+plen]=garageTempc[i++];
               plen++;
       }
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br></font></h2>") );
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</center><hr>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("V1.0 <a href=\"http://www.stuffjimmakes.com\">http://www.stuffjimmakes.com</a>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</body></html>"));
 
  return(plen);
}
 
 
void setup(){
  Serial.begin(9600);
  // Initialise SPI interface
  es.ES_enc28j60SpiInit();
  // initialize enc28j60
  es.ES_enc28j60Init(mymac,8);
  // init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  sensors.begin();      // Start up the library
}
 
void loop(){
  uint16_t plen, dat_p;
 
  while(1) {
    // read packet, handle ping and wait for a tcp packet:
    dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
 
    /* dat_p will be unequal to zero if there is a valid
     * http get */
    if(dat_p==0){
      // no http request
      continue;
    }
    // tcp port 80 begin
    if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
      // head, post and other methods:
      dat_p=http200ok();
      dat_p=es.ES_fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>"));
      goto SENDTCP;
    }
    // just one web page in the "root directory" of the web server
    if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
      dat_p=print_webpage(buf);
      goto SENDTCP;
    }
    else{
      dat_p=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>"));
      goto SENDTCP;
    }
SENDTCP:
    es.ES_www_server_reply(buf,dat_p); // send web page data
    // tcp port 80 end
 
  }
 
}

Tags: , , , ,

Posted by Jim under arduino & Electronics & pcb | 1 Comment »

Arduino Based Garage Monitor

August 11th 2011

Whenever I leave my house I always wonder if I forgot to shut my garage door. Again I grabbed an arduino with an ethernet shield. This time I used a nanode. I combined this with a temp sensor, an LDR, a switch and a relay. With this setup I’m able to monitor the temperature of my garage, see if I left the light on, and even control the garage door from anywhere on the internet. It should be known that there is no security on this right now so I only allow access to this website from my internal LAN. I also used appInventor to create an app for my andriod based phone. Also note that I used the example webserver pde as a starting point. Code and schematics below… I have future plans of figuring out a way to secure this as well as a way to monitor this via cacti or nagios.

I used the toner transfer method to make this board. I’ll likely do a post about that as well.

Schematic and Board design to follow

Output:
 
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include <EtherShield.h>
#include <stdlib.h>
#include <OneWire.h>
#include <DallasTemperature.h>
 
#define ONE_WIRE_BUS 8  // Data wire is plugged into pin 8 on the Arduino
OneWire oneWire(ONE_WIRE_BUS);  // Setup a oneWire instance to communicate with any OneWire devices 
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
 
int doorPin = 7;   // pushbutton connected to digital pin 7
int doorTrigger = 5; // this will be tied to the relay, activate it to open / close
// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {
  0x54,0x55,0x58,0x10,0x00,0x25};
 
static uint8_t myip[4] = {
  192,168,230,20};
 
#define MYWWWPORT 80
#define BUFFER_SIZE 550
static uint8_t buf[BUFFER_SIZE+1];
 
// The ethernet shield
EtherShield es=EtherShield();
 
uint16_t http200ok(void)
{
  return(es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n")));
}
 
// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf)
{
  String Output1;
  String buffer;
  int doorOpen = 0;
  float garageTempf = 0.0;
  char garageTempc[7];
  int i=0;
  uint16_t plen;
  plen=http200ok();
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<html><head><title>Jim's Garage V1.0</title></head><body>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<center><h1>Welcome to Jim's Garage Ethernet Shield V1.0</h1>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr><br><h2><font color=\"red\">"));
  // Varible Data Here 
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("The Light is : ") );
  if (analogRead(0) > 500)
  {
    // The light is on!
    Output1 = "ON";
    Serial.print("The Light is ON - ");
    Serial.println(analogRead(0));
  }
  else
  {
    // The light is off!
    Output1 = "OFF";
    Serial.print("The Light is OFF - ");
    Serial.println(analogRead(0));
  }
 
 
 
//SensorData = itoa(analogRead(0), Output1, 10);
  while (Output1[i]) {
                buf[TCP_CHECKSUM_L_P+3+plen]=Output1[i++];
                plen++;
        }
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br>The Door is: ") );
  doorOpen = digitalRead(doorPin);
  if (doorOpen)
  { // The door is open because the switch it pushed
    Output1 = "OPEN!";
    Serial.println("the door is open");
    Serial.println(doorOpen);
  }
  else
  {
    Output1 = "CLOSED";
    Serial.println("the door is closed");
    Serial.println(doorOpen);
  }
  i=0;
   while (Output1[i]) {
                buf[TCP_CHECKSUM_L_P+3+plen]=Output1[i++];
                plen++;
        }
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br>The Temp is: ") );
  sensors.requestTemperatures(); // Send the command to get temperatures
  garageTempf = DallasTemperature::toFahrenheit(sensors.getTempCByIndex(0));
  dtostrf(garageTempf, 3, 2, garageTempc);
  Serial.println(garageTempf);
   i=0;
   while (garageTempc[i]) {
                buf[TCP_CHECKSUM_L_P+3+plen]=garageTempc[i++];
                plen++;
        }
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br></font></h2>") );
  // end of variable data
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<a href=\"http://192.168.230.20/operate\">Open/Close The Garage</a>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr><br>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</center>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("V1.0 <a href=\"http://www.stuffjimmakes.com\">www.stuffjimmakes.com</a>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</body></html>"));
 
  return(plen);
}
/////////////////////////////////////////////////////////////////////
uint16_t print_opening_webpage(uint8_t *buf)
{
  digitalWrite(doorTrigger, HIGH);
  delay(250);
  digitalWrite(doorTrigger, LOW);
  uint16_t plen;
  plen=http200ok();
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<html><head><title>Jim's Garage V1.0</title><meta http-equiv=\"REFRESH\" content=\"15;url=http://192.168.230.20\"></head><body>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<center><h1>Welcome to Jim's Garage Ethernet Shield V1.0</h1>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr><br><h2><font color=\"red\">"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("The door is MOVING!") );
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br></font></h2>") );
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr><br>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</center>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("V1.0 <a href=\"http://www.stuffjimmakes.com\">www.stuffjimmakes.com</a>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</body></html>"));
  return(plen);
}
/////////////////////////////////////////////////////////////////////
 
void setup(){
  Serial.begin(9600);
  // initialize enc28j60
  es.ES_enc28j60Init(mymac);
 
  // init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
 
  pinMode(doorPin, INPUT);      // sets the digital pin 7 as input
  pinMode(doorTrigger, OUTPUT); // Sets digital pin 5 as my relay trigger output
 
  sensors.begin();      // Start up the library
}
 
void loop(){
 
  uint16_t plen, dat_p;
 
  while(1) {
    // read packet, handle ping and wait for a tcp packet:
    dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
 
    /* dat_p will be unequal to zero if there is a valid
     * http get */
    if(dat_p==0){
      // no http request
      continue;
    }
    // tcp port 80 begin
    if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
      // head, post and other methods:
      dat_p=http200ok();
      dat_p=es.ES_fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>"));
      goto SENDTCP;
    }
    // just one web page in the "root directory" of the web server
    if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
      dat_p=print_webpage(buf);
      goto SENDTCP;
    }
    // This is if we want to trigger the door to open / close
    if (strncmp("/operate ",(char *)&(buf[dat_p+4]),2)==0){
      dat_p=print_opening_webpage(buf);
      goto SENDTCP;
    }
    else{
      dat_p=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>"));
      goto SENDTCP;
    }
SENDTCP:
    es.ES_www_server_reply(buf,dat_p); // send web page data
    // tcp port 80 end
 
  }
 
}

Tags: , , , , , , ,

Posted by Jim under arduino & Electronics | No Comments »

Temperature Monitoring

December 31st 2010

I recently bought a used chest freezer on craigslist to store a lot of beef. I went in on half a cow with a co-worker. It seemed like every time I walked past the freezer the compressor was on and I became concerned that I might have gotten a bad freezer. I did what any self respecting geek would do and took some measurements.

In comes the arduino in about 15 minutes I’d found code to output temps from my DS18S20 temp sensor. I breadboarded up the sensor and threw it into the freezer. It was outputting the temp every minute or so.

I then hacked my way through my first processing sketch to take the incoming value and append the date / time to it. This created me a nice little csv file I could open in excel and make a pretty graph. The graph shows that the compressor is on nearly 50% of the time. I think this is due in part to the freezer only being about 1/5 full. I’m going to add some more stuff in there to give it some more thermal mass and see if that helps.

Below are all sketches I used and the graph I created. Thanks to all who contributed to the arduino / processing playground. I couldn’t have whipped this together so fast without your help. I tried to leave credits in the code wherever I found it. If I missed something please let me know! I only wrote about 5% of this code.

I should have done a better job labeling my axis, but I have since deleted the files…The vertical axis is temp in F and horizontal is time.

Dropping temps indicate compressor is on

Arduino Sketch:

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
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices  //(not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
void setup(void)
{
// start serial port
Serial.begin(9600);
//Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
}
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
//Serial.print("Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
//Serial.println("DONE");
//Serial.print("Temperature for Device 1 is: ");  
//Serial.print(",");  Serial.println(DallasTemperature::toFahrenheit(sensors.getTempCByIndex(0))); 
delay(5000);
}
float printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  //Serial.print("Temp C: ");
  //Serial.print(tempC);
  //Serial.print(" Temp F: ");
  //Serial.print(DallasTemperature::toFahrenheit(tempC));
  return tempC;
}
Processing Sketch:
// Serial Example by Tom Igoe
import processing.serial.*;
PrintWriter output;
int lf = 10;    // Linefeed in ASCII
String myString = null;
Serial myPort;  // The serial port
void setup() {
  // List all the available serial ports
  println(Serial.list());
  // I know that the first port in the serial list on my mac
  // is always my Keyspan adaptor, so I open Serial.list()[0].
  // Open whatever port is the one you're using.
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.clear();
  // Throw out the first reading, in case we started reading 
  // in the middle of a string from the sender.
  myString = myPort.readStringUntil(lf);
  myString = null;
  // size(200, 200);
  // Create a new file in the sketch directory
  output = createWriter("/Users/jim/Documents/temps.txt");
  frameRate(12);
}
void draw() {
  while (myPort.available() > 0) {
    myString = myPort.readStringUntil(lf);
    if (myString != null) {
      println(myString);
      output.print(hour());
      output.print(":");
      output.print(minute());
      output.print(":");
      output.print(second());
      output.print(",");
      output.print(myString);
    }
  }
}
void keyPressed() { // Press a key to save the data
  output.flush(); // Write the remaining data
  output.close(); // Finish the file
  exit(); // Stop the program
}

Tags: , , , , , , ,

Posted by Jim under arduino & Electronics | 5 Comments »

First circuit board sent to the fab house

November 23rd 2010

I’ve been working on an arduino based kegerator. It monitors flows (how much is left in each keg) and temperatures. It’s a pretty simple system but I needed to make an arduino shield for all of the sensors to connect up to it. I’ll post more about the kegerator here soon but here’s a tease of the shield schematics. I should get the board back from batchpcb in a little while.

Tags: , , , , , ,

Posted by Jim under Electronics | No Comments »

Arduino – Part 2 – Accelerometer

November 23rd 2010

One of my main goals of buying an accelerometer is to fit it inside one of my RC airplanes. It would take basic readings and change the color of a BUNCH of RGB LEDs. I thought I’d breadboard up the project really quick. In this I figured out how to use an accelerometer to tell which way is up. Sadly, I never finished the airplane…or got this off the breadboard…

ooohhh, pretty lights....AND LEDs!

Tags: , , , , , , ,

Posted by Jim under Electronics | No Comments »

Arduino – Part 1 – Hello World

November 23rd 2010

I finally broke down and brought an arduino. It took me the better part of a minute and a half to download the arduino software, install it, and have blinky running. What a great little platform!

Tags: , , ,

Posted by Jim under Electronics | No Comments »