Arduino Analog Input and Outputs

Arduino Analog Input and Outputs

Arduino analog input and outputs control 2018

In this blog, we will see a very different kind of interaction that not only supports an on and an off state but also a number of different states between them. We will deal with Arduino analog outputs and outputs control. We will begin by fading an LED to later see a new circuit that controls the speed of a motor through an analog output.

 

Dealing with analog signals

As an introduction to the connection and programming of analog outputs, we will use the simplest circuit we have already seen, that is, we will connect an LED to our Arduino board but to deal with it analogically this time.

 

Before going into the details, I would like to introduce a couple of concepts that will help you when working with these kinds of signals.

 

The first thing you should know is that Arduino isn't really able to generate an infinite continuous analog signal, but instead, it uses a little trick to simulate it. Digital devices such as microcontrollers usually incorporate a peripheral called Digital to Analog Converter (DAC), which they use especially to perform this trick.

 

When working with a microcontroller, we pass a digital value to the DAC, and it converts it to an analog value but in a predefined range of possible values. The DAC is unable to generate an infinite set of output values; it has a finite input range of digital values and can generate a finite output range of analog voltages.

 

The number of steps the DAC can generate is called the resolution of the DAC. The Arduino DAC has an 8-bit resolution, so it accepts input values ranging from 0 to 255, which will be converted to analog values between 0V and 5V. If you divide the voltage range between the total number of steps the Arduino DAC accepts, you will conclude that every step of the input range increments the output voltage by almost 0.02V.

 

To perform this conversion, the DAC uses a method called Pulse Width Modulation (PWM) that consists of turning the output at very high frequencies on and off, resulting in a medium voltage that is the proportion of the on time with respect to the off time.

 

If you want to learn more about DACs and PWM, you can visit the corresponding pages on Wikipedia at http://en.wikipedia.org/wiki/Digital-to-analog_ converter and http://en.wikipedia.org/wiki/Pulse-width_modulation.

 

The analog output circuit

Once we know what is going to happen when we deal with analog outputs, I'll show you the circuit we are going to work with. The circuit to connect an LED to a PWM pin

Arduino Analog Input and Outputs

As you can see in the previous schematic, Interacting with the Environment the Digital Way, to deal digitally with an LEDHowever, in this case, we have to connect it to a PWM pin of the Arduino, pin 11 for this example, so that later in the program we can use the corresponding code to deal with it analogically.

 

The rest of the circuit is just the same as the blinking LED one, and we will use the same 220 Ohms resistance to limit the current that will flow through the LED to no more than 20 mA.

 

Connections diagram

If you still see connections better in the connections diagram for the breadboard, here you have the complete diagram for this example:

Arduino Analog Input

Analog control through code

The most valuable part of this example is not its physical part but its logical one, and I'll show you the associated functions to deal with analog outputs and a very important control structure in any programming language called a for loop in the code we will be using for this circuit.

 

The analogWrite() function

Dealing with analog outputs from the programming side is just a matter of using the analogWrite() function, which, as its name implies, writes an analog value through a pin.

 

It takes two parameters, similar to the digitalWrite() function:

  • The first one is the pin on which we want to operate (remember that it has to be one marked as PWM) on
  • The second parameter is the value we want to output, and that, as I told you previously, can take any value in the range of 0 to 255, 0 meaning 0V and 255 meaning 5V

 

The for loop

The other important concept we will come across in this example is a for loop, which is a very important control structure present in almost every programing language that allows you to repeat a block of code a specific number of times.

 

For its operation, a for loop needs what is usually called a control variable, that is, a variable that is going to take different values in a range for every iteration of the loop until it reaches a final value.

 

The general syntax of a for loop is as follows:

for (initialization; condition; increment) { instructions;

}

The three parts inside the parentheses have the following mission:

 

• Initialization: An initial value has to be given to the control variable. The loop will begin to iterate, with the control variable taking this value the first time.

 

• Condition: The loop will go on iterating as long as this condition remains true, stopping the iterations and going on with the next instruction as soon as the condition evaluates to false. The condition is usually based on the control variable remaining under or above an extreme value.

 

• Increment: This is a sentence where we change the control variable in order to continue adopting different values in the range through its way to the final value. Normally, we simply increment the control variable, but in some cases, as we will see in our example code, we could also decrement it.

An example will greatly clarify the concept. We could write the following block of code:

  • for(time = 100 ; time <= 1000; time=time+50){ digitalWrite(led, HIGH);
  • delay(time);
  • digitalWrite(led, LOW);
  • delay(time);
  • }

 

In this example code, we will begin by making the time variable take a value of 100 and make the loop iterate, executing all instructions inside as long as the time variable has a value less than or equal to 1000, incrementing it by 50 in every iteration. This way, we would make an LED blink with lower frequencies for every iteration, given that we have used the time variable as the parameter of the delay() calls.

 

It would result in delay(100) as the first iteration, delay(150) as the second one, delay(200) as the third one, and so on until the time variable gets to a value of 1000, in which case, the condition will evaluate to false and the for loop won't continue to iterate. The program execution will follow through the next line of code just after the closing curly bracket of the for loop.

 

For more information and some other examples of the use of a for loop, you can go and visit the for loop page on the Arduino site's Reference section at http://arduino.cc/en/Reference/ For.

 

Complete the fading LED code

Regarding the rest of the code, I'm going to use three variables; two of them, which I've called led and increment, won't really change throughout the execution of the program, but they will greatly increase the readability of the code.

 

The led variable is going to be used to store the pin number I'll use to control the LED, pin number 11, in this example. Remember that you can use whichever pin you want from those marked as PWM in the Arduino board and that you will have to set this variable as per your choice, accordingly.

 

The increment variable will hold the step size we will use in the for loops that we will use later. Using a variable just to use the increment value makes it very convenient to make future modifications by just changing its value at the beginning of the code without the hassle of having to search throughout the code for every occurrence of the pretended value.

 

The other variable, which is intensity, will be the key of this sketch, as it is going to be used as the control variable of two for loops that we are going to use to go all along the range of possible values for the analogWrite() calls we will use to gradually change the brightness of the LED.

Well, let's see this theory in action. Here is the complete code for the LED fading sketch:

// Global variables we will use int led = 11;
int intensity = 0;
int increment = 5;
// Configuration of the board void setup() {
// Set the pin we are going to use as an output pinMode(led, OUTPUT);
}
// Main loop void loop() {
// fade from minimum to maximum
for(intensity=0; intensity<=255; intensity=intensity+increment){ analogWrite(led, intensity); delay(30); } // fade from maximum to minimum for(intensity=255; intensity>0; intensity=intensity-increment){ analogWrite(led, intensity);
delay(30);
}
}

 

As I have explained previously, we begin by declaring and assigning initial values to the three global variables we are going to use all along the program. In the setup() function, we simply set the pin we are going to use as an output. In the loop() function, we have just two for loops: one taking values from 0 to 255 in increments of 5 and the other taking values from 255 to 0 using -5 increments.

 

In every iteration of each for loop, we simply set the changing value of the control variable, which is intensity in our code, as the analog value we want to output to the LED and wait for 30 milliseconds to allow our eyes to see the change. The first loop makes the intensity of the LED increase from 0V to 5V and the second one makes the intensity decrease from 5V to 0V, which is just the opposite.

 

I'll suggest that you play with this code, and as an exercise, you could make both parts of the fading run at different frequencies simply by setting different values for the increment variable just before entering the for loops, making it 10 when going up and 50 when going down. The resulting code could be as follows:

void loop() {
// fade from minimum to maximum in increments of 10 increment = 10;
for(intensity=0; intensity<=255; intensity=intensity+increment){ analogWrite(led, intensity); delay(30); } // fade from maximum to minimum in decrements of 50 increment=50; for(intensity=255; intensity>0; intensity=intensity-increment){ analogWrite(led, intensity);
delay(30);
}
}

 

Motor control with a transistor

Analog outputs can be very useful sometimes and not just to change the brightness of an LED. There are plenty of devices that operate on an analog signal; motors, for example, where you can change its speed by varying the voltage you apply to them.

 

However, motors can be sometimes tricky to operate, mainly due to the fact that they are big current consumers. A typical toy DC motor can easily consume more than 200 mA when running without a load and up to 1 Amp when stalled.

 

We mentioned in the previous blog that an Arduino pin can't give more than 40 mA, or it could burn. So, how can we deal with a motor using an Arduino? Well, usually when dealing with high-current devices, we use a driver circuit that allows the device to be powered from an external power source and use the Arduino pin just as a regulator.

 

This way, we can avoid the need to power the device directly from the Arduino pinlike we have done till now when dealing with LEDs that operate with under 30 mA and can be directly fed from Arduino pins.

 

Motor driver

This kind of circuit usually uses a transistor as an intermediate device that receives the Arduino signal and provides a proportional current coming from an external power source to the device. In the following schematic, you can see a typical assembly when operating a DC motor from Arduino:

 

The key element of this circuit is the transistor component, the one with the arrow pointing out that has three legs:

  • Base: This is the leg that we connect to the Arduino board through a resistor and that acts as the control element
  • Collector: This, simply said, is the leg where the current comes into the transistor
  • Emitter: This is the leg through which current flows out of the transistor

 

Regarding its operation, I like to compare a transistor with a water tap, where we turn the handle and, more or less, water comes out of it. In the transistor case, we set a variable voltage on the base, which allows more or less current to flow from the collector to the emitter and consequently, through all components we connect in between.

 

Keeping this in mind and taking a closer look at the previous schematic, we can realize that by connecting the base to an Arduino analog output, we can make a varying current flow through the motor, thus making its speed vary.

 

When dealing with transistors, it is important that you know which of the three legs is the base, collector, and emitter of your transistor. You should refer to its datasheet, which you can easily find on sites such as http://octopart.com.

 

There are two more components on the circuit that deserve a short explanation:

• The resistor: This allows the connection between the Arduino pin and the transistor base. Without going into too much detail, we will use a 1K resistance here.

 

• The diode: Without going into too much detail, you should know that a motor acts much like a big electromagnet and thus, when turned off, generates what is called a back Electromagnetic Force (EMF), which can even be 100 volts and with an opposite direction from the main voltage applied to the motor, which could damage your circuit.

 

By placing a diode in the opposite direction of the main voltage, you help suppress this dangerous back EMF. Any protection diode will do, such as the 1N4007, but if you don't have one to hand, you could even use an LED as long as you connect it correctly.

 

Power source considerations

There is the last question to consider before going hands-on with our motor control circuit, and that is the powering of the motor. For the purposes of this example, I'll suppose that you are going to connect a small DC motor that consumes no more than 250 mA when operating without a load.

 

This way, we could take current directly from the 5V pin of the Arduino board. It's important to keep this in mind because the power regulator present in your Arduino board takes current in the last instance from your USB port, which can't typically support more than 500 mA.

 

You should take some precautions before connecting a bigger motor to your Arduino board by measuring its typical power consumption. You can do this by placing an ammeter in the serial with a battery or another external power source and take note of the current it needs to run.

 

If the motor doesn't need more than the maximum 500 mA that your USB port and Arduino voltage regulator can give, then you can safely power it from the 5V Arduino pin. In other cases, you will have to provide another power source for the motor and connect both grounds: the one for your external power source and the one for your Arduino board.

 

The complete circuit

Well, that is enough theory for the moment; let's go into the real nuts and bolts of our circuit. Here, you have the complete schematic of the motor speed control circuit we are going to assemble for this example:

 

Arduino Analog  Outputs 2018

A motor speed control circuit Connections diagram

For the breadboard connections, we can save some wires by placing the diode just in contact with the transistor collector.

Notice that for the transistor used in this diagram, the legs are looking at it with the plain side in front from the left to the right, collector, base, and emitter, or, as you will usually find, CBE.

 

A breadboard connections diagram for the motor speed control circuit

dc_motor

Motor varying speed code

The code for this circuit is very similar to the LED fading one, but instead of using the for loop to go all over the range of values of the analog output, we will just use it to generate a three-iteration loop that will give us just three different speeds for the motor, which will make its changing state more evident.

 

Further, I couldn't make my motor spin with a voltage lower than 1V, so I will configure the loop to take the values 150, 200, and 250, which made my transistor deliver voltages of 1.5V, 2.5V, and 3.5V.

 

Here, you have the complete code I used for this example:

Global variables we will use int base = 6;

int speed = 0;
// Configuration of the board void setup() {
// Set the pin that we will connect to the transistor base as an output
pinMode(base,OUTPUT);
}
// Main loop
void loop() {
// Increment the speed of the motor in three steps, each for 3 seconds
for (speed=150; speed<=250; speed=speed+50){ analogWrite(base, speed);
delay(3000);
}
// Stop the motor for 1 second and begin again analogWrite(base, 0);
delay(1000);
}

Notice that every change in speed lasts three seconds and that once the three steps' loop ends, we stop the motor for one second before beginning all over again.

 

The assembled circuit

Motor_circuit

I'd like to show you a picture of the complete assembly that could perhaps clarify even more what we are doing:

A real assembly for the motor speed control circuit, As you can see, I've used a little piece of tape around the motor axle in order to make it clear when it changes its speed.

 

Bigger power motors

As I told you previously, when dealing with motors, this can consume more current than the maximum 500 mA your USB port can give. You will have to provide another power source just for the motor, such as an external battery or DC transformer.

analog

I have used an excellent and totally recommendable free software called EAGLE (http://www.cadsoftusa.com) to prepare a schematic for this kind of circuit that can perhaps help you understand what we pretend.

 

Here, you can see how the motor gets its current from the big battery and the only component between both circuits is the transistor, which is connected through its base to the Arduino board, its collector to the external power source, and the emitter to both grounds: the battery one and the Arduino one.

 

This way, you can not only provide a bigger current but also a different voltage to the motor that could, for example, operate at 12V as opposed to the 5V of the Arduino board. One final consideration with respect to this circuit is that you should look for an appropriate transistor, because every transistor has a maximum current that it can support, so be careful if you don't want to see little fireworks show on your desktop.

 

Sensing the Real World through Digital Inputs

Dealing with outputs is really just the half of the pie. Inputs are the other half, and if I may, I'd say they are the most interesting part of any project you will work on. In this blog, I'll introduce you to the use of digital inputs as a way to make your project sense their environment through the assembly and programming of two different examples that I'm sure you will like.

 

Sensing by using inputs

Inputs, whether they are digital or analog, are the way through which Arduino can sense what is happening around it. In some cases, they are used as an interface with the user, such as when we connect buttons and switches. In other cases, we use inputs to measure a physical variable that will make our project react in some way or other.

 

Nowadays, we can find almost a different sensor for every physical variable we want to measure and an endless number of devices that allow humans to interact with electronic devices. So, the first thing we will have to consider is the type of sensor we will need for our project and, most importantly, from the point of view of connection and programming, the type of signal it generates, digital or analog. This is because it will affect the way in which we have to connect it to our Arduino board, by way of a digital or analog input, and program our sketch accordingly.

 

peak

Digital sensors usually give us a 0V or 5V voltage or any way to obtain it, which can be easily traduced into HIGH or LOW values in the Arduino code. In other cases, they provide a different value that we will have, by means of additional circuitry, to adapt to the Arduino digital input allowed voltage, that is, 0V to 5V.

 

Regarding analog sensors, their main characteristic is that they provide a continuous value between a range, and we will also have to adapt them to our Arduino allowed range, but we will talk deeply about analog inputs and sensors in Blog 6, Analog Inputs to Feel between All and Nothing. At the moment, let's see the simplest digital input circuit, a switch, and how to program it.

 

Connecting a button as a digital input

The simplest circuit that we can prepare to be used as a digital input is that consisting of a switch connected to a digital input of the Arduino board.

 

A typical momentary push button usually has two states, open or closed, and acts like a switch that, when not pressed, keeps the circuit open, preventing the connection between the two parts of the circuit it connects, and when pressed, makes these two parts connected.

 

Keeping in mind that an Arduino digital input can sense values of 0V and 5V, we have to prepare our circuitry in such a way that it provides a 0V signal to the Arduino digital input when we want to consider it LOW and a 5V signal when we want to consider it HIGH. To be precise, the Arduino microcontroller can sense anything between 3V and 5V as a HIGH value and something between 1.5V and 0V as a LOW value, the range between 1.5V and 3V undetermined and, thus, not valid.

 

A basic switch connection to Arduino

Although it is a simple circuit, it may deserve some explanation. It basically exposes two different states: the button or switches pressed or released:

 

• Released: When the button is not pressed, the two parts of the circuit remain unconnected, thus not flowing any current through that branch of the circuit.

 

In this case, the Arduino board only senses a GND or 0V value through the digital input by which we connect this circuit to it due to the fact that it is physically connected to the ground through the resistor.

 

• Pressed: When we press the button or close the switch, what we are internally doing is connecting both parts of the circuit, that is, the 5V upper side to the GND lower side, allowing current to flow from one to the other through the 10K resistor. This is precisely why we use the 10K resistor:

 

To provide some load to this branch of the circuit, preventing the short-circuiting of the power source. From the point of view of the Arduino board, it senses a 5V signal in the pin we use to connect this circuit to the board.

 

The momentary push button

push_button

• The printed circuit board (PCB) soldering: These used to be smaller, really tiny in some cases, and they come with little legs that allow them to be soldered through holes in a PCB. In the screenshot, they are the three on the left-hand side.

 

• Panel mounting: These are the three on the right-hand side in the picture. Usually, they come in a much bigger size than the PCB kind and come with bigger connections so that wires can be soldered to them. They usually come with some kind of nuts that they can be fixed to a panel.

 

Different momentary push buttons

Physical differences apart and looking at them from the connection point of view, we have to notice an important difference between both groups.

If you take a closer look at the PCB group or, even better, if you perform a simple search on the Internet, you will notice that these kinds of momentary buttons usually come with a total of four legs instead of simply two. Usually, the reason is to give a stronger union to the PCB group by allowing up to four soldering points, but also because they have their connections duplicated to provide a more reliable connection between both points of the switch.

 

This simple feature has to be taken into serious consideration when connecting one of these buttons through a breadboard because if we connect them in the wrong way, we could easily short-circuit the Arduino board, with subsequent bad consequences.

 

The first thing you should do when using one of these momentary push buttons is to identify every leg so that you know which of them are internally connected. They usually come with some kind of indication or a diagram, but if they don't, you could always use a voltmeter or continuity tester to find out.

 

Once you have determined which legs are connected, you should always connect the momentary push button just above the centerline of the breadboard, which divides the two groups of holes in such a way that you leave two of the replicated connections out of use and ensure that the other two corresponding to the two contact points of the switch are always connected in different columns of the breadboard connections block. This way, they prevent a short circuit when you connect them to the positive rail (5V) and ground.

 

Also, remember that this kind of circuit needs a current limiting resistor in a part of the branch that gets closed between V+ and the ground to prevent a short circuit again. A value of 10K is more than sufficient.

 

Complete circuit schematic

Here, you have the complete circuit schematic for this example. As you can see, the connection point between the switch and the resistor is connected to the Arduino pin number 7 in this example, and we will use pin number 9 as an output to connect the LED that we will use to blink or fade.

 

Given that we will deal with the LED as a digital or analog device up to the pressing of the button, we have to connect it to the Arduino board through any of the PWM pins that will allow us to use it with the digitalWrite() or analogWrite() functions. The only consideration to be made about this circuit is regarding the right connection of the momentary button we will use, and we have talked about this in the previous paragraph.

A blink or fade circuit schematic diagram

push_circuit

 

Breadboard connections diagram

All that said, I'm sure you will see it clearly in the breadboard connections diagram, where you can notice how the two upper legs of the momentary push button are left on the upper-side connections block of the breadboard without connecting anything to them and separating them from the other two legs, thanks to the central space of the breadboard.

 

You can also see how once we push the button, the current flows from the positive rail to the ground through the switch and the current limiting resistor, and it is at just this point, after the switch and before the resistor, where we take a wire to the Arduino pin that we will use as a digital input.

 

Writing code to react to a press

Before we go into the details of the programming of such a circuit, we'll have to decide what behavior we will unchain in our project once the event of a press is detected. For the sake of simplicity, we will make an LED blink or fade depending on the press of the button.

 

This way, we can test all that we have already learned in a simple example and this will also lead us to meet another very important control structure of any programming language, called a conditional bifurcation, which some say is the basic structure that makes any program a logical structure and not a simple sequence of instructions.

 

Once the circuit is assembled, let's take a look at the code we are going to write to detect and react to the button press as a digital input. Here, you have the complete code for this example:

// Global variables we will use int led = 9;

int button = 7; int pressed = 0; int intensity = 0; int increment = 10;
// Configuration of the board: one output and one input void setup() {
pinMode(led, OUTPUT); pinMode(button, INPUT);
}
// Sketch execution loop
void loop(){
// We read the button pin pressed = digitalRead(button);
// if it is not pressed lets blink digitally if (pressed == LOW) {
digitalWrite(led, LOW); delay(50);
digitalWrite(led, HIGH);
delay(50);
}
// otherwise lets fade analogly else {
for(intensity=0; intensity<=255; intensity=intensity+increment){ analogWrite(led, intensity); delay(30); } for(intensity=255; intensity>0; intensity=intensity-increment){
analogWrite(led, intensity);
delay(30);
}}
}

 

Configuring and reading a digital input

From the point of view of programming, there are basically two main new concepts in this example regarding the use of a digital input:

 

• pinMode(button, INPUT): In the setup() function, we have to set the pin we are going to sense as an input so that Arduino can read from it. The function is just the same pinMode() function we have been using so far, but instead of using the OUTPUT constant, this time, we use INPUT to set the pin accordingly.

 

• digitalRead(button): When we deal with an input whether it is a digital or analog one, we are going to receive the real value instead of setting a value like how we have been using outputs. This means that we only pass a parameter indicating the pin to be read to the reading function, analogRead() in this case, but it also means that this function, as opposed to writing functions, is going to return us a value that we have, in some cases, to store in a variable for later use.

 

Being realistic, in this example, it isn't really necessary to store the real value in a variable because we are not going to use it anymore in the rest of the code, and we could simply have used the digitalRead() function inside the if parentheses like if(digitalRead(button) == LOW), but for the sake of clarity in this first example, I preferred to use a variable this time.

 

Taking decisions with conditional bifurcations

Besides the differences between the use of inputs and outputs, there is an even more important concept in this example, and it is the use of the if control structure to decide what has to be done depending on the state of a previous event. The if control structure is the basis of any programming language, giving them the power to decide and act on consequences.

 

The simplest syntax of the if the sentence is as follows:

  • if (condition) {
  • Block of instructions to be executed
  • }

Being a condition, any logic expression is one that evaluates as true or false and that can use logical operators such as == (is equal to), > (is bigger than), < (is less than), or != (is different).

 

In a more complex format, the if control structure can even include a block of instructions to be executed in case the condition evaluates as false, in which case, its syntax is as follows:

  • if (condition) {
  • instructions to be executed in case the condition evaluates as true
  • }
  • else {
  • instructions to be executed in case the condition evaluates as false
  • }

As you can see in the code for our example, this format is the one we have used to get two different reactions on the pressing of the button:

• If the pressed == LOW condition is true, being pressed the value read from the digital input and meaning no press on the button, we execute a simple blink

 

• In the case of the condition being false, which means that there has been a press on the button, we execute the block of instructions contained in the else branch of the code

 

For a deeper reference with respect to the if control structure in the Arduino programming language, you can visit the Arduino website's Reference section, particularly the pages related to if and if … else at http://arduino.cc/en/ Reference/If and http://arduino.cc/en/Reference/Else.

 

Timing and debouncing

If you play a little with the previous circuit once programmed, you can easily conclude that the reaction to the button press is not immediate, and it is due to the fact that in the code, the button press is only read once the reaction, blinking or fading, has concluded and both of them take their time, even if short.

 

There is another final consideration with respect to this example that is called debouncing, and that is due to the physical way in which electrical contacts are made when pressing a button.

 

Although it's hard to imagine, when you press a button, the state oscillates between on and off before the contract settles down, which can lead to incorrect readings of a sensor in the code.

 

You can learn more about switches and debounce them on the Wikipedia page for switches at http://en.wikipedia.org/wiki/Switch. The Arduino site also has a very interesting page exclusively dedicated to buttons debouncing at http://arduino.cc/en/pmwiki.php?n=Tutorial/Debounce, which deserves a reading.

 

Other types of digital sensors

Switches are perhaps the most used devices as digital input sensors but obviously not the only ones. Any device that can open or close a circuit branch can be easily configured and connected to Arduino to act like a digital input sensor, from a reed relay (http://en.wikipedia.org/wiki/Reed_relay) to a PIR motion detector (http://en.wikipedia.org/wiki/Passive_infrared_sensor). One of those devices that are very cheap and easy to acquire are optocouplers or, as they are sometimes referred to, optical switches.

 

An optocoupler is a very simple device that has two parts:

• An infrared light emitter: This is a simple infrared LED in a housing that directs its light emission in a precise direction

 

• A phototransistor: This is a special kind of transistor whose base is activated by the reception of light, infrared light in this case, and also in a special case that ensures that the phototransistor gets excited only with light coming from a concrete direction—that of the infrared LED on the other part of the housing

 

The world through Digital Inputs

In the following couple of images, you can see the schematic of the internal structure of a typical optocoupler and a real picture of the one I used for my own assembly of the next project: The internal structure of an optocoupler and a real one. If you take a closer look at the picture, you may even notice the indications on the plastic housing of the emitter part with its diode sign to reference the anode and cathode and the collector and emitter markings on the phototransistor part.

 

If we connect the phototransistor part to our Arduino board, we could easily detect whether it is being excited or not, thus indicating whether there is something placed just in the middle of the plastic housing or not.

 

This was the same principle that used the first mechanical computer mice to detect and count the X and Y movement, and for that, they used a very recognizable small slotted wheel that allowed for its internal microcontroller to account for every step the mouse took in every axis.

 

If you are too young, perhaps you have never seen one of this kind of mice, but you could take a look at the Wikipedia entry for mouse under the Mechanical mice section at http://en.wikipedia.org/ wiki/Mouse_(computing). In the next example, we will use an optocoupler as a light barrier that when interrupted, triggers a digital input.

 

Using an optocoupler as a coin detector

coin_detector

If we take advantage of the fact that there is a small space between the emitter and receptor part of a typical optocoupler that allows a coin to pass through, we could easily use one of them to create a simple coin detector that could be used for a bigger project—who knows, perhaps a candy vending machine or your next arcade game cabinet.

 

From the point of view of the circuit, we will have to provide little additional circuitry—only a pair of resistors: one to limit the current through the infrared LED and another to act as a load for the phototransistor between its emitter and collector.

 

Regarding the reaction we will get once the coin has been detected, I'll simply turn on an LED for the sake of simplicity in this example project and to allow you to focus on the digital input side of the circuit and corresponding code.

The schematic of the coin detector In the following diagram, you can see the complete schematic for the circuit we will use in this example:

                         coin_dector

 

The complete circuit for an optical coin detector

As you can see, from the optocoupler side, I have only added the two resistors I mentioned previously: a 10K to act as a load for the phototransistor and a 470 Ohms one to limit the current through the infrared LED. There is just an additional consideration. If you take a closer look, you could notice that in this case, I have connected the LED that is going to be used as the output side of our project in a different way than in other examples in the blog.

 

In this case, I haven't connected the LED from the Arduino pin to the ground but just the opposite way, that is, from 5V to the Arduino pin, just to show you that you can also operate the LED in a negative way. This means that setting the Arduino pin to HIGH won't allow any current to flow through the LED, and setting the pin to LOW will allow approximately 10 mA to flow through the LED and into the Arduino board.

 

I've done it this way just to show you that it is not always necessary to provide current to output devices, but they can also can be powered from the V+ voltage source and use the Arduino pin as a virtual ground as long as the total current doesn't exceed the 20 mA limit of the total current capacity of any Arduino pin.

 

Regarding the breadboard connections, they are a little more complex this time due to the fact that the optocoupler housing of the Fritzing part I used was a little too big for the breadboard, so I've had to use some extra wires.

 

That apart, please keep in mind that the exact optocoupler you may find might not have the same pin distribution as the one used in this diagram, and you should refer to your specific component datasheet to adapt the wiring connections to your optocoupler or you could easily damage it.

 

Sensing the Real World through Digital Inputs

The complete example code

There is nothing really new in the code that we will use for this example. We will, just like in the previous one, simply read the digital input corresponding to the phototransistor and only if it is a HIGH value, which means it is not receiving any light and thus not conducting, will we make the output LED blink.

 

Once again, just for the sake of simplicity, and given that now we know that we don't really need to store the value read with digitalRead() and we can simply call the functions inside the if condition, I have opted this time to save up this variable and simplify even a little more of the code:

// Global variables we will use int led = 13;
int phototransistor = 8;
// Configuration of the board: one output and one input void setup() {
pinMode(led, OUTPUT); pinMode(phototransistor, INPUT);
}
// Sketch execution loop
void loop(){
// We read the optocoupler pin
// and if the phototransistor doesn't receive light keep blinking
if(digitalRead(phototransistor)==HIGH){ //simply blink
digitalWrite(led, LOW); delay(50); digitalWrite(led, HIGH); delay(50);
}
}

 

A real working project

Finally, here you have a real picture of the complete circuit assembled with the optocoupler I had and a coin being detected:

Analog Inputs to Feel Between All and Nothing

We have come a long way up to this point, learning to deal with digital and analog outputs and also digital inputs. It is now the moment to show you how to manage analog inputs, as they are what enrich the microcontroller field of application the most.

 

In this blog, I have prepared two projects to help you understand how to connect, configure, and program analog inputs and what kind of things we can do with them. I'm sure you will be totally amazed once you get the point.

 

Sensing analog values

In this blog, we need to know about the DAC cousin, the Analog to Digital Converter (ADC). An ADC is a device with just the opposite mission of a DAC, that is, a device that takes a signal that can theoretically have an infinite number of states and convert it to just a few concrete values, or in Arduino jargon, takes an analog signal and converts it to a digital value.

 

Just like the DAC, the Arduino board comes with a six-channel ADC with a 10-bit resolution for each channel. This means that we can deal with up to six different analog signals ranging from 0V to 5V that will be converted to values between 0 and 1024.

 

Controlling Outputs Softly with Analog Outputs, the DAC had just an 8-bit resolution, allowing for values between 0 and 255, so we will have to keep this little difference in mind when working on projects that sense and act in an analog way, and we will have to make some kind of correspondence between the 1024 possible input values and the 255 maximum output values: a usual operation commonly called mapping.

 

The Arduino map function

Mapping a value from one range to another is a very simple thing. It's just a matter of finding which value will be at the same point of the output range as compared to the input range. Let's see it with a simple example.

 

If we have a possible input value of 0 to 100 and an allowed output range of 0 to 500 and we take a sample value of 75, we can say that it is at 75 percent of its input range, can't we? Well, which value will be at 75 percent of the output range, then? We will usually just make a simple correspondence:

 

  • Output Value = (Input Value x Maximum Output Value) / Maximum Input Value Or, we will use the values in our example:
  • Output Value = (75 x 500) / 100 = 375
  • Here, 375 is just 75 percent of 500. Simple, isn't it?

 

It is so simple but also so common in the Arduino environment that we have a specific function to make this kind of mapping in the Arduino language, which is appropriately called the map() function.

 

As you can see by following the previous example, the map() function takes no less than five parameters: map(value, from Low, from High, to Low, to High) and returns us another value. The map() function parameters' meanings are as follows:

  • value: This is the value we already have and want to tap into a new range
  • from Low: This is the lower limit of the possible input range
  • from High: This is the upper limit of the possible input range
  • to Low: This is the lower limit of the possible output range
  • to High: This is the upper limit of the possible output range

 

Finally, the function simply returns to us the mapped value corresponding to the output range.

Perhaps all this seems a little complex, and you don't want to make so many mathematical operations, but in just a moment, when we see our first example using analog inputs and outputs, you will immediately get the point and will love the map() function; believe me.

 

An ambient light meter

For our first example using analog inputs, I'd propose that you build an ambient light meter: a device that indicates the amount of ambient light it can sense from its environment in some way and shows it in a visual manner, which is a perfect beginning for your next burglar detector.

 

For the purpose of this example, we will use a very interesting electronic device called a photocell or light-dependent resistor. A photocell is simply a specific type of resistor that varies the resistance it offers according to the amount of light it receives from its environment, exhibiting a photoconductive behavior, that is, lowering its resistance as the light increases and vice versa, commonly ranging between a few ohms when exposed to a bright light and up to some megaohms when totally in darkness.

 

In the following picture, you can see a typical photocell and the usual schematic symbols you can find to refer to it:

 

A real photocell and its most common schematic symbols

Unlike any other resistor, a photocell doesn't have a polarity, which means that you don't have to observe the way you connect it in your circuit. It does its job equally in one way or the other, but being a variable device it makes us give some considerations when connecting it to our Arduino board.

 

Connecting a variable resistor to Arduino

As mentioned previously, a photocell can decrease its internal resistance up to only a few ohms when exposed to a bright light and theoretically, it could even reduce it to zero when in the presence of a very bright light; in this case, it acts like just a simple wire with 0 ohms resistance. With this in mind, we need to modify our circuit to prevent a short circuit in case this situation arrives.

 

Given those connecting variable resistors as analog input sensors to Arduino is a very common case, let's see a simple circuit that will ensure we will never damage the Arduino board.

  • A general variable resistor circuit to connect to Arduino can be like what is shown in the following diagram:
  • A typical circuit to connect a variable resistor to an Arduino analog input

 

As you can see, in some way, the circuit is very similar to the one used when connecting a digital input to Arduino. It also uses a 10K ohm load resistor to prevent a short circuit in case the photocell internal resistance decreases down to zero.

This is not a typical situation but it could happen, especially when connecting other types of variable resistors.

 

Voltage divider

This kind of circuit is commonly known in the electronic jargon as a voltage divider, because it splits the provided voltage in two steps according to the proportion of the value of the first resistor to the other. We should keep this in mind when selecting the resistance we are going to use as protection.

 

We should always try to select a protection resistor of a value lower than the main variable resistor; this way, the main voltage drop will be placed just in the variable resistor acting as a sensor, that is, the photocell in our case. This way, we allow Arduino to sense what is happening in the variable resistor with greater precision and use only the load resistor as protection.

 

An ambient light meter circuit

Here, you have my proposed circuit to be used as our first analog input example: It has a voltage divider consisting of the photocell and a 10K ohm load resistor as the input circuit, just like the one I showed you in the previous section.

 

Regarding the output part of this circuit and trying to keep things simple, I have reused the assembly of the traffic light, but this time, we will use it as a level indicator with four possible states: low, medium, high, and maximum, being represented by none, one, two, or three turned-on LEDs.

 

From the point of view of used pins, I have connected the three LEDs to digital pins 11, 12, and 13 and the voltage divider to analog input 0.

 

Breadboard connections

At this point in our work, I assume that you will be very accustomed to working with the breadboard, but in case you still have some doubts or the schematic is not clear enough for you, here you have the breadboard connection diagram of the ambient light meter project: A breadboard connections diagram of the ambient light meter circuit

 

Programming to sense the light

  • From the point of view of programming, dealing with an analog input is not that different when compared to dealing with a digital one.
  • Just like when reading a digital input, we are going to receive a value from the reading function, analogRead(pin) in this case.
  • We will read from a pin that we have previously set as an input in the setup() function of our sketch by a call to the pinMode() function.

 

Interacting with the Environment the Digital Way, the Arduino board has different pin headers for digital and analog input connections. When connecting something to your board that is going to be read in an analog way, you have to mandatorily use one of the Analog In pins of the Arduino board—those on the lower side of the board close to the Power pin headers.

 

You can only read an analog value through the use of the analogRead(pin) function from one of the Analog In pins of your board; definitely take this into consideration.

 

Due to the fact that the analog inputs have their own exclusive pins, it is not compulsory to configure them as INPUT in the setup() function, because they are always inputs, but for the sake of clarity and learning purposes, I'll include this pinMode(pin, INPUT) function call in the examples.

 

An ambient light meter code

This example is a typical case that resolves a common situation when working with microcontrollers: it is common to have to act in a set of ways depending on an input value. In our case, the project aims to turn on zero, one, two, or three LEDs depending on the magnitude of the ambient light surrounding the photocell. Just for this typical case, most of today's programming languages have a similar control structure commonly known as switch/case.

 

Analog Inputs to Feel Between All and Nothing

The switch / case control structure

The general syntax of a switch / case control structure in the Arduino programming language is as follows:

switch (var) {

case label:
// statements break;
case label:
// statements break;
default:
// statements
}

 

The operation of this sentence allows us to opt for a branch of code execution depending on the value of a variable. In the preceding general syntax, we can end up executing any of the statements of the three case branches depending on the value of the var variable enclosed in parentheses following the switch word. If none of the labels equal the variable value, the optional default section will be used, if present.

 

In our example, we will manage to obtain a variable that represents the light level divided into four possible states that will be used to separate the code in four different branches, each one turning on the LEDs accordingly. Well, enough of theory for the moment. Let's take a look at the complete code of this project, and I'm sure you will get a clearer picture:

Global variables we will use

// One for each pin we will use and
// two for the value reading and conversion int redLED = 13;
int yellowLED = 12; int greenLED = 11;
int photocell = 0;
int value = 0;
int state = 0;
// Configuration of the board: three outputs and one input void setup() {
pinMode(redLED, OUTPUT); pinMode(yellowLED, OUTPUT); pinMode(greenLED, OUTPUT); pinMode(photocell, INPUT); //optional
}
// Sketch execution loop
void loop(){
// Read the sensor and convert the value to
// one of the four states we will use value = analogRead(photocell); state = map(value,0, 200, 1, 4);
// acts depending on the obtained states switch(state){
case 1: digitalWrite(greenLED,LOW); digitalWrite(yellowLED,LOW); digitalWrite(redLED,LOW); break;
case 2: digitalWrite(greenLED,HIGH); digitalWrite(yellowLED,LOW); digitalWrite(redLED,LOW); break;
case 3: digitalWrite(greenLED,HIGH); digitalWrite(yellowLED,HIGH); digitalWrite(redLED,LOW); break;
case 4: digitalWrite(greenLED,HIGH); digitalWrite(yellowLED,HIGH); digitalWrite(redLED,HIGH); break;
}
}

 

Most of this code has already been explained, but let's make it clearer.

We begin by declaring some variables we will use all around the code: four just to reference the pins' numbers (red LED, yellow LED, green LED, and photocell), two more to store the analog sensor read value (value), and the converted one to meet our need in the switch / case control structure (state), as follows:

int redLED = 13;

int yellowLED = 12;
int greenLED = 11;
int photocell = 0;
int value = 0;
int state = 0;
In the setup() function, we just configure the pins we are going to use. Remember that it is not compulsory to declare the analog input pins as INPUT, but it doesn't hurt:
pinMode(redLED, OUTPUT);
pinMode(yellowLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(photocell, INPUT); //optional
In the main loop of our sketch, we simply read the analog value given by the sensor (value) and convert it to the desired output range (1 to 4 in our case) in the state variable:
value = analogRead(photocell);
state = map(value,0, 200, 1, 4);
Finally, we use this mapped returned value as the conditional element of the switch / case structure to select one out of four possible code branches:
switch(state){
case 1:
digitalWrite(greenLED,LOW);
digitalWrite(yellowLED,LOW);
digitalWrite(redLED,LOW);
break;
case 2:
digitalWrite(greenLED,HIGH);
digitalWrite(yellowLED,LOW);
digitalWrite(redLED,LOW);
break;
case 3:
digitalWrite(greenLED,HIGH);
digitalWrite(yellowLED,HIGH);
digitalWrite(redLED,LOW);
break;
case 4:
digitalWrite(greenLED,HIGH);
digitalWrite(yellowLED,HIGH);
digitalWrite(redLED,HIGH);
break;
}

 

Calibrating the sensor

If you take a closer look at the previous code, you should notice the two parameters corresponding to the input range in the state = map(value,0, 200, 1, 4); sentence.

 

I found these values valid for my photocell by using a technique to calibrate our sensors that I'll show you in Blog 8, Communicating with Others; for the sake of simplicity for this example, I won't show you until then. For this project, you'll have to find the valid range of values that your photocell is returning by trial and error. If you still aren't able to find valid values, Communicating with Others, and come back later.

 

Once you've correctly set the valid input range for the map function, the ambient light meter should turn off every LED with a normal ambient light and turn the LEDs on sequentially as you cover the photocell with your hand, turning the LEDs completely when you completely cover the photocell with your finger; isn't it a good way to detect someone approaching?

 

DC motor speed control revisited

For the second example of using analog inputs, I have to use a very common electronic component in almost any project: a potentiometer, or simply, a variable resistor, which is a component that by the use of some kind of knob, allows us to change the resistance it offers. Potentiometers are all around us, from the volume knob on your sound equipment to the temperature regulator of your heating system.

 

The potentiometer

Two typical potentiometers along with their corresponding schematic symbol are shown as follows: Two typical potentiometers and their schematic symbol

 

The component itself has three legs. If you measure the resistance between the external two legs, you should get the total resistance of the potentiometer, but if you take the measure between the central leg, usually called cursor, and any other, you will get a resistance proportional to the rotational angle of the potentiometer.

 

In our project, we will use it as a kind of a throttle for our DC motor by making the speed of the motor a function, or dependent, of the potentiometer position.

 

The motor speed control schematic

Here, you have the project schematic. It's nothing new, as you can see. The input side of the circuitry is similar to the input part of the ambient light meter, and the output side is similar to that of the motor driver in Blog 4, Controlling Outputs Softly with Analog Outputs.

I have once again used pin A0 to read the input and in this case, I will act on PWM pin 6 to control the motor speed through a transistor.

 

The DC motor speed control schematic

Next, you can find the breadboard connections diagram for the proposed circuit. The only components you should care about are the diode and the transistor.

 

The diode should be correctly placed because of its polarity. The bar indicating its cathode should be in contact with 5V. Regarding the transistor, I used a BC547 with its legs ordered as CBE in my assembly; keep this in mind or refer to your transistor datasheet to know its own pinout before connecting it.

The DC motor speed control breadboard connections diagram

 

A simple code to control the motor speed

The code for this project couldn't be simpler. Just read, convert, and output the mapped value to the motor. Here is the code:

// Global variables we will use

// One for for the potentiometer
// and another to command the transistor
// Two variables to store read and converted values int pot = 0;
int base = 6;
int potvalue = 0; int motorspeed = 0;
// Configuration of the board: three outputs and one input void setup() {
pinMode(base, OUTPUT); pinMode(pot, INPUT); //optional
}
// Sketch execution loop
void loop(){
// Read the sensor and convert to the
// allowed output range for an analog output potvalue = analogRead(pot);
motorspeed = map(potvalue, 512, 1023, 100, 255); analogWrite(base, motorspeed);
}

 

Once again, I have used a little bit of calibration to get to the best values for the input and output ranges of the map() function. By using a 10K ohm potentiometer and a 10K ohm protection resistor, I got values from 512 to 1024 from the potentiometer. Regarding the motor, outputting less than 100 was unable to make it spin, so finally, my conversion is motor speed = map(potvalue, 512, 1023, 100, 255);.