If you are working on a project that responds to sounds, your circuit will require some type of microphone to transduce the sound into a modulated voltage and, most likely, some type of amplification of this modulated voltage. I like to use electret microphones to transduce sound because they require relatively simple circuits. For example, the circuit below passes the output of an electret microphone (hooked up according to its datasheet) through a band-pass amplifier based on an LM358 operational amplifier. This circuit is suitable for a 5-V system. The op-amp circuit has both a high-pass portion (R1 and C1) and a low-pass portion (R2 and C2). Thus, the circuit attenuates frequencies below f = 1/(2πR1C1) = 5.9 Hz and frequencies above f = 1/(2πR2C2) = 15915 Hz. The op-amp acts like an inverting amplifier with a gain of -R2/R1=37. The voltage divider (R4 and R5) is used to give the output about a 1.6 V DC offset. This allows both the positive and negative portions of the input to be amplified and present in the output. After building this circuit, I discovered a very similar circuit is implemented by SparkFun’s electret microphone breakout board but different resistor and capacitor values are used yielding a different gain and different band-pass characteristics, a different op amp is used, and a capacitor is placed in parallel with R4 presumably to stabilize the voltage to the non-inverting input of the op-amp. This additional capacitor may be a good idea, but I actually think my circuit is superior in that the voltage divider introduces a smaller DC offset that more closely matches the midpoint of the op-amp’s dynamic range when powered by 5 volts. Just my opinion.

IR Photodiode Circuit Schematic

Posted April 4th, 2013. Filed under Basics Electronics Guides

The following schematic demonstrates a simple infrared (IR) photodiode circuit using a analog-to-digital converter (ADC) to monitor the photodiode. An analog pin on an Arduino used with the analogRead() function will do the job. Photodiodes are two-pin analog devices. This makes them relatively easy to use and makes their output graded. Some of my students are using one in a project along with an IR LED as an IR absorption meter. On the other hand, their output is relatively weak so they can’t detect extremely small or distant IR signals. Notice that the photodiode is reverse biased. Thus, when no light is present, no current flows through the diode and the 1 megaohm pull-up resistor ensures that the ADC monitoring the photodiode reads 5 V. When light, in this case IR light, strikes the photodiode, electron-hole pairs are created in the semiconductor which creates a small current causing the voltage at the ADC pin to drop. So the lower the voltage read by the ADC, the more IR light is being received.

The ATmega328 has a total of three input/output ports, port B, port C, and port D. Two of these ports, namely port B and port D, are associated with the 14 digital input/output pins on the Arduino Uno. Port C is associated with the analog input pins which can also be used as digital input/output pins if needed. The following table summarizes the mapping between the Arduino Uno digital pins and the ATmega328 port pins.

Arduino Digital Pin Port Pin
0 PD0
1 PD1
2 PD2
3 PD3
4 PD4
5 PD5
6 PD6
7 PD7
8 PB0
9 PB1
10 PB2
11 PB3
12 PB4
13 PB5


 

To turn on or off a Arduino digital pin, its mode is first set using pinMode() and then its state is set using digitalWrite(). For example, to turn on digital pin 5 for one second then turn if off for one second repeatedly, the following code could be used.


int myPin = 5;
void setup() {
   pinMode(myPin,OUTPUT);
}
void loop() {
   digitalWrite(myPin,HIGH);
   delay(1000);
   digitalWrite(myPin,LOW);
   delay(1000);
}

It is also possible to control the digital pins by accessing the port registers directly. For example, the following achieves the same result as the above code. It is explained below.


void setup() {
   DDRD = DDRD | B00100000; 
}
void loop() {
   PORTD = PORTD | B00100000;
   delay(1000);
   PORTD = PORTD & B11011111;
   delay(1000);
}

Each port has a one byte register defining the direction of the associated pins. This register is called DDRD for port D and DDRB for port B. From zero to seven, each bit in this register corresponds to the comparably numbered pin of that port. For example, the fifth bit of DDRD controls port pin D5 or Arduino digital pin 5. If this bit is set to zero, the pin is an input. If this bit is set to one, the pin is an output pin. Thus, the line of code in the setup function above sets Arduino digital pin 5 to an output pin using a bitwise or operator. Each port also has a one byte register defining the state of the associated pins. This register is called PORTD for port D and PORTB for port B. Just like the DDRx registers, each bit in these registers from zero to seven corresponds to the comparably numbered pin of that port. For example, the fifth bit of PORTD controls the state of pin D5 or Arduino digital pin 5. If this bit is set to zero, the pin is set to 0 V. If this bit is set to one, the pin is set to 5 V (on the Arduino Uno). Thus the lines of code in the loop function above first turns on Arduino digital pin 5 using a bitwise or and then turns this pin off using a bitwise and.

Controlling digital i/o pins at the register level is incredibly powerful. For example, you could turn all 8 pins of port D using a single line of code if you wanted to. However, with great power comes great responsibility. Manipulating registers can be tricky and may yield unexpected results. For example, buried in the ATmega328 data sheet is a warning that one can not change a pin from the high impedance input off state to the output on state in one step. You must first go to an intermediate state of output low or input high before going to output high.

Serial communication is a method for two computers or microcontrollers (or one computer and a microcontroller) to talk to one another. Arduino uses the transistor-transistor logic (TTL) serial protocol. This protocol sends bits using voltages of zero (for a zero bit) and five (for a one bit). Another popular serial protocol is RS-232 which uses +13 V to represent zeros and -13 V to represent ones. In both cases, serial communication involves sending bytes one bit at a time starting with the least significant bit (LSB). Each bit is preceded by a start bit (0 V for TTL serial communication) and immediately followed by a stop bit (0 V for TTL serial communication). Therefore, the figure below shows the signals that would be generated if the bytes 11011001 (top) and 00010010 (bottom) where sent via a serial channel.

In order for two devices to communicate via a serial signal, both must be configured with the same baud rate or bits per second (bps) rate. This tells both machines the interval of time between individual bits so they can synchronize. The most common baud rate for Arduino is 9600. In fact, this is the default baud rate when a new serial monitor is opened from the Arduino IDE. Other baud rates are sometimes necessary. For example, communication with GPS modules often uses a baud rate of 4800.

The following sketch demonstrates serial communication between an Arduino Uno and a the serial monitor on a computer. When a character is sent to the Arduino from the serial monitor on a computer, the Arduino reads this byte and immediately will send it back. The Serial.begin(), Serial.available(), Serial.read(), Serial.print(), and Serial.write() commands are used to start serial communication, test to see if any bytes are available in the serial buffer, read in the next byte in the serial buffer, print a decimal number to the serial monitor, and print the ASCII character corresponding to this decimal number, respectively. The comments in the code should help you figure out what each component does.

// Program Name: Serial Echo

// note: serial bytes are read as ASCII 
// (American Standard Code for Information Interchange) 
// characters

byte myByte; // a variable to store a byte read from the serial 
// buffer

void setup() {
  Serial.begin(9600); // begin serial communications at 9600 bps
}

void loop() {
 if (Serial.available()>0) {
  while(Serial.available()>0){ // while bytes remain in the serial 
  // buffer
  myByte = Serial.read(); // read in the current byte
  // = is ASCII character 61
  // 0-9 are ASCII characters 48 to 57
  // - is ASCII character 45
  // + is ASCII character 43
  }
  Serial.print("ASCII Character Value of Byte Read: \n");
  Serial.write(myByte);
  Serial.print('\n');
  Serial.print("ASCII Decimal Value of Byte Read: \n");
  Serial.print(myByte); // prints ASCII character corresponding 
  // to myByte
  Serial.print('\n');
 }
}

One important concept to understand is that serial information is sent out of and read into the Arduino one byte at a time. Moreover, each byte that is read into memory corresponds to the decimal ASCII encoding for the ASCII character being received. So, if the character A is sent, the value stored in myByte would be 65 since this is the decimal code for the ASCII character A. For more on ASCII characters and serial communications see this post.

A common-cathode RGB LED has a total of four pins. One of the pins is the cathode which must be connected to ground and the others each control a color. The pinout shown below is for a typical RGB LED. Notice that each of the pins is a slightly different length; the cathode is the longest.

Since there are three colors, controlling a common-cathode RGB LED with an Arduino requires three digital output pins (and three current limiting resistors). You could turn these pins off and on one at a time using digitalWrite() commands. You could also use a byte (of which one bit controls each of the colors so five bits would be unused) and a bit-mask. See this post for more details. This would result in more compact code.

When lights of different colors are combined, new colors result. But unlike pigment mixing, which is subtractive color mixing, light mixing results in additive color mixing. Red and green makes yellow, red and blue makes magenta, and green and blue makes cyan. If red, green, and blue are simultaneously turned on, white light is produced. In order to obtain more fine grained control over the color produced by an RGB LED, you can use PWM and analogWrite() (see this post for more details).