Tricking the machines

So far, we’ve managed to get the micro controller to read digital & analog inputs, ad set a variety of fancy LED effects. Now it’s time to make some even more fancy things happen.

The microcontroller has the ability to red variable voltages, but what about sending out a variable voltage? Unfortunately, unless we’re using a high end microcontroller with a built in DAC (digital to analog converter), there’s no way to get a true analog voltage out of the microcontroller. However, we can fake it with a technique called Pulse Width Modification (PWM).

On your Arduino Uno, you’ll notice that there are some digital pins with a ~ next to the number. These pins have PWM capabilities.

PWM is a method in which you pulse a pin on and off rapidly to give the illusion of a variable voltage. This is also called an effective voltage. The Arduino has an 8-bit PWM, which means there are 256 discrete steps available to us. In each period the pin will be pulled HIGH for a fraction of the time and LOW for the rest. The percentage of time this rapid on/off happens can be described as the duty cycle.

The method for communicating with the Arduino is called analogWrite(). It takes to arguments. The first argument is the pin you’re communicating with. The second argument is the value you wish to write. 0 is the same as 0V, 255 is the same a 5V. 127 would be 2.5V, and everything else in between maps out linearly.

It’s pretty simple to hook up a pot to an analog input and use that to control an LED’s brightness. Remember though, analogRead() returns a value between 0-1023, while analogWrite() only goes between 0-255. 256 goes into 1024 four times, so we can divide by 4 to get a nice mapping between the two :

Speaking of mapping, it’s not a bad idea to think about how we would go about getting the full range of an LED when using a sensor like a photocell (which tends to have a more limited range than a pot).

Let’s assume we have a photocell that gives us 400 as a low value from analogRead() and 800 as an upper value. Clearly this isn’t going to work well for fading an LED. We could math our way out of the problem, but fortunately for us, we can use a function called map() which does the math for us. map() changes a number from one value to another based on a set of ranges. It takes 5 arguments : value to change, low value from input, high value from input, low output, high output. So if we were to use map() in out existing example, and we wanted 400 from the sensor to be 0 to analogWrite(), and 800 from the sensor to 255 for analogWrite(), we could do the following :

map() doesn;t constrain numbers, so it’s possible to get mapped values outside the desired range. We can remedy that by 1) adding or subtracting some to the incoming values, or 2) calling the constrain() function. constrain() places an upper and lower bound on a number.

Another way to deal with sensors that have variability in their inputs (and deal with environmental differences) is to calibrate your sensors, mapping from the max & min values.

Related to PWM, but different, is frequency modulation. We can use this in conjunction with a small speaker or piezo element to generate a sound. In PWM, there’s a fixed frequency. With tone(), you can change the frequency of a duty cycle fixed at 50%. In this example, there are switches attached to pins 2, 3 & 4.

We can also use pulses to control other things .. like motors! A servo motor is a geared motor with a circuit and a potentiometer inside. The pot measures the angle of the gearhead, allowing us to position it exactly where we would like. Most servos rotate 180 degrees.

The circuit inside the servo listens for a series of pulses that dictate where the motor should rotate to. While it’s possible to write code that sends the pulses using delayMicroseconds() and a self-programmed timer like below :

it’s hella easier to simply use a library.

A library is an assemblage of code that extends the Arduino’s capabilities. The Servo library is bundled with Arduino (you can install other libraries, or write your own if you’re feeling inspired).

The servo library generalizes the “problem” of writing the above code, and wraps it all up with a few easy to use functions. To use a library in a sketch, you must first import it at the beginning of your sketch.

Once that’s there, you have access to all the functions in the library. To use a servo once you’ve imported the library, you’ll need to create an instance of the servo library. Think of it like creating a specialized variable (instead of int or long, you’re creating a type Servo). Once that’s done, you’ll need to attach() the servo to the pin it’s on, then you’ll be able to write() any angle you want. Below is code that will allow you to control the position of a servo with a pot or another analog sensor.

 

Comments are closed.