PWM for servos, motors, and LEDs plus plus


47 posts   Page 1 of 2   1, 2
by joan » Sun May 12, 2013 8:40 pm
I have just released pigpio version 3, a gpio library.

Available from http://abyz.co.uk/rpi/pigpio/pigpio.tar

Some documentation http://abyz.co.uk/rpi/pigpio/

Miscellaneous videos at https://www.youtube.com/channel/UCr4lLU ... 4aDtWOhZOg

N.B. The pigpio library uses the DMA (channel 14 by default) and the PWM or PCM peripherals.

Consider the pigpio library to be experimental and use at your own risk. That said I have not had a problem.

Its main features are:

  • provision of PWM on any number of gpios 0-31 simultaneously.
  • provision of servo pulses on any number of gpios 0-31 simultaneously.
  • callbacks when any of gpios 0-31 change state.
  • notifications via a pipe when gpios change state.
  • provides a socket interface to most of the functionality.
  • provides a pipe interface to most of the functionality.
  • callbacks at timed intervals.
  • reading/writing all of the gpios in a bank (0-31, 32-53) as a single operation.
  • individually setting gpio modes, reading and writing.

    NOTE: ALL gpios are identified by their Broadcom number.

    There are several significant enhancements over version 2.
    • The socket and pipe interfaces allow access to the library from all popular languages. Pipe commands are written to /dev/pigpio. Results are returned in /dev/pigout. Errors will be reported to /dev/pigerr. The pigs utility demonstrates the socket interface.
    • The underlying gpio sample rate can be set to every n microseconds where n may be 1, 2, 4, 5, 8, or 10. i.e. the gpios can be sampled 1 million times per second.
    • The PWM cycle may be separately set per gpio to one of 18 different frequencies. The actual frequencies depend upon the chosen gpio sample rate.
    • The levels of all user gpios (0-31) are read and time stamped up to a million times per second (previously 200 thousand times per second).

    The following utilities are provided.
    • pigpiod: this starts the library as a daemon. Thereafter the gpios may be accessed without needing to use sudo.
    • pigs: this provides a socket based interface to the library daemon. Sockets are available from most programming languages.
    • pig2vcd: this converts pigpio notifications into a form viewable with GTKWave.
The following session shows the download of the library and making/installing the utilities.

NOTE. The library is compiled for soft float and for hard float. After expanding the archive you need to copy the correct library for your architecture, libpigpio.a-hard, or libpigpio.a-soft to libpigpio.a. As far as I'm aware all distributions are hard float other than the Debian version.

The library is started as a daemon.

The socket (pigs) and pipe interfaces are demonstrated.

Finally pwm is set up on four gpios and a notification is used to capture the changes in gpio state.

The state changes are converted by pig2vcd into a format suitable for display by GTKWave.
Code: Select all
joan@soft's password:
Linux soft 3.6.11+ #446 PREEMPT Fri May 10 20:17:25 BST 2013 armv6l
joan@soft ~ $ wget abyz.co.uk/rpi/pigpio/pigpio.tar
--2013-05-12 18:54:13--  http://abyz.co.uk/rpi/pigpio/pigpio.tar
Resolving abyz.co.uk (abyz.co.uk)... 91.238.161.4
Connecting to abyz.co.uk (abyz.co.uk)|91.238.161.4|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 317440 (310K) [application/x-tar]
Saving to: ‘pigpio.tar’

100%[======================================>] 317,440     1.07MB/s   in 0.3s   

2013-05-12 18:54:14 (1.07 MB/s) - ‘pigpio.tar’ saved [317440/317440]

joan@soft ~ $ tar xvf pigpio.tar
PIGPIO/
PIGPIO/command.h
PIGPIO/pigpiod.c
PIGPIO/pigs.c
PIGPIO/README
PIGPIO/libpigpio.a-soft
PIGPIO/command.c
PIGPIO/pigpio.h
PIGPIO/Makefile
PIGPIO/pigpio.c.cpt
PIGPIO/pig2vcd.c
PIGPIO/demolib.c
PIGPIO/libpigpio.a-hard
PIGPIO/checklib.c
joan@soft ~ $ cd PIGPIO
joan@soft ~/PIGPIO $ cp libpigpio.a-soft libpigpio.a
joan@soft ~/PIGPIO $ make
gcc -c -O2 -Wall checklib.c
gcc -o checklib checklib.c -L. -lpigpio -lpthread -lrt
gcc -c -O2 -Wall demolib.c
gcc -o demolib demolib.c -L. -lpigpio -lpthread -lrt
gcc -c -O2 -Wall pig2vcd.c
gcc -o pig2vcd pig2vcd.c
gcc -c -O2 -Wall pigpiod.c
gcc -o pigpiod pigpiod.c -L. -lpigpio -lpthread -lrt
gcc -c -O2 -Wall pigs.c
gcc -c -O2 -Wall command.c
gcc -o pigs pigs.c command.c
joan@soft ~/PIGPIO $ make install
sudo install -m 0755 -d          /usr/local/bin
sudo install -m 0755 -d          /usr/local/include
sudo install -m 0755 -d          /usr/local/lib
sudo install -m 0755 pig2vcd     /usr/local/bin
sudo install -m 0755 pigpiod     /usr/local/bin
sudo install -m 0755 pigs        /usr/local/bin
sudo install -m 0644 pigpio.h    /usr/local/include
sudo install -m 0644 libpigpio.a /usr/local/lib
joan@soft ~/PIGPIO $ sudo ./pigpiod -?
joan@soft ~/PIGPIO $ ./pigpiod: invalid option -- '?'

Usage: sudo pigpiod [OPTION] ...
   -b value, gpio sample buffer in milliseconds, default 120
   -d value, DMA channel, 0-14,                  default 14
   -f,       disable fifo interface,             default enabled
   -k,       disable socket interface,           default enabled
   -p value, socket port, 1024-32000,            default 8888
   -s value, sample rate, 1, 2, 4, 5, 8, or 10,  default 5
   -t value, clock peripheral, 0=PWM 1=PCM,      default PCM
   -u value, clock source, 0=OSC 1=PLLD,         default PLLD
EXAMPLE
sudo pigpiod -s 2 -b 200 -f
  Set a sample rate of 2 microseconds with a 200 millisecond
  buffer.  Disable the fifo interface.


joan@soft ~/PIGPIO $ sudo pigpiod -s 1
joan@soft ~/PIGPIO $ pigs help
BR1          read gpios bank 1
BR2          read gpios bank 2
BC1 x        clear gpios in bank 1
BC2 x        clear gpios in bank 2
BS1 x        set gpios in bank 1
BS2 x        set gpios in bank 2
HWVER        return hardware version
MODES/M g m  set gpio mode
MODEG/MG g   get gpio mode
NO           request notification handle
NB h x       start notification
NP h         pause notification
NC h         close notification
PWM/P u d    set PWM value for gpio
PFS u d      set PWM frequency for gpio
PFG u        get PWM frequency for gpio
PRS u d      set PWM range for gpio
PRG u        get PWM range for gpio
PRRG u       get PWM real range for gpio
PUD g p      set gpio pull up/down
READ/R g     read gpio
SERVO/S u d  set servo value for gpio
WRITE/W g d  write value to gpio
WDOG u d     set watchdog on gpio
TICK/T       return current tick
HELP/H       displays command help

d = decimal value
g = gpio (0-53)
h = handle (0-31)
m = mode (RW540123)
p = pud (ODU)
u = user gpio (0-31)
x = hex value

joan@soft ~/PIGPIO $ pigs t
2646959531
joan@soft ~/PIGPIO $ pigs br1
128180CF
joan@soft ~/PIGPIO $ cat /dev/pigout &
[1] 5490
joan@soft ~/PIGPIO $ cat /dev/pigerr &
[2] 5492
joan@soft ~/PIGPIO $ pigs w 4 5
ERROR: level not 0-1
joan@soft ~/PIGPIO $ 2013-05-12 18:59:05 gpioWrite: gpio 4, bad level (5)

joan@soft ~/PIGPIO $ echo "t" >/dev/pigpio
joan@soft ~/PIGPIO $ 2710032608

joan@soft ~/PIGPIO $ echo "w 100 0" >/dev/pigpio
-3
joan@soft ~/PIGPIO $ 2013-05-12 18:59:50 gpioWrite: bad gpio (100)

joan@soft ~/PIGPIO $ pigs p 4 50
joan@soft ~/PIGPIO $ pigs p 7 100
joan@soft ~/PIGPIO $ pigs p 8 150
joan@soft ~/PIGPIO $ pigs p 9 200
joan@soft ~/PIGPIO $ pigs no
0
joan@soft ~/PIGPIO $ pig2vcd </dev/pigpio0 >log.vcd &
[3] 5505
joan@soft ~/PIGPIO $ pigs nb 0 -1
joan@soft ~/PIGPIO $ ls -lh log.vcd
-rw-r--r-- 1 joan joan 3.8M May 12 19:02 log.vcd
joan@soft ~/PIGPIO $ ls -lh log.vcd
-rw-r--r-- 1 joan joan 4.2M May 12 19:02 log.vcd
joan@soft ~/PIGPIO $ ls -lh log.vcd
-rw-r--r-- 1 joan joan 4.5M May 12 19:02 log.vcd
joan@soft ~/PIGPIO $ pigs nc 0
[3]+  Done                    pig2vcd < /dev/pigpio0 > log.vcd
joan@soft ~/PIGPIO $ head log.vcd
$date 2013-05-12 19:02:02 $end
$version pig2vcd V1 $end
$timescale 1 us $end
$scope module top $end
$var wire 1 A 0 $end
$var wire 1 B 1 $end
$var wire 1 C 2 $end
$var wire 1 D 3 $end
$var wire 1 E 4 $end
$var wire 1 F 5 $end
joan@soft ~/PIGPIO $ tail log.vcd
0J
#22236590
1X
#22236626
0X
#22236643
1E
1H
1I
1J
joan@soft ~/PIGPIO $ sudo killall pigpiod
joan@soft ~/PIGPIO $ SIGHUP/SIGTERM received

[1]-  Done                    cat /dev/pigout
[2]+  Done                    cat /dev/pigerr
joan@soft ~/PIGPIO $

pigpio.h details the additional functions available to C/C++ programmers. It also documents the function parameters.

NOTES
  • As far as I am aware the resolution of the system clock is 1 microsecond. I don't see any point in sampling the gpios any faster.
  • There is servo jitter at a sample rate of 1 microsecond.
  • gpios 32-53 (the system gpios) are no longer sampled.
  • there are bound to be errors. I'll fix them if I can.
EDITS
changed sudo ./pigpiod -s 1 to the correct sudo pigpiod -s 1
added note about copying hard or soft float library
corrected the hard and soft float library file names
added links to youtube videos
Last edited by joan on Fri Dec 20, 2013 9:31 am, edited 8 times in total.
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by xcadaverx » Sun May 26, 2013 7:43 am
Thank you for this work. I've been scouring the internet for a solution to running multiple peristaltic pumps at the same time at different PWM rates. When i get my system set up, i'll let you know how it works out, as your library seems to be the solution.
Posts: 3
Joined: Fri Feb 22, 2013 11:16 pm
by Tage » Mon May 27, 2013 1:40 am
Thank you for sharing this work. I did not have any issues with following the instructions once I noticed there was a -hard and a -soft float version (I read the README file, finally) :)
I am working on a remotely controlled wifi camera using the Pi with camera module and a number of servos to move the camera, and needed a way to control several servos from the Pi. My first approach was to use an Arduino Pro Mini controlled by the Pi, but this is a better solution. Thanks!
User avatar
Posts: 228
Joined: Fri May 24, 2013 2:29 am
Location: Fremont, California
by joan » Mon May 27, 2013 7:53 am
Tage wrote:... I did not have any issues with following the instructions once I noticed there was a -hard and a -soft float version ...

I've added a note. :)
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by deefunkt » Sun Jun 02, 2013 6:36 am
Hi Joan, I really want to try out your library, would you mind posting perhaps more usage examples in code for noobs?

for example, how would I go about setting a pwm pulse of 1500 microseconds across a signal repeating at 50hz?

I cant figure out the usage details of pigs, and 'pigs help' doesnt make sense to me either...

Thanks a lot
Posts: 9
Joined: Fri Mar 15, 2013 11:19 pm
by joan » Sun Jun 02, 2013 7:50 am
deefunkt wrote:Hi Joan, I really want to try out your library, would you mind posting perhaps more usage examples in code for noobs?

for example, how would I go about setting a pwm pulse of 1500 microseconds across a signal repeating at 50hz?

I cant figure out the usage details of pigs, and 'pigs help' doesnt make sense to me either...

Thanks a lot

That sounds like you want to control a servo. There is a function specially for servos, e.g. pigs s 4 1500 or pigs servo 4 1500 (s and servo are synonyms) will start servo pulses of width 1500 on gpio 4 (pin P1-7, see http://elinux.org/Rpi_Low-level_peripherals). That will move a servo whose control line is connected to gpio 4 to its mid-point.

Change 4 to reflect the gpio to which your servo is connected.

For instance I have a servo connected to gpio 17 (pin P1-11).

Start daemon (if not already running)

sudo pigpiod

for ((i=1000;i<2000;i++)); do pigs s 17 $i; sleep 0.05; done

Will slowly move a servo from the 1000us to 2000us positions.

You can use pwm (pigs p or pigs pwm, p and pwm are synonyms) to control a servo but the set up is more involved and should only be used if you need to invert the servo signal.

p.s. you can get the identical affect by sending the commands to the pigpio pipe,

e.g. echo "s 17 1200" >/dev/pigpio achieves the same as pigs s 17 1200. That follows for all the pigpiod daemon commands.
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by AMazinG » Tue Jun 04, 2013 10:21 pm
Amazing library, really. Thanks. I was using previously BCM2835 library for GPIO, but certainly this one outperforms the other one.

A bit of simple examples would be nice, but just look into the .h files to get started.
[AMG]
User avatar
Posts: 7
Joined: Fri May 17, 2013 11:05 pm
Location: Hamburg, DE
by AMazinG » Wed Jun 05, 2013 9:36 am
Hi,

I am having some trouble with GPIO 0 and GPIO 1.
As I have read, they have pull-up 1.8K resistors.
When I change the values of these pins to OFF, they remain ON.
As I understand, pull up resistors should not affect their behavior. Or should I disable the pull up resistors? I guess they are enable by default.

EDIT: I figured it out, my board is not Revision 1 as I assumed. So such GPIO's are not on pin3 and pin5 of port1.
For more information look into the documentation of the library (pigpio.h) , specifically look into the function gpioHardwareRevision().
Last edited by AMazinG on Wed Jun 05, 2013 9:54 am, edited 1 time in total.
[AMG]
User avatar
Posts: 7
Joined: Fri May 17, 2013 11:05 pm
Location: Hamburg, DE
by joan » Wed Jun 05, 2013 9:48 am
Pins P1-3 and P1-5 have 1K8 pull up resistors on the board itself which I guess will easily dominate any internal pull up/downs. Of the user gpios only these two pins have hard wired pull-up/downs as far as I know (the pins are used for the I2c bus).
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by AMazinG » Wed Jun 05, 2013 9:55 am
joan wrote:Pins P1-3 and P1-5 have 1K8 pull up resistors on the board itself which I guess will easily dominate any internal pull up/downs. Of the user gpios only these two pins have hard wired pull-up/downs as far as I know (the pins are used for the I2c bus).


Thanks for the answer! Good to know that. Actually my problem was the Revision number (see the edit of my original post). Anyway, thank you again for this amazing library!
[AMG]
User avatar
Posts: 7
Joined: Fri May 17, 2013 11:05 pm
Location: Hamburg, DE
by Raspberry wino » Tue Jun 11, 2013 6:25 pm
This seems like just what I always wanted but I don't know whether to choose hard or soft float version. It's months since I got my RPi and I can't remember which OS I've got. It mentions Debian when it boots so that mean I'm on Raspian? If so which should I choose hard or soft?

Thanks.
Posts: 49
Joined: Mon Mar 05, 2012 11:48 am
by joan » Tue Jun 11, 2013 6:38 pm
You are more likely to be using hard float.

You won't do any harm either way, the build will just fail with a complaint.

Try

cp libpigpio.a-hard libpigpio.a

with make.

If that fails use

cp libpigpio.a-soft libpigpio.a
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by Raspberry wino » Tue Jun 11, 2013 6:47 pm
Will do; thanks for rapid response.
Posts: 49
Joined: Mon Mar 05, 2012 11:48 am
by AMazinG » Wed Jun 12, 2013 3:19 pm
Hi!

I have used this library successfully with Raspbian. Do I have to follow the same steps to install it for ArchLinux? Will it have better performance or something will be different in my programs?

Thank you!
[AMG]
User avatar
Posts: 7
Joined: Fri May 17, 2013 11:05 pm
Location: Hamburg, DE
by joan » Wed Jun 12, 2013 3:26 pm
Arch on the Pi is hard float. Same as Raspbian.
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by Raspberry wino » Fri Jun 14, 2013 1:52 pm
This looks so useful - and very nicely documented too.
A C library of functions to control GPIO with command line interface too makes it just what I wanted but I'm not sure your thread title will bring it the attention this deserves.

...anyway...

I installed the hard float version as you suggested and it all went well. I was ridiculously pleased to be able to control a couple of LEDs from the command line on my normal Linux PC. I want to move on and write something in C to control a display.

Now, today it says "gpioInitialise: Can't lock /var/run/pigpio.pid"
I don't know what that means or what I did differently. Can you help please?

Thanks.
Posts: 49
Joined: Mon Mar 05, 2012 11:48 am
by joan » Fri Jun 14, 2013 2:16 pm
Raspberry wino wrote:This looks so useful - and very nicely documented too.
A C library of functions to control GPIO with command line interface too makes it just what I wanted but I'm not sure your thread title will bring it the attention this deserves.

...anyway...

I installed the hard float version as you suggested and it all went well. I was ridiculously pleased to be able to control a couple of LEDs from the command line on my normal Linux PC. I want to move on and write something in C to control a display.

Now, today it says "gpioInitialise: Can't lock /var/run/pigpio.pid"
I don't know what that means or what I did differently. Can you help please?

Thanks.

It's meant to be a safety feature. The library locks a file when it starts to ensure only one copy is running at a time. The file should be deleted when the library terminates.

Just delete the file,

e.g.

rm /var/run/pigpiod.pid
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by PiGraham » Fri Jun 14, 2013 2:36 pm
joan wrote:It's meant to be a safety feature. The library locks a file when it starts to ensure only one copy is running at a time. The file should be deleted when the library terminates.

Just delete the file,

e.g.

rm /var/run/pigpiod.pid


Presumably turning off the Pi with the library active will leave a lock file on the SD card.
It's good practice to "sudo halt" before switching off, but sometimes that doesn't happen.

It might be a good idea to add "rm /var/run/pigpiod.pid" in a script file in \etc\init.d\ so that the system is ready to go after every boot.
Posts: 1045
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville
by Raspberry wino » Fri Jun 14, 2013 2:58 pm
Thanks joan.
Posts: 49
Joined: Mon Mar 05, 2012 11:48 am
by wuffzack » Wed Oct 23, 2013 10:25 am
Hi Joan,

thank you for this library. I have accomplished many things, which are usually only possible with kernel mode drivers are external hardware (IR & RF decoding).

I am very impressed with the wave out interface, as I can reliably send pulses down to 2 us, even if the sample rate is set to 5 us.

It should be possible to construct a modulated carrier wave (like an IR remote) with gpioWaveAddGeneric, but the limit of 3000 pulses can get in the way. It should be enough for most ir signals, but it can get tight for complex protocols.

Where does the limit of 3000 pulses come from? Is there some kind of workaround, like starting one wave, constructing a new one, while the first is transmitted, and append the second to the first seamlessly?

Thank you!
Posts: 8
Joined: Sat Oct 19, 2013 2:19 am
by joan » Wed Oct 23, 2013 11:29 am
wuffzack wrote:Hi Joan,

thank you for this library. I have accomplished many things, which are usually only possible with kernel mode drivers are external hardware (IR & RF decoding).

I am very impressed with the wave out interface, as I can reliably send pulses down to 2 us, even if the sample rate is set to 5 us.

It should be possible to construct a modulated carrier wave (like an IR remote) with gpioWaveAddGeneric, but the limit of 3000 pulses can get in the way. It should be enough for most ir signals, but it can get tight for complex protocols.

Where does the limit of 3000 pulses come from? Is there some kind of workaround, like starting one wave, constructing a new one, while the first is transmitted, and append the second to the first seamlessly?

Thank you!

The 3000 pulse limit is arbitrary. The software allocates one "block" for outgoing DMA which equates to 53*118= 6254 DMA control blocks. The 3000 limit was added as on average each pulse requires two DMA control blocks (one to switch gpios, one to delay for a number of microseconds).

#define PAGES_PER_BLOCK 53
#define CBS_PER_OPAGE 118

The software uses different clocks for input DMA and output DMA. Using the same clock for more than one DMA channel is problematic. The output DMA clock is fixed as 2us. The input DMA clock is configurable between 1, 2, 4, 5, 8 or 10.

I had a particular use in mind for outgoing waveforms so they aren't as flexible as they should or could be.

Once you have sent a waveform (called gpioWaveTxStart) you can create a new waveform. Monitor gpioWaveTxBusy and send the new waveform when false is returned. I use that for serial data transmission. Fine for serial data, not so good for complicated IR signals.

Do you think 6000 pulses would be enough?

I'm not sure if this change is trivial or not.

If you want to make the change yourself I'll send you the source.
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by wuffzack » Wed Oct 23, 2013 12:41 pm
joan wrote:The 3000 pulse limit is arbitrary. The software allocates one "block" for outgoing DMA which equates to 53*118= 6254 DMA control blocks. The 3000 limit was added as on average each pulse requires two DMA control blocks (one to switch gpios, one to delay for a number of microseconds).

#define PAGES_PER_BLOCK 53
#define CBS_PER_OPAGE 118

The software uses different clocks for input DMA and output DMA. Using the same clock for more than one DMA channel is problematic. The output DMA clock is fixed as 2us.

This is exactly what I measured. And the output wave is rock solid, without any glitches. Very impressive.
joan wrote:I had a particular use in mind for outgoing waveforms so they aren't as flexible as they should or could be.

Once you have sent a waveform (called gpioWaveTxStart) you can create a new waveform. Monitor gpioWaveTxBusy and send the new waveform when false is returned. I use that for serial data transmission. Fine for serial data, not so good for complicated IR signals.

Do you think 6000 pulses would be enough?

I haven't calculated all the details for all the esoteric protocols, but I strongly believe 6000 pulses should be enough.

joan wrote:I'm not sure if this change is trivial or not.

If you want to make the change yourself I'll send you the source.


Yes, this would be fine. Maybe I can think of an improved interface, like "gpioWaveAddCarrier". Although it is certainly possible to construct a modulated carrier with gpioWaveAddGeneric, it feels a little .... awkward.
Posts: 8
Joined: Sat Oct 19, 2013 2:19 am
by limpens » Wed Oct 23, 2013 1:59 pm
@Joan

Any change in releasing the source code of your library? I'm impressed by its possibilities and like to add it as a buildroot recipe to the cross-compile environment I'm using. Adding binary libraries is a bit odd when hundreds of packages are rebuild from source.
Posts: 35
Joined: Thu Sep 13, 2012 1:15 pm
by joan » Wed Oct 23, 2013 2:17 pm
limpens wrote:@Joan

Any change in releasing the source code of your library? I'm impressed by its possibilities and like to add it as a buildroot recipe to the cross-compile environment I'm using. Adding binary libraries is a bit odd when hundreds of packages are rebuild from source.

As long as you are happy with a non-restrictive licence, i.e. public domain.
User avatar
Posts: 6000
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by limpens » Thu Oct 24, 2013 10:13 am
Ofcourse. And with the proper credits where due.
Posts: 35
Joined: Thu Sep 13, 2012 1:15 pm