Raspberry Pi Bulletin Board




Introduction: Raspberry Pi Bulletin Board

This is a project I worked on for my church. We wanted an electronic bulletin board that would be mounted in the narthex/lobby area and would cycle through static slides every few seconds.

These were our design goals:

  • Static slides, no video or audio
  • Admin generates slides in Powerpoint (familiar tool, no new software to learn)
  • Admin can drag and drop new presentation to replace old one
  • No cloud-based solution, since the bulletin board would be on our private wireless network
  • No monthly license fees or proprietary software, other than what we already had (Windows, Office, Powerpoint)
  • 49" screen, in portrait/vertical mode (though landscape/horizontal mode is also possible and described below)
  • Desired cost: <$1000

We managed to do this and came in under budget. I recently helped another nearby church do the same project, and the total cost (not including cost of an electrician to bring power to the right place on the wall and the labor involved in mounting) was less than $500.

Because of the low cost and essentially zero ongoing costs (just electricity), this would also fit well with schools, libraries, museums, non-profits, or other organizations with limited budget.

Feedback is welcome.

Step 1: Equipment List

Here is a list of equipment we used. Comments are added. I try to link to the manufacturer's site where possible, rather than a retailer.

  • TV/monitor. Most any modern TV or monitor will do, as long as it has CEC (see this article on Wikipedia for more information about CEC: https://en.wikipedia.org/wiki/Consumer_Electronics_Control). Most monitors are made to be mounted in either vertical/portrait or in horizontal/landscape mode. TVs are designed to be horizontal, so mounting them vertically is a bit trickier. Also, many TVs are asymmetric top-to-bottom (i.e. the bottom edge is often bigger than the top), so mounting it vertically may look a bit odd. Still, TVs are cheaper overall, so we went with a TV. Of course, if your preferred orientation is landscape, it doesn't matter. We went with this one: LG 49" LED TV.
  • TV Mount: This was tricky, because we bought a TV and wanted to mount it vertically. Things to consider are the style of mount and whether it will be visible, especially if the TV is mounted vertically. The mount is placed on the wall in the same orientation as if you were mounting the TV horizontally. If you opt to mount the TV vertically, you need to consider whether the screw mounting holes in the TV mount can accomodate the rotated mounting holes in the TV. Some TVs space their mount screws in a square pattern, whereas some are a rectangular pattern. Think this through and make sure you mount will work in the desired location before purchasing.
  • Raspberry Pi, case, cables, heat sink, fan, etc.: I recommend you get the latest and greatest version. At the time we built the project, it was the Raspberry Pi 3 B+, but now the Raspberry Pi 4 B is out. As far as case, power cord, heat sinks, fan, we decided that since the Raspberry Pi will be running 24/7, we wanted a case with a fan, albeit a quiet one. And having a power cord with an inline power switch makes it easy to reset the system without having to pull the plug. The other main difference between the Raspberry Pi 3 B+ and Raspberry Pi 4B is that the 4 B has a micro-HDMI plug, which means you need an adapter (it is included in the kit below).
  • HDMI cable: Any is fine, as long as it supports CEC. Note that typically, the Raspberry Pi will be mounted on the wall behind the TV/monitor or possibly attached to the TV/monitor itself, so a short 3' cable is probably plenty. Too long of a cable and it will show. Also consider where the HDMI ports are on the TV/monitor and whether you might consider a 90-degree cable end (for example, if the HDMI ports are on one side).
  • MicroSD card. This doesn't matter much, either. We chose 32GB rather than standard 16GB, just to have extra space for additional software, if we wanted, and to have a place to store multiple presentations. We chose this one: SanDisk Ultra PLUS 32GB MicroSD Card . Note that it is easier if you buy a MicroSD card with NOOBS already installed, like this one: SD Card with NOOBS. I didn't do that, but you can save a step if you do. See here for more information: NOOBS

A note on CEC: CEC (Consumer Electronics Control) allows some components control each other through the HDMI cable. For example, a DVD player could turn on/off the connected TV through the HDMI cable if both support CEC. This is useful in our case, as the Raspberry Pi can turn on/off the TV/monitor as it wishes. For example, in a church setting, we would like to have the monitor on only during hours when the church is open, and that varies by day of the week. CEC allows the Pi to turn the TV on and off in an arbitrarily complex time schedule.

Step 2: Assemble the Pi Case

Assembly is fairly straightforward. Stick the heat sinks on the chips of corresponding size on the Raspberry Pi, assemble the case layer by layer. Don't forget to remove the thin plastic protective sheets from each layer.

Step 3: Install Raspbian

There is an excellent guide on the Raspberry Pi site. Follow those instructions to set it up.

Setting up your Raspberry Pi

I used Raspbian Lite, as it doesn't have extra applications that you won't need for this project.

Step 4: Add Standard and Custom Software

Once NOOBS installs Raspbian, the first time you login, you will be prompted for things like language, time zone, etc. It will also prompt for WiFi network and password information, unless you are on a wired connection. Finally, it will download and install any Raspbian updates. It helps if you are on the same internet connection as in the final setup, but it doesn't have to be. That is, you can do this step at home before setting up in the final location. Just remember to set up the new internet connection before the final reboot in the last step.

Open a terminal window (click on the black rectangular icon near the upper left corner of the screen).

First we double-check to see if there are any further Raspbian updates. Type the following lines, one at a time

sudo apt update
sudo apt upgrade

(say "Y" if it asks whether you want to install updates).

Next we install Samba, which allows folder sharing with the Windows machine(s) on the network.

sudo apt install samba samba-common-bin smbclient cifs-utils

Next we install fbi. fbi is the unix utility that displays graphics on a screen not running a window manager.

sudo apt install fbi

Next we install inotify-tools. inotify-tools allows the slideshow to watch the shared folder for any changes.

sudo apt install inotify-tools

Next we install cec-utils. cec-utils allows the Raspberry Pi to turn the TV on and off via the HDMI cable.

sudo apt install cec-utils

Next you'll need to download the small utilities I wrote to play the slideshow.

git clone https://github.com/dgrannes/raspi_slideshow.git

This will fetch the code and put it in a directory called raspi_slideshow.

Now all the software is available on the Raspberry Pi. The next steps go through the configuration.

Step 5: Set Up Shared Folder

By default, the slideshow code searches for a directory (folder) /shared/Presentation.

We need to create that directory. Since it is at the root level, we need root permissions, so a sudo is in order. You may need to type the password (default is raspberry) when you do this command:

sudo mkdir -p /shared/Presentation

Next, we need to make this readable and writable by anyone on this Pi. Type the following command:

sudo chmod a+rwx /shared/Presentation

This makes it visible only on this Pi. Next, we need to share this folder with the world (actually, only other machines on the same network). That is why we recommend this be on a private (password-protected) Wi-Fi network or a wired local network.

When we installed samba in the previous step, it created a default file /etc/samba/smb.conf

We need to add a bunch of lines to the end of that file. The lines are in the file raspi_slideshow/add_to_smb.conf

The easiest way to do this is the following:

sudo bash

cat raspi_slideshow/add_to_smb.conf >> /etc/samba/smb.conf


This basically concatenates the add_to_smb.conf file to the end of /etc/samba/smb.conf

You may choose to do it via an editor like nano if you prefer, but it's a fair amount of typing.

Basically it shares the /shared directory as a directory that is readable and writable by anyone on the local network. I won't go through how to protect it here, but if you want it to be protected (to require a password to edit), you can read up on Samba and change the settings accordingly.

Step 6: Configure Monitor On/off Settings

We use cron to turn on and off the TV/monitor at scheduled times. Cron is a linux utility that runs tasks at scheduled times. If you want your TV/monitor to run 24/7 or you want to turn it on and off manually, you may skip this step.

Copy the example crontab file from the raspi_slideshow directory to the home directory.

cp raspi_slideshow/crontab_example.pi crontab.pi

The file crontab_example.pi is an example that shows how this type of file works. There is plenty of documentation in Wikipedia and elsewhere: https://en.wikipedia.org/wiki/Cron

Now we edit it. It helps to have your schedule already figured out. The example schedule is

  • Sunday: on at 7am, off at 9pm
  • Wednesday: on at 8am, off at 9pm
  • Saturday: on at 7am, off at 9pm
  • Other days: on at 8am, off at 5pm

I like nano since it is installed with Raspbian and easy to use. You may use vi or any other editor.

nano crontab.pi 

Edit the file to specify on/off times for each day. Use the arrow keys to move around. Backspace to delete, type to insert. When you are finished, Control-O to save (you will have to hit "enter" to confirm the file name), and Control-X to exit nano.

Once you have your cron file the way you want it, tell Raspbian you want to execute it:

crontab crontab.pi

If you ever want to change your schedule, you may edit $HOME/crontab.pi and re-execute the crontab command immediately above. That will replace your old schedule with the new one.

Step 7: Configure Display Settings

We are almost done! We need to configure the display settings. fbi is the utility that we use to display the slides. It reads its settings from the file .fbirc in the home directory.

First, make sure we are in the home directory.

cd $HOME

Next copy the file from the raspi_slideshow directory to home

cp raspi_slideshow/.fbirc .

You shouldn't need to edit the file. However, if you choose, the three settings that are of interest are:

random = false

blend-msecs = 500

timeout = 8

The random line determines whether fbi randomizes the slide order. true means it does randomize the slides, false means it doesn't. Since we wanted some control over what order the slides are in, we set it to false.

The blend-msecs line says how many milliseconds (1000= 1 second) does each transition last. A value of 0 means the slides change instantly from one to the next. Our setting of 500 means the slides fade into each other over a period of 0.5 seconds.

Timeout is the time (in seconds) that each slide is displayed before transitioning to the next. You may adjust this if you want slides to be longer or shorter. Just remember that this applies to all slides equally. There is no way to have some slides appear longer and others shorter.

Rotate display

If you have your TV/monitor mounted vertically, as we do, you will need to rotate the display 90 degrees or 270 degrees. If you have your TV/monitor mounted horizontally, you can skip the rest of this step.

Use nano again. This time you need to run as root, so you'll need to sudo, which may require you to reenter your password (default is raspberry)

sudo nano /boot/config.txt

Use the down arrow to go all the way to the bottom of this file. Add the following line to the end of the file:


This will rotate the display 90 degrees. If after mounting, your display is upside down, change the 1 to a 3.

Basically display_rotate = 0 (no rotation), 1 (90 degrees), 2 (180 degrees), 3 (270 degrees)

In the picture above, we had set display_rotate=1 and had to go back and change it to display_rotate=3. Much easier than re-mounting the TV!

Step 8: Change Password and Set Up Auto-run

At this point, we are almost finished!

Click on the raspberry menu in the upper left, select Preferences->Raspberry Pi Configuration

That brings up a dialog box. Click on "Change Password..." and change it to something you will remember!

You may choose to change the name of the system (Hostname field).

Make sure you click Boot "To CLI"

Set auto-login ("Login as user 'pi'")

Now you need to set up the slideshow to run when you boot. The easiest way is to add one line to your .bashrc file. Firing up our nano editor:

nano .bashrc

Down-arrow to the end of the file and add the following line:

python3 raspi_slideshow/play_slideshow.py

These settings mean that:

  • Whenever it is rebooted, the Raspberry Pi will automatically login as user pi
  • It will not start a window manager, but just run on the screen ("Boot to CLI")
  • It will start up the bash shell, which reads the .bashrc file, and the last line of that file says to run the slideshow.

After this, reboots will NOT fire up the window manager, and will automatically run the slideshow. You can stop the slideshow by hitting Control-C during the slideshow. This will bounce you back out to the bash prompt ($).

If you want to start the window manager from this point (for debugging or easier manipulation of settings), you can do it by typing "startx" at the command line.

Step 9: Use (Setting Up the Windows Machine)

In actual use, our Raspberry Pi connects to our private wireless network on startup. It shares its /shared directory (and everything beneath) to the network. In order to see this folder from a Windows machine, make sure you are on the same network.

I assume you will be connecting to this from a Windows computer in an office. For either Windows 7 or Windows 10, open up a File Explorer to view the files/folders on your computer. Right-click on the left where it says "Computer" or "My Computer", then select "Map Network Drive..."

That will bring up a dialog box. Choose what letter, e.g. "Z:" you want to map your drive to. Then in the Folder field, type:


where {name-of-your-Pi-computer} is the name you gave your Raspberry pi back in the previous step (see previous picture with the dialog box).

Be sure to click "Reconnect at login". It is possible that if the Raspberry Pi is powered off when the Windows computer boots, that this step may have to be repeated (or the Windows computer rebooted) in order to see the shared folder.

If you choose to password-protect your folder, you can add credentials by selecting "Connect using different credentials" and entering the username/password for the Raspberry Pi.

Now, when you want slides to go into your slideshow, copy individual slide images(*) into the Presentation folder.

The script will monitor and display ONLY the contents of the Presentation folder, and nothing at the level above that (\shared). Thus, we sometimes use the trick of putting commonly-used slides in the top level and then dragging them as needed into or out of the Presentation folder.

Remember, when anything in the Presentation folder changes (files are added, deleted, or modified) the slideshow script waits 2 minutes (120 seconds, configurable in play_slideshow.py, search for wait_time) before resetting and displaying the new slides. This gives the person time to make all the changes necessary without resetting after each new file is added.

Individual slide images are jpeg, gif, or png files that represent a single slide. The easiest way to generate these is using Microsoft PowerPoint or a similar program. You can generate as many slides as you'd like in Microsoft PowerPoint and save it as a PowerPoint presentation. Then click File->Export->Change File Type and save as either PNG or JPEG. This will output the slides as individual files, e.g. slide1.png, slide2.png, etc. You can then drag and drop individual files into Z:\Presentation (or whatever drive letter you used). Note that the presentation is put together in alphabetical (not numerical) order, so slide11.png comes after slide1.png and before slide2.png. You may of course rename the slides before copying them into the network folder. Just make sure they retain their extension (e.g. .png). The slideshow script currently looks only for files with the following extensions: .PNG, .png, .GIF, .gif, .JPG, .jpg This is configurable in play_slideshow.py (search for glob_strings).

Step 10: Troubleshooting

Most problems can be solved by the old "try turning it off and on again" solution.

If your Raspberry Pi is not connecting, not updating, or seems to be generally stuck, try power cycling it.

If your Windows machine loses the mapped network drive, try power cycling it or manually add the drive again.

If you have other questions/problems, please post in the comments and I'll update this step with common problems and their solutions.

Step 11: Conclusion and Future Work


At this point, you can reboot your Raspberry Pi, either through the menus or with the power button on the power cord. The nice thing about this setup is that whenever the Pi boots (power failure, crash, whatever), it starts up in slideshow mode, so you can power-cycle at will and it should recover fine. Once this is installed and working, you can pretty much "set it and forget it", other than the updates to the slides. In our case, our church admin updates the slides weekly, and this system has been working flawlessly for about a year.

Please give feedback! I'm receptive to fixing bugs or inaccuracies. I understand there are many different ways to do things, so I'm not excited about answering questions like "why did you use python instead of {programming language X}?" Or suggestions that are functionally the same (like "sudo apt" all the packages at once instead of one at a time). However, functional improvements are always welcome! I try to make this as functional and useful as possible while also being easy to install and easy to maintain. I particularly enjoy feedback from those who have benefited from this Instructable. I am happy to help if I am able.

Future work

I am starting to work on a version that will allow video files (with sound) to be intermixed with the static slides. I think I can use vlc for that from the command line. I will update this if I am able to get it to work. Feel free to make suggestions!

Be the First to Share


    • Plastic Challenge

      Plastic Challenge
    • Halloween Contest

      Halloween Contest
    • Organization Contest

      Organization Contest



    2 days ago

    Excellent, did you ever work out a video version?


    Question 3 months ago on Step 10

    Thank you for the instructions. I have got most of it to work, I have tried PNG and JPG files and it comes up as "loading failed" for all the files. do you have a suggestion of where to look?


    Answer 3 months ago

    Sorry you're having problems! It appears from this site:
    (even though we're not using java) that the error message is coming from fbi and that it cannot find the files. The python code tries to expand any wildcards, but I could imagine that it would fail if you have spaces or perhaps other special characters (e.g. hyphens) in your filenames. Try making sure that your filenames have only letters, numbers, and underscores "_" for readability. And of course the "." before the extension, e.g. my_long_filename.PNG

    Let me know if that helps!


    Reply 3 months ago

    I have taken all symbals and spaces out and it still does the same thing "loading failed". Here is the list of file names and screen shot of file explorer.

    Screenshot 2021-06-11 124440.png

    Reply 3 months ago

    If you're comfortable doing some software debugging, edit the play_slideshow.py file. Between lines 46 and 47, add a print statement:

    filelist.insert(0, 'fbi')

    That is, add the middle statement above between the two other statements that are already there. Be sure that you have the same spacing (4 spaces) before the word print--it should line up with the lines above and below.

    You should be able to edit it with nano or your editor of choice. Let me know what the print statement prints out.

    If you're not comfortable with that, then I would recommend you double-check that there are no spaces hiding at the beginning or ending of the filenames. Try retyping the names completely.

    I'm sorry you're having problems with this! I'll keep working with you until we figure this out.


    Reply 3 months ago

    I'm fine with modifying code, do you know a command to pause the script long enough to read the print out? I tried
    read -t 5 -p "Waiting for 5 seconds.."
    sleep 5
    nether of them worked.
    I know the print is working and gives a list but it flies by to fast.


    Reply 3 months ago

    The "big hammer" solution would be to just put
    after the print statement, which should stop the program entirely. That should give you a chance to read the output.
    Again, Python is sensitive to whitespace, so make sure the lines are aligned (should be 4 spaces before each line within that function).


    Reply 3 months ago

    Thank you. the line that was printed, I also attached a screenshot.

    ['fbi', '/shared/Presentation/slide1.jpg', '/shared/Presentation/slide2.jpg', '/shared/Presentation/slide3.jpg', '/shared/Presentation/slide4.jpg' ]


    Reply 3 months ago

    I was thinking what else could affect this and I was going through the menu and found the image viewer, I decided to see if it would be able to view the slides. It errored out on each slide saying the file was not a valid jpg. From my machine i went to the share drive and tested them out again. I got the same thing. I went to the original slides and they worked. I deleted what was in the share drive and copied them again. while they were in the share folder I tested them from my machine and image viewer on the raspberry pi and they worked. I rebooted and it all works now. Thank you for pointing me in the right direction and helping me out.


    Reply 3 months ago

    Great to hear! Glad it works now.


    Question 7 months ago on Introduction

    thank you for the instructions.. i got mine to work after a few modifications. may i ask.. how do you restart the fbi service after you've uploaded (replaced) NEW mage files within the presentation folder? tia


    Answer 7 months ago

    The play_slideshow.py program, should remain running at all times. It uses inotify to watch the folder where the images are. When the folder changes, the program wakes up and processes the new images.
    Because the user typically would update multiple images at a time, I put a wait_time in there. It defaults to 120 seconds but you can change it if you want. Basically, if you updated one file, then another, then another, I didn't want it to kill/restart fbi each time, so when it detects a change it waits wait_time seconds for things to settle down.
    Does that make sense? Assuming you got the inotify-tools installed correctly, the program should automatically update, just with the delay.
    Let me know if it works or if you need more help.


    Question 1 year ago

    I have tried to download the files from github but i'll get isked a username and pasword for de download. I can not find the login on the page so what am i doing wrong?
    Edit: probably I had the link wrong, after retyping it worked.


    1 year ago

    I've tried it and not been able to link it up with the Map Network Drive to upload the files, how did you get yours to link up?


    Reply 1 year ago

    Are both the Raspberry Pi and the desktop computer on the same network? Some offices have a wired network that the computers are on and a separate wireless network.
    Did everything go well in Step 5? That's the bit where the shared folder is set up.


    1 year ago

    This looks slick, and very useful. Nicely done! : )