Using all 17 available GPIO pins (to build a binary clock)


125 posts   Page 5 of 5   1, 2, 3, 4, 5
by gordon@drogon.net » Tue Nov 06, 2012 9:51 am
Un4Seen wrote:Yes, it has crossed my mind that the slowness could come from the fact that each command is executed separately, but still I find it hard to believe that it's so slow on a 700 MHz processor. I really hope that the writing to the standard output is slowing it down and not the internal workings of it. I'll try redirecting to file, see if that speeds it up.

Luckily for me, C/C++ is what I'm most familiar with :) I've spent the last 7 years working in C++ 8 hours a day or more :) I've never compiled C/C++ code under Linux until now, but it can't be that hard :) So if the bash script can't live up to my performance expectations, C is the next one to try.


It won't be writing to standard output that's the slow bit..

Have a look at the wiringPi/examples directory, and the Makefile for the gpio utility to get you started with C on the Pi. test1.c will run directly on your board.

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1543
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by Un4Seen » Tue Nov 06, 2012 9:56 am
I've done some testing.. Sadly it's not the writing to the standard output that's slowing it down. If I remove this writing or if I redirect it to file, it's not running any faster. But here comes the even more tragic part: if I comment the line that writes the 17 values to the GPIO pins, it runs about 3 times faster!
With all code enabled (except the sleep at the end which was supposed to slow it down, but it seems that it's not required), it is able to complete about 2 cycles per second now. With the writing to GPIO commented, it is able to complete about 6-7 cycles per second. Could it be that the gpio utility is a bit slow?

Probably the C code is the answer to my problems, but for the sake of theory, I'm trying to find out why the bash script is slow.
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by Un4Seen » Tue Nov 06, 2012 10:02 am
Un4Seen wrote:Could it be that the gpio utility is a bit slow?


Or perhaps the problem is that bash needs to switch context (or whatever) 17 times and the call to external utility programs is slow. Maybe if the gpio utility's write command could take a 17-element array in one call, that would improve things. I'm not trying to give you work, I'm just thinking here :)
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by RaTTuS » Tue Nov 06, 2012 12:38 pm
think about it differently -
you don't need to update all 17 each seconds do you ?
you only need to do the minuets each min ... and the hours each hour
http://www.catb.org/esr/faqs/smart-questions.html <- ask smart Questions
"That's not right, the badgers have moved the goalposts."
1QC43qbL5FySu2Pi51vGqKqxy3UiJgukSX - Prosliver FTW
User avatar
Posts: 5575
Joined: Tue Nov 29, 2011 11:12 am
Location: North West UK
by gordon@drogon.net » Tue Nov 06, 2012 12:43 pm
Un4Seen wrote:
Un4Seen wrote:Could it be that the gpio utility is a bit slow?


Or perhaps the problem is that bash needs to switch context (or whatever) 17 times and the call to external utility programs is slow. Maybe if the gpio utility's write command could take a 17-element array in one call, that would improve things. I'm not trying to give you work, I'm just thinking here :)


Where do you draw the line though - I intended the gpio command to just be something to let me quickly test a few IO pins - although I did write a few demo programs in bash using it. I did get a patch once to allow multiple updates too, and it wouldn't be that hard to modify it, but... where do you draw the line.

I'm happy with it the way it is - might encourage you to be more efficient - see the post by RaTTuS ;-)

Or just write it in C :-)

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1543
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by Un4Seen » Tue Nov 06, 2012 12:45 pm
I have updated the bash script. The most important change is that it does not keep updating the GPIO pins all the time, instead it stores the previously obtained time and updates the GPIO only when the new time is different from the old time (when the second changes). This is not only hardware-efficient, but also speeds things up considerably. With this approach I was able to obtain refresh rates of well over 10 cycles per second (it's able to scan the time more than 10 times per second and when the time changes, it sends the updated binary buffer to the GPIO). I've also avoided calling the date command more than once by passing it to functions inside parameters. Other changes include mostly code beautification. I've even had to put back the sleep to avoid overloading the processor :)

Code: Select all
#! /bin/bash

function parseOptions() {
   if [ "$#" -ge 1 ]; then
      for i in "$@"; do
         if [ $i == "-noseconds" ]; then
            opt_noseconds=true
         fi
      done
   fi
}

function initGPIOPins() {
   #Initialize all the GPIO ports to output mode
   for i in `seq 0 16`; do gpio mode $i out; done
}

function fillBufferWithCurrentTime() {
   #Hours
   local hr=$1
   bitmask=16
   for i in `seq 0 4`; do
      binbuf[$i]=$((hr / bitmask))
      hr=$((hr % bitmask))
      bitmask=$((bitmask / 2))
   done

   #Minutes
   local min=$2
   bitmask=32
        for i in `seq 5 10`; do
                binbuf[$i]=$((min / bitmask))
                min=$((min % bitmask))
                bitmask=$((bitmask / 2))
        done

   #Seconds
   local sec=$3
   if [ $opt_noseconds == false ]; then
      bitmask=32
           for i in `seq 11 16`; do
                   binbuf[$i]=$((sec / bitmask))
                   sec=$((sec % bitmask))
                   bitmask=$((bitmask / 2))
           done
   else
      for i in `seq 11 16`; do binbuf[$i]=0 ; done
   fi
}

function outputBufferToStdOut() {
   echo -ne "$1:$2:$3 "

   for i in `seq 0 4`; do echo -ne ${binbuf[$i]} ; done
   echo -ne " "

   for i in `seq 5 10`; do echo -ne ${binbuf[$i]} ; done
        echo -ne " "

   for i in `seq 11 16`; do echo -ne ${binbuf[$i]} ; done
        echo -ne " "

   echo
}

function ouputBufferToGPIO() {
        for i in `seq 0 16`; do gpio write $i ${binbuf[$i]} ; done
}


#main starts here
echo "Binary Clock v1.0 (2012.11.06.) by Bazso-Dombi Andras"

#Binary buffer consisting of 17 elements
#(5 for hours, 6 for minutes, 6 for seconds)
declare -a binbuf=( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )

#Delay constant (in seconds)
declare -r Delay=0.1

#Options
opt_noseconds=false

#Initializations
parseOptions "$@"
initGPIOPins
prevTime="0:0:0"

#Main loop
while true; do
   currentTime=`date +%-H:%-M:%-S`
   echo -ne .

   if [ $currentTime != $prevTime ]; then
      echo
      read hr min sec <<< ${currentTime//[-:]/ }
           fillBufferWithCurrentTime "$hr" "$min" "$sec"
           outputBufferToStdOut "$hr" "$min" "$sec"
           ouputBufferToGPIO
      prevTime=$currentTime
   fi

   sleep $Delay
done
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by Un4Seen » Tue Nov 06, 2012 12:48 pm
RaTTuS wrote:think about it differently -
you don't need to update all 17 each seconds do you ?
you only need to do the minuets each min ... and the hours each hour


Seems that I've guessed your advice before you even gave it to me :)
I haven't gone that far, though. I just made sure that a full update is done only once per second. What you suggested is even better and I might consider implementing it :)
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by jojopi » Tue Nov 06, 2012 2:13 pm
Instead of checking the time repeatedly, you can sleep until (after) the beginning of the next second:
Code: Select all
sleep $(printf "0.%09d" $((1000000000-`date +%-N`)))
User avatar
Posts: 2122
Joined: Tue Oct 11, 2011 8:38 pm
by Un4Seen » Tue Nov 06, 2012 3:05 pm
jojopi wrote:Instead of checking the time repeatedly, you can sleep until (after) the beginning of the next second:
Code: Select all
sleep $(printf "0.%09d" $((1000000000-`date +%-N`)))


That's actually a very good idea. Unfortunately I don't really understand the above code. Does it really guarantee that the process will wake up exactly at the beginning of the next second and not randomly somewhere in the middle of it?
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by Un4Seen » Tue Nov 06, 2012 3:33 pm
Anyway, I've tried it and it works :)

So here's the updated code which takes into account the suggestions of RaTTuS and jojopi:
1) Only update the GPIO pins that have actually changed since the last update
2) Always execute the cycle a single time and after that sleep until the beginning of the next second

Code: Select all
#! /bin/bash

function parseOptions() {
   if [ "$#" -ge 1 ]; then
      for i in "$@"; do
         if [ $i == "-noseconds" ]; then
            opt_noseconds=true
         fi
      done
   fi
}

function initGPIOPins() {
   #Initialize all the GPIO ports to output mode
   for i in `seq 0 16`; do gpio mode $i out; done
}

function fillBufferWithCurrentTime() {
   #Hours
   local hr=$1
   bitmask=16
   for i in `seq 0 4`; do
      curBinBuf[$i]=$((hr / bitmask))
      hr=$((hr % bitmask))
      bitmask=$((bitmask / 2))
   done

   #Minutes
   local min=$2
   bitmask=32
        for i in `seq 5 10`; do
                curBinBuf[$i]=$((min / bitmask))
                min=$((min % bitmask))
                bitmask=$((bitmask / 2))
        done

   #Seconds
   local sec=$3
   if [ $opt_noseconds == false ]; then
      bitmask=32
           for i in `seq 11 16`; do
                   curBinBuf[$i]=$((sec / bitmask))
                   sec=$((sec % bitmask))
                   bitmask=$((bitmask / 2))
           done
   else
      for i in `seq 11 16`; do binbuf[$i]=0 ; done
   fi
}

function outputToStdOut() {
   echo -ne "[$1:$2:$3:$4] "

   for i in `seq 0 4`; do echo -ne ${curBinBuf[$i]}; done
   echo -ne " "

   for i in `seq 5 10`; do echo -ne ${curBinBuf[$i]}; done
        echo -ne " "

   for i in `seq 11 16`; do echo -ne ${curBinBuf[$i]}; done
        echo -ne " "
}

function ouputToGPIO() {
        for i in `seq 0 16`; do
      if ((${curBinBuf[$i]} != ${prevBinBuf[$i]})); then
         gpio write $i ${curBinBuf[$i]}
         echo -ne "$i=${curBinBuf[$i]} "
      fi
   done
}


#main starts here
echo "Binary Clock v1.0 (2012.11.06.) by Bazso-Dombi Andras"

#Binary buffers consisting of 17 elements
#(5 for hours, 6 for minutes, 6 for seconds)
declare -a prevBinBuf=( 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 )
declare -a curBinBuf=( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )

#Options
opt_noseconds=false

#Initializations
parseOptions "$@"
initGPIOPins

#Main loop
while true; do
   currentTime=`date +%-H:%-M:%-S:%N`
   read hr min sec nanosec <<< ${currentTime//[-:]/ }

          fillBufferWithCurrentTime "$hr" "$min" "$sec"
        outputToStdOut "$hr" "$min" "$sec" "$nanosec"
          ouputToGPIO

   for i in `seq 0 16`; do
                  prevBinBuf[$i]=${curBinBuf[$i]}
          done

   echo

   sleep $(printf "0.%09d" $((1000000000-`date +%-N`)))
done


By the way, I don't know if you have noticed, the script can be called with the -noseconds option. This makes it ignore the seconds LEDs. Useful if you build a clock that does not have seconds LEDs or if it bothers you that the seconds LEDs change frequently.

One other note: the fact that the GPIO pins are only updated when the values really change is useful if you use multicolor LEDs which change their color over time. Writing the values to the GPIO pins all the time would probably reset the multicolor LEDs to their first color, unless the hardware ignores setting a pin to the same value that it had before.
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by Un4Seen » Tue Nov 06, 2012 4:12 pm
Using quite much CPU though...
CPU usage with/without the binary clock bash script running:
Without: ~8%
With: ~30%

:roll:
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by Un4Seen » Tue Nov 06, 2012 11:55 pm
Updated bash script (for whoever might need it in the future :) ):

Code: Select all
#! /bin/bash

function printHelp() {
   echo "Usage:" $0 "[OPTION_1][OPTION_2]... [OPTION_N]"
        echo
        echo "Possible options:"
          echo -e "--help\t\tThis help."
   echo -e "--verbose\tWrite information to standard output."
        echo -e "--nosec\t\tIgnore the seconds (always set them to 0)."
        echo
   echo "Binary clock bash script v1.0 (2012.11.06) written by Bazso-Dombi Andras."
   echo "Special thanks to the members of the official Raspberry Pi Forum!"
        echo "For more info visit:"
        echo "http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=21677"
        echo
}

function parseArguments() {
   if [ "$#" -ge 1 ]; then
      for i in "$@"; do
         if [ $i == "--help" ]; then
            printHelp
            exit 0
         elif [ $i == "--verbose" ]; then
            opt_verbose=true
         elif [ $i == "--nosec" ]; then
            opt_noseconds=true
         else
            printHelp
            exit 0
         fi
      done
   fi
}

function initGPIOPins() {
   #Initialize all the GPIO ports to output mode
   for i in `seq 0 16`; do gpio mode $i out; done
}

function fillBufferFromTime() {
   #Hours
   for i in `seq 0 4`; do curBinBuf[$i]=$((($1 & (1 << (4 - i))) >> (4 - i))); done

   #Minutes
        for i in `seq 5 10`; do curBinBuf[$i]=$((($2 & (1 << (10 - i))) >> (10 - i))); done

   #Seconds
   if [ $opt_noseconds == false ]; then
           for i in `seq 11 16`; do curBinBuf[$i]=$((($3 & (1 << (16 - i))) >> (16-i))); done
   else
      for i in `seq 11 16`; do binbuf[$i]=0 ; done
   fi
}

function outputToStdOut() {
   if [ $opt_verbose == true ]; then
      echo -n "[$1:$2:$3.$4]"

      for i in `seq 0 4`; do echo -n ${curBinBuf[$i]}; done
      echo -n " "
      for i in `seq 5 10`; do echo -n ${curBinBuf[$i]}; done
           echo -n " "
      for i in `seq 11 16`; do echo -n ${curBinBuf[$i]}; done
           echo -n " "

      for i in `seq 0 16`; do
                   if ((${curBinBuf[$i]} != ${prevBinBuf[$i]})); then
                                echo -n "$i=${curBinBuf[$i]} "
                   fi
           done

      echo
   fi
}

function ouputToGPIO() {
        for i in `seq 0 16`; do
      if ((${curBinBuf[$i]} != ${prevBinBuf[$i]})); then
         gpio write $i ${curBinBuf[$i]}
      fi
   done
}


#main starts here

#Binary buffers consisting of 17 elements
#(5 for hours, 6 for minutes, 6 for seconds)
declare -a prevBinBuf=( 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 ) #use 2 here so that the first time the loop runs, it detects that every value has changed
declare -a curBinBuf=( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )

#Options
opt_noseconds=false #Ignore the seconds, always set them to 0
opt_verbose=false #Write info to standard ouput

#Initializations
parseArguments "$@"
initGPIOPins

#Main loop
while true; do
   t=`date +%-H:%-M:%-S:%4N`
   read hr min sec nanosec <<< ${t//[-:]/ }

          fillBufferFromTime "$hr" "$min" "$sec"
        outputToStdOut "$hr" "$min" "$sec" "$nanosec"
          ouputToGPIO

   prevBinBuf=("${curBinBuf[@]}")

   sleep $(printf "0.%09d" $((1000000000-`date +%-N`)))
done

The CPU usage is not much better I'm afraid, but the code is more clean and organized.
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by Un4Seen » Thu Nov 08, 2012 9:15 am
Yesterday I have finally received the jumper wires I've been waiting for and have connected the binary LED clock to the Raspberry Pi :)
At first, when I turned on the Pi, I immediately saw that something was wrong because one of the LEDs was always on, even when the ULN2003s were not inserted into their sockets, so clearly there was a short somewhere. It took me about half an hour to find it and fix it. After that, to my great enjoyment, the whole thing started working exactly as expected :D So the first version of the project is completed! Thank you all very much for your help, I could not have done it without all the useful information that I have learned from you on this forum. I will post a nice video about it soon. It will take a few days because I want to do a nice video, with explanations, etc, not just some low quality amateur stuff. Be patient, it's coming :)

A few things worth mentioning:
1. Although I have followed Gordon's advice and have removed the serial lines from /boot/cmdline.txt and /etc/inittab, when the RPI boots up, 3 or 4 LEDs are on. It doesn't bother me much, I just wonder why this happens.
2. As I have stated earlier, I've designed the circuit to deliver 5 mA max to each LED (by adding 390R and 760R resistors to the LEDs) and I have also connected 10K variable resistors in series with the normal resistors in order to be able to limit the current going through the LEDs to 0.5 mA or less. The purpose of this was not just not to waste current, but also to be able to reduce the light of the LEDs so much that I could sleep next to the clock. Well, I have graciously failed :) even when the 10K variable resistors are turned to their max setting (10K), the light of the LEDs is still much too powerful in the dark :) I guess modern LEDs are extremely efficient. Not much I can do about it now without un-soldering components (which I don't want to do), but for the second version I'm going to experiment and find out exactly how much resistance is required to dim the LEDs as much as possible.

Questions:
1. For the next version of the circuit I plan to add components which will make it possible for the clock to automatically dim itself depending on the sensed ambient light intensity. I know that this can be done because you guys have told me that it is :) Can you please explain what component needs to be added where in order to achieve this? Let's say that I'd like 2 mA to pass through each LED in strong daylight and 0.1 mA at night. I'm also thinking that the clock's own light (generated by the LEDs) might influence the behavior of this automatic dimming so it needs to be taken into consideration.
2. I'd like to measure the total current consumption of my current circuit. I plan to do this by disconnecting the 5V or 0V pin from the RPI and connecting a multimeter in series, between the RPI's 5V (or 0V) pin and the clock's 5V (or 0V) pin, with the multimeter set to small current measurement mode. This is the correct way to do it, right?
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by gordon@drogon.net » Thu Nov 08, 2012 9:26 am
Un4Seen wrote:A few things worth mentioning:
1. Although I have followed Gordon's advice and have removed the serial lines from /boot/cmdline.txt and /etc/inittab, when the RPI boots up, 3 or 4 LEDs are on. It doesn't bother me much, I just wonder why this happens.


Because the I2C lines have on-board pull-ups, this may be responsible for 2 LEDs lighting up - it happens on my Ladder board. It's not big deal and once the pins are programmed as outputs it's fine.

However one slightly more worying one is pin7 (BCM_GPIO 4) This appears to be set high at power up time (but not after a reboot) but is quickly changed to an input (I think) before the Linux kernel starts up. Anyone relying on that pin to remain high impedance at power up time had better take additional precautions...

Other than that - make sure you don't have the SPI or I2C modules loaded at boot time (type lsmod) and you should be fine. For LEDs it's probably no big issue, and it's always a good idea to explicitly set the state of all your pins at program start time.

And if you ever do connect anything up to the Pi that could have H&S implications you need to make absolutely sure nothing can be accidentally activated during a power cycle/reboot...

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1543
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by Un4Seen » Thu Nov 08, 2012 9:40 am
gordon@drogon.net wrote:Other than that - make sure you don't have the SPI or I2C modules loaded at boot time (type lsmod) and you should be fine. For LEDs it's probably no big issue, and it's always a good idea to explicitly set the state of all your pins at program start time.

And if you ever do connect anything up to the Pi that could have H&S implications you need to make absolutely sure nothing can be accidentally activated during a power cycle/reboot...

-Gordon


This is the output of lsmod on my Pi:
Code: Select all
Module                  Size  Used by
evdev                   8682  1
gspca_zc3xx            38803  1
gspca_main             19788  2 gspca_zc3xx
videodev               88790  2 gspca_main
snd_bcm2835            12808  1
snd_pcm                74834  1 snd_bcm2835
snd_page_alloc          4951  1 snd_pcm
snd_seq                52536  0
snd_seq_device          6300  1 snd_seq
snd_timer              19698  2 snd_seq,snd_pcm
snd                    52489  7 snd_timer,snd_seq_device,snd_seq,snd_pcm,snd_bcm2835
8192cu                485042  0

I guess this means that SPI and I2C are not used (not listed here).
What does "H&S implication" stand for? :)
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by piglet » Thu Nov 08, 2012 10:03 am
gordon@drogon.net wrote:
Un4Seen wrote:A few things worth mentioning:
1. Although I have followed Gordon's advice and have removed the serial lines from /boot/cmdline.txt and /etc/inittab, when the RPI boots up, 3 or 4 LEDs are on. It doesn't bother me much, I just wonder why this happens.


Because the I2C lines have on-board pull-ups, this may be responsible for 2 LEDs lighting up - it happens on my Ladder board. It's not big deal and once the pins are programmed as outputs it's fine.

However one slightly more worying one is pin7 (BCM_GPIO 4) This appears to be set high at power up time (but not after a reboot) but is quickly changed to an input (I think) before the Linux kernel starts up. Anyone relying on that pin to remain high impedance at power up time had better take additional precautions...

Other than that - make sure you don't have the SPI or I2C modules loaded at boot time (type lsmod) and you should be fine. For LEDs it's probably no big issue, and it's always a good idea to explicitly set the state of all your pins at program start time.

And if you ever do connect anything up to the Pi that could have H&S implications you need to make absolutely sure nothing can be accidentally activated during a power cycle/reboot...

-Gordon



This is really useful information. Please could you add it into the appropriate place in the Wiki? (I know I could mechanically do it - but it's always best if the person who knows the best does the update to ensure correctness)
User avatar
Posts: 569
Joined: Sat Aug 27, 2011 1:16 pm
by joan » Thu Nov 08, 2012 10:12 am
Health & Safety probably.
User avatar
Posts: 6326
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by gordon@drogon.net » Thu Nov 08, 2012 10:15 am
joan wrote:Health & Safety probably.


Yes. You probably shouldn't be using the Pi for anythingl ike that anyway, but if for example you had a motor connected to that pin, then it will turn if the Pi is power cycled...

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1543
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by Un4Seen » Sun Nov 11, 2012 11:28 pm
So, as promised, here comes the video :)

http://www.youtube.com/watch?v=dY3wTtFPn48
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by bgirardot » Mon Nov 12, 2012 1:20 am
It looks great. Congratulations! And thank you for sharing all the details on how you built it.
Posts: 517
Joined: Wed Oct 10, 2012 6:20 am
Location: Switzerland
by Un4Seen » Mon Nov 12, 2012 8:48 am
bgirardot wrote:It looks great. Congratulations! And thank you for sharing all the details on how you built it.


Thank you :) Hope this can help somebody in the future to build his/her own binary LED clock :)
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by Un4Seen » Thu Jan 31, 2013 9:22 pm
Hi Guys!

Now that I have my own tech site, I have published a detailed article covering all the theoretical and practical aspects of making this Raspberry Pi driven binary LED clock. It should help others build their own without any problems. You may take a look here:

http://iqjar.com/jar/raspberry-pi-binary-led-clock/

It is hosted on my Raspberry Pi, which I sometimes reboot and even turn off for 15 minutes or so occasionally, to back up the SD card, so if you happen to catch one of these periods and can't access the link, just try again a bit later.
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by gordon@drogon.net » Thu Jan 31, 2013 9:31 pm
Un4Seen wrote:Hi Guys!

Now that I have my own tech site, I have published a detailed article covering all the theoretical and practical aspects of making this Raspberry Pi driven binary LED clock. It should help others build their own without any problems. You may take a look here:

http://iqjar.com/jar/raspberry-pi-binary-led-clock/

It is hosted on my Raspberry Pi, which I sometimes reboot and even turn off for 15 minutes or so occasionally, to back up the SD card, so if you happen to catch one of these periods and can't access the link, just try again a bit later.


Fantastic!

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1543
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by Un4Seen » Thu Jan 31, 2013 9:39 pm
gordon@drogon.net wrote:
Fantastic!

-Gordon


Thanks! :)
But let's not forget that this would not have been possible without the help of the members of this forum. Thank you!
Andras
http://iqjar.com
User avatar
Posts: 288
Joined: Wed Oct 31, 2012 8:43 am
Location: Cluj-Napoca, Romania
by smiffydotcom » Sun Sep 29, 2013 3:03 pm
I've been experimenting with a couple of shift registers with a view to building a "steampunk" binary clock using 1930's mains neon indicators.... the outputs drive HV transistors...

But heres a proof of concept bit of (poorly written} python code which gives a 12 hour BCD (Binary) clock in 16 bits using 3 I/O lines

Not quite the 17 I/O pin route - but a "working" Binary Clock nevertheless.

(I''m using 2 cascaded 74HC595N's)


Regards

smifffy

Code: Select all

#########################
# BCD )Binary) Clock    #
#########################
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
import time
localtime =time.localtime(time.time())
#########################
# cobbler pinout        #
#########################
#  1 = 3v3  |  5v0 = 2  #
#  3 = SDA  |  5v0 = 4  #
#  5 = SCL  |  GND = 6  #
#  7 = #4   |  TXD = 8  #
#  9 = GND  |  RXD = 10 #
# 11 = #17  |  #18 = 12 #
# 13 = #21  |  GND = 14 #
# 15 = #22  |  #23 = 16 #
# 17 = 3v3  |  #24 = 18 #
# 19 = MOSI |  GND = 20 #
# 21 = MISO |  #25 = 22 #
# 23 = CLK  |  CE0 = 24 #
# 25 = GND  |  CE1 = 26 #
#########################

GPIO.setup(7,  GPIO.OUT)    #DATA
GPIO.setup(11, GPIO.OUT)    #CLOCK
GPIO.setup(13, GPIO.OUT)    #LATCH
#Set ouputs to OFF
GPIO.output(7, False)
GPIO.output(11,False)
GPIO.output(13,False)

###############################
def display(data):
###############################
    bit=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]   
    aa=data
    print "Binary ",
    GPIO.output(13,False)
    for bi in range (0,16):
        bit[bi]=data%2
        if bit[bi]:
            # bit = 1
            GPIO.output(7,True)
            #wiggle clock pin 
            GPIO.output(11,True)
            GPIO.output(11,False)
            print "X",
        else:
            # bit = 0
            GPIO.output(7,False)
            #wiggle clock pin
            GPIO.output(11,True)
            GPIO.output(11,False)
            print ".",
        data = data/2
    GPIO.output(13,True)
    print "  Dec",aa,"Hour",h,"min",m,"sec",secs
    return (0)

###################################
go=1
while go:
   
    hour = int(time.strftime("%H"))
# limited to 4 bits for hours
    if hour > 12:
        hour=hour-12
    mins = int(time.strftime("%M"))
    secs = int(time.strftime("%S"))
# push the data to the desired position
    h=hour
    hour = hour*4096
    m=mins
    mins = mins*64
# make 16 bit number   
    data = hour+mins+secs
    display (data)
    time.sleep(1)
   
GPIO.cleanup()

###################################
# data is sent as a 16 bit digit
# to the 2 8bit shift registers.
# It is in the format:
# 6 bits for Seconds
# 6 bits for Minutes
# 4 bits for Hours (12 hour clock)
###################################
#           1  2  4  8  16  32 64  128 256 512 1024 2048 4096 8192 16384 32767
#    Hours                                                  x    x    x    x 
#    Mins                      x    x   x   x    x   x
#    Secs   x  x  x  x   x  x
####################################
# by laying out the LEDs correctly
# it looks great
#
#   0 0 0 0
#   0 0 0 0 0 0
#   0 0 0 0 0 0
#





Posts: 5
Joined: Wed Jan 30, 2013 3:18 pm