Microcontrollers
The Next Step
6th June, 2020. Author - Anirudh Singh.

What is a microcontroller really?

A microcontroller is a single-chip computer - a small computer with the bare minimum stuff to run programs on and create cool stuff.

Microcontrollers vs Microprocessors

You might have heard both the terms at least a bazillion times. Here's the difference: Basically, a microcontroller constitutes a microprocessor. It's like your desktop tower. There's a CPU who's the big kid on the street and runs the show. Then there are these small kids whose sole purpose of existence is to serve the requirements for the big fat kid. These include RAM, Secondary storage, I/O ports, among several other things. When put together, it makes a microcontroller. Here's a diagram to support the explanation:

Now, development boards (like the Arduino Uno, as featured in the last post) house in these microcontrollers and allow us to program and control them. (Uno has the ATmega 328p, but what's in the name anyway?)

Microcontrollers are used everywhere - from washing machines to satellites; from toy cars to cutting-edge autonomous cars. But to do that, they need more help, from devices like sensors, which leads us to:

An Intro to Sensors

Sensors are those thing-a-ma-jigs which allow a microcontroller to sense the real world. They convert a physical stimulus (like change in temp, height, acceleration) to digital (binary) signals, so the microcontroller can read them. There's a sensor available to measure almost every physical phenomenon.

Want to record the temperature for your fish tank project? Cool, there's the temperature sensor. Want to control the height of your autonomous drone? Look, there's the altitude sensor. You can measure the humidity, orientation, measure light intensity, acceleration, record images, make 3D scans of the real world (like what some self-driving cars do), and do any other thing imaginable with the right sensors!

Turning an LED on (...again?)

Here we go, making an LED on an Arduino Uno blink. Again. But this time, we are going to do it with a push-button (a nice example for a sensor).
A push-button looks like this.

It is a simple switch like the one that turns your fans on and off, really. The only difference is since these devils are so small. Because they have elastic metallic contacts, they tend to generate noise on clicking.
This is called a switch bounce.

So come, young padawan, we are going to hack these little devils and read proper click on a push button.

int ledPin = 13; // choose the pin for the LED (ADD A RESISTOR TO any electrode of led
int inPin = 7; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
void setup() {
pinMode(ledPin, OUTPUT); // declare LED as output
pinMode(inPin, INPUT_PULLUP);
// declare pushbutton as input and *TURN ON THE INPUT PULLUP RESISTOR
//enabling the input pullup prevents directly shorting the digital pin to ground
void loop(){
val = digitalRead(inPin); // read input value
//with input pullup enabled, the inPin is HIGH when button is released and LOW when pressed
if (val == HIGH) { // check if the input is HIGH (button released) digitalWrite(ledPin, LOW); // turn LED OFF
}
else {
digitalWrite(ledPin, HIGH); // turn LED ON
}
}
view raw btnSimple.c hosted with ❤ by GitHub

Now, since these switches undergo an identity crisis when we click them. To go around this, we are going to 'delay' (the Arduino way to say: waiting for a specified period) and recheck, just to make sure if the button was really clicked.

const int buttonPin = 7; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = HIGH; // the previous reading from the input pin
lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
// set initial LED state
digitalWrite(ledPin, ledState);
}
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from to LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is LOW(button pressed)
if (buttonState == LOWHIGH) {
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}
view raw btnBounce.ino hosted with ❤ by GitHub

Voila! We have successfully captured a button press. Now think about this: your TV remote, smartphone, laptop, gamepads - all have been doing all this, without fail, recording each of your keypresses precisely (they are not necessarily mechanical push-buttons, but you know what I mean!).

With this, let’s turn our heads to...

PWM

Cool. We have officially turned on and off LEDs with timers and buttons. But we want more! Now we are going to change the intensity of the LED. To change the power output, we can change the average power supplied to the LED in two ways:

However, LEDs have an optimal operating voltage (deviating too much from may break it). And what if we want to connect it to a Digital Pin(A pin that can only output at 2 levels: ON or OFF)? As eccentric as it may sound, we usually go about the second way to dim a LED. And this is called PWM (Pulse Width Modulation).
Here's an image showing PWM at different duty cycles (or simply put, the percentage of time the signal is high in a cycle)

Here's a crude way to turn it on and off for half a cycle of 20 milliseconds.

int ledPin = 13; // LED connected to digital pin 13
void setup() {
pinMode(ledPin, OUTPUT); // sets the pin as output
}
int cycle_len = 20; //cycle len of approx 20ms = 50Hz
float duty_cycle = 0.5; // turn it on for half a cycle
void loop() {
digitalWrite(ledPin, HIGH);
delay(int(duty_cycle * cycle_len));
digitalWrite(ledPin, LOW);//turn it off for another 10ms
delay(int((1 - duty_cycle) * cycle_len));
}
view raw pwmSimple.ino hosted with ❤ by GitHub

Hooray! But there's more. Luckily, this ugly piece of code has already been written in libraries. So here we go:

int ledPin = 9; // LED connected to digital pin 9
//IMP: Only some digital pins support PWM(labelled with '~'). Be sure of the connections!
void setup() {
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop() {
analogWrite(ledPin, 128); //analogWrite takes values from 0 to 255.
//0 meaning off, and 255 = complete on
}
view raw pwmLibrary.ino hosted with ❤ by GitHub

Now, that’s more like it!
We can now read misbehaving button clicks and change the brightness of LEDs. If you want to try, you can also mimic sinusoidal signals with PWM! There’s a lot more you can do, but I’ll leave you with room to think of more applications of what we’ve learnt today!

Kudos for making it all the way till here!
Until next time...

Resources

Subscribe below to receive emails about more such awesome articles

Click here
to receive emails about new posts