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

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.

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.

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

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

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

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

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?

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 update2) Always execute the cycle a single time and after that sleep until the beginning of the next second

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.

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 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?

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@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...

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)

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:

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.

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:

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.