Wednesday, December 29, 2010

Arduino Pins - Digital pins

For an Arduino beginners, to talk to microcontrollers, you interfaces sensors, actuators and chips (integrated circuit) using pins. There are a few types of pins, input output (I/O) pins : digital pins & analog pins  and other pins like power pins (+5V, +3.3V, Ground ) and others like analog reference, reset and crystal pins. Some of these pins are not accessible on an Arduino board but need to be wired up for an Arduino breadboard version.  Let me explain each of these in more details.

ATMega 168/328 pinout


Arduino Digital Pins 





Digital pins are much easy to understand as there are only two state, either ON or OFF state. In Arduino sketch terms, a ON state is known as HIGH (5V) and OFF state is known as LOW (0V).

You can use these digital pins either as input or output pins. Use the function pinMode() to configure the pins either to INPUT or OUTPUT. The default mode is INPUT if you do not specify them using pinMode().

Sample Code :
pinMode(12, OUTPUT);   // Set digital pin 12 as OUTPUT pins

For advance users, you can use AVR port registers to manipulate the pins using low level method describe at : http://www.arduino.cc/en/Reference/PortManipulation.

When you set a digital pin as HIGH, you send a +5V to the pin and when you set the digital pin as LOW, the pins is pulldown to 0V. You can verify this with a multimeter (red probe to the pin to be tested, black probe to the ground)  or put a LED and resistor between the pin and the ground pin.

The first Arduino tutorial, "Hello World" or Blink tutorial does just that with a delay() in between.

Use the function digitalWrite(12, HIGH) or digitalWrite(10,LOW) to set the state of the pin.

There was once, when I was doing my realtime clock project to have the pin 13 blink every second ( turn on for 500 millisecond and turn off for 500 millisecond ). 

  digitalWrite(13,HIGH);
  delay(500);
  digitalWrite(13,LOW);
  delay(500);

After a restart Arduino, I notice the LED on pin 13 was very dim.  As I did not change the resistor value, I was wondering why the LED at pin 13 became so dim. After reviewing the codes, I notice that I did not put the statement : 

pinMode(13, OUTPUT) in setup().

The default mode of the pin was INPUT. As INPUT mode, with digitalWrite(13,HIGH), it have activate an internal 20K pull-up resistors and lit the LED dimly. Changing the pinMode(13, OUTPUT) solved this issue.

All Arduino pins as OUTPUT mode will send a maximum current of 40mA, enough to drive a LED, LCD modules, opto-isolators or low powered sensors  but not high enough current to drive coils, relays or motors. Always refer to the datasheet for the maximum value the sensors or actuators can accept.

Digital Pin as INPUT

With pinMode() set as INPUT, you can use digitalRead() function to get a status of the pin.

The easiest way to explain this is reading a status from a push button / tactile switch.  

Push button with pull-up resistor to 5V


Digital Pin 3 is connected with a 100 ohm resistor to another 10K ohm pull-up resistor to +5V pin. With the +5V and 10K resistor, the default state of Pin 3 will be HIGH when you read it with digitalRead() function. On the same circuit, a wire connect to a push button to the Ground pin (Orange wire).

When the push button is pressed, due to lower resistance, the circuit is grounded and the state of Pin 3 would be LOW or 0V.

It is easier to hold the pin at HIGH state using pull-up resistor like 10K ohm than a LOW state. An example to turn on and off a LED using the push button at default HIGH state. Always have input pins in a known state ( pull-up or pull-down ) instead of an unconnected state to prevent any intermittent issues.

Pin 3 is connected like the above example.

pinMode(3, INPUT);
pinMode(13,OUTOUT);

 if ( digitalRead(3) == HIGH  ) { // Button not pushed
        digitalWrite(13, LOW )        // Turn off the LED
 } else {                                          // Button is pushed
        digitalWrite(13,HIGH)         // Turn on the LED
 }


Switches without a resistor trick


Like the above example, if you do not want to use a resistor between the switch/push button, you can do this neat feature by utilizing the ATMEGA328 internal 20K pull-up resistor.


The command to activate the internal 20K pull-up resistor is :- digitalWrite(HIGH)


Arduino switch without resistor




Using Digital pin 3 as an example :-


pinMode(3,INPUT);            // default mode is INPUT
digitalWrite(3, HIGH);     // Turn on the internal pull-up resistor, default state is HIGH
state  = digitalRead(3);      // read the state of the pin


For the programming logic, when the switch is OPEN, the state is HIGH and when the switch is CLOSED or pressed, the state is LOW. 


There is another neat Arduino trick to read two switches using only one digital pins at Arduino reference site. It is a combination of the above two examples.




Saturday, December 18, 2010

Digital Clock with 7-segments LED and RTC (Realtime Clock)

Arduino 7-segment RTC

After making so many Arduino prototypes on a breadboard, I decide to make something useful that everyone in the house can use. What is more useful that a digital clock as the year 2010 is coming to an end. I starter doing my research on making a digital clock and gathering the components needed to make one. One of the criteria is that all the components must be easily available locally in Kuala Lumpur, Malaysia. Visually, it looks like those countdown timer bomb found on old movies where the hero needs to cut some wires to deactivate the bomb.

In order to make a clock to tell the time, I have a few options, either set the time in Arduino, keep the Arduino power on all the time but this method is not very feasible as I would need to set the time everytime I need to power cycle the Arduino. The second option was an idea of a hugh 7-segments LED powered by a GPS from Sparkfun article. As GPS give a very accurate time, this option should good and I do not need to set the clock everyime it was powered on. I took out my Garmin GPS60C, plug in the serial connection to the Arduino, load a few GPS libraries and I got myself a very accurate time. The problem with this method is that since I live in the middle of Kuala Lumpur, a concrete jungle with condominium surrounding my condominium unit, I need to put an external GPS antenna outside my windows to receive GPS signal directly from the sky. Without a satellite lock, the GPS unit was not able to receive any satellite signals from the key. And the clock either need to be close to the window or I had to run GPS antenna to the place I put my 7-segments digital clock.

The third method is the best, running Arduino with a DS1307 realtime clock (RTC) powered by a 3V coin size battery that can keep the time when it is powered off or during power cycle. I went to the local electronic heaven called Jalan Pasar (market street in english), located in a very congested part of town and try my luck to find the necessary components. To my surprise, I found all the necessary parts to built this digital clock. The main components are :-

- Arduino board
- Four red 7-segments LED ( could not find other cool colour locally )
- DS1307 realtime clock
- 32.768 kHz crystals
- coin size battery holder
- Four shift registers 74HC595 to control the 7-segment LEDS
- resistors and hookups cables
- header pins and integrated circuit/chip (IC) sockets

As I have not acquired the skills to make a printed circuit board (PCB) yet, I decide to use a veroboard ( board with holes to make the components permanent also called a doughnut board ) and solder all the header pins and IC sockets. All the 7-segments LEDs and IC can be easily replaced with this method. As the board size is quite limited, I can only fit four 35mm size 7-segments LED and have enough space for a battery holder. I wanted to get a much bigger 7-segments LED but the bigger ones would requires higher voltage above the 5V and my circuit would need to support dual power rails. I did not want to deal with a dual voltage power regulator circuit at the moment and focus on making my first digital clock.

Uploading sketch on digital clock


This Arduino digital clock only uses 5 pins, 3 digital pins for the 74595 shift registers and 2 analog pins for the RTC using I2C connection. What is different between my Arduino Digital Clock vs the commercial digital clock is that I can control the behavior of the clock and can easily add any functions I see fit. Some ideas are like alternating display between hours/minute and minute/seconds,  playing a tune every 1 hour, add in a LM35 to double as a thermometer, sound an alarm in the morning or even control other electrical appliance via a solid-state relay based on time related events or readings from other sensors. As the four digit are quite big and bright, I can use it to display other information too.


I discovered the first issue after I soldered the first digit from the 74595 shift registers to the common cathode 7-segments LEDs. I only use one 220 ohm resistor connected to the common cathode to save the number of resistors needed and found that the number 8, all segments turn on was very dim. This is okay for a prototype but this is not acceptable for a real useful digital clock. Would be very annoying to have different digits with different brightness. So I remove all the wires and went out to get a lot of 220 ohm resistors to connect them to each of the seven segments.

7-segment with 74595 shift registers


The second issue I found was that I forgot to allocate space for two 5mm LEDs as the colon to blink as a second indicator after I soldered the third digit. As it is quite a lot of work just to make one digit with all the soldering, joining the resistors to the wires, I decide to do away with the 2 colon dots between the hour and the minute digits. I will find a way to install a LED or two as second indicators. The photo in the current photo, I just blink LED on pin 13 for 500 ms delays.

Here are some photos of the finished working product, now I just need to some some acrylic to mount the board and hide the Arduino board behind the digital clock.

The codes are based on Paul's Electronics 7-segment shift register.

Arduino clock with blue LED second indicator

Arduino clock without 7-Seg LEDs
Back of clock with perfboarduino
This Arduino clock is powered by a perfboard version of Arduino with FTDI header and DC plug.

Arduino clock with DHT11 sensor
Complete Arduino clock with DHT11 Humidity and Temp sensors.

The full sketch are located at https://github.com/stanleyseow/Arduino-realtime-clock-with-four-7-segment-LED-and-74595-shift-registers



Thursday, December 9, 2010

Arduino Output : LCD Modules, Part 2 - Software

On the previous posting, I talk about LCD Modules on the hardware and how to hook up a LCD module. On this posting, I will talk about setting up the display using Arduino LCD library to drive the LCD module. Almost all my sketches and testing are done with a breadboard version of Arduino with a LCD template.

Here are my template of the LCD library for Arduino :-


#include <LiquidCrystal.h>
// My wiring for LCD on breadboard
// format is RS, Enable, DB4, DB5, DB6, DB7
LiquidCrystal lcd(12, 11, 5, 6, 7, 8);


void setup() { 
     // LCD format is Col,Row for 16 columns and 2 rows
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.print("LCD Ready...");




  lcd.setCursor(0,1);
  lcd.print("Version 1.0.0");
  delay(1000); // Display the message for 1 sec
  lcd.clear(); // clear the screen

}


void loop() {
  // format is col,row
  lcd.setCursor(0,0);
  lcd.print("Arduino LCD");
  lcd.setCursor(0,1);
  lcd.print("rocks!!");
}

Explanation of the template codes :-


It starts with including the standard Liquid Crystal library from Arduino. The second line tells the Arduino software how the pins are connected to match the hardware hookups.

Most of the LCD library commands are located at : Arduino LCD Reference. The common ones are :-

Print
lcd.print(data, BASE);

The BASE is optional, tell the Arduino what format to display on the LCD Module.
BIN - binary or base 2
DEC - decimal or base 10
OCT - octal or base 8
HEX - hexadecimal or base 16

Note - If you do a search and replace Serial.print() to lcd.print(), there are no lcd.println() as you would need to use the setCursor() to move to the next line.

Examples of lcd.print()  :-
lcd.print("Hello World");

lcd.print(variable);

lcd.print(variable,DEC);

*** Make sure you do not exceed the number of columns of the LCD module.

Set Cursor
lcd.setCursor();

This command set the location of the cursor, the format is column, row.
The column and row starts with 0, so a 16x2 LCD, valid columns would be 0 to 15, valid rows would be from 0 to 1.

Examples of setCursor() :-
lcd.setCursor(0,0);   // Jump to the top left corner
lcd.setCursor(9,1);  // Jump to column 10, second row

Clear Screen
lcd.clear();

This command will clear the screen as the LCD LiquidCrystal library would just overwrite from a previous display.


To make the Arduino more interactive, I usually output useful information ( status, temperature, date or time ) to the LCD module instead of sending the data over to the serial monitor. The advantage of this is that you do not need to have Arduino connected to the PC as most of the Arduino project, it should be as stand alone as possible disconnected from the PC USB port.

What else can you do with a 16x2 LCD Module ? Someone wrote a cool Truck Lane game with custom charactor. For the steering wheel, you can use a potentiometer (POT) to steer the truck up and down the screen. Just hook the POT to Analog Pin 1 to the voltage divider ( middle connector ) of the POT. Give it a try.