Digital Signage Player
This is where we are documenting our long and evolving search for the perfect fabrication lab signage. The signage will/has been used for basic info, but ideally can be adapted for use with specific equipment, quickly edited in-house and easily updated.
A brief explanation of each of the solutions we have trial or research is given, then detailed instructions are provided where appropriate. Resources for the signage can also found here.
Prototype One - The Pi-looper
IMPLEMENTED - in occasional use for installations
The pi-looper prototype was explored in 2015-2016 as a solution for signature programming by Daniel. It has two versions, one that uses video on the SD card, a second that plays back of a USB. Other options include output of sound over HDMI or minijack.
The Signage was used in the fabrication Lab in 2015 before the refurbishment.
Credit goes to Steven Hickson for this work, This is the latest info.
http://stevenhickson.blogspot.com.au/2015/04/rpi-videolooper-not-booting-blinking.html
Source is here.
https://github.com/StevenHickson/RPiVideoLooper
Check out the pi-maker documentation to make your own pi looper.
PROS:
- Existing solution
- Documented
- Works
- Minimal hardware spec (pi2)
CONS:
- Only video files.
- Limited Customisation
Verdict
Useful for stand-alone player only. Not updated easily or web-based.
Prototype Two - The Chromecast
STALLED - with ICTS networking
This was seen as possibly the cheapest way to get a remote screen working. It has stalled due to network requirements which SLQ ICT is working on. It seems the chromecast requires multicast and TCP/UDP set-up outside the scope of usual SLQ wifi networks. This uses a webpage as source which is opened in a browser (chrome) and then 'cast' to the chromecast.
Pros
- Cheap solution
- reliable, available hardware
- will play video
- can be used for presentations
Cons
- Networking set-up is not enterprise friendly (requires multicast and dns)
- Each screen requires a browser on another device (or possibly tabs?)
Prototype Three - The Pi Kiosk + Reveal.js Signage Server
implimented - then discarded due to need for extra node service needed on server
Based on a running a simple web slide show as the signage, with a pi running a web browser in kiosk (full screen) mode.
PROS:
- Existing solution
- Documented
- Works
- Minimal hardware spec (pi2)
- Web-based
CONS:
- Complexity of client/server
Raspberry Pi Kiosk
This is a pi running in kiosk mode which boots to full screen browser (using lxde autostart) and goes to web address using a web browser call kweb
Info found here
https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=40860
Manuals here
http://steinerdatenbank.de/software/kweb_manual.pdf
The browser has comprehensive keyboard shortcuts, designed to control the pi entirely through a browser.
Signage Server
Many options exist for web signage, from simple stand-alone players to networked client-server models. As we want a simple proof-of-concept, I've gone with a simple web-based slide presenter called reveal.js. There is an online editor for making slides here Reveal.js can run locally, over a network on a server, or multicast over web sockets. For this prototype it run an the programming server.
Reveal.js
This was the first attempt. For our purposes I've hacked the index.html, modifying the css to fomat inline, a couple of pictures as background, added adding the supervisor's name (mick) and turned on autoslide in the js options.
This is the changed index.html, renamed to welcome.html
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>welcome to The Fab Lab</title> <link rel="stylesheet" href="css/reveal.css"> <link rel="stylesheet" href="css/theme/black.css"> <!-- Theme used for syntax highlighting of code --> <link rel="stylesheet" href="lib/css/zenburn.css"> <!-- Printing and PDF exports --> <script> var link = document.createElement( 'link' ); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css'; document.getElementsByTagName( 'head' )[0].appendChild( link ); </script> </head> <body> <div class="reveal"> <div class="slides"> <section data-background-image = "fabrication_lab_signage_v1-01.png"> </section> <section data-background-image = "3pointcheck_one_page.png"> <h1 style="color:black;align-content: center;margin-top: 580px;"> Mick </h1> </section> </div> </div> <script src="lib/js/head.min.js"></script> <script src="js/reveal.js"></script> <script> // More info https://github.com/hakimel/reveal.js#configuration Reveal.initialize({ history: true, // More info https://github.com/hakimel/reveal.js#dependencies dependencies: [ { src: 'plugin/markdown/marked.js' }, { src: 'plugin/markdown/markdown.js' }, { src: 'plugin/notes/notes.js', async: true }, { src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } } ] }); </script> </body> </html>
These are the background images:
and the settings changed in reveal.js are;
// Loop the presentation loop: true, // Number of milliseconds between automatically proceeding to the // next slide, disabled when set to 0, this value can be overwritten // by using a data-autoslide attribute on your slides autoSlide: 7000, // Stop auto-sliding after user input autoSlideStoppable: true,
This is the working version revealjsfablab which can be copied to a server or opened locally.
You can see it running here: http://192.168.36.78/reveal/welcome.html#/
Prototype Four - The Pi Kiosk + Dokuwiki Reveal.js Signage Server
implimented - but broken - power pulled and wiped SD card
Reveal.js is great - but ideally we'd like to hang it off our wiki - Once again a dokuwiki plug-in to the rescue. Therevealjs plugin for dokuwiki lets us use standard wiki pages and markup to create our slides. Here us the welcome signage. For more examples check out the fabrication lab Fabrication Lab Signage page.
PI
Raspian Lite install built with pibakery, a gui based piSD authoring utility
Minimal customisation;
- /LXDE-pi/autostart launches start.sh
- start.sh has 180 sec delay then launches chromium, kiosk mode, pointed to signage http address
- sudo crontab -e has shutdown at 830pm
Teensy
Arduino sketch that reads the teensy buttons and sends out up/down/left/right/F5/esc
/* Buttons to USB Keyboard Example You must select Keyboard from the "Tools > USB Type" menu This example code is in the public domain. */ #include <Bounce.h> // Create Bounce objects for each button. The Bounce object // automatically deals with contact chatter or "bounce", and // it makes detecting changes very simple. Bounce button0 = Bounce(0, 10); Bounce button1 = Bounce(1, 10); // 10 = 10 ms debounce time Bounce button2 = Bounce(2, 10); // which is appropriate for Bounce button3 = Bounce(3, 10); // most mechanical pushbuttons Bounce button4 = Bounce(4, 10); Bounce button5 = Bounce(5, 10); // if a button is too "sensitive" Bounce button6 = Bounce(6, 10); // to rapid touch, you can Bounce button7 = Bounce(7, 10); // increase this time. Bounce button8 = Bounce(8, 10); Bounce button9 = Bounce(9, 10); void setup() { // Configure the pins for input mode with pullup resistors. // The pushbuttons connect from each pin to ground. When // the button is pressed, the pin reads LOW because the button // shorts it to ground. When released, the pin reads HIGH // because the pullup resistor connects to +5 volts inside // the chip. LOW for "on", and HIGH for "off" may seem // backwards, but using the on-chip pullup resistors is very // convenient. The scheme is called "active low", and it's // very commonly used in electronics... so much that the chip // has built-in pullup resistors! pinMode(0, INPUT_PULLUP); pinMode(1, INPUT_PULLUP); pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP); pinMode(4, INPUT_PULLUP); pinMode(5, INPUT_PULLUP); pinMode(6, INPUT_PULLUP); // Teensy++ LED, may need 1k resistor pullup pinMode(7, INPUT_PULLUP); pinMode(8, INPUT_PULLUP); pinMode(9, INPUT_PULLUP); } void loop() { // Update all the buttons. There should not be any long // delays in loop(), so this runs repetitively at a rate // faster than the buttons could be pressed and released. button0.update(); button1.update(); button2.update(); button3.update(); button4.update(); button5.update(); button6.update(); button7.update(); button8.update(); button9.update(); // Check each button for "falling" edge. // Type a message on the Keyboard when each button presses // Update the Joystick buttons only upon changes. // falling = high (not pressed - voltage from pullup resistor) // to low (pressed - button connects pin to ground) if (button0.fallingEdge()) { Keyboard.press(KEY_LEFT); } if (button1.fallingEdge()) { Keyboard.press(KEY_RIGHT); } if (button2.fallingEdge()) { Keyboard.press(KEY_UP); } if (button3.fallingEdge()) { Keyboard.press(KEY_DOWN); } if (button4.fallingEdge()) { Keyboard.press(KEY_F5); } if (button5.fallingEdge()) { Keyboard.press(KEY_ESC); } if (button6.fallingEdge()) { Keyboard.println("B6 press"); } if (button7.fallingEdge()) { Keyboard.println("B7 press"); } if (button8.fallingEdge()) { Keyboard.println("B8 press"); } if (button9.fallingEdge()) { Keyboard.println("B9 press"); } // Check each button for "rising" edge // Type a message on the Keyboard when each button releases. // For many types of projects, you only care when the button // is pressed and the release isn't needed. // rising = low (pressed - button connects pin to ground) // to high (not pressed - voltage from pullup resistor) if (button0.risingEdge()) { Keyboard.release(KEY_LEFT); } if (button1.risingEdge()) { Keyboard.release(KEY_RIGHT); } if (button2.risingEdge()) { Keyboard.release(KEY_UP); } if (button3.risingEdge()) { Keyboard.release(KEY_DOWN); } if (button4.risingEdge()) { Keyboard.release(KEY_F5); } if (button5.risingEdge()) { Keyboard.println("B5 release"); } if (button6.risingEdge()) { Keyboard.println("B6 release"); } if (button7.risingEdge()) { Keyboard.println("B7 release"); } if (button8.risingEdge()) { Keyboard.println("B8 release"); } if (button9.risingEdge()) { Keyboard.println("B9 release"); } }
Prototype Five - The picade + Dokuwiki + Reveals
Build on the suceess of the last version - its time make it all self contained and build in the essential features.
PROS:
- Builds Existing solution
- Minimal hardware spec (pi + picade hat)
- Web-based
CONS:
- Requires custom Pi Image
- Requires Picade Hat ( for shutdown switch and extra buttons)
Install Retro Pi
Use official instructions
https://github.com/RetroPie/RetroPie-Setup/wiki/First-Installation
Install Picade hat
Once again, the official installer
Install Extras
- xdtools to create a refresh loop (make the web browser refresh by pressing ctrl+f5 with a script)
- unclutter to hide pointer
Configure Retro Pi
These instructions are based on this raspberry pi forum thread, summarised here.
Run Retro-pi Setup to boot to terminal - this is included in RetroPi and accessible on boot.
mod .bashrc to start start on TTY1 (this means the pi starts with the first virtual terminal - which we will then use to launch our desktop, otherwise for some reason it starts the desktop on a different terminal - meaning we can't see it…)
# Startx if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then exec startx; fi
Edit the default user (called pi) autostart, which sets up our desktop, makes the mouse disappear after 5secs with unclutter, and calls a couple of scripts which we will write next.
nano /home/pi/.config/lxsession/LXDE-pi/autostart
@lxpanel --profile LXDE-pi @pcmanfm --desktop --profile LXDE-pi @point-rpi @xset s off @xset s noblank @xset -dpms @unclutter -idle 5 -root @/home/pi/start_URLrefresh.sh @/home/pi/start_chromium.sh
Create Start-up Scripts
nano /home/pi/start_chromium.sh
# Run browser after boot to desktop /bin/sleep 3 # run as pi user sudo -u pi # clean chromium on disk prefs to disable messages sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' ~/.config/chromium/'Local State' sed -i 's/"exited_cleanly":false/"exited_cleanly":true/; s/"exit_type":"[^"]\+"/"exit_type":"Normal"/' ~/.config/chromium/Default/Preferences # launch chromium chromium-browser --kiosk --no-default-browser-check --no-first-run --disable-infobars --disable-session-crashed-bubble # End of script
nano /home/pi/start_URLrefresh.sh
# Start a goofy command loop to refresh the browser every 560 seconds usubg xdt$ /bin/sleep 6 /usr/bin/lxterminal --command watch -n 560 xdotool key ctrl+F5 & # End of goofy script
Configure Chromium
All we need to to is set our desired slide as the homepage, this way when Chromium launches, it goes straight to the slide we want. For example, to set the player to display the welcome signage for the Fabrication Lab - the link below will work.
Just set the link as the homepage in chromium.
Its important to use an external link and not a wiki link.
Future Changes
Things that could be built into future versions.
What if Wifi goes Down?
And it always does… check out this