Last active
July 9, 2016 20:29
-
-
Save john212/ca30f6746488e8a32f116cab60c9df00 to your computer and use it in GitHub Desktop.
Arduino With Ethernet Shield Controlling LED via Telent and Displaying Temp., Humidity, LDR Readings via Telnet and on 16x2 Display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************************************************** | |
Udemy Arduino Step-by-Step Course | |
Section 6 Lecture 60 Ethernet Shield Telnet Control | |
With 16x2 LCD Text Display and DHT11 Temperature/Humidity Sensor | |
Quiz - Just For Fun - No Grade | |
by J. Cantlin | |
July 8, 2016 | |
***************************************************/ | |
/************************************************** | |
Description of Program | |
In this demonstration, a W5100 based Ethernet Shield with | |
an Arduino Uno is used to show how remote control, in this | |
case via telnet, can be used to read the analog output of | |
an LDR (light dependent resistor). read the temperature | |
and humidity from an HT22 sensor, and turn an LED on | |
or off. | |
Upon connection to the remote PC, a 16x2 LCD | |
will display the IP address used for the network connection. | |
A remote telnet command will display secected data via | |
Telnet, the serial monitor and the 16x2 display at the same time. | |
The W5100 Ethernet Shield communicates via SPI. | |
The 16x2 LCD Display communicates via I2C. | |
A 1k ohm resistor is used to limit the current through the LED, | |
and another 1k ohm resistor is used as a voltage divider | |
with the LDR to provide a good range of voltages between | |
the LDR and the 1k ohm resistor. | |
***************************************************/ | |
/************************************************** | |
BIG TIP! THIS PROGRAM USES A LOT OF Serial.print("some string") lines. | |
EACH "some string" IS STORED IN PRECIOUS VOLATILE SDRAM AND NOT | |
IN THE NON-VOLATILE PROGRAM MEMORY ON THE UNO. THE UNO HAS ONLY | |
2K OF SDRAM AND 32K OF PROGRAM MEMORY. THERE IS AN EASY BUT SOMEWHAT | |
OBSCURE WAY TO TELL THE ARDUINO COMPILER NOT TO PUT "some string" | |
INTO SDRAM BUT TO PUT IT IN PROGRAM MEMORY. IT IS CALLED "F() MACRO" | |
AND YOU WILL WANT TO USE IT OR YOUR PROGRAM WILL NOT RUN! | |
F() Macro is easy to use, just change each string (mostly in the | |
Serial.print() functions as follows: | |
Change: Serial.print("some string") | |
To: Serial.print(F("some string")) | |
This program stopped working (at midnight of course)after I had added | |
so many strings in the Serial.print() lines that I was using 82% | |
of the 2k SDRAM. The compiler gave me a "low SDRAM warning" | |
otherwise this problem would have been, at least for me, unsolvable. | |
After adding F() around all of the Serial.print() strings the | |
SDRAM usage dropped to 42% and the program ran fine. | |
More information about "F() Macro" is here: | |
http://playground.arduino.cc/Learning/Memory | |
https://www.baldengineer.com/arduino-f-macro.html | |
***************************************************/ | |
/************************************************** | |
Description of W5100 Ethernet Shield | |
The Wiznet 5100 based ethernet shield includes a micro | |
SD card for data storage. The W5100 controller has a | |
hardwired RJ-45 Ethernet controller and supports the following | |
communication protocols TCP, UDP, ICMP, IPv4, ARP, IGMP, | |
PPPoE, and the physcial Ethernet layer. It can use DHCP | |
to dynamically pull an IP address from your router. | |
The Arduino communicates with both the W5100 and SD card using the | |
SPI bus (through the ICSP header). This is on digital | |
pins 10, 11, 12, and 13 on the Uno. Pin 10 is used to for the SPI | |
"SS" (slave select) to select the W5100 on the SPI bus | |
and pin 4 is SS for the for the micro SD card so these pins cannot | |
be used for general I/O when using the ethernet shield. | |
The Wiznet W5100 needs more power than the Arduino can supply. | |
The Arduino and shield are powered via USB and 9VDC. A | |
separate breadboad 5vdc is used to power the display and DH22 | |
sensor to limit the electrical load on the Arduino. | |
The shield also has numerous status LEDs and a reset button. | |
***************************************************/ | |
/************************************************** | |
Telnet | |
Telnet is a protocol that allows you to connect to remote computers | |
(called hosts) over a TCP/IP network (such as the Internet). | |
Using telnet client software on your computer, you can make a | |
connection to a telnet server (i.e., the remote host). Once your | |
telnet client establishes a connection to the remote host, | |
your client becomes a virtual terminal, allowing you to communicate | |
with the remote host. A login may be required but is not in this case. | |
A Telnet client (or even server) is built in to most operatiing systems. | |
The latest versions of Windows have it deactivated by default. Below is a | |
link to a good reference for activating it: | |
http://www.sysprobs.com/install-and-enable-telnet-in-windows-8-use-as-telnet-client | |
Putty is a free SSH and Telnet Client I recommend. Download it here: | |
http://www.chiark.greenend.org.uk/~sgtatham/putty/ | |
***************************************************/ | |
/************************************************** | |
Ethernet Library | |
The build-in Ethernet Library allows an Arduino board to connect | |
to the internet. It can serve as either a server accepting | |
incoming connections or a client making outgoing ones. | |
The library supports up to four concurrent connection | |
(incoming or outgoing or a combination). | |
***************************************************/ | |
#include <SPI.h> //the ethernet shild uses SPI to communicate | |
#include <Ethernet.h> //the ethernet library | |
EthernetServer server(23); //start new server object, Telnet port is 23 | |
/************************************************** | |
16x2 LCD Display Libraries | |
Since the display uses I2C, the display's unique I2C address must be used. | |
For information on how to determine (via a sketch) any devices' I2C address: | |
http://todbot.com/blog/2009/11/29/i2cscanner-pde-arduino-as-i2c-bus-scanner/ | |
The NewLiquidCrystal.h Library needed for the 16x2 display using I2C is on | |
BitBucket at: | |
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads | |
To use the I2C sublibraries, replace "include LiquidCrystal.h", with | |
"include LiquidCrystal_I2C.h" and "include LCD.h". Also call | |
"include Wire.h" for I2C functions. | |
Common display I2C addresses: Probably 0x27 or 0x3F Use an I2C scanning program | |
to find the device's address and be sure. | |
Constructor with backlight control: | |
(lcd_Addr, Enable, ReadWrite, ReSet, d4, d5, d6, d7, backlightPin, backlighPolarity) | |
The 8 pins from PCF8574T serial board connect to the LCD display as follows: | |
LCD======>>>pcf8574T CHIP (use these pins in the constructor definitions) | |
RS(pin4) pin 0 | |
RW(pin5) pin 1 | |
EN(pin6) pin 2 | |
V0-BL(pin3) pin 3 | |
D4(pin11) pin 4 | |
D5(pin12) pin 5 | |
D6(pin13) pin 6 | |
D7(pin14) pin 7 | |
************************************************ */ | |
#include <Wire.h> //native I2C library | |
#include <LCD.h> //sub library of LiquidCrystal library | |
#include <LiquidCrystal_I2C.h> //sub library of LiquidCrystal library | |
#define I2C_ADDR 0x3F //16x2 I2C address, found using I2C Scanner sketch | |
#define BackLt_pin 3 | |
#define En_pin 2 | |
#define Rw_pin 1 | |
#define Rs_pin 0 | |
#define D4_pin 4 | |
#define D5_pin 5 | |
#define D6_pin 6 | |
#define D7_pin 7 | |
//start a new lcd class | |
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin,BackLt_pin,POSITIVE); | |
/************************************************** | |
DHT Temperature-Humidity Sensor Library | |
Uses library DHT.h, must define DHT sensor type, DHT11, DHT21, DHT22. | |
Call the library using DHT dht(pin_used,dht_sensor_type). | |
The DHT sensor needs a 6.6k ohm pullup resistor, connect it between the | |
5v power and the signal line. The Arduino has internal pull-ups | |
which could be used, but their exact value in unknown and is low in any case. | |
So use a known 6.6k ohm external pull up resistor instead. A 100nF | |
capacitor may be added between Vcc and Ground for "wave filtering". (not used) | |
Using high quality shielded wire the signal wire may be up to 20 m (~65 ft)! | |
Only one digital pin is needed to connect the capacitive type DHT22 to the | |
Arduino. A burst of digital pulses whose width determines 1 or 0 is converted | |
by the software library into a temperature reading. The digital pulse encodes | |
a 40 bit signal in one burst. Sort of like high speed Morse code :-). Cool. | |
A bare DHT sensor has 4 pins. Looking at the latticed front of the sensor | |
(the mounting hole is through the back), the 4 pins from left to right are: | |
1 = 3.3 to 6vdc (use 5vdc) | |
2 = output digital signal (to Arduino digital pin) | |
3 = not used | |
4 = Ground | |
***************************************************/ | |
#include "DHT.h" //dht library | |
#define DHTPIN 7 //digital pin DHT sensor uses | |
#define DHTTYPE DHT11 //dht model (type) of sensor | |
DHT dht(DHTPIN, DHTTYPE); //start a new dht class | |
/**************************************************/ | |
/************************************************** | |
SD Library | |
The SD library allows for reading from and writing to SD cards. | |
The library supports FAT16 and FAT32 file systems on standard | |
SD cards and SDHC cards. It uses short 8.3 names for files. | |
The file names passed to the SD library functions can include | |
paths separated by forward-slashes, /, e.g. "directory/filename.txt". | |
Because the working directory is always the root of the SD card, | |
a name refers to the same file whether or not it includes a leading | |
slash (e.g. "/file.txt" is equivalent to "file.txt"). | |
***************************************************/ | |
// #include <SD.h> //SD is not used in this sketch | |
/************************************************** | |
Summary of Arduino Uno Analog Pins Used: | |
A0 = LDR (light dependent resistor) signal | |
A1 = | |
A2 = | |
A3 = | |
A4 = I2C SDA (serial data) for 16x2 Display | |
A5 = I2C SCL (serial clock) for 16x2 Display | |
***************************************************/ | |
/************************************************** | |
Summary of Arduino Uno Digital Pins Used: | |
00 = | |
01 = | |
02 = Optional Interrupt for W5100 (set with jumper)-not used | |
03 = LED 5vdc supply (on or off) | |
04 = SPI SS (slave select) for SD card - hardwired in ethernet shield | |
05 = | |
06 = | |
07 = DHT11 Temperature-Humidity Sensor | |
08 = | |
09 = | |
10 = SPI SS (slave select) for W5100 - hardwired in ethernet shield | |
11 = SPI MOSI (master out slave in) for ethernet and SD card | |
12 = SPI MISO (master in slave out) for ethernet and SD card | |
13 = SPI SCK (serial clock) | |
***************************************************/ | |
// Store a MAC address and IP address for the Ethernet Shield. | |
// The MAC address is, in this case, made up. | |
// The IP address is on the local network and is normally issued by the router via DHCP. | |
// The gateway and subnet are optional. | |
// The subnet used, 255.255.255.0, is for a Class C subnet which is the "small" | |
// class used for most residential networks, IP's = 192.0.0.0 to 223.0.0.0 | |
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; | |
IPAddress ip(192,168,1,110); | |
IPAddress myDNS(192,168,1, 1); | |
IPAddress gateway(192,168,1, 1); | |
IPAddress subnet(255, 255, 255, 0); | |
// Initialize Variables | |
boolean alreadyConnected = false; //client connected previously flag | |
String commandString; //variable to hold the user typed Telnet command | |
#define orangeLED 3 // assign digital pin to an LED, #define only uses 1 byte | |
void setup() | |
{//****start setup function**** | |
//Call "Begin" Functions At The Beginning of Setup | |
Serial.begin(9600); // Open serial communications at 9600b baud | |
lcd.begin(16, 2); //start LCD with 16 colums 2 rows | |
dht.begin(); //start dht function for measuring temp/hum. | |
Ethernet.begin(mac, ip, myDNS, gateway, subnet); // start ethernet without using DHCP | |
//setup LEDs | |
pinMode(orangeLED, OUTPUT); //declare LED pins as output. | |
digitalWrite(orangeLED, LOW); //start with orange LED off | |
// start listening for clients | |
//Note: by enclosing Serial.print("strings") in the "F() Macro" | |
//that is, Serial.print(F("strings")) the string is stored in | |
//Flash Ram instead of the scarce SRAM -- who knew? | |
// print to the serial monitor | |
Serial.print(F("Assigned gateway address: ")); | |
Serial.println(gateway); | |
Serial.print(F("Assigned DNS server address: ")); | |
Serial.println(myDNS); | |
Serial.print("Assigned Class C subnet address: "); | |
Serial.println(subnet); | |
Serial.print(F("Assigned IP Address: ")); | |
Serial.println(ip); | |
Serial.print(F("Actual Chat server address from Ethernet.localIP(): ")); | |
Serial.println(Ethernet.localIP()); | |
Serial.print(F("LDR sensor reading: ")); | |
Serial.println(analogRead(A0)); | |
//print to the 16x2 LCD | |
// Switch on the backlight | |
lcd.setBacklightPin(BackLt_pin,POSITIVE); | |
lcd.setBacklight(HIGH); //turns backlight on, use LOW for off | |
lcd.clear(); | |
lcd.home(); // go home | |
lcd.print("IP Address"); | |
lcd.setCursor (0,1); // go to start of 2nd line | |
lcd.print(Ethernet.localIP()); | |
delay(3000); | |
}//****endof setup function**** | |
void loop() | |
{//****start infinite loop**** | |
/*********************************************************/ | |
// Ethernet Connection | |
/*********************************************************/ | |
// wait for a new client: | |
EthernetClient client = server.available(); | |
// when the client sends the first byte, say hello: | |
if (client) | |
{ | |
if (!alreadyConnected) | |
{ | |
// clear out the input buffer: | |
client.flush(); | |
commandString = ""; //clear the commandString variable | |
server.println("--> Please type your command and hit Return..."); | |
alreadyConnected = true; | |
} | |
while (client.available()) | |
{ | |
// read the bytes incoming from the client: | |
char newChar = client.read(); | |
if (newChar == 0x0D) //If a 0x0D is received, a Carriage Return, then evaluate the command | |
{ | |
server.print("Received this command: "); | |
server.println(commandString); | |
processCommand(commandString); | |
} | |
else | |
{ | |
Serial.println(newChar); | |
commandString += newChar; | |
} | |
} | |
} | |
/*********************************************************/ | |
// DHT22 Temperature and Humidy Data | |
/*********************************************************/ | |
// Wait between measurements. | |
delay(1000); | |
// Reading temperature or humidity takes about 250 milliseconds! | |
// Sensor readings may also be up to 2 seconds 'old' (sensor is slow) | |
float h = dht.readHumidity(); | |
// Read temperature as Celsius (the default) | |
float t = dht.readTemperature(); | |
// Read temperature as Fahrenheit (isFahrenheit = true) | |
float f = dht.readTemperature(true); | |
// Check if any reads failed and exit early (to try again). | |
if (isnan(h) || isnan(t) || isnan(f)) { | |
Serial.println(F("Failed to read from DHT sensor!")); | |
return; | |
} | |
/*********************************************************/ | |
// LDR - Light Dependent Resistor DatA | |
/*********************************************************/ | |
float ldr = analogRead(A0); //1023 = sun, 0 dark | |
//print data to the serial monitor | |
Serial.print(F("Humidity: ")); | |
Serial.print(h); | |
Serial.print(F(" %\t")); | |
Serial.print(F("Temperature: ")); | |
Serial.print(t); | |
Serial.print(F(" *C ")); | |
Serial.print(f); | |
Serial.println(F(" *F\t")); | |
Serial.print(F("LDR 1023 = sun, 0 = Dark: ")); | |
Serial.println(ldr); | |
//print data to the 16x2 LCD | |
// Switch on the backlight | |
lcd.setBacklightPin(BackLt_pin,POSITIVE); | |
lcd.setBacklight(HIGH); //turns backlight on, use LOW for off | |
lcd.clear(); | |
lcd.home(); // go home | |
lcd.print(F("Temp-Deg. F")); | |
lcd.setCursor (0,1); // go to start of 2nd line | |
lcd.print(f,1); | |
delay(2000); | |
lcd.clear(); | |
lcd.home(); // go home | |
lcd.print(F("Rel. Humidity-%")); | |
lcd.setCursor (0,1); // go to start of 2nd line | |
lcd.print(h,1); | |
delay(2000); | |
lcd.clear(); | |
lcd.home(); // go home | |
lcd.print(F("LDR-1023max sun")); | |
lcd.setCursor (0,1); // go to start of 2nd line | |
lcd.print(ldr); | |
delay(2000); | |
}//****endof infinite loop**** | |
/******************************************************************** | |
// start of subroutines i.e. supporting functions | |
*******************************************************************/ | |
//option: use Telnet command to display serial data on LCD, e.g. LDR, DHT22 | |
//ref.: https://www.arduino.cc/en/Tutorial/LiquidCrystalSerialDisplay | |
void processCommand(String command) | |
{//****start processCommand function**** | |
server.print(F("Processing command ")); | |
server.println(command); | |
if (command.indexOf("ldr") > -1){ | |
Serial.println(F("Photo command received")); | |
server.print(F("Reading from photoresistor: " )); | |
server.println(analogRead(A0)); //Print the integer returned by analogRead to the server object | |
commandString = ""; | |
return; | |
} | |
if (command.indexOf("ledon") > -1){ | |
server.println(F("LED On command received")); | |
digitalWrite(orangeLED, HIGH); // sets the LED on | |
server.println(F("LED was turned on")); | |
commandString = ""; | |
return; | |
} | |
if (command.indexOf("ledoff") > -1){ | |
Serial.println(F("LED Off command received")); | |
digitalWrite(orangeLED, LOW); // sets the LED off | |
server.println(F("LED was turned off")); | |
commandString = ""; | |
return; | |
} | |
if (command.indexOf("tempc") > -1){ | |
Serial.println(F("tempc command received")); | |
server.print(F("Temperature - Deg. C: " )); | |
server.println(dht.readTemperature()); //Print the temp. | |
commandString = ""; | |
//print data to the 16x2 LCD | |
// Switch on the backlight | |
lcd.setBacklightPin(BackLt_pin,POSITIVE); | |
lcd.setBacklight(HIGH); //turns backlight on, use LOW for off | |
lcd.clear(); | |
lcd.home(); // go home | |
lcd.print(F("Temp-Deg. C")); | |
lcd.setCursor (0,1); // go to start of 2nd line | |
lcd.print(dht.readTemperature(),1); | |
delay(10000); | |
return; | |
} | |
if (command.indexOf("tempf") > -1){ | |
Serial.println(F("tempc command received")); | |
server.print(F("Temperature - Deg. F: " )); | |
server.println(1.8*dht.readTemperature()+32); //Print the temp. | |
commandString = ""; | |
//print data to the 16x2 LCD | |
// Switch on the backlight | |
lcd.setBacklightPin(BackLt_pin,POSITIVE); | |
lcd.setBacklight(HIGH); //turns backlight on, use LOW for off | |
lcd.clear(); | |
lcd.home(); // go home | |
lcd.print(F("Temp-Deg. F")); | |
lcd.setCursor (0,1); // go to start of 2nd line | |
lcd.print(1.8*dht.readTemperature()+32,1); | |
delay(10000); | |
return; | |
} | |
if (command.indexOf("rh") > -1){ | |
Serial.println(F("rh command received")); | |
server.print(F("Rel. Humidity - %: " )); | |
server.println(dht.readHumidity()); //Print the rel. humidity. | |
commandString = ""; | |
//print data to the 16x2 LCD | |
// Switch on the backlight | |
lcd.setBacklightPin(BackLt_pin,POSITIVE); | |
lcd.setBacklight(HIGH); //turns backlight on, use LOW for off | |
lcd.clear(); | |
lcd.home(); // go home | |
lcd.print(F("Rel. Humidity-%")); | |
lcd.setCursor (0,1); // go to start of 2nd line | |
lcd.print(dht.readHumidity(),1); | |
delay(10000); | |
return; | |
} | |
commandString = ""; | |
instructions(); | |
}//****endof processCommand function**** | |
/********************************************************************/ | |
void instructions() | |
{//****start instructions function**** | |
server.println(F("I don't understand")); | |
server.println(F("Please use one of these commands:")); | |
server.println(F("* ldr, to get a reading from the light dependent resistor")); | |
server.println(F("* ledon, to turn on the LED")); | |
server.println(F("* ledoff, to turn off the LED")); | |
server.println(F("* tempc, to read temperature, deg. C")); | |
server.println(F("* tempf, to read temperature, deg. F")); | |
server.println(F("* rh, to read rel. humidity, %")); | |
}//****endof instructions function**** | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment