Another Arduino Sketch for the DHT-11 

If you would prefer a web-based sketch, I've also been playing around with this one. This may require a 2560. I haven't tried it on an Uno...

This one also has a telnet interface. There is no real need for it, I suppose. I just built it because it sounded interesting.

#include <Ethernet.h>
#include <SPI.h>
#include "DHTSensor.h"

// Network config
byte mac[] = { 0xAA, 0x00, 0x00, 0xE1, 0x00, 0x72};
byte ip[] = {192, 168, 100, 72};
byte gateway[] = {192, 168, 100, 254};
byte subnet[] = {255, 255, 255, 0};

// Device config
#define DEVID "F2"
#define SENSORNAME "Upstairs"

// Other globals
#define VERSION "1.3"
#define TELNETPORT 2323
#define WEBPORT 8080
#define DHTTYPE DHT11
#define DHTPIN 2
#define textBuffSize 20 //length of longest command string plus two spaces for CR + LF
String rcvdCmd = "";
int charsReceived = 0;
boolean connectFlag = 0;
unsigned long timeOfLastActivity; //time in milliseconds of last activity
unsigned long allowedConnectTime = 300000; //five minutes
EthernetServer telnetServer(TELNETPORT);
EthernetClient telnetClient = 0;
EthernetServer webServer(WEBPORT);
EthernetClient webClient = 0;
DHT dht(DHTPIN, DHTTYPE);
float humid;
float tempf;

// State Variables
char* commandText = "";
char* devId = DEVID;
char* sensorName = SENSORNAME;

void setup()
{
Ethernet.begin(mac, ip, gateway, subnet);
Serial.begin(9600);
telnetServer.begin();
webServer.begin();
Serial.println("Remote Environment Monitor");
Serial.print("Version ");
Serial.println(VERSION);
Serial.println();
Serial.print("Telnet service listening on port ");
Serial.println(TELNETPORT);
Serial.print("Web service listening on port ");
Serial.println(WEBPORT);
Serial.println();
dht.begin();
}

void loop()
{
if (telnetServer.available() && !connectFlag) {
connectFlag = 1;
telnetClient = telnetServer.available();
telnetClient.println("\nRemote Environment Monitor");
telnetClient.print("Device: ");
telnetClient.print(devId);
telnetClient.print(" Sensor: ");
telnetClient.println(sensorName);
telnetClient.println();
showPrompt();
}

if (telnetClient.connected() && telnetClient.available()) getReceivedText();

if(connectFlag) checkConnectionTimeout();

webClient = webServer.available();

if (webClient) {
sendWebPage();
}
}

void showPrompt()
{
timeOfLastActivity = millis();
telnetClient.flush();
charsReceived = 0;
telnetClient.println();
telnetClient.print(devId);
telnetClient.print("> ");
}

void checkConnectionTimeout()
{
if(millis() - timeOfLastActivity > allowedConnectTime) {
telnetClient.println();
telnetClient.println("\n*** SESSION TIMED OUT ***\n");
telnetClient.stop();
connectFlag = 0;
}
}

void getReceivedText()
{
char c;
int charsWaiting;

charsWaiting = telnetClient.available();
do {
c = telnetClient.read();
if(c != 0x0d) {
rcvdCmd += c;
charsReceived++;
charsWaiting--;
}
}
while(charsReceived <= textBuffSize && c != 0x0d && charsWaiting > 0);

if(c == 0x0d) {
parseReceivedText();
showPrompt();
}

if(charsReceived >= textBuffSize) {
telnetClient.println();
showErrorMessage();
showPrompt();
}
}

void parseReceivedText()
{
if (rcvdCmd == "help") {
showHelpMessage();
} else if (rcvdCmd == "show version") {
telnetClient.print("\nVersion ");
telnetClient.println(VERSION);
telnetClient.println();
} else if (rcvdCmd == "quit") {
closeConnection();
} else if (rcvdCmd == "show reading") {
showReading();
} else if (rcvdCmd == "reset") {
telnetClient.println("\n--- Reset in 5 Seconds");
closeConnection();
delay(5000);
softwareReset();
} else {
showErrorMessage();
}
rcvdCmd = "";
}

void showErrorMessage()
{
telnetClient.println(">>> Unrecognized Command");
}

void closeConnection()
{
telnetClient.println("\n*** DISCONNECT ***\n");
telnetClient.stop();
connectFlag = 0;
}

void showHelpMessage()
{
telnetClient.println("\nSupported commands:\n");
telnetClient.println(" reset Restart the firmware");
telnetClient.println(" show reading Show current temperature/humidity");
telnetClient.println(" show version Show version number");
telnetClient.println(" help Print this help message");
telnetClient.println(" quit Exit telnet session");
telnetClient.println();
}

void showReading() {
humid = dht.readHumidity();
tempf = dht.readTemperature(1);
telnetClient.println("\nCurrent Reading");
telnetClient.println("================================");
telnetClient.print("Device ID : ");
telnetClient.println(devId);
telnetClient.print("Sensor Name : ");
telnetClient.println(sensorName);
telnetClient.print("Temperature : ");
telnetClient.println(tempf);
telnetClient.print("Humidity : ");
telnetClient.println(humid);
telnetClient.println("================================\n");
}

void sendWebPage() {
humid = dht.readHumidity();
tempf = dht.readTemperature(1);
boolean currentLineIsBlank = true;
while (webClient.connected()) {
if (webClient.available()) {
char c = webClient.read();
if (c == '\n' && currentLineIsBlank) {
webClient.println("HTTP/1.1 200 OK");
webClient.println("Content-Type: text/html");
webClient.println();
webClient.print("Device:");
webClient.print(devId);
webClient.print(",SensorName:");
webClient.print(sensorName);
webClient.print(",Temperature:");
webClient.print(tempf);
webClient.print(",Humidity:");
webClient.println(humid);
break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
webClient.stop();
}

void softwareReset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}


[ add comment ] ( 2870 views ) permalink
Arduino Sketch for DHT11 Temperature Sensor 

Hi kids. So, I have this thing where I like to know exactly how cold it is in the garage before I head out there. Since I've been wanting to play around with the arduino stuff, this seemed like a good project.

This code pushes the sensor readings over MQTT, which I can then pick up and incorporate into the various places I want it. The code is running on an arduino Uno with a wiznet ethernet shield. I'm running the ethernet through a bridged wifi client until I get some network in the garage.

Here's the sketch:
/*

Environment Monitor
Build for Garage - 1 DHT11 Sensor
2014-01-23

*/

#include <stdarg.h>
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include "DHTSensor.h"
#include <ICMPPing.h>

// Fixed Definitions
#define VERSION "1.2-Garage"
#define DEVID "F3"
#define SENSORNAME "Outdoors"
#define CMDQ "net-command"
#define DHTTYPE DHT11
#define DHTPIN 2

// Network config
byte mac[]= {0xAA, 0x00, 0x00, 0xE1, 0x00, 0x73};
byte ip[]= {192, 168, 100, 73};
byte gateway[]= {192, 168, 100, 254};
byte subnet[]= {255, 255, 255, 0};
byte mqtt_broker[]= {192, 168, 100, 150};

// Function declarations
String splitString(String s, char parser,int index);
void callback(char* topic, byte* payload, unsigned int length);

// Instances
EthernetClient ethClient;
PubSubClient client(mqtt_broker, 1883, callback, ethClient);
DHT dht(DHTPIN, DHTTYPE);

// sockets
SOCKET pingSocket = 3;

// State Variables
char* commandText = "";
char* deviceId = DEVID;
char* cmdTopic = CMDQ;
char* sensorName = SENSORNAME;
char* sensorTemp = "";
char* sensorRh = "";
int sampleDelay = 30000;
long lastSampleTime = 0;
char pingBuffer[256];
int pingDelay = 10000;
long lastPingTime = 0;
int netUp = 1;

// printf work-around
char* p(char *fmt, ... ){
char tmp[128]; // resulting string limited to 128 chars
va_list args;
va_start (args, fmt );
vsnprintf(tmp, 128, fmt, args);
va_end (args);
return tmp;
}

void softwareReset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}

void clientConnect() {
if (client.connect(deviceId)) {
commandText = p("Status:%s:Connected",deviceId);
client.publish(cmdTopic,commandText);
Serial.println(commandText);
commandText = p("Status:%s:%i.%i.%i.%i",deviceId,ip[0],ip[1],ip[2],ip[3]);
client.publish(cmdTopic,commandText);
Serial.println(commandText);
client.subscribe(cmdTopic);
commandText = p("Status:%s:Subscribed to %s",deviceId,cmdTopic);
Serial.println(commandText);
} else {
Serial.println("Connection failed to MQTT");
netUp = 0; // Set network down - loop will retry connect
}
}

// Program setup
void setup() {
delay(200);
Ethernet.begin(mac,ip,gateway,subnet);
delay(200);

dht.begin();

Serial.begin(9600);

Serial.println();
Serial.println("Environment Monitor");
Serial.println(VERSION);
Serial.println();

clientConnect();

Serial.println();
}

char* deblank(char* input)
{
char *output=input;
int k,j;
for (k = 0, j = 0; i<strlen(input); k++,j++)
{
if (input[k]!=' ')
output[j]=input[k];
else
j--;
}
output[j]=0;
return output;
}

// splitString function
String splitString(String s, char parser,int index){
String rs='\0';
int parserIndex = index;
int parserCnt=0;
int rFromIndex=0, rToIndex=-1;

while(index>=parserCnt){
rFromIndex = rToIndex+1;
rToIndex = s.indexOf(parser,rFromIndex);

if(index == parserCnt){
if(rToIndex == 0 || rToIndex == -1){
return '\0';
}
return s.substring(rFromIndex,rToIndex);
}
else{
parserCnt++;
}
}
return rs;
}

void sendHumidity1() {
float hum = dht.readHumidity();
char hum_c[5] = "";

dtostrf(hum,5, 1, hum_c);
sensorRh = hum_c;

commandText = p("Status:%s:RH=%s",deviceId,deblank(hum_c));
client.publish(cmdTopic,commandText);
Serial.println(commandText);
}

void sendTemperature1() {
float tempf = dht.readTemperature(1);
char tempf_c[5] = "";

dtostrf(tempf,5, 1, tempf_c);
sensorTemp = tempf_c;

commandText = p("Status:%s:Temp=%s",deviceId,deblank(tempf_c));
client.publish(cmdTopic,commandText);
Serial.println(commandText);
}

// Callback function
void callback(char* topic, byte* payload, unsigned int length) {
//convert byte to char
payload[length] = '\0';
String strPayload = String((char*)payload);
String strPayloadOrig = strPayload;
strPayload += ":"; // splitString has issues...
String receiveId = splitString(strPayload,':',0);
String receiveCmd = splitString(strPayload,':',1);
String receiveChn = splitString(strPayload,':',2);

if (strPayloadOrig != commandText) {
if (receiveId == deviceId) {
if (receiveCmd == "REQ") {
commandText = p("Status:%s:OK",deviceId);
client.publish(cmdTopic,commandText);
Serial.println(commandText);
}
if (receiveCmd == "RST") {
commandText = p("Status:%s:Reset in 5 seconds",deviceId);
client.publish(cmdTopic,commandText);
Serial.println(commandText);
delay(5000);
softwareReset();
}
if (receiveCmd == "VER") {
commandText = p("Status:%s:%s",deviceId,VERSION);
client.publish(cmdTopic,commandText);
Serial.println(commandText);
}
}
}
}

void loop() {

client.loop();

if ((millis() - lastPingTime) > pingDelay) {
if ( netUp == 0 ) {
delay(5000);
clientConnect(); // Wait 5 seconds, and re-init client
}
ICMPPing ping(pingSocket);
if (ping(4, mqtt_broker, pingBuffer)) {
netUp = 1;
} else {
Serial.println("NetFail");
netUp = 0;
}
lastPingTime = millis();
}

if ((millis() - lastSampleTime) > sampleDelay) {
if ( netUp == 1 ) {
commandText = p("Status:%s:Name=%s",deviceId,sensorName);
client.publish(cmdTopic,commandText);
Serial.println(commandText);
sendTemperature1();
sendHumidity1();
lastSampleTime = millis();
}
}
}



To use it, you'll need a few libraries. The DHT sensor library is from Adafruit. You can read about it here. The MQTT piece uses the PubSubClient library, found here. To handle network glitches, it's using ping to check connectivity, and will reconnect if it can't find the server. The ping library is here. All-in-all, it may not be the most sophisticated sketch, but this one is getting the job done. Good luck!
[ add comment ] ( 2499 views ) permalink
The Solar Project 

Now I'll be honest with you, boys and girls. I had only the most vague of thoughts on the topic of alternate energy. Basically, I just sort of wondered what I would do for power if it went off and stayed off for any length of time. That was it. I had gone no further...

Now, if you know me, you know that I love gadgets. You also know that I love money. Consequently, I put a good deal of time and effort into getting more of the former without giving up much of the latter. This is where the Harbor Freight parking lot sales come into the conversation. You see, I'm a regular at those. Now I know some of you are shaking your heads and muttering about how you won't even touch it if it doesn't say "snap-on" in there somewhere, but you have to understand, I'm cheap.

At yesterday's sale, they had one of these:

Solar Panel Kit

It was a return, and the note on the box said "LED doesn't work". I asked the guy if he knew anymore about it, but he basically just confirmed that where normally the LED works, this particular one doesn't. He was very polite about it. So by virtue of the regular sale discount, parking lot sale discount, returned item discount, and probably harmonic convergence, the final price was $75. Like any good DIYer, I thought "I bet I can fix it". In this case I was right! Hey, don't act so surprised... Oh OK, act surprised. Heck, I was.

So now I have a solar project. I'll put the details here. Maybe we can learn together.

Check back later, if you want....
[ add comment ] ( 2155 views ) permalink
Removing Moss from Your Roof 

Hello, fellow DIYers!

I just wanted to pass this along, since I've tried it, and it works.

If your roof has overhanging tree limbs, or just plain doesn't get a lot of sun, you may end up with a moss problem. I didn't even know I had one until my insurance company sent me a very unfriendly note about getting rid of it "or else". In my case, they also insisted upon having me hire a contractor to certify the work, blah, blah, blah, etc, etc. Well, I wasn't too pleased with the whole idea. So I took a look at the moderately small amount of moss in question, and asked my friend the internet what I should do about it. Here's the short version:

1. Put on clothes that you wouldn't mind throwing away when you're done. I'll explain later... You should also take a look at what's at the end of your downspouts. If it's alive, you may not want to use this method, or you may want to find a way to direct them to somewhere that doesn't have living stuff.

2. Get your garden hose up there and give it a good spray! Be careful if you need a ladder for this. I wouldn't do the power-washer thing, but a fair amount of pressure will lift up a lot of the moss right away (without lifting up the shingles too much).

3. Mix household bleach and clean water in a sprayer. My sprayer was 10 bucks from Harbor Freight during the parking lot sale. Bleach is about $2 a gollon where I live.

4. Carefully climb up and get close enough to give the moss a REALLY good soak with the bleach and water. I mean really. The sprayer should have an adjustable nozzle. I set mine for "long stream", not "fine spray" so I wouldn't have to climb all the way up. You're likely to get a good deal of blow-back if it's windy. That's why you wanted those old, crappy clothes instead of your Sunday best.

5. Wait a few minutes. I gave it something like 45 minutes to sit.

6. Pull the garden hose back up, and rinse well. The rest of the moss came right off for me. At this point, you've probably guessed why we cared about what was below the downspout. All that bleachy water will be draining there as we hose her down. I'm no expert, but I'm guessing plants don't take well to that kind of treatment.

At the end of the day, I had no moss at all. I also had a new insurance company (one that never saw a hint of moss on my roof), and maybe I made some contractor out there buy his own lunch (no worries, I've got lots of stuff I'm happy to pay him for - just not this one).

That's the whole story, kids. Remember: Be careful when you're playing with bleach on a ladder.

[ add comment ] ( 2343 views ) permalink
Ossian Road Trip with Braxton 




Braxton and I decided to make the Donut Run again Saturday. The weather was awesome, and not all that hot for August. We ended up clocking about 40 miles, round-trip. Here are a few pictures.

--> Click <--





[ add comment ] ( 1509 views ) permalink

<Back | 1 | 2 | 3 | Next> Last>>