Latest Entries »

In this post we’ll see how to control an LED connected to NODEMCU from a WebBrowser.

The WebBrowser is a CLIENT & the NodeMCU is the SERVER .

The Nodemcu has to be installed with Boards Manager Arduino core. Refer to the previous post on how to do this.

 

Image 1

 

Connect the long pin of LED to D2 pin of NodeMCU , short pin to GND through a 470E resistor.

Connect the NodeMCU to USB port of PC & note the COM port allotted.Feed in this COM port number in IDE & select the board as NodeMcu v1.0 (ESP12E).

Upload the following code.

 

You can Download the code used in this post HERE

————————————-

 

#include <ESP8266WiFi.h>
#define LED D2
const char* ssid = “SARAVANA-ACT”;
const char* password = “str5412stk4141”;
unsigned char status_led=0;

WiFiServer server(80);

void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
Serial.println();
Serial.println();
Serial.print(“Connecting to “);
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED )
{
delay(500);
Serial.print(“.”);
}
Serial.println(“”);
Serial.println(“WiFi connected”);
server.begin();
Serial.println(“Server started”);
Serial.println(WiFi.localIP());
}

void loop() {
WiFiClient client = server.available();
if (!client) {
return;
}

Serial.println(“new client”);
while(!client.available())
{
delay(1);
}
String req = client.readStringUntil(‘\r’);
Serial.println(req);
client.flush();
if (req.indexOf(“/ledoff”) != -1)
{
status_led=0;
digitalWrite(LED,LOW);
Serial.println(“LED OFF”);
}
else if(req.indexOf(“/ledon”) != -1)
{
status_led=1;
digitalWrite(LED,HIGH);
Serial.println(“LED ON”);
}
String web = “HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n”;
web += “<html>\r\n”;
web += “<body>\r\n”;
web += “<h1>LED Status</h1>\r\n”;
web += “<p>\r\n”;
if(status_led==1)
web += “LED On\r\n”;
else
web += “LED Off\r\n”;
web += “</p>\r\n”;
web += “</p>\r\n”;
web += “<a href=\”/ledon\”>\r\n”;
web += “<button>LED On</button >\r\n”;
web += “</a>\r\n”;
web += “</p>\r\n”;

web += “<a href=\”/ledoff\”>\r\n”;
web += “<button>LED Off</button >\r\n”;
web += “</a>\r\n”;

web += “</body>\r\n”;
web += “</html>\r\n”;

client.print(web);
}

——————————————-

First of all, we include the ESP8266WiFi library, which will make available the functionality needed for the ESP8266 to connect to a WiFi network.Then we define the D2 pin as LED where an Led is connected.

#include <ESP8266WiFi.h>
#define LED D2

The SSID name & password are stored in char variables.

A WiFiserver object called “server “ is created & we pass the port 80 where the server will be listening ( 80 is the default port of HTTP)

WiFiServer server(80);

In the setup() function serial monitor is started at baud 115200 & the LED pin is declared as Output.

The begin() function of WiFi class is used with parameters ssid & password to start connection to WiFIi

WiFi.begin(ssid, password);

We wait till the WiFi.status() becomes WL_CONNECTED which indicates that connection is established .Until then we print a dot every 500msec.

while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(“.”);
}

Once connection is established , an IP address is allotted to NodeMCU by your Router.We print the IP address using the localIP() function.

Serial.println(WiFi.localIP());

Inside the loop we create an object called client of class WiFiClient & assign the server.available() result (it returns true or false) to it.

WiFiClient client = server.available();

It waits for a client ( here a web browser is the client) to connect with.

Once a request is received  , the client.readStringUntil (‘\r”) will read the request till it encounters a  carriage return & assign it to a String variable req

String req = client.readStringUntil(‘\r’);

indexOf() function of String is used to find out ehether the request is ledoff or ledon.

if (req.indexOf(“/ledoff”) != -1)

The indexOf() function returns a –1 if no match found.

Accordingly the LED is made ON or OFF.

Now let us see how a HTML page is served to webbrowser when a client request is received

ode will be stored in strings that will be returned in the HTTP responses

we can declare it in a string and just return it when a HTTP request is performed on the desired URL.

 

String web = “HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n”;
web += “<html>\r\n”;
web += “<body>\r\n”;
web += “<h1>LED Status</h1>\r\n”;

 

First, we  return the 200 HTTP code (OK code). Then, we need to make sure that we specify the return content as text/html, so the browser will know that it should be interpreted and rendered as such

Finally, we pass the string with the HTML/CSS code

The <html> element represents the root of an HTML document. All other elements must be descendants of this element .

The <body> tag specifies where the body of the document starts .

The <h1> tag specifies the Heading of Webpage

The <p> tag specifies a paragraph and thus we use it to indicate our description message.

 

web += “<a href=\”/ledon\”>\r\n”;
web += “<button>LED On</button >\r\n”;

The <a> tag allows us to create a hyperlink by specifying the URL of a page and the message of the hyperlink. So, in the href attribute we specify the URL we want the user to be redirected to, and between the two tags we specify the message of the hyperlink.

In this case, we are specifying a path in the current address, so we don’t need to put the IP and the port. So, when a user clicks the hyperlink, the browser knows it will need to redirect the user to

http://IP Port/[href value]

As we will see later, the paths we are specifying in the href will correspond to the paths where the NodeMcu will be programmed to return the corresponding code.

the <br> tag is just a simple line break between the hyperlinks.

One thing that is very important is that we are specifying the HTML code inside a string, and thus some details need to be taken in consideration.

First, in order to leave the code structured, we should split the declaration of the string in multiple lines. To do so, we need to put the double quotes in each line so the compiler will know that it should be considered as a single string. So, the outermost quotes of the previous code are not from the HTML but from the declaration of a string in multiple lines.

Finally, every quote that is part of the HTML code (for example, the quotes around the URLs in the <a> tag) needs to be escaped with the \ character. So, the \ characters we see before the quotes are also not part of the HTML code but rather the escaping mechanism.

The <button> tag allows for the definition of a clickable button. One of its functionalities allows us to specify a function that is executed when the button is clicked

 

web += “<button>LED Off</button >\r\n”;

Now upload the code & open the serial monitor

Image 5_1

WiFi connection starts & displays IP if connection established.

Open your web browser & type in the IP you got from the serial monitor.

Once you click the Enter button , a CLIENT request is sent to NodeMCU.

Now the HTML page is served & buttons LED ON & LED OFF are displayed on the browser.

Image 6_1

If you click LED ON button , the message string “ledon” is added to URL & sent to Nodemcu.

The string is read and accordingly the LED will be ON or OFF.

Image 7_1

 

Here is another version of code where we use client.print() to serve the Webpage

 

———————————-

 

#include <ESP8266WiFi.h>
#define LED D2  // LED at GPIO4 D2

const char* ssid = “SARAVANA-ACT”;
const char* password = “str5412stk4141”;
unsigned char status_led=0;

WiFiServer server(80);

void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);

// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print(“Connecting to “);
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
}
Serial.println(“”);
Serial.println(“WiFi connected”);

// Start the server
server.begin();
Serial.println(“Server started at…”);
Serial.println(WiFi.localIP());

}

void loop() {

// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}

// Wait until the client sends some data
Serial.println(“new client”);
while (! client.available())
{
delay (1);
}

// Read the first line of the request
String req = client.readStringUntil(‘\r’);
Serial.println(req);
client.flush();

// Match the request

if (req.indexOf(“/ledoff”) != -1)  {
status_led=0;
digitalWrite(LED, LOW);
Serial.println(“LED OFF”);
}
else if(req.indexOf(“/ledon”) != -1)
{
status_led=1;
digitalWrite(LED,HIGH);
Serial.println(“LED ON”);
}

// Return the response
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-Type: text/html”);
client.println(“Connection: close”);
client.println(“”);

client.println(“<!DOCTYPE HTML>”);
client.println(“<HTML>”);
client.println(“<H1> LED CONTROL </H1>”);
client.println(“<br />”);

client.println(“<a href=\”/ledon\”\”> <button style=’FONT-SIZE: 50px; HEIGHT: 200px;WIDTH: 300px; 126px; Z-INDEX: 0; TOP: 200px;’> LED ON </button> </a>”);
client.println(“<a href=\”/ledoff\”\”> <button style=’FONT-SIZE: 50px; HEIGHT: 200px; WIDTH: 300px; 126px; Z-INDEX: 0; TOP: 200px;’> LED OFF </button> </a>”);
client.println(“</html>”);

delay(1);
Serial.println(“Client disconnected”);
Serial.println(“”);

}
———————————–

Inside <button> tag we create a style to make big size buttons.

On clicking the respective buttons the LED is made ON or OFF.

 

Image 9

 

Image 10

 

Image 11

VIDEO DEMO :

cooltext753793315   cooltext753790696

Advertisements

NODEMCU is built on ESP8266 12E Module & is an excellent , economical IOT PLATFORM.

Generally it is shipped from factory with NODEMCU FIRMWARE which can be programmed with LUA Script.

In this post we shall install the ARDUINO CORE for ESP8266 on NODEMCU & start exploring how to use the ARDUINO IDE to code NODEMCU

nodemcu_pins1

 

To use the ARDUINO IDE , first thing is to install the ARDUINO CORE on to NODEMCU.

Open the ARDUINO IDE & under FILE –> PREFERENCES paste the link provided below :

Arduino Boards Manager file link is HERE

 

Image 1

under Tools –> BOARDS –> BOARDS MANAGER

search for ESP8266 & then click on it to install the latest version.

Image 2

 

Connect the NODEMCU to the USB of PC & open the DEVICE MANAGER to note the COM PORT allotted.If you see exclamation mark , then install the CP2102 driver for the NODEMCU.

Under Tools –>

select the board as NODEMCU V1.0 (ESP12E) , Port as the COM port alloted, Programmer as USBASP , UPLOAD SPEED as 115200.

Image 3

 

Under FILE –> EXAMPLES –> ESP8266 select the BLINK sketch

Image 4

 

Here the LED_BUILTIN is mapped to the inbuilt LED on board NODEMCU.

So , just click on the UPLOAD button.

Image 5

 

Once the sketch is compiled , the uploading starts , as seen at the bottom of the IDE.

It takes some time to upload ( i.e the reason to select upload speed 115200 , to make it fast)

as the code upload is like upgrading Firmware.

As the sketch is uploaded , the blue LED on the ESP chip (near WIFI antenna) flickers & finally the RED LED on board blinks.

In the next example let us connect an LED at pin D2 through a resistor.

D2 pin is GPIO4 of NODEMCU , but in the code we use the notation Dx to represent GPIO pin.

To control GPIO4 pin we use D2 in the code & not GPIO4 directly.

Image 7

 

In the blink code , the following line is added

#define LED_BUILTIN D2

Image 8

Upload the code to see the LED connected at DS2 blinking.

In the same way we can use ANALOG WRITE function to give a fade effect on the LED.

 

Now let us explore the NETWORKING capabilities of NODEMCU.

To start with we include the ESP8266WiFi.h header file.

The WIFI library is enhanced version of Arduino & is installed along with the Boards Manager.

This ESP8266WiFi  library has several classes, methods and properties  , which combines many powerful FUNCTIONS .

In the first line of sketch #include <ESP8266WiFi.h> we are including ESP8266WiFi library. This library provides ESP8266 specific Wi-Fi routines we are calling to connect to network.

After the header file  , we store the SSID name & Password as character arrays

#include <ESP8266WiFi.h>
char ssid[]=”SSID_NAME”;
char pass[]=”Password”;

Inside the setup function , Serial communication is started with 9600 baud & the name of SSID is printed.

void setup() {
Serial.begin(9600);
delay(500);
Serial.print(“Connecting to..”);
Serial.println(ssid);
delay(500);

WiFi.disconnect() function is called to disconnect any previous connections

While using the WiFi CLASS , there is no need to create WiFi Object.Simply call the function like

begin(),  SSID(), status(), disconnect(), scanNetworks(), localIP(), etc..

Actual connection to Wi-Fi is initialized by calling the begin() function.We pass on the 2 parameters to WiFi.begin() function to start the connection

  WiFi.disconnect();
WiFi.begin(ssid,pass);

We use a While loop to test the status of WiFi.status(). Here we check whether it returns WL_CONNECTED

IF not connected , a dot is printed every 500 msec.

while(WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.println(“.”);
}

Once connection is established , it jumps out of loop & prints the SSID name connected with.

if connection is established, and then lost for some reason, ESP will automatically reconnect to last used access point once it is again back on-line. This will be done automatically by Wi-Fi library, without any user intervention.

Serial.print(“SSID…”);
Serial.println (WiFi.SSID());
Serial.println(“Successfully connected!!!”);

 

Next the IP address allotted to the NODEMCU by the Router  (by DHCP method) is printed by calling the function WiFi.localIP()

The MAC address is printed using WiFi.macaddress()

 

Serial.print(“IP Address allotted to NodeMcu ESP..”);
Serial.println(WiFi.localIP());

Serial.print(“MAC Address of ESP…”);
Serial.println(WiFi.macAddress());

WiFi.printDiag(Serial) prints all the WiFi credentials like Channel , SSID name , Password , etc..

This specific function  prints out key Wi-Fi diagnostic information:

WiFi.printDiag(Serial);
}

void loop()
{
}

Upload the code & open the Serial monitor at baud 9600 to see the result.

 

Image 10

Next example is to scan the surrounding networks & print the name of SSIDs.

Here we use the function scanNetworks() which returns an Integer value on the number of surrounding SSIDs.

We assign this to an integer variable

int n = WiFi.scanNetworks();

& then in a For loop iterate to print out name of each surrounding SSIDs

 

for (int i=0; i<n; i++)

{

Serial.println(  WiFi.SSID (i) )

}

Image 11

 

Scan for available Wi-Fi networks in one run and return the number of networks that has been discovered.

WiFi.scanNetworks();

There is on Overload of this function that accepts two optional parameters to provide extended functionality of asynchronous scanning as well as looking for hidden networks

WiFi.scanNetworks(async,show_hidden);

Both function parameters are of boolean type. They provide the flowing functionality: * asysnc – if set to true then scanning will start in background and function will exit without waiting for result. To check for result use separate function scanComplete . * show_hidden – set it to true to include The in scan result networks with hidden SSID.

 

Image12

Download code samples HERE

Download ESP8266 Library document PDF HERE

VIDEO TUTORIALS :

 

 

cooltext753793315   cooltext753790696

 

VIDEO TUTORIAL ON TIMER1

 

 

ATMEGA 16/32 has 3 TIMERS —TIMER0 8 bit , TIMER 1 (16 Bit) , Timer 2 (8 bit).

In the previous post we tested with TIMER0 .

This post is related to TIMER 1 , particularly the INTERRUPT functions.

As we know Timers work by incrementing a counter variable called counter register. The counter register can count to a certain value, depending on its size. The timer increments this counter one step at a time until it reaches its maximum value, at which point the counter overflows, and resets back to zero.

Since Timer1 is 16 bits, it can hold a maximum value of (2^16 – 1), or 65535.

In order to increment the counter value at regular intervals, the timer must have access to a clock source.  The clock source generates a consistent repeating signal.  Every time the timer detects this signal, it increases its counter by one.

If clock source is 8MHz we’ll go through one clock cycle every 1 / 8000000 seconds, or 0.000000125 secs or 0.125 usec . That means Timer1 Counter takes 65535 * 0.000000125 = 0.0082

timer counts will elapse in 0.0082 secs

So , if we need a one second delay ( 1000msec) , 1000/0.0082 = 121951 which obviously higher than 65535 which is the highest count for TIMER1.

Here comes the need of PRESCALER

Clock source can be divided by 8 , 64, 256 , 1024 by setting the bits 0:2 of TCCR1B

After counting 65535 , The timer normally sets a flag (OverFlow Flag) bit to let you know an overflow has occurred.

In case of TIMER1 , COUNTER Register is made of 2 , 8 bit Registers TCCR1A & TCCR1B put together forms a 16 bit Register

You can check this flag manually, or you can also have the timer trigger an interrupt as soon as the flag is set. You can specify an Interrupt Service Routine (ISR) to run code of your choice when the timer overflows. The ISR will reset the overflow flag behind the scenes,

Following table shows the list of REGISTERs associated with TIMER1

clip_image002

clip_image004

TCCR1 is actually composed of two registers TCCR1A & TCCR1B

TCCR1A controls the compare modes & the pulse width modulation modes

TCCR1B controls the prescaler & input multiplexer & input capture modes

TCCR1B COUNTER SELECT bits 0:2 control the input to Timer1 .These 3 select bits provide clock signals that are absolutely identical to those of Timer0

clip_image006

When the timer counts past 65535 (0xFFFF) , it sets the Flag TOV1 (bit 2 of TIFR ) register.The registers TIFR & TIMSK are common for all 3 timers.

When Compare register is used , the OCF1B or OCF1A flag is set according to the channel (A or B) used for Compare operation.

clip_image008

Instead of manually checking the Flags in TIFR , Interrupts can be used to trigger ISR automatically when the particular Interrupt bit is Enabled in TIMSK register.

As seen below bits 2 to 5 are for TIMER1

If TOIE1 bit is enabled , on Timer 1 overflow , the corresponding Interrupt Service Routine ISR is called automatically & the code inside ISR is executed

clip_image010

Following is the list of Vector table.You have to use the correct VECTOR NAME in the ISR Function

clip_image012

From above table you can see RESET is on the top of table & is unmaskable ,having the highest priority

if Timer overflow interrupt TOIE1 is enabled , You need to use the ISR function Vector 9 in table

 

First example code is using OVERFLOW INTERRUPT.

Using this interrupt we blink an LED connected to PD6 – pin 20

We use the external crystal 8MHZ as clock source. ( High FUSE 0XD9 , LOW Fuse 0XFD)

To start with include the 2 Header files at the top of code.

Inside the Main Function PD6 pin is made as OUTPUT , as we’ve connected an LED at pin20.

DDRD |= (1<<6);

The prescaler we’ve selected is 256 .To apply this we need to set the bit CS12 in the TCCR1B register.In Timer1 the control register is of 2 parts TCCR1A & TCCR1B .

clip_image016

Prescaler select bits are found in TCCR1B.

clip_image020

TCCR1B |= (1<<CS12); // prescaler 256 selected , clock is now 8000000/256= 31250Hz

Next load the TCNT1 counter with the calculated value

TCNT1 = 49910;

Calculation is as follows :

Suppose we want to blink the LED at at the rate 2HZ , i.e., 0.5sec ( 500 milli secs) interval

We selected  prescaler 256

The clock frequency becomes 8000000 / 256 = 31250 Hz

Time for each Tick is 1 / 31250 = 0.000032 sec = 32usec

For 500 msec to elapse the count is 500 / 0.032 = 15625

Timer 1 counts from 0 to  65535 & overflows.

65535 – 15625 = 49910

So if you preload the counter with 49910 , the counter starts at 49910 & counts up to 65535 elapsing 15625 count & creating 500 msec delay

You can also use the Timer Calculator from

https://www.easycalculation.com/engineering/electrical/avr-timer-calculator.php

 

Next enable the Timer OverFlow Interrupt TOIE1 in the TIMSK Register

 

TIMSK |= (1<<TOIE1);

timsk

 

Enable the Global Interrupt using the command

sei();

 

Now we’ve to write the code for ISR with correct vector name TIMER1_OVF_vect

Inside the ISR Function we toggle the LED at PD6 & THEN AGAIN LOAD THE TCNT1 Register with the calcuated value.This is important as otherwise the TCNT1 will start counting from 0.

ISR (TIMER1_OVF_vect)

{

PORTD ^= (1<<6); // toggle LED

TCNT1 = 49910; // again load counter with calculated value

}

 

Complete code is here :

——————————

#include <avr/io.h>

#include <avr/interrupt.h>

 

int main (void)

{

DDRD |= (1<<6); // PD6 is Output

TCCR1B |= (1<<CS12); // prescaler 256 selected , clock is now 8000000/256= 31250Hz

TCNT1 = 49910; // load counter with calculated value

TIMSK |= (1<<TOIE1); // enable Timer overflow interrupt

sei();

while (1) {}

ISR (TIMER1_OVF_vect)

{

PORTD ^= (1<<6); // toggle LED

TCNT1 = 49910; // again load counter with calculated value

}

————————————-

Compile the code as we’ve done in previous examples & upload the HEX code to see the LED blinking at 500 msec delay.

You can also use the code creator for AVR from :

ONLINE AVR CODE creator

http://www.dioda.ro/avrwiz/index.html

 

CLEAR TIMER ON COMPARE MATCH CTC MODE

 

In previous above example we loaded the Counter with a calculated value & then waited for the counter to Overflow & used the Overflow interrupt to execute TIMER1_OVF_vect ISR

In compare mode, there is one compare register, where we can set value to compare with the Timer / counter register value. Once the compare value matches with timer / counter register value, compare match occurs. This compare match event can be used for waveform generation.

The Timer counts up until the value of the TCNT1 (Timer / counter register) register becomes equal to the content of OCRx (Compare register). As soon as TCNT1 becomes equal to the OCRx, compare match occurs and then timer will get cleared and OCFx flag will get set.

Hence, this comparison takes place  inside the AVR CPU hardware . Once the counts value becomes equal to the compare value, a flag in the status register is set and the timer is reset automatically.  Hence the name – CTC – Clear Timer on Compare

 

ctc_img1

 

 

Let us explore the code :

 

First we enable the CTC mode by setting the bit WGM12 bit of TCCR1B.

Prescaler selected is 256 by setting CS12 bit in TCCR1B

TCCR1B |= (1 << WGM12) | (1 << CS12);

 

clip_image016

The WGM bits are found in both the registers.But we need to set only the WGM12 bit to enable CTC. This bit is found inside TCCR1B Register. So no need to set the TCCR1A register.

ctc

We then initialize the TCNT1 value to start from 0.

When the TCNT1 value reaches a compare value , an interrupt is enabled.

This compare value is loaded into a  OCR1 x Register.

The Output Compare Register 1A – OCR1A and the Output Compare Register 1B – OCR1B are utilized for this purpose.

Since the compare value will be a 16-bit value (in between 0 and 65535), OCR1A and OCR1B are 16-bit registers. In ATMEGA16/32, there are two CTC channels – A and B. We can use any one of them or both. Let’s use OCR1A.

Let us load the Compare value as

OCR1A = 31250 ;

Calculation is as follows :

Clock is 8 MHz & we use a prescaler of 256

Now the clock to Timer1 is 8000000/256 = 31250 Hz

Time period is reciprocal of freq = 1/31250 = 0.000032 usec or 0.032 milli sec

To generate a delay of 500 ms 500ms/ 0.032 msec = 15625 counts

To generate 1 sec delay ( 1000millisec) 1000/0.032 = 31250

Now enable the OCIE1A Interrupt in TIMSK Register

tim

 

TIMSK |= (1 << OCIE1A);

Whenever a match occurs (TCNT1 becomes equal to OCR1A ), an interrupt is fired (as OCIE1A is set) and the OCF1A flag is set (we do not check this flag manually, as we use interrupt).

Now  we need an Interrupt Service Routine (ISR) to attend to the interrupt.

Executing the ISR clears the OCF1A flag bit automatically and the timer value (TCNT1) is reset.

The ISR is defined as follows with the correct vector name TIMER1_COMPA_vect

ISR (TIMER1_COMPA_vect)

{

PORTD ^= (1 << 6);

}

 

Complete code is as below :

———————————————-

#include <avr/io.h>

#include <avr/interrupt.h>

void timer1_init()

{

TCCR1B |= (1 << WGM12) | (1 << CS12);

TCNT1 = 0;

OCR1A = 31250;

TIMSK |= (1 << OCIE1A);

sei();

}

 

ISR (TIMER1_COMPA_vect)

{

PORTD ^= (1 << 6);

}

int main(void)

{

DDRD |= (1 << 6);

timer1_init();

while(1)  {}

}

———————————-

Compile & upload the HEX file to see the LED blinking at 1 sec interval

 

Hardware CTC Mode

Without Interrupt enable you can toggle or generate waveform on certain predefined OC pins which is called Hardware CTC , Output Compare

PB3, PD4, PD5 and PD7 represent the OUTPUT COMPARE pins

OC0 , OC1A, OC1B , OC2

These are the Output Compare pins of TIMER0, TIMER1 and TIMER2 respectively.

 

clip_image014_thumb2

 

 

Timer/Counter1 Control Register A

The TCCR1A Register bits 4 to 7 decide the Compare output mode of unit  A or B

These bits control the behaviour of the Output Compare (OC) pins. The behaviour changes depending upon the following modes:

· Non-PWM mode (normal / CTC mode)

· Fast PWM mode

· Phase Correct / Phase & Frequency Correct PWM mode

.  CTC Mode

clip_image022

 

clip_image024

 

clip_image018

Simply set the timer1 to the mode 01 as seen in table above.

Whenever a compare match occurs, the OC1A pin is automatically toggled.

Only PD5 or PD4 (OC1A or OC1B) can be controlled this way, which means that we should connect the LED to PD5 (since we are using channel A

 

————————————-

#include <avr/io.h>

#include <avr/interrupt.h>

void timer1_init()

{

TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);

// set up timer OC1A pin in toggle mode

TCCR1A |= (1 << COM1A0);

TCNT1 = 0;

// initialize compare value

OCR1A = 31250;

}

int main(void)

{

DDRD |= (1 << 5);

timer1_init();

while(1) {}

}

——————————————-

 

cooltext753793315    cooltext753790696

VIDEO TUTORIALS ON TIMER0 :

 

Timers/counters are an independent unit inside AVR. They  run independently of what task CPU is performing. In this post we’ll explore the TIMER 0 Interrupts of AVR ATMEGA 16 .The previous post was on External Interrupts , this TIMER 0 is Internal Interrupt.

AVR ATMEGA 16 has 3 timers TIMER0 ,TIMER 1 & TIMER 2.Of these TIMER 1 is 16 bit Timer while others are 8 bit timers.

8-bit timer is capable of counting 2^8=256 steps from 0 to 255

Similarly a 16 bit timer is capable of counting 2^16=65536 steps from 0 to 65535. Due to this feature, timers are also known as counters. When the timer returns to its initial value of zero , We say that the timer/counter overflows.

Timer Events

  1. OVERFLOW

In normal operation overflow occurs when the count value passes 0XFF & becomes 00

Timer 0 is a 8 bit timer. It basically means it can count from 0 to 2^8 255. The operation of timer 0 is straight forward. The TCNT0 register hold the timer Count and it is incremented on every timer “tick”. If the timer is turned on it ticks from 0 to 255 and overflows. If it does so, a Timer OverFlow Flag (TOV) is set.

The Flags are present inside the Register TIFR which is common for all 3 timers.

 

2. COMPARE MATCH

Another interesting feature is that a value can be set in the Output Compare Register (OCR0), and whenever TCNT0 reaches that value, the Output Compare Flag (OCF0) flag is Set.

We say Compare Match has occurred  when the count value equals the contents of the output compare register

In this post we handle these above 2 events using the Interrupt concept.

 

OVERFLOW INTERRUPT

TCNT0 is the register that holds the current value of Timer

You can read from or write to this register to set your own time.

Timer0 works by incrementing this TCNT0a counter variable, also known as a counter register. The counter register can count to a value 0XFF , as Timer 0 is 8 bit .

The timer increments this counter one step at a time until it reaches its maximum value (255), at which point the counter overflows, and resets back to zero. The timer sets a flag (OVF0) bit .

You can check this flag inside TIFR register manually, or you can also have the timer trigger an interrupt (TOIE0) as soon as the flag is set. An  Interrupt Service Routine (ISR) is called automatically to run code of your choice when the timer overflows.

The ISR will reset the overflow flag behind the scenes automatically

 

TIMER0 uses 2 8 bit DATA REGISTERS  TCNT0 , OCR0

If you enable TCNT0 the register will increment from 0 counts upto 255 then overflos & start counting again ,

OCR0 never increments.You need to set a value bet 0 & 255

2 conditions occur OVERFLOW , COMPARE MATCH (TCNT0=OCR0)

The corresponding ISR vector name to be used in the ISR Function

ISR (TIMER0_OVF_vect) {}    for Overflow interrupt

ISR (TIMER0_COMP_vect) {}    for Compare Interrupt

 

Now let us Calculate the period of clock source .We use an external crystal oscillator of 8MHz

Period = 1/ clock freq = 1/8000000 = 0.125 usec

Timer counter overflows 256 * 0.000125ms = 0.032 msec

For 1 sec delay 10000/0.032 = 31250

Timer0 counter has to overflow 31250 times to generate one sec delay.

 

To increase the time delay we can reduce the clock applied to counter applying a prescaler

Prescalers of 1 ,8, 256  or  1024 can be applied by setting the CS0:2 bits of TCCR0 register

TCCR0 is the TIMER COUNTER CONTROL REGISTER for TIMER0

PRESCALER decides the speed of increment of TCNT0

Prescaler = 0 timer off

Prescaler = 1 speed of clock on which uc runs

= 2 clk/8      = 3 clk/64      =4 clk/256 ,       =5 clk/1024

=6 ext clock falling edge count ,   =7 ext clock at p0 pin rising edge count

Let us select prescaler of 1024

 

Programming steps:

1. Initialize TNCNT0 to value 0.

2. Program Prescaler by setting CS bits of TCCR0.

3. Set Timer OverFlow Interrupt TOIE0 bit of TIMSK register.

4. Enable global interrupt by sei () command.

5. Write code for ISR function with vector name TIMER0_OVF_vect

 

 

1. Code using OVERFLOW Interrupt that blinks LED at PD6 at 1 second interval

————————————————-

#include <avr/io.h>

#include <avr/interrupt.h>

 

volatile uint8_t count;

int main (void)

{

DDRD |= (1<<6); //PD6 as output

TCNT0 = 0;

count = 0;

TCCR0 |= (1<<CS02) | (1<<CS00); // PRESCALER 1024

TIMSK = (1<<TOIE0);

sei();

while(1)  {}

}

 

ISR (TIMER0_OVF_vect)

{

if (count == 31)

{

PORTD ^= (1<<6);

count=0;

}

else

count++;

}

—————————————–

To start with we include the 2 Header files & then declare a variable count.

volatile uint8_t count;

Here we use the keyword Volatile , as the variable is a Global one & will be used inside  the ISR Function.If you do not use the volatile keyword & use the variable within ISR , the AVR-GCC compiler may report error while optimizing the code.

As we connect an LED at PD6 we make it as OUTPUT using left shift operator.

We then initialize the TCNT0 & the count variable to 0.

To set the prescaler as 1024 we need to set the bits CS00 & CS02 to 1inside the TCCR0 Register.

TCCR0 |= (1<<CS02) | (1<<CS00);

 

tccr0_1

Next step is to enable the TIMER OVERFLOW INTERRUPT TOIE0 inside the

TIMSK Register

TIMSK = (1<<TOIE0);

clip_image006

Enable the Global interrupt using

sei();

which sets the I bit of SREG.

Next we’ve to write the code for ISR Function.

Correct Vector name must be used in this function.As we use the overflow interrupt select the correct vector name from the vector table  TIMER0_OVF_vect

gfgf

ISR (TIMER0_OVF_vect)

{

if (count == 31)

{

PORTD ^= (1<<6);

count=0;

}

else

count++;

}

Let us see the calculation how we arrived at value 31 in the if condition.

The clock is external crystal 8MHz.We apply a prescaler of 1024.

Now the clock freq to counter becomes 8000000/1024 = 7812.5 Hz

Time period = 1/freq = 1/7812.5 = 0.000128usec or 0.128 milli sec

Overflow occurs every 256*0.000128 = 0.032768sec = 32.768 msec

To generate a time delay of 1 sec 1000/32.768 =  30.5 or 31

So the counter TCNT0 has to overflow 31 times to generate A TIME DELAY OF 1 SEC.

As done in previous example , save this file as main.c

Save  the MFILE  inside the same folder.You can use the same MFILE  as of the previous post example.(Remember to save the C file as main.c)

Make ALL from WINAVR’s Programmers Notepad to create HEX file & then click Program to upload the file.Now the LED at PD6 blinks exactly at 1 second interval.

 

CTC mode operation:

Clear Timer on Compare Match It is better to use instead of Normal mode because in CTC mode, frequency can be easily adjusted.

When the Timer is triggered, register TCNT0 starts counting.

Timer0 has a OCR0 (Output Compare Register), which is continuously compared with TCNT0 register.

In CTC mode whenever match occurs, OCF0 (Output Compare Flag) will set to 1. If continuous wave form generation is required, OCF0 must be reset again.

Alternatively, if OCIE0 (Output Compare interrupt) and Global interrupt flags in SREG are set, OCF0 will reset automatically after interrupt execution.
The bits WGM0 [1:0] are programmed to select waveform generation mode. For enabling CTC set the bit WGM01

Programming steps:

1. Select CTC mode by programming WGM0 [1:0] bit.

2. Program Prescaler by setting CS bits of TCCR0.

3. Load Compare register OCR0 with a value between 0 & 255

4. Set compare Interrupt OCIE0 bit of TIMSK register.

5. Enable global interrupt by sei () command.

 

6. Write code for ISR function with vector name TIMER0_COMP_vect

 

clip_image008

OCF0 – Output Compare Flag 0 — Bit 1 of TIFR

is set whenever a compare match occurs. It is cleared automatically whenever the corresponding ISR is executed. Alternatively it is cleared by writing ‘1’ to it.

 

———————–

#include <avr/io.h>
#include <avr/interrupt.h>

void  timer_init(void)
{
// set up timer with prescaler = 1024 and CTC mode
TCCR0 = (1 << WGM01) ;
TCCR0=  (1 << CS00) | ( 1<<CS02);
// initialize counter
TCNT0 = 0;
// initialize compare value
OCR0 = 220;
// enable compare interrupt
TIMSK |= (1 << OCIE0);
// enable global interrupts
sei();

}

ISR (TIMER0_COMP_vect)
{
PORTD ^= (1 << 6);
}

int main(void)
{

DDRD |= (1 << 6);
timer_init();

while(1)
{
// do nothing
}
}

————————————–

 

TCCR0 = (1 << WGM01) ;

We enable the CTC mode in the TCCR0 Register by setting the bit WGM01

clip_image010

 

clip_image012

We then set the prescaler to 1024 by setting the bits CS00 & CS02

TCCR0=  (1 << CS00) | ( 1<<CS02);

Initialize the TCNT0 Register with 0 value & then load the Output Compare Register with a value 220

OCR0 = 220;

As the TIMER0 is 8 bit timer we can only load the counter with a value between 0 & 255 .This will not create a longer delay & the LED will blink fast , almost stable.In the next post we’ll see the TIMER1 capable of generating longer delay as TIMER1 is 16 bit .

Next enable the Compare Interrupt  OCIE0 within the TIMSK Register

TIMSK |= (1 << OCIE0);
TIMSK_0

Enable the Global interrupt using sei();

Inside the ISR function we just toggle the LED at PD6

ISR (TIMER0_COMP_vect)
{
PORTD ^= (1 << 6);
}

Note the usage of correct Vector name TIMER0_COMP_vect

Compile the code as done in previous examples & see the LED blinking very fast , as we could generate delay in millisec only using Compare mode.

HARDWARE INTERRUPT USING OC Pins

Instead of enabling the Interrupt we can make use of the OUTPUT COMPARE pins of AVR

The Output Compare Pins are seen as OC pins OC0 at PB3 for Timer0

 

clip_image014

 

Programming steps:

1. Select CTC mode by programming WGM0 [1:0] bit.
2. Program COM0 [1:0] bits and select “toggle OC0 if compare match”.

3. Set OC0 (PB3) pin as output pin.
4. Set OCIE0 bit of TIMSK register.

5. Enable global interrupt by “sei ()” command.

 

 

Mode    WGM0[1:0]    Mode
0    00    Normal
1    01    PWM,Phase Correct
2    10    CTC
3    11    Fast PWM

The Register TCCR0 also consists COM0 [1:0] bits. These bits are used to select functionality of OC0 pin. Following table shows function of COM 0[1:0]:

COM0[1:0]    Description
00                Normal,OC0 disconnected
01                Toggle OC0 on compare match
10                Clear OC0 on compare match
11               Set OC0 on compare match

 

#include <avr/io.h>

#include <avr/interrupt.h>

void timer_init(void)

{

// set up timer with prescaler = 1024 and CTC mode

TCCR0 |= (1 << WGM01)|(1 << CS00)|(1 << CS02);

// set up timer OC0 pin (PB3) in toggle mode

TCCR0 |= (1 << COM00);

// initialize counter

TCNT0 = 0;

// initialize compare value

OCR0 = 220;

}

int main(void)

{

// connect led to pin PB3

DDRB |= (1 << 3);

// initialize timer

timer_init();

// loop forever

while(1)  {}

}

OC0  is toggled automatically  no need to keep track of any flag bits or ISR

cooltext753793315   cooltext753790696

AVR – ATMEGA16 – EXTERNAL INTERRUPTS

Interrupts in AVR can be external (port pin sensing) or internal (Timers,ADC,UART,etc..)

When Interrupt occurs , the following things are done by AVR

1. AVR controller stops the current program execution and saves the context.

2.  Control jumps to Interrupt Service Routine (ISR). (Each interrupt have an associated ISR which is a piece of code executed when an interrupt occurs.)

3.  Execution of ISR is performed automatically..

4.  When ISR is complete, the Controller resumes processing where it left off before the interrupt occurred.(main program resumes)

Interrupt sources of AVR are

PORT PINS INT0 (PD2), INT1 (PD3) , INT2 (PB2) & RESET

RESET is unmaskable interrupt & has the highest priority.

Other interrupt sources are Internal to AVR like -Timer , UART , ADC ,SPI , I2C ,etc..

This post is on the PORT PIN Interrupts i.e., EXTERNAL INTERRUPT

EXT_INT

Let us connect an LED at PD0 & a switch at PD2.

PD2 is where Interrupt INT0 is sensed.

PD0 – LED

PD2 – SWITCH

 

LED_SW

Steps to configure the Interrupt:

————————————-

1. Set INT0 bit in the General Interrupt Control Register (GICR)

2. Configure MCU Control Register (MCUCR) to select interrupt type( let us configure for Falling edge).

3. Set Global Interrupt(I-bit) Enable bit in the AVR Status Register(SREG) sei()

4. Handle the interrupt in the Interrupt Service Routine code.

———————————-

 

General Interrupt Control Register (GICR)

In the GICR register enable the bit6 which configures INT0 Interrupt

It’s a good practice to mention the bit name itself in the code

GICR |= (1<<INT0) ;

Here we use the left shift operator to make the bit INT0 as 1

image

 

Type of INTERRUPT ( Rising Edge or Falling edge) is decided by setting bits 0 & 1of MCUCR Register

The MCUCR contains configuration bits which tells what signals will trigger INT0 and INT1

For this you need to set the ISC bits ( Interrupt Sense Control )

ISC00 & ISC01 configures the INT0 interrupt type.These are bits 0 & 1.

 

image

As seen in fig. above set this to Falling edge trigger by making ISC01 as 1.

MCUCR |= (1<< ISC01) ; (or you can also write MCUCR =0x02;)

Mentioning the bit name is always a good practice in coding

Now the Interrupt on INT0 is Falling edge-triggered (meaning that the interrupt is triggered when the signal changes from high to low)

image

We’ve connected a Reset type micro switch at PD2. When the switch is pressed 1 is applied to PD2 & when switch is released 0 is applied .Falling edge level triggering is from High to Low edge.

MCUCR is to configure INT0 & INT1 Interrupts.

 

INT2 is configured by another Register MCUCSR

INT2 can only be used as an edge-triggered interrupt.(no level trigger)

image

 

Now enable the Global Interrupt by setting the I-bit in SREG

It is the master control for all interrupts in AVR micro-controller.

This is done by calling sei();

When Interrupt occurs the ISR – Interrupt Service Routine is called automatically.Inside the ISR function we toggle the LED state.

ISR(INT0_vect)

{

PORTD ^= (1<<0);

}

The vector name used in this ISR is INT0_vect

Correct vector name to be used in the ISR function .Select it from the table below :

image

 

Complete code

—————————————————-

#include <avr/io.h>

#include <avr/interrupt.h>

int main (void)

{

DDRD = (1<< 0) ; // PORT pin PD0 is Output

PORTD | = (1<<0); // PD0 is High normally

GICR = (1<< INT0); // enable INT0 Interrupt

MCUCR |= (1<< ISC01) ; // configure Falling Edge Trigger

sei(); // Enable Global Interrupt

while(1) {}

}

ISR(INT0_vect) // Interrupt Service Routine

{

PORTD ^= (1<<0);

}

———————————————

 

We use Programmers Notepad of WINAVR to develop the C code.

Save the file as main.c inside a folder.

Open the MFILE utility of WINAVR to create the MFILE required for compilation.

Select the MCU type as ATMEGA16 , port as usb & programmer as usbasp.

Usbasp is not in the list of programmer.You need to select any one in the list & then Enable Editing.

Now you can edit your selection to usbasp

Save the MFILE in the same folder where you’ve stored the main.c file.

Click on Tools à MakeAll to compile & then Tools à Program to upload the hex file .

Now the LED at PD0 glows.

When switch connected to PD2 is pressed & then released , a Interrupt occurs (falling edge)

The LED at PD0 changes state to LOW.

Again press the switch & release , the LED changes state to HIGH.

VIDEO DEMO :

Links to previous posts :

https://alselectro.wordpress.com/2017/06/20/avr-self-learning-kit-getting-started/

https://alselectro.wordpress.com/2017/08/13/avr-self-learning-kit-interfacing-16-x-2-lcd-in-8-bit-mode/

 

In this tutorial we shall explore how to connect 16 X 2 LCD with ATMEGA 16 on Development board.

By 2 ways we can connect , first one is 8 bit mode & the second is 4 bit mode

 

DEMO_BOARD

This post is on 8 BIT MODE

In 8 bit mode all port pins of a Port , say PORT B is assigned for DATA communication.

For CONTROL we need 3 more pins RS , RW & EN

RS is REGISTER SELECT RS=0 Command Register of LCD selected , RS=1 DATA Register is selected

RW is READ/WRITE pin when RW=1 LCD is in Read mode , when RW=0 LCD is in WRITE mode

Generally LCD is used to display data.So mostly RW is connected to GND ( RW=0)

PB0 to PB7 – D0 to D7 of LCD

PD4 (PIN 18) — > RS

PD5 (PIN 19)– > RW

PD6 (PIN 20) — > EN

The backlight connection & Contrast pot are taken care in the development board.

 

LCD_DATA_CTRL_PIN_CON

 

We use PROGRAMMERS NOTEPAD of WINAVR to develop the C code & Hex file .

WINAVR is a lightweight excellent tool for AVR Programming compared to the AVR STUDIO ( which is a huge download)

You can download WINAVR

https://sourceforge.net/projects/winavr/files/latest/download?source=files

Its only 29MB download & easy to install.

Once WINAVR is installed , you can see the Programmers Notepad & MFILE inside the WINAVR Folder.

winavr

Open Programmers Notepad to type in the C code.

To start with the code , include the 2 Header files on the top . avr/io.h defines all Port Registers & port pins of AVR IC & the util/delay.h is responsible for the Delay we use in the code.

 

#include <avr/io.h>

#include <util/delay.h>

 

Next we define the LCD Function definitions like

 

void LCD_send_command(unsigned char cmnd);

void LCD_send_data(unsigned char data);

void LCD_init(void);

 

Above all are user defined Functions & we’ve to write code for these functions.

For better code readability & reuse of coded we use # define statements

 

#define DATA_PORT PORTB

#define DATA_DDR DDRB

#define CNTRL_PORT PORTD

#define CNTRL_DDR DDRD

#define RS_PIN 4

#define RW_PIN 5

#define ENABLE_PIN 6

 

PORTB is defined as DATA_PORT & PORTD is defined as CNTRL_PORT , DDRB as DATA_DDR, DDRD as CNTRL_DDR

In the code , wherever DATA_PORT is mentioned it is replaced with PORTD & wherever CNTRL_PORT is mentioned is replaced with PORTD.

Also pins PD4 is defined as RS_PIN , PD5 as RW_PIN , PD6 as ENABLE_PIN .Its enough to mention only the pin number. Instead of PD5 you can mention only 5.

Later if you decide to change the port pins assigned to LCD , you need to change it in the #define statements and the rest of the code is left as it is.

First let us see the LCD_init() function which initializes the LCD

 

void LCD_init()

{

_delay_ms(10);

LCD_send_command(0x38);

LCD_send_command(0x0E);

LCD_send_command(0x01);

_delay_ms(10);

LCD_send_command(0x06);

}

 

To initialize the LCD we send the HEX values as command.The HEX command codes are

clip_image002

We send HEX value 0x38 to define 16 x 2 LCD 2lines & character size is 5 x 7

0x0E forDisplay ON & cursor blinking

0x06 to increment cursor

& 0x01 to Clear Screen

We send Command using Function LCD_sendcommand

Which accepts parameter as unsigned char

—————————————————–

void LCD_send_command(unsigned char cmnd)

{

DATA_PORT = cmnd;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT &= ~(1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

————————————————–

Command received as unsigned char is assigned to DATA_PORT

RW pin is made LOW to enable Write operation

RS pin is made LOW to select COMMAND REGISTER

ENABLE pin is made HIGH & after a small delay made LOW ( pulse)

In the same way DATA is sent to LCD for Display using the following function :

——————————————–

void LCD_send_data(unsigned char data)

{

DATA_PORT = data;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT |= (1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

—————————————

 

Data received as unsigned char is assigned to DATA_PORT

RW pin is made LOW to enable Write operation

RS pin is made HIGH to select DATA REGISTER

ENABLE pin is made HIGH & after a small delay made LOW ( pulse)

The next function takes 2 variables y & x & moves the cursor to that location on LCD

——————————————-

void LCD_goto(unsigned char y, unsigned char x)

{

unsigned char firstAddress[] = {0x80,0xC0,0x94,0xD4};

LCD_send_command(firstAddress[y-1] + x-1);

_delay_ms(10);

}

————————————————-

 

 

Following is the Function to print String characters on LCD

We put a string in memory location & use it as a Pointer

While String is greater than 0 , all the characters represented or pointed by the string variable is sent to LCD for printing

 

void LCD_print(char *string)

{

while(*string > 0)

{

LCD_send_data(*string++);

}

}

 

In the LCD_blink() function we send command , a hex value 0x08 to make the display OFF & after a delay we send a command Hex 0x 0C to ON the display, thus generating a blink effect

 

void LCD_blink()

{

LCD_send_command(0x08);

_delay_ms(250);

LCD_send_command(0x0C);

_delay_ms(250);

}

 

To clear the display we send command Hex 0x01 as seen in the LCD_clear function below

 

void LCD_clear(void)

{

LCD_send_command(0x01);

_delay_ms(100);

}

 

Finally in the main Function we declare PORTD as Output , as well as PORTC as OUTPUT.

This is done by assigning 0x FF to CNTRL_DDR ( PORTD) & DATA_DDR (PORTB)

Then we clear the LCD , Initialize it & go to first position & print the String

 

int main(void)

{

CNTRL_DDR = 0xFF;

CNTRL_PORT = 0x00;

DATA_DDR = 0xFF;

DATA_PORT = 0x00;

 

LCD_clear();

LCD_init();

LCD_goto(1,2);

LCD_print(“ALSELECTRO.COM”);

LCD_goto(2,3);

LCD_print(“16×2 LCD DEMO”);

 

 

Complete code for 8bit LCD MODE is as below :

—————————————————

 

#include <avr/io.h>

#include <util/delay.h>

#define F_CPU 8000000UL // FCPU Definition for util/delay used in AVR STUDIO only

 

/*LCD function declarations */

void LCD_send_command(unsigned char cmnd);

void LCD_send_data(unsigned char data);

void LCD_init(void);

void LCD_goto(unsigned char y, unsigned char x);

void LCD_print(char *string);

void LCD_blink(void);

void LCD_clear(void);

 

#define DATA_PORT PORTB

#define DATA_DDR DDRB

#define CNTRL_PORT PORTD

#define CNTRL_DDR DDRD

#define RS_PIN 4

#define RW_PIN 5

#define ENABLE_PIN 6

 

int main(void)

{

CNTRL_DDR = 0xFF;

CNTRL_PORT = 0x00;

DATA_DDR = 0xFF;

DATA_PORT = 0x00;

 

LCD_clear();

LCD_init();

LCD_goto(1,2);

LCD_print(“ALSELECTRO.COM”);

LCD_goto(2,3);

LCD_print(“16×2 LCD DEMO”);

 

while(1)

{

}

}

 

/* This function sends a command ‘cmnd’ to the LCD module*/

void LCD_send_command(unsigned char cmnd)

{

DATA_PORT = cmnd;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT &= ~(1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

 

/* This function sends the data ‘data’ to the LCD module*/

void LCD_send_data(unsigned char data)

{

DATA_PORT = data;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT |= (1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

 

void LCD_init()

{

_delay_ms(10);

LCD_send_command(0x38);

LCD_send_command(0x0E);

LCD_send_command(0x01);

_delay_ms(10);

LCD_send_command(0x06);

}

 

/* This function moves the cursor the line y column x on the LCD module*/

 

void LCD_goto(unsigned char y, unsigned char x)

{

unsigned char firstAddress[] = {0x80,0xC0,0x94,0xD4};

LCD_send_command(firstAddress[y-1] + x-1);

_delay_ms(10);

}

void LCD_print(char *string)

//put a string in memory location & use it as POINTER

{

while(*string > 0)

{

LCD_send_data(*string++);

}

}

 

void LCD_blink()

{

LCD_send_command(0x08);

_delay_ms(250);

LCD_send_command(0x0C);

_delay_ms(250);

}

 

void LCD_clear(void)

{

LCD_send_command(0x01);

_delay_ms(100);

}

—————————————–

Download code from here

Save the file inside a folder with .C extension.

Now open the MFILE of WINAVR & set the MCU as ATMEGA16 , Port as usb , Programmer as usbasp.

To make programmer as usbasp , you need to enable editing & type in usbasp against Programmer.

If the C code is saved as main.c , then you need not change the Target in Makefile.

Save the Makefile inside the same folder where .c file exists.

Click on Tools à MakeALL to generate HEX file & then click on Program to upload the HEX file on to the ATMEGA16 chip.

To create a Header file , watch the following video :

 

cooltext753793315  cooltext753790696

This post is intended to assist you getting started with AVR DEVELOPMENT SELF LEARNING KIT.

It supports 40 pin AVR ICs like ATMEGA 16 /32 & a ZIF socket is provided to host the chip.All PORT pins are extended with berg pins for easy connections with peripherals.

For Analog input testing 2 nos variable pot are provided & for testing Digital inputs 4 nos switches are provided.A 4×4 keypad matrix is on board.

4 NOS 7 SEGMENT DISPLAY with driver circuit is provided.Other features include , EEPROM 24C16 , RTC  DS1307, UART MAX232 , MOTOR DRIVER ULN2003. An LCD can be plugged with the port provided.

An ISP connector accepts USBASP programmer through a 10 pin FRC Header.

 

board2

 

Download sample code ,WINAVR , USBASP DRIVER, AVRPAL.NET from HERE

Watch this video for details of installing USBASP driver & getting started with AVR Kit.

 

Connect the USBASP AVRDUDE with ISP connector & USB cable to your port on PC.Power up the kit with the 12v/1A adapter provided.Once the driver is installed , under Device manager USBASP appears

Image 1

 

WINAVR is used to develop C code & upload HEX file on to the Target chip.WINAVR has a PROGRAMMERS NOTEPAD which is the IDE we use to develop code.

MFILE in WINAVR helps us to create the rules for making.This MAKE FILE must be saved within the same folder where you saved the C file.Compared to ATMEL STUDIO ( a HUGE Download) WINAVR is small & powerful.

Image 2

 

To start with create an empty Folder , say LED ,inside your drive.Here is where we’ll be saving all our files.

Open PROGRAMMERS NOTEPAD & type in the following C code.

Save the file as LED.c inside the folder we created earlier.

Do not forget the .C Extension.

————————————————–

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRC = 0xFF; //Makes PORTC  as Output

while(1) //infinite loop
{
PORTC = 0b00000001 ; // LED ON at PC0
_delay_ms(100); // delay

PORTC = 0b00000000 ; // LED OFF at PC0
_delay_ms(100); // delay

}
}

——————————————

The code starts with PREPROCESSOR Directives

# include <avr/io.h>     defines all PORT names & pins of AVR

# include <util/delay.h>   defines the delay timing

Then starts the MAIN function under which we first declare PORTC pis as all OUTPUT.

Notre that in AVR we use 1  to declare OUTPUT & a 0 to declare as INPUT (REVERSE TO PIC programming)

I/O Pins of AVR has 2 to 3 functions & each PORT is associated with 3 REGISTERS

For e.g PORTC is associated with 3 registers

DDRC —>  DATA DIRECTION REGISTER  Configures   Port as INPUT (0) or OUTPUT  (1)

PORTC —> Write Data to PORT Pins

PINC   —> READ DATA from PORT Pins

 

Next is the indefinite loop while(1)

Inside which we make PORTC bit 0 as HIGH & all other pins LOW.

This is achieved by Binary notation

PORTC = 0b00000001 ;

After a delay

  _delay_ms(100);

we make PORTC bit 0 as LOW

PORTC = 0b00000000 ;

Now we need to create the RULES for Making which is done through MFILE of WINAVR

Open MFILE.Click on MakeFile

Select MCUtYPE as ATmega16

Port as usb

Programmer as usbasp.

 

Image 5

 

Under Progammer usbasp  is not listed. Select any other type like STK500 & then click on Enable Editing.

Now you’re allowed to make changes.Type in usbasp against Programmer.

Image 9

Scroll up to locate TARGET=main

Change this main to your C file name without any .c extension

Image 6

Save the Makefile inside the same folder where your C code is stored.

Image 7

Now click on MAKE ALL to generate HEX file.

Tools –> Program to load the HEX file automatically on to the target chip.

Image 4

Now let us see how to use the BITWISE OPERATORS in C code

To improve code clarity & to leave generation of  1s & 0s to the compiler we use SHIFT OPERATORS.

For e.g  instead of writing 0b0010 0000

we can write    0b0000 0001 <<5

or simply         1<<5     This is left shift operation.

0B0001 0000 << 3   will result 0B1000 0000    SHIFTING LEFT 3 TIMES

To generate  0B1110 1111    SHIFT FIRST & THEN INVERT IT

~(1<<5)

 

SETTING A BIT

To set an individual BIT we use the OR OPERATOR  |

e.g   DDRD = 0b0000 0001    To SET bit 4

SHIFT it 4 times to get 0b0001 0000

OR this result with DDRD Register

DDRD = DDRD | (0b00000001 <<4);

DDRD = DDRD | (1<<4); 

or you  can write simply   DDRD |= (1<<4);

Only BIT 4 is SET & other bits not affected.

You can also define a constant & use it

# define LED 4

DDRD |= (1<<LED);

 

CLEAR A BIT

e.g  DDRD = 0b0101 0101;

To clear the bit 2 (shown in bold letter above)

start with binary no.    0b0000 0001

Left SHIT 2 TIMES  to get  0b0000 0100

Invert this to get    0b1111 1011

use the & OPERATOR with DDRD Register

 

#define switch 2

DDRD &= ~ (1<< SWITCH);

 

CHECKING A BIT WHETHER 1 OR 0

To check status of 4th bit of PIND Register

Notice the use of PIN Register here

#define switch 4

status = (PIND & (1<< SWITCH) !=0);

 

 

TOGGLING A BIT

To toggle 4th bit of PORT D

PORTD = 0B0000 0000

START with 0b0000 0001   shift by 4 times to get

0b0001 000

X OR with PORTD

#define LED 4

PORTD ^= (1<< LED);

Every time this statement is executed the LED changes state

 

Following is the code with BITWISE operators implemented.

We use OR EQUAL LEFT SHIFT to declare portC as output

Inside while loop PORTC BIT 0 is made ON & then OFF after a delay , which is repeated for ever.

———————————————–

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRC |= (1 << PC0); //Makes PORTC PC0 Pin22 as Output

while(1) //infinite loop
{
PORTC |= (1 << PC0); //Turns ON LED at PC0 or PORTC=0b00000001
_delay_ms(100); // delay

PORTC &= ~(1 << PC0); //Turns OFF LED or PORTC=0b00000000
_delay_ms(100); // delay
}
}

——————————————-

 

cooltext753793315    cooltext753790696

Arduino ProMini , as the name indicates , is a miniature version of UNO .It runs on 16 MHz crystal ,ATMEGA328 ,but lacks USB connectivity. There are 5V  (16MHz) & 3.3V (8MHz) versions. In this demo I use the 5v version.

 

ArduinoProMini000b

 

There is a voltage regulator on board so it can accept voltage up to 12VDC. If you’re supplying unregulated power to the board, be sure to connect to the RAW pin and not VCC.

Vcc accepts only 5v.

The latest version of this board breaks out the ADC6 and ADC7 pins ,also adds footprints for optional I2C pull-up resistors.

To upload code on to pro mini , a USB-TTL adapter is required.There are many types of  USB adapters available.The most reliable one that works up to Windows 10  is the one built on CP2102 IC .

CP2102 adapters are available in 2 variants .One with 6 pins that include the DTR  , Data Terminal Ready , which handles the RESET required by the promini board.

The other board is commonly available one with 5 pins.Here RESET must be done manually on promini while code is uploaded.

 

CP12

 

CP13

 

First let us upload code using the 6 pin version .

The connections are

PROMINI                USB-TTL

DTR   —–>   DTR

TxO   —–>  Rx

RxI    ——> Tx

Vcc   ——> 5v

GND  ——> GND

In some Promini boards the DTR pin is printed as GRN.

pro1

Plug in the USB board to PC & open the Device Manager . If the driver is installed previously , a COM port will be allotted.Otherwise , download the silicon labs cp2102 driver from here & install.

 

Image 1

Open the Arduino IDE , feed in the COM port allotted.

Select Board as Arduino Pro or Pro Mini , Programmer as USBasp.

In newer versions of IDE there is option to select type of ProMini board.Under Processor select ATmega328 5v,16MHz

Image 2

From Examples open the BL;INK sketch

Image 3

Click on UPLOAD button.

The DTR pin of USB board takes care of the RESET  & your code will be uploaded to PROMINI without any manual reset.

 

Image 4

Uploading code using a 5 pin version , needs a manual RESET on PROMINI.

The connections are

PROMINI                USB-TTL

TxO   —–>  RxD

RxI    ——> TxD

Vcc   ——> 5v

GND  ——> GND

 

IMG_20170512_165334

Plug in the USB to PC & note the COM Port allotted.

Open Arduino IDE .Feed in the COM port , select board as Arduino Pro or Promini & Programmer as USBASP

From Examples , open the BLINK Sketch

Image 2.1

Click on UPLOAD button.

Image 2.6

Watch out for the message at the bottom of IDE.

“ Compiling Sketch “ message appears first.

Then it changes to “Uploading”

Image 2.2

As  soon as you see “Uploading” message , gently press the RESET Key on Promini.

This should be done instantly , as soon as you see “UPLOADING” message.

Image 2.3

 

IMG_20170512_164431

If the KEY Press is at the right time , your code will be uploaded successfully.

Image2.4

 

You can also use your UNO board to upload code on Promini.

To use the UNO board , you need to by pass the bootloader .For this  upload an empty code to UNO or connect the RST pin to GND

Connecting RST pin to GND bypasses the bootloader & only the serial converter IC located near the USB socket is used as USB-TTL.

The connection here is STRAIGHT & not reverse

Tx of Arduino UNO goes to Tx of Promini

Rx of UNO goes to Rx of Promini

Gnd to Gnd

c12

 

Connect the USB cable to PC & open the IDE.

Select the port where UNO is connected.

Image 2.5

 

Select the board as Arduino Pro or ProMini

Image 3.1

Open the BLINK sketch & UPLOAD.

Watch out the message at the bottom of IDE.

Initially “Compiling Sketch “ appears.

Then the message changes to UPLOADING…

 

Image 6

Once you see UPLOADING… message  , press the RESET key on PROMINI.

 

IMG_20170512_171519

 

The code is now Uploaded successfully.

Image 7

Support VIDEO :

cooltext753793315   cooltext753790696

In the previous post we’ve seen how to connect the Arduino ETHERNET SHIELD to a Router directly  & upload LM35 data to Thingspeak.

What if  you do not have physical access to your Router & your Laptop is connected over WIFI to the Router. Or you cannot run a RJ45 cable from Router to Ethernet shield.

The procedure we follow is similar to the one we did for connecting Raspberry PI to Laptop.

Link here

First step is to enable SHARING of your existing internet.In my case , Laptop is connected to Router

over WIFI.

Open Control Panel –> Network & Internet –> Network & Sharing Center

Click on the existing internet connection

Image 1

On the next screen click PROPERTIES &  then SHARING

Image 2

Tick mark to ENABLE SHARING of Internet connection

Image 3

 

Now plug in the USB cable to Arduino & then connect the RJ45 Straight cable from shield to the RJ45

Port of LAPTOP.

ETH_SETUP

As soon as you connect the RJ45 cable you can see an UNIDENTIFIED NETWORK

 

Image 4

 

Click on that new Network , select PROPERTIES.

On the next screen double click on Internet Protocol version 4 (TCP/IPV4)

Image 5

You can see an IP address like 192.168.137.1.

Note that this is the new Gateway IP of the new network formed by Ethernet shield.If you do not see any IP , just select the “ Use the following IP “ &  feed in manually the IP.

 

Image 6

Now RUN  –> CMD  > IPCONFIG /ALL

to verify the IP.

Under Ethernet adapter the Gateway IP of new network is displayed.

Note that this is the GATEWAY IP & Ethernet shield will be allotted IP in this range  .

 

Image 7

Let us try some built in example codes.

Under Examples  –> Ethernet –> select  DhcpAddressPrinter

This will print the IP allotted to the Shield.

Image8

Upload the code & open up the Serial monitor.

The IP allotted to the shield here is 192.168.137.30  which is in range of new Gateway .

Image 9

 

Next example is WEBSERVER

Image 10

 

Open the WEBSERVER code .

You need to change the IP Address as 192.168.137.xxx

 

Image11

 

Here change it to 192.168.137.177 where the SERVER will be started. Note the usage of comma instead of dot between each byte.

Image 12

 

Upload the code & open the serial monitor to verify that SERVER is started.

Image 13

You can use your Browser as CLIENT.

Type in the IP 192.168.137.177 to access the server.

On the Serial monitor “Client connected “ information will apper.

Image 14

On the browser you can see the values of ANALOG Pins of Arduino.

As nothing is connected to the Analog pins , you get random values.

Image 17

 

Next example is the TELNETCLIENT

Image 2

 

Open the code.

Here Ethernet shield is used  as CLIENT & you need to change the IP of client in range with the new Gateway  192.168.137.177

Next is the IP of the SERVER . This may be another PC or Android phone connected to the same Network .

Here the SERVER is started on PC with IP 192.168.0.103

Note that this IP is in the range of Gateway of Router 192.168.0.xxx

Image 3

Scroll down further & note the PORT number on which the SERVER will LISTEN.

Here it is 10002.

Upload the code on to Arduino.

Image 4

To test the setup , you need to start a SERVER on another PC on the same network with IP 192.168.0.103

For this we use HERCULES software. DOWNLOAD HERE

Click on TCP Server tab on Hercules , feed in the port number 10002 & click LISTEN.

The server is started on PC with IP 192.168.0.103 , so , no need to enter the IP

Image 5

Now open the Serial Monitor of Arduino where SHIELD is declared as CLIENT.

You can see the “Connected..”  feed back from the Server.

Type in some characters on Arduino side , as well as Hercules side to verify 2 way communication.

Image 6

Instead of PC & HERCULES you can use your Android mobile ( to be connected over WIFI to the same Network).

On your mobile install TCP TOOLS

mobile1

Open TCP SERVER

The IP of Android device is shown with default port 8080.Click on LISTEN

In the TELNET CLIENT code you need to change the SERVER IP t from 1,1,1,1

to  192.168.0.102 & then change the port of server to 8080 & then upload to Arduino

 

mobile 2

Once code is uploaded open the Serial monitor.

On mobile you see the IP of CLIENT connected

mobile3

Test 2 way communication by typing in characters.

mobile4

 

mobile5

 

Next we shall test the code which sends LM35 Data to THINGSPEAK SERVER.

You can check my previous post for details

Upload the same code without any change in IP.

IT WORKS FOR BOTH RANGE OF ipS 192.168.0.xxx    &   192.168.137.xxx

Image 7

Open the Serial Monitor to see the data being uploaded to THINGSPEAK.

Image 8

WATCH THIS VIDEO  :

cooltext753793315   cooltext753790696

Ethernet shield acts as wired Gateway between your Arduino & Internet.

This post demonstrates how to upload  temperature data from LM35 sensor to the server on THINGSPEAK.Before starting you should know how to connect the shield to Network.

There are 2 options by which your shield is connected to the Network.

First is the direct connection to your Router .You’ve an available RJ-45 port on your Router & you directly use a straight RJ45 cable to plug Ethernet shield to Router .Your PC/Laptop is also connected to the same Router either by wire or through WIfi (if your Router is WIFI capable).

Second is the indirect connection.Your shield is connected to your Laptop’s RJ45 with wire.Your Laptop is connected to Router through WIFI.In this case you need to bridge the connections or use the shield as unidentified second network with a different IP.

In this post we use the first Direct connection to Router method.

Check this connection image where my Ethernet shield is connected directly to  Router.My PC is also connected to the same Router by WIFI . Router is provided Internet access by the Internet Service Provider ACT.

 

eth_connect1

 

eth2

 

To start with let us fix the IP of Ethernet shield STATIC , so that it is always the same on every boot up of Router.

From your PC  RUN –> CMD

Type in  ipconfig /all

The Default Gateway here is 192.168.0.1 which is the IP of the Router.

All clients connected to this Router will be assigned IP in this range 192.168.0.xxx  where the last byte is from 2 to 255 (allotted on first come basis)

Image 1

In the above screenshot you can see (ipV4 address), my PC is assigned IP 192.168.0.101.

IP is assigned automatically by Router , only when the DHCP is enabled in Router setting.

Type in your browser 192.168.0.1 , the gateway IP & feed in your Router’s username & password  (generally both are “admin”)

Under DHCP settings ensure that DHCP is Enabled.

Image 2

 

Now click on the DHCP CLIENT LIST to know the devices connected to the Router.

In my case 2 devices connected.One is my PC which is allotted IP 192.168.0.101

& the second device is Ethernet shield which is allotted 192.160.0.100.

But in our code we use IP 192.168.0.150 .

Let us change the IP to 192.168.0.150 & make it STATIC.

ip_allot1

Click on  ADDRESS RESERVATION  under DHCP

& then click ADD NEW

dhcp_res1

 

Feed in the MAC address of the Ethernet shield & the reserved IP as 192.168.0.150

The MAC address is the one you used in the code.This may be random unless you use more than one shield in the same network.

ADDNEW

Click on SAVE & then REBOOT your Router to enable the changes made.

dhcp_res2

Now under DHCP Client list you can see your shield allotted 192.168.0.150 & permanent (means STATIC IP)

dhcdp_res3

 

lm35

Connect the 1st pin of LM35 to 5v of Ethernet shield , 3rd pin to GND. 2nd pin is connected to A0

Analog pin.

Connect the USB cable from ARDUINO to PC & note the PORT allotted.The RJ45 STRAIGHT CABLE is connected from Ethernet shield to Router directly.

Upload the following code on to Arduino.You need not change the MAC address.

You need to change the Gateway IP as per your Router & also change the IP of shield in this range.

Also you need to change the THINGSPEAK API according to your CHANNEL setting

Download Arduino CODE Here

—————————————————-

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

int pin = 0; // analog pin
int tempc = 0,tempf=0; // temperature variables
int samples[8]; // variables to make a better precision
int maxi = -100,mini = 100; // to start max/min temperature
int i;

// Local Network Settings
byte mac[]     = { 0xD4, 0xA8, 0xE2, 0xFE, 0xA0, 0xA1 }; // Must be unique on local network
byte ip[]      = { 192,168,0,150 };                // Must be unique on local network
byte gateway[] = { 192,168,0,1};
byte subnet[]  = { 255, 255, 255, 0 };

// ThingSpeak Settings
char thingSpeakAddress[] = “api.thingspeak.com”;
String writeAPIKey = “QGBA1G3872XSHBAC”;    // Write API Key for a ThingSpeak Channel
const int updateInterval = 10000;        // Time interval in milliseconds to update ThingSpeak

// Variable Setup
long lastConnectionTime = 0;
boolean lastConnected = false;
int failedCounter = 0;

// Initialize Arduino Ethernet Client
EthernetClient client;

void setup()
{

Serial.begin(9600);
Ethernet.begin(mac, ip, gateway, subnet);
delay(1000);
Serial.print(“ETHERNET SHIELD ip  is     : “);
Serial.println(Ethernet.localIP());
// Start Ethernet on Arduino
startEthernet();
}

void loop()
{

tempc = ( 5.0 * analogRead(pin) * 100.0) / 1024.0;

String analogPin0 = String(tempc);

// Print Update Response to Serial Monitor
if (client.available())
{
char c = client.read();
Serial.print(c);
}

// Disconnect from ThingSpeak
if (!client.connected() && lastConnected)
{
Serial.println();
Serial.println(“…disconnected.”);
Serial.println();

client.stop();
}

// Update ThingSpeak
if(!client.connected() && (millis() – lastConnectionTime > updateInterval))
{
updateThingSpeak(“field1=”+analogPin0);
}

lastConnected = client.connected();
}

void updateThingSpeak(String tsData)
{
if (client.connect(thingSpeakAddress, 80))
{
client.print(“POST /update HTTP/1.1\n”);
client.print(“Host: api.thingspeak.com\n”);
client.print(“Connection: close\n”);
client.print(“X-THINGSPEAKAPIKEY: “+writeAPIKey+”\n”);
client.print(“Content-Type: application/x-www-form-urlencoded\n”);
client.print(“Content-Length: “);
client.print(tsData.length());
client.print(“\n\n”);

client.print(tsData);

lastConnectionTime = millis();

if (client.connected())
{
Serial.println(“Connecting to ThingSpeak…”);
Serial.println();

failedCounter = 0;
}
else
{
failedCounter++;

Serial.println(“Connection to ThingSpeak failed (“+String(failedCounter, DEC)+”)”);
Serial.println();
}

}
else
{
failedCounter++;

Serial.println(“Connection to ThingSpeak Failed (“+String(failedCounter, DEC)+”)”);
Serial.println();

lastConnectionTime = millis();
}
}

void startEthernet()
{

client.stop();

Serial.println(“Connecting Arduino to network…”);
Serial.println();

delay(1000);

// Connect to network amd obtain an IP address using DHCP
if (Ethernet.begin(mac) == 0)
{
Serial.println(“DHCP Failed, reset Arduino to try again”);
Serial.println();
}
else {
Serial.println(“Arduino connected to network using DHCP”);
Serial.println();
Serial.println(“Data being uploaded to THINGSPEAK Server…….”);
Serial.println();
}

delay(1000);
}

————————————————–

ip_allot

 

You need to sign up with www.thingspeak.com  to upload your data to the server.

Open your account on THINGSPEAK & select MYCHANNELS under CHANNELS

thing2

Click on NEW CHANNEL

thing3

Feed in Name & Description of your channel & under FIELD1 enter name of field like TEMPERATURE

Scroll down & Enable PUBLIC VIEW.

thing4

Save the CHANNEL & then click on API KEY tag

thing5

Note down the WRITE API KEY

thing6

Replace this code with yours inside the Arduino code.

thing7

Upload the code.

Please ensure that you’ve changed following settings in your code before uploading:

1. Gate way IP of your Router.

2. IP address of your Shield in range with gateway IP.

3. Thingspeak  API WRITE KEY from your Channel

upload

Once uploaded you can open the Serial Monitor of Arduino , to see data being uploaded to the Server

eth_connected1

On your THINGSPEAK Channel click on Public View to see the Graphical representation of the LM35 data being uploaded.

thing1

If you get Arduino Failed to connect to Network,  then you need to check the IP address credentials again.

 

HTTP POST Method to write data on to server

 

In the Arduino code data is converted to STRING type & uploaded to Thingspeak. Thingspeak server accepts only String type data.,

The HTTPS method used in code is POST method .Other HTTPS methods are  GET ( to read data), PUT ( to update data), DELETE ( to delete data).

Understand the basics of this method which we will be using in upcoming posts of ESP8266 & other IOT related projects.

We use POST to submit data to THINGSPEAK Server.

POST request is a bunch of STRINGs.

Each request line is separated & ends with a newline.

——————————–

client.print(“POST /update HTTP/1.1\n”);
client.print(“Host: api.thingspeak.com\n”);
client.print(“Connection: close\n”);
client.print(“X-THINGSPEAKAPIKEY: “+writeAPIKey+”\n”);
client.print(“Content-Type: application/x-www-form-urlencoded\n”);
client.print(“Content-Length: “);
client.print(tsData.length());
client.print(“\n\n”);

——————————

The first string is the Message STARTLINE which has 3 elements separated by SPACE

POST /update HTTP/1.1\n

First element is the URI –Uniform Resource Identifier ( not URL) which is nothing but the method POST all in capital letters. Next element is the protocol /update & the 3rd element is the version  HTTP/1.1 . At the end  \n is used for new line , or you can use println instead of print.

Once we send the message start line string, then we need to  send different header fields. The HEADSER FIELDS are  predefined fields that give the Thingspeak server , information about our POST request. Apart from standard fields , there’s some non-standard fields.

If it’s a non-standard field, the header name is usually preceded by an x. Each header field that we send is going to be its own string, separated by a newline.

We’re going to send following different Headers :

1.Host header field,

2.Connection header field,

3.The x ThingSpeak API key header field,

4.Content type header field,

5.  Content length header field.

1} For ThingSpeak, the host is going to be —–>   api.thingspeak.com.

2) For the connection header, we specify close, and that’s because after we make our request and after we get our response, we want to close the connection with the server. There’s no need to keep that connection open between sending information, so we close it.

3) The X-ThingSpeak API key header is a non-standard header, and that is going to be set to our Write API key that we can find out  from our ThingSpeak channel.

4) The content type header is going to indicate the kind of media that we planned on sending in the header body, In HTTP there are two ways to POST data:

application/x-www-form-urlencoded

and

multipart/form-data.

We use the first one as we update string data.

For application/x-www-form-urlencoded, the body of the HTTP message sent to the server is essentially one  query string — name/value pairs are separated by the ampersand (&), and names are separated from values by the equals symbol (=).

5) The content length header specifies the size of the media that we’re going to be sending in bytes.

 

Once we’ve set the header fields, the last thing we do is send the message body.

The message body is the actual data that we want to update & post to the server. Just like the message start line, and just like the header fields, the message body is going to be a string of text. The message body is  separated from the header fields by two newlines.

client.print(tsData.length());
client.print(“\n\n”);     // 2 new lines

client.print(tsData);

Those two newlines are what let the server know that  we’re done with the header fields & we’re moving on to the message body.

Our message body is simply listing the field that we want to update with an equals sign followed by the value that we want to update it as.

updateThingSpeak(“field1=”+analogPin0);

If we want to do multiple fields, we separate them with the “and” sign. There’s no spaces in this message body

We’ve got the message start line. We’re identifying the method, the URI, the resource we want to use, and the protocol type. Then we specify the header fields. This is giving information to the server about the request that we’re making.

Finally, we have the actual message that we’re sending.

That makes up a basic HTTP POST  request

VIDEO TUTORIAL :

 

cooltext753793315   cooltext753790696