الجمعة، 10 يوليو 2015

Microcontroller Basics - How to Make an LED Blink Using AVR microcontroller

In the last discussion , we learned how to make an LED switch ON through a microcontroller, it was outstanding wasn't it? May be not so much!



Here we will learn how to spice-up the above LED illumination by attributing a bi-directional functionality, that is we’ll try to make it flash or blink at some specified frequency or rate. We’ll also see how this rate could be increased or decreased as desired by the user.

Let’s have a look into this:


#include <avr/io.h>

#include <util/delay.h>

int main(void)

{

DDRB |= 1 << PINB0; 

while (1)

{

PORTB ^= 1 << PINB0;

_delay_ms(100);

}

}

If you are feeling baffled with those strange symbols (&, ^, | etc) used in the above expression (& is not there but could be used in other similar codes), here are the related information you would be interested to know about these:

It includes many standard logical algorithms such AND, OR, NOT and XOR which are typically used with the above code.

These logical functionality specifically compare the two bits “1” and “0” according to their assigned truth tables.

We’ll get an idea by analyzing the following bit arrangement:

01001011 &
10001101
equals
00001001

In the above code & refers to AND as used in C programming.

Reading the rows vertically, it suggests that 0 and 1 equals 0, 1 and 0 also equals 0, 0 and 0 equals 0, 1 and 1 equals 1. Reading it is as simple as that. These are as per the truth table of a AND operator.

If we assess the following table, it indicates the symbol “|” denoting the use of “OR” functionality, the “|” could be found just on the left of “backspace” in your computer keyboard:

01001011 |
10001101
equals
11001111

Identically this truth table of an OR logic functionality indicates that bits 0 or 1 equals 1, 1 or 0 also equals 1, 0 or 0 equals 0, while 1 or 1 equals 1.

The following bit combination is for XOR logic operator denoted by ^ and may be studied just as we did with the AND, OR truth tables:

01001011 ^
10001101
equals
11000110 

Now let’s continue with the first program and learn what the following line in it signifies:

#include <util/delay.h>

Through our previous tutorials we know how the expression <avr/io.h> functions, so we won’t be reiterating it however their seems to be a new “include” expressed by #include which needs to be investigated.

In this “include” the delay.h allows us with some easy methods of implementation.

As the name suggests the delay.h enables us to induce a delay in the particular program.

The next expression int main (void) could be omitted from the ongoing discussion since we have already covered this in our earlier posts.

Next comes the altered DDRB.

The following shows the earlier form which is not a better way of assigning the pins since all the pins from 0 to 7 were switched to form the inputs. But just imagine what would be the situation if we wanted to create a lengthier program requiring those pins for some other functionality? For instance pin2 could be needed for applying a remote switching of an appliance. In that case we wouldn’t appreciate assigning the same as an input just through trial and error. That could mean incorrect response from the remote transmitter to the appliance receiver. 

DDRB = 0b00000001;

We rather want to influence just one bit, hat pin0 bit, glancing at the “OR” functionality this could be executed through a binary masking.

DDRB = DDRB | 0b00000001; 

Here it’s veiled with an “OR” mask: 0b00000001, although it quite appears to be an authentic binary number, in case the earlier DDRB for instance: 0b01001010, then applying an OR to this through masking could give: 0b01001010 | 0b00000001 = 0b01001011.

The resultant difference as could be witnessed is only with the pin0, whose bits have changed!

Compressing the above statement even further via C++ gives:

DDRB |= 0b00000001; 

However we find that there’s even more in the given program. Although it may look quite legit and obvious we ought to take the benefit of some of the statements from the io.h header file especially when it’s fundamentally created for our convenience?

So if “DDRB |= 1 < < PINBO, why it’s like that?

1 < < PINBO is implemented for applying the masking effect. The “1” indicates what may be introduced inside the mask, while the < < is simply the left shift functionality. It executes exactly as it’s named, and PINBO is the number of locations that the “1” would sequence across the left hand side. To be precise PINBO may be equivalent of a 0.

So we begin with a 0b00000000, and put a “1” to produce 0b0000001 and then we transfer it to left 0 positions, which gives a exactly identical 0b00000001 as above.

Now, if supposing it was PINB4, the statement could be expressed as 1 < < PINB4. I this case the “1” would be pushed to the left 4 locations producing: 0b00010000.

Beware we are employing a zero index meaning there are four zeros after the “1”.

Now proceeding on to the “while” loop we had noting across the “infinite loop” earlier. But perhaps now we want the microcontroller to implement some of the desired executions. This may be only feasible inside the given loop. It’s the loop where the particular sequence is repeated again and again.

In case the execution would be placed prior to the loop, it would have implemented just once.

However in order to make the LED blink indefinitely it would required to switch the PINB0 alternately ON/OFF within the loop. Here we also find the delays being introduced, without which the blinking of the LED would be impossible. But this would force the LED to blink at a very rapid rate difficult to recognize with the naked eye, it would need to slow down a bit to become identifiable with our eyes.

We are aware the setting up procedure of a particular bit in the binary number, but not sure the method of applying a specific bit “0” in case it’s a “1” yet.

The following program could be seen doing this but we’ll also find that it may not be visible in the program.

The initial two statements changes the bit to “1” (5V, LED lights), then a pause is introduced for 100 ms.

The next couple of lines turns the PINB0 bit into “0” (zero voltage, LED shut off), but sorry the AND compare won’t be able to execute a “0” from the bit, but if we use NOT “~” for the binary mask it could switch all 0s into 1s and vice versa. 

This will enable us to influence only the PINB0 bit and flip it to “0”. The parenthesis was included in order to contain the masking execution such that the NOT operation could be applied for the whole masks and not simply over the “1” prior to the left shift “< <”.

PORTB |= 1 << PINB0;
_delay_ms(100);
PORTB &= ~(1 << PINB0);
_delay_ms(100); 

In order to create the ON OFF delays or the periods of equal duration, we may cut-short the previous four lines to two and apply XOR functionality in our benefit. It must be noted tat an XOR execution an assigned pin to a 1 in case it’s 0 and vice versa. This execution would only influence the PINB0. As may times the command is applied, it would simply turn the bit into the opposite of the existing logic.

PORTB ^= 1 << PINB0;
_delay_ms(100);

DONE! Your LED would be blinking now as per the set rate….Simple, wasn't that?

ليست هناك تعليقات:

إرسال تعليق