Maker.io main logo

Circuit Playground Analog Input

2017-03-14 | By Adafruit Industries

License: See Original Project

Courtesy of Adafruit

Guide by Carter Nelson

Overview

In this guide we will use our Circuit Playground along with a potentiometer and some alligator clips to explore how we can read analog signals into our digital computer.

No soldering required!

 

Required Parts

In addition to the Circuit Playground, you will need some alligator clips and a potentiometer. While not required, a knob makes turning the potentiometer easier and provides a nice reference mark to see where you are at.

Required Parts

Optional Parts

Another option is to use a breadboard along with a trim pot and alligator to male jumper wires. The hardware outlined in the previous section is recommended, but if you already have these items, they will work as well.

Before Starting

If you are new to the Circuit Playground, you may want to first read these overview guides.

This project will use the Arduino IDE. Make sure you have added the board support for the Circuit Playground as well as installed the Circuit Playground library. MUST DO BOTH. This is covered in the guides linked above.

Analog vs. Digital

Analog World

Pretty much every phenomenon in the natural world is analog. What does "analog" mean? The key bits boil down to this phrase in the definition for analog:

...continuously variable physical quantities...

The "physical quantity" can be anything - temperature of an apple, pressure in a balloon, water level of some lake, total internal energy of the third moon of Omicron Persei 8, voltage between two points in an electrical circuit, etc.

To understand the "continuously variable" part, consider the plot of some physical quantity below as it happily marches along in time changing its value.

Value/Time Chart

If we were to zoom in on some part of the curve, we would again see a nice smooth variation. Zoom again, still the same. No matter how far we zoom in, we would see a nice smooth "continuous" variation in the value.

Value/Time Chart

Hurray for nature! But what about digital computers, like our Circuit Playground? Let's look at that next.

Digital World

You've probably heard the phrase before, something like how everything in a computer is either a 1 or 0, either YES or NO, either ON or OFF, either HIGH or LOW, etc. This is entirely true for digital computers (yes, there are analog computers), and the basic unit of information that stores that 1 or 0 is called a bit. All information must somehow be represented by using one or more of these bits.

If we try to use just 1 bit, we don't get very far. It only allows us to represent two values.

1 BIT Chart

By simply adding a second bit, we can now represent up to 4 different values.

2 BIT Chart

The more bits we add, the more values we can represent. What about 10 bits?

10 BITS Chart

Here's a summary of how many values can be represented by using 1 to 10 bits. Note that the variation is not linear.

Vaules/Bits Chart

Analog World to Digital World

So how do we get those nice analog values into our digital computer so we can do cool things with the information? Simple - just use an Analog to Digital Converter (ADC). There's all kinds of technical mumbo jumbo for how an ADC works, but for this guide it's good enough to just think of an ADC as a device where an analog signal goes in and a digital (1s and 0s) signal comes out.

To illustrate this, let's start by considering the gray scale range shown below - this is our analog signal. It is continuously variable (remember that from above?) from some MIN value up to some MAX value.

Gray Scale Range

An ADC will take that and chop it up into discrete (digital) segments. ADCs come in different resolutions - the total number of bits they use. That's why you here people say things like "it has a 10bit ADC". The more bits, the more segments, and the better the ADC can represent (resolve) the analog values.

A 1 bit ADC would be pretty crude. All that beautiful grayness would just become black or white.

Black/White Range

Let's add one more bit and see what happens. Here's what a 2 bit ADC would do.

2 Bit ADC range

That's much better. We can start to see some grayness. But it's still pretty crude. Let's add one more bit. Here's what a 3 bit ADC would do.

3 Bit ADC Range

And that's even better.

You can see the trend here. The more bits we use, the closer we get to the original analog signal. If we could use an infinite number of bits, we'd actually get the original signal. But that's just not practical. No one's come up with a way store an infinite number of 1s and 0s on a digital computer.

If we were to feed the signal we introduced at the beginning into a 3 bit ADC, it would get turned into something like shown below. The orange (analog) signal becomes the black (digital) signal.

Value/Time Graph

How Many Bits?

So why not just use the biggest most bit-est ADC there is for everything? The answer is cost. The ADC hardware will generally cost more, but there is also the consideration of storage cost. Even if money didn't matter and you could buy a 900000000bit ADC, do you have a place to store all those 1 and 0s? The speed of the ADC conversion is another consideration. Hey. Trade offs.

So you wave your engineering magic wand and pick the ADC that is best suited for your application. Or, you just work with what you've been given. In the case of the Circuit Playground, that's a 10bit ADC.

Circuit Hookup

Alright. Fun time.

In order to create an analog signal we can control, we will connect a potentiometer to the Circuit Playground. By connecting the ends of the potentiometer to the 3.3V and GND there will be a variable voltage on the middle (sweep) pin.

Voltage Divider

Using Panel Mount Potentiometer

Overall view of Hookup

This is the overall view of the hookup.

      • RED to 3.3V
      • YELLOW to #10
      • BLACK to GND

connect alligator clips to the gold pads of Playground

Simply connect the alligator clips to the gold pads on the edge of the Circuit Playground as shown.

clips should clamp onto  leads of the potentiometer

The alligator clips should clamp nicely onto the leads of the potentiometer as shown.

Voltage will vary with Knob Position

With this hookup, the voltage on the yellow (OUT) will vary with knob position as shown.

Using Breadboard Trim Pot

The test circuit can also be setup on a breadboard as shown below. You can go this route if you want, like if you already have some of these parts, but the knob on the panel mount potentiometer is bigger and easier to work with.

overall view of the hookup

This is the overall view of the hookup.

      • RED to 3.3V
      • YELLOW to #10
      • BLACK to GND

Hello Analog

To read the value from the analog input, we will use the good 'ole Arduino library function analogRead(). You can use the sketch below to read the value from the potentiometer (attached to #10) and print it on the serial output.

Copy Code
///////////////////////////////////////////////////////////////////////////////
// Circuit Playground Analog In - Serial Print
//
// Author: Carter Nelson
// MIT License (https://opensource.org/licenses/MIT)

#include <Adafruit_CircuitPlayground.h>

uint16_t value;

///////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
CircuitPlayground.begin();
}

///////////////////////////////////////////////////////////////////////////////
void loop() {
value = analogRead(10);
Serial.println(value);
delay(100);
}

With this sketch running on the Circuit Playground, open the Serial Monitor:

Tools -> Serial Monitor

You should see the value being printed out. Now try spinning the knob and you should see the value change.

Spin Knob and you should see the value change

If you turn the knob all the way in one direction, you should get a value of 0. If you turn the knob all the way in the other direction, you should get a value of 1023. This is the range of values provided by the 10 bit analog to digital converter.

You can also use the Serial Plotter to watch the value change.

Tools -> Serial Plotter

Now try turning the knob and watch the line go up and down. Wheeeee!!!!

Line Graph

NeoPixel Fun

Now let's take the analog value and do something fun with it. How about turning on the NeoPixels to represent knob position? Like all NeoPixels off is one direction, and all NeoPixels on is the other direction.

We can do this pretty easy using the map function. We know the range of values we expect from the analog input, 0-1023, and we just want to map that to how many NeoPixels to light up, 0-10. So, it's just a matter of coding it up.

And here it is.

Copy Code
///////////////////////////////////////////////////////////////////////////////
// Circuit Playground Analog In - NeoPixel Fun
//
// Author: Carter Nelson
// MIT License (https://opensource.org/licenses/MIT)

#include <Adafruit_CircuitPlayground.h>

uint16_t value;
uint8_t pixels;

///////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
CircuitPlayground.begin();
}

///////////////////////////////////////////////////////////////////////////////
void loop() {
value = analogRead(10);
pixels = map(value, 0, 1023, 0, 10);

CircuitPlayground.clearPixels();
for (int p=0; p<pixels; p ) {
CircuitPlayground.setPixelColor(p, 0xFF00FF);
}
delay(100);
}

With this code loaded and running on the Circuit Playground, try turning the knob. You should see the NeoPixels light up in accordance with the knob position.

Turn Knob and see NeoPixels Light up in accordance

Speaker Fun

Oooooo. What about having the knob change the tone of the speaker? No prob. Same idea as the previous sketch. Just map the knob values to tone frequencies.

The Circuit Playground speaker is really only usable over a range of about 100Hz to 10000Hz, which leads us to the following code.

Copy Code
///////////////////////////////////////////////////////////////////////////////
// Circuit Playground Analog In - Speaker Fun ?
//
// Author: Carter Nelson
// MIT License (https://opensource.org/licenses/MIT)

#include <Adafruit_CircuitPlayground.h>

uint16_t value;
uint16_t freq;

///////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
CircuitPlayground.begin();
}

///////////////////////////////////////////////////////////////////////////////
void loop() {
value = analogRead(10);
freq = map(value, 0, 1023, 100, 10000);

CircuitPlayground.playTone(freq, 100, false);
}

Load that code up and run it. Spin the knob. Make some weird outer space theremin like music sounds. Hopefully the dogs don't start howling.

Under The Hood

So you might have noticed we didn't use one of those CircuitPlayground.something() functions to get our analog value. Why not, and how did it work without doing so?

The answer to the second question is pretty easy - we just use the Arduino library. The Circuit Playground library is built (largely) on top of the Arduino library and 'hides' the details of using its various bells and whistles. However, you can still use the Arduino library if you want (and know what you're doing).

No real good answer to the other question. This could've been done, say with something like CircuitPlayground.analogRead() or CircuitPlayground.giveMeTheAnalogPlease() or whatever. But this would have likely done nothing more than just call the same Arduino function. So, guess it just never made the cut.

However, there are a few of the Circuit Playground sensors that are essentially the same as the potentiometer we used in this guide, namely the light sensor , sound sensor , and temperature sensor. They all output a voltage that varies with the physical quantity they sense. In order for this to be used in the Circuit Playground, those signals are fed into ADCs, just like we did with the potentiometer. And that's pretty much all there is to it.

Don't believe me? Well, take a look...

Light Sensor

Here's the circuit path for the output of the light sensor. The big red square that says 'THERMAL' is the brain of the Circuit Playground.

Light Sensor Circuit Path

And here's the code for the CircuitPlayground.lightSensor() function. (direct link to repo)

Copy Code
uint16_t Adafruit_CircuitPlayground::lightSensor(void) {
return analogRead(CPLAY_LIGHTSENSOR);
}

Sound Sensor

Here's the circuit path for the output of the sound sensor (microphone off screen).

Microphone Output Circuit Path

And here's the code for the CircuitPlayground.soundSensor() function. (direct link to repo)

Copy Code
uint16_t Adafruit_CircuitPlayground::soundSensor(void) {
return analogRead(CPLAY_SOUNDSENSOR);
}

Pretty boring. Nothing fancy or magical. Both the light sensor and sound sensor just call analogRead() for the pins they are attached to and return the value. And now you know why those functions return values from 0 to 1023. It's just the raw 10 bit analog to digital conversion.

Temperature Sensor

Here's the circuit path for the output of the temperature sensor.

Temperature Sensor Circuit Path

And here's the code for the CircuitPlayground.temperature() function. (direct link to repo)

Copy Code
float Adafruit_CircuitPlayground::temperature(void) {
// Thermistor test
float reading;

reading = analogRead(CPLAY_THERMISTORPIN);

//Serial.print("Thermistor reading: "); Serial.println(reading);

// convert the value to resistance
reading = ((1023.0 * SERIESRESISTOR) / reading);
reading -= SERIESRESISTOR;

//Serial.print("Thermistor resistance: "); Serial.println(reading);

float steinhart;
steinhart = reading / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart = 1.0 / (TEMPERATURENOMINAL 273.15); // (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C

return steinhart;
}

OK, a bit more going on. But not really. Note that pretty much the first thing that happens is to read the analog value. The rest is just math to turn that into a temperature. In this case, that's more useful than the raw analog value. For the light and sound sensors, there's no really useful thing to convert to, so those just return the raw values.

Questions and Code Challenges

The following are some questions related to this project along with some suggested code challenges. The idea is to provoke thought, test your understanding, and get you coding!

While the sketches provided in this guide work, there is room for improvement and additional features. Have fun playing with the provided code to see what you can do with it. Or do something new and exciting!

Questions

      • A 10 bit ADC has 1024 values, but why is the highest one 1023?
      • Can you think of any natural phenomenon that behaves digitally?

Code Challenges

      • Make the knob change the color of the NeoPixels.
      • Make the NeoPixels blink at different rates set by the knob.
      • Change the range of the tones generated in Speaker Fun.
      • Try using something other than map(). Something non-linear maybe?
      • Combine the NeoPixel and Speaker Fun code into one - lights and sounds!
制造商零件编号 3000
CIRC PLAYGROUND CLASS ATMEGA32U4
Adafruit Industries LLC
制造商零件编号 1008
TEST LEAD GATOR TO GATOR 15"
Adafruit Industries LLC
制造商零件编号 P160KN-0QC15B10K
POT 10K OHM 1/5W PLASTIC LINEAR
TT Electronics/BI
制造商零件编号 OEJL-50-4-7
KNOB KNURLED 0.236" METAL
Kilo International
制造商零件编号 3255
TEST LEAD GATOR TO TIP PLUG 6"
Adafruit Industries LLC
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum