====== Laboratory on ESP 8266 ======
While ESP 8266 (Espressiff) is, in general, a network processor with broad applications in IoT, here we focus on using it as an embedded-class microcontroller.\\
As you will have remote access to the pre-defined hardware, focus on the node's configuration as they vary between nodes.
All you need is a web browser and broadband Internet connection.
===== Laboratory hardware in details =====
You can book for use nodes 1 through 4 and 8 through 11 at the moment.
Every node contains sensors and actuators. Every node has a 4x20 (4 lines, 20 characters) LCD display, which you can observe via web camera, and also at least a DHT (temperature + humidity) sensor.
The 4x20 LCD display is connected via I2C bus to the ESP microcontroller and its address varies, depending on the node, see the documentation below.
==== Actuators ====
Here we focus on the 4x20 LCD screen solely.
This type of LCD can display 4 rows, 20 characters each, and is controlled via the I2C interface. \\
The I2C bus is connected to D1/GPIO5 and D2/GPIO4 pins of the ESP microcontroller (D1 is SCL and D2 is SDA). All nodes share the same connection configuration.\\
__There is a difference in the addressing__, however:
* Nodes 1 through 4, 8 and 9 use 0x3F;
* Nodes 10 and 11 use 0x27;
You need to provide appropriate initialisation in the software library that controls the LCD regarding the note you've booked.
==== Sensors ====
In the following scenarios, you will use a DHT, integrated temperature-humidity sensor. \\
{{:en:edu:zmitac:macro:embedeed:lab:weather_dhtsensors.jpg?300|}}
DHT 11 (left) and DHT 22 (right) temperature and humidity sensors
All of our laboratory nodes use DHT11 sensors(blue one on the Figure {{ref>dhtsensors}}). \\ In general, DHT11 and DHT22 sensors differ with accuracy.
Regarding DHTs, all nodes share the same configuration on the connection level: your DHT is always connected to the D4/GPIO2 pin of the ESP microcontroller.
Warning: sending continuous requests, without a delay, to the DHT sensors is a really bad idea as you will frequently get NaN (not a number) results or zero values. Consider introducing some at least 5s delay between consecutive reads.
===== Connecting to the nodes =====
You need to create an account (Figure {{ref>registeraccount}}), please see an instructional video on how to connect and create an account.
Please follow instructions and remember to fix your theme for Revolution! Your environment should look like in Figure {{ref>vrellab}}.\\
__**Do not book a device for more than 30 minutes in a row (Figure {{ref>vrelbooking}}): respect other students!**__ \\
You can continue working with devices out of regular working hours, see the supervisor's guidance on lab availability.
The URL for accessing the VREL lab is: [[http://distance.roboticlab.eu]].
{{:en:edu:zmitac:macro:embedeed:lab:screenshot_from_2020-10-25_10-04-50.png?400|}}
===== Programming =====
You program it the same way, as popular Arduino.
The general program structure is composed of two functions:
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
Setup is executed once after you upload your code (eventually when you press "Reset" in the interface), while ''loop()'' is executed indefinitely, once ''setup()'' has finished.
==== platformio.ini ====
One more step is necessary to finish the configuration of your environment:
you need to tell the compiler, what is your target platform and which libraries will you use. To do so, there is a file named ''platformio.ini'' that you need to edit (see top tab bar with files, there is platformio.ini to the left). Simply paste the following contents:
[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
lib_ldf_mode = deep+
lib_deps = Wire, 1574, PubSubClient, DHT sensor library@1.3.5, 31@1.0.3, 528@1.0.4, Adafruit Unified Sensor
Obviously, this contains all hardware and software libraries, even more than is necessary to use in case of the following two scenarios, but you will have it ready for future experimentation.
Remember to remove other content than presented above. Wrong development environment configuration can cause the inability to compile and run your code!Note, sometime when you copy-paste content from this PDF file, there may be some extra characters included (i.e. text formatting), that are not visible on the screen, but they do exist and they may cause errors during compilation. To avoid, use copying through a proxy, dummy text editor, i.e. Notepad or Notepad++. First copy from PDF to Notepad then from Notepad to the web browser.
**Remember to save the file!**
==== Software libraries ====
In general, you need to use two software libraries: for DHT and LCD.\\
The LCD library is [[https://github.com/tonykambo/LiquidCrystal_I2C|LiquidCrystal_I2C]] one while using DHT requires two libraries from Adafruit: Adafruit_Sensor and DHT.
And obviously, if you use some preconfigured values (i.e. as when you refer to the D1 and D0 when initialising the I2C communication library), you need to include the ''Arduino'' library that contains declarations of the constants and some useful functions, i.e. ''delay(xxx)''.
#include
//Hardware specific libraries
#include
#include
#include
===== Scenarios to implement during labs =====
There are two scenarios to be implemented within the scope of this laboratory work:
* Basic operations on the LCD;
* Presenting temperature and humidity on the screen;
==== Scenario 1: Basic operations on the 4x20 LCD screen ====
Whatever you do, you expect to have some output of the system. Sometimes there is a blinking LED, sometimes information about connected/disconnected network and some other time simply trace algorithm progress. In laboratories where you have physically connected MCU to your programming device (i.e. computer), you usually would choose the ''Serial'' port to report what is going on. However here all you have is access via the video stream. Perhaps those are reasons you will use this LCD display in your every lab work.
Note, the video stream from the camera is limited in bandwidth and presents some 5-10fps maximum (usually around 1 fps) so you shouldn't change display content nor LED state faster than once every 2 seconds, to let you notice any change!
=== Prerequisites ===
There are no other prerequisites than the LCD I2C library. Mind, LCD is controlled via the I2C bus. LCD Display is 4×20 characters. LCD is controlled via an I2C extender:
PCF8574.
There are two types of I2C extenders differing their I2C address:
* Nodes 1 through 4, 8 and 9 use 0x3F address
* Nodes 10 and 11 use 0x27 address
=== Scenario ===
Initialize the LCD screen, clear it, then write some fancy text on it, i.e. "Hello SMIW!" in the first line. Then your first name in the second line and the name of the city you're in, in the third. Note, out of the box, the LCD screen does not contain polish special characters like //śćżółńź//, so do not include them unless you re-define character definitions (advanced). In the fourth line, print the right-aligned number of ''loop'' iterations (delay it for 1 second between updates - to observe video stream lag and delays). Note, delays are provided in ms, not in s.
=== Result ===
You should see the texts and ticking counter in the video stream.
=== Start ===
There are no special steps to be performed.
=== Steps ===
== Step 1 ==
Include LCD driver library (and obviously you need an Arduino library as well):
#include
#include
== Step 2 ==
Instantiate software controller component for the LCD display:
LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for nodes 1 through 5, 8 and 9
//LiquidCrystal_I2C lcd(0x27,20,4); // for nodes 10 and 11 only!
// for a 20 chars and 4 line display
== Step 3 ==
Declare some variables: counter ''i'', its length ''n'' and ''buffer'' for the into to string conversion:
int i = 0;
char buffer [50];
int n;
We will use them in the further part of the code.
== Step 3 ==
Initialize display - we suggest to do it in ''setup()'' function:
...
lcd.init(D2,D1); // initialize the lcd I2C
lcd.backlight(); // switch on the backlight
...
== Step 4 ==
Clear the contents, set cursor and draw static text - still in ''setup()'' function:
...
lcd.home();
lcd.print("Hello World!");
...
The ''setCursor(x,y);'' function will help you to a position in the place you want the text to be rendered:
...
lcd.setCursor(0, 1);
...
Indexing is zero-based and the upper left corner is (0,0).
== Step 5 ==
Implement ''loop()'' to draw number of loop executions:
...
i++;
n=sprintf(buffer,"%d",i);
lcd.setCursor(20-n,3);
lcd.print(i);
delay(1000);
...
''sprintf'' uses number of wildcards that are rendered with data. Refer to the c/c++ documentation on ''sprintf''. Here ''%d'' means: having integer number render it to string and as we do not specify number of digits, it is up to the engine to convert it properly. ''delay(time)'' is measured in milliseconds.
=== Result validation ===
Observe text, its position and counter ticking in the lower, right corner.
==== Scenario 2: Presenting temperature and humidity on the LCD ====
In this scenario, you will present temperature and humidity as read by the attached DHT11 sensor, on the LCD screen.
=== Prerequisites ===
You need to know, how to print and position text on the LCD display.
Use LCD I2C library to control it (and obviously you need an Arduino library as well):
#include
#include
The temperature and humidity sensor is all-in-one, DHT11 (blue), connected to the pin D4. Observe your camera to check which sensor is equipped with your lab and consult node documentation.\\
To read data you may use a dedicated library (libraries):
#include
#include
=== Scenario ===
Once you initialise sensor and LCD display, read sensor data (temperature and humidity, mind they're float values, not integers) and then display them in the loop. Give each loop execution some 5-10s delay.
Do not try to read temperature and humidity too frequent. Once every 5s is quite enough both for information and safe enough to not let your readings race with the communication protocol. If you read too frequent, your sensor may not be able to deliver data on time and you will obtain a 'nan' (not a number) instead of temperature and humidity.
The first line of the LCD should display: "//Temperature is://"\\
The second line should provide temperature within the "//NN.N C//" form, in Celcius.\\
The third line should display: "//Humidity is://"\\
Finally, the fourth should present relative humidity: "//NN.N%Rh//"\\
You will use ''sprintf'' function to format string and convert from float to string.
=== Result ===
You should be able to see temperature and humidity readings on the LCD display using the video stream.
=== Start ===
There are no special steps to be performed.
=== Steps ===
== Step 1 ==
Include LCD and DHT sensor driver libraries (and obviously you need an Arduino library as well):
#include
#include
#include
#include
== Step 2 ==
Instantiate software controller components for the LCD display and DHT sensor:
LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for nodes 1 through 5, 8 and 9
//LiquidCrystal_I2C lcd(0x27,20,4); // for nodes 10 and 11 only!
// for a 20 chars and 4 line display
DHT dht(DHTpin,DHT11,50);
== Step 3 ==
Declare a buffer for ''sprintf'' function:
char buffer [10];
== Step 4 ==
Initialize LCD and DHT sensor:
...
lcd.init(D2,D1); // initialize the lcd
lcd.backlight();
lcd.home();
...
dht.begin();
delay(1000); // give it a second to let the sensor initialize
...
== Step 5 ==
Read in the loop:
...
float hum = dht.readHumidity();
float temp = dht.readTemperature();
...
To convert float into the string with formatting use ''sprintf'' function:
...
sprintf(buffer,"%2.1f C",temp);
...
sprintf(buffer,"%2.1f%%Rh",hum);
...
delay(5000);
...
''sprintf'' uses number of wildcards that are rendered with data. Refer to the c/c++ documentation on ''sprintf''. Here %2.1f means: having float number render it to string using two digits before decimal point and one after. Temperature in our lab is always above 10C. %% is an escape character to print a % (percent) symbol. ''delay(time)'' is measured in milliseconds.
=== Result validation ===
Observe temperature and humidity readings on the LCD. The temperature in our lab usually ranges between 20-30C (not, we observed over 30C during really hot summer!) while humidity is usually between 35-60%Rh.
===== FAQ =====
**Q: Help, my LCD seems to be frozen!**\\
A1: Check the I2C address is correct, regarding the laboratory node you're using. Consult details in the hardware section, as above.\\
A2: Still not working? And you're sure the I2C address is correct so ... It is rare, but may happen that the I2C bus becomes in an inconsistent state. In such case run the following program (in the separate source file, eventually merge with your code):
#include
#include
LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
pinMode(4,OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(4,LOW);
digitalWrite(5,LOW);
delay(2000);
pinMode(5, INPUT); // reset pin
pinMode(4, INPUT);
delay(50);
delay(2000);
lcd.init(D2,D1);
lcd.backlight();
lcd.home();
lcd.print("Hello world...");
}
void loop()
{
}