This instructable will show you how you to build your own storytelling box. Feel free to choose your own adventure.
The so called "GrimmsBox" was a project by students from the Hochschule der Medien Stuttgart, Germany. We use a common receipt printer to print out the first part of a story. At the end of the part a decision needs to be made. Using buttons you can choose how the story shall go on. We use a Raspberry Pi to run the software.
Two of the Boxes will be in use very soon. The public library in Mannheim is organizing workshops with children. The children can create their own stories and they can experience their stories with the help of GrimmsBox. The main goal of such workshops is the promotion of reading and writing abilities.The storytelling boxes will also be taken to events so children from classes 3 to 6 will be introduced to an immersive reading experience.
Step 1: How to Make the Case for GrimmsBox
- 1x 6 mm plywood plate (1200x600x6mm)
- 1x 4 mm plywood plate (1200x600x4mm)
- wood glue
- required devices: laser cutter, computer
The files used by GrimmsBox are available as free download. The files are svg and dxf files of the individual components of GrimmsBox. This is on the one hand the substructure where the Raspberry Pi finds its place, then the book with a bending hinge and a self-designed book stand.
The 6mm plywood plate is used for the substructure and the book stand. The book was cut out of 4mm plywood plate. The thicker plate would be too thick to make the book. The bending hinge only works with 3-4mm plywood panels. Otherwise, it would break.
The dxf files are the right choice for those who don't want to change anything anymore. These are ready to use on the laser cutter.
But for those who still want to give the box their own touch, can use SVG files in the box. These can be changed as desired. To do this, the file must be opened in a program (e. g. Inkscape). With these programs you can edit the individual components. If you have changed something (e. g. the size of the holes for the buttons or the pull-around) you have to save the SVG file as a dxf file.
The dxf file must be opened at the laser cutter. As soon as the file is displayed on the PC, it must be selected which lines are to be cut and which are to be engraved. The lettering on the side of the box was engraved on Grimm's box and the lettering on the book was weakly cut. Depending on what you like better, you can use one or the other. The outer lines must of course all be cut. However, the use of the laser cutter can depend on the model of the laser cutter and can be different.
Step 2: How to Assemble the Buttons for GrimmsBox
- 6 normally open momentary push buttons, e.g. buttons for arcade gaming
- 8 jumper wires with at least one female ending, ours were about 40 cm long
- some braid
- heat-shrink tubing the box used for your project, in our case the laser-cutted top cover and the two side covers which include the extra buttons
- solder and a soldering iron
- wire cutter
- wire stripper
- lighter or a hot air gun
- In our code we used internal resistors, so we only need to do two things: first, connect a female jumper wire to each button which will lead to the respective GPIO pin and second, connect the buttons to each other, which will then be led to ground via another female jumper wire. We connected the shutdown button and the restart program button together and used one ground pin for them. The four buttons which will be used by the choose-your-own-adventure engine were also connected to each other and shared one ground pin.
- If your buttons have more than two pins, use a multimeter to figure out which ones are suitable for connecting the GPIO pin and ground. With the sound function, you should only hear a sound if you touch two pins and the button is currently being pushed. You can do a continuity test, a guide how to do that is available at ifixit: https://www.ifixit.com/Guide/How+To+Use+A+Multime...
- Take one button and insert it into the box part. Take one of the jumper wires and cut of one end, which should leave you with a jumper wire with one female ending. Use the wire stripper to cut of about 5 millimeters of the isolation. Twist the loose wires for a bit so no single wire sticks out. Use a little tin to make a nice coating for the wires. If you are new to soldering, there is a great, short comic book teaching you how to solder. It’s called Soldering is easy and the PDF is available in multiple languages at https://mightyohm.com/blog/2011/04/soldering-is-e... Measure and cut the heat-shrink tubing, which you will use to isolate the part where the button and the jumper wire will be soldered together. Pull the heat-shrink tubing over the jumper wire. Solder the jumper wire to one of the pins on the button.
- Repeat the last step for all buttons. Always be sure to pull the heat-shrink tubing over the jumper wire before soldering, as it might not fit over the connector.
- Now you will connect the shutdown button and the restart button. We used enamelled copper wire, but as it proved a bit fiddly, I would suggest using normal braid. Cut of some centimeters of braid. As before, dismantle it using the wire stripper, but this time on both ends. Then, solder one end to the pin of either the shutdown or the restart button. Again, cut of a bit of the heat-shrink tubing and pull it over the braid.
- Next, you will connect the braid to the free pin of the other button. But you will also connect another jumper wire here, which will lead to ground. Prepare the jumper wire as you did with the others, including the heat-shrink tubing. Now bend the braid so you can solder it to the free pin coming from the button facing towards the free end. Then solder the jumper wire to the pin as well. Soldering the braid coming from one side and the jumper wire from the other side ensures you can pull the heat-shrink tubing over the soldered part.
- Connect the four buttons used for the game engine by building little bridges. Always be sure to pull the heat-shrink tubing over the braid before soldering. (And also be sure that your buttons are in the correct position before connecting them to each other). When connecting the last button you should again, as with the other two buttons, connect the braid from below and connect a jumper wire as well.
Using the multimeter’s sound function you can check if everything is connected well. Finally you should check if all heat-shrink tubing is in the right spot. Then you can use a lighter or a hot air gun to actually shrink it. Now you’re finished with assembling the buttons!
Step 3: Setting Up the Software
You will need:
- a Raspberry Pi with Raspbian installed (you should be able to use other distributions as well, but need to adjust some commands) – we used a package consisting of a Raspberry Pi 3 Model B+ with a pre-installed SD card, a power supply and a case, other models should work as well
- a receipt printer – bear in mind that you need to connect the printer to the Raspberry Pi, so connecting via USB might be easiest
- your buttons
- Connect your Raspberry Pi to a screen, mouse and keyboard. You will also need to connect it to the printer and the buttons eventually. The buttons need to be connected to specific GPIO pins. If you want to use different pins than we did, you can change that in the code. For now, this list will tell you which button needs to be connected to which pin. I’ll use BCM numbering which is also used in the code. There’s a chart at https://www.raspberrypi.org/documentation/usage/g... showing you which pin has which number.
• shutdown button – 17
• restart button – 27
• first button used for options in the story/adventure – 5
• second button – 6
• third button – 13
• fourth button – 19
• the two jumper wires connected to the pins which join all the buttons need to go to ground – in the chart marked by black dots
Start the Raspberry Pi by plugging in the power supply. Connect the Raspberry Pi to the internet using a LAN cable or wireless network.
First thing to do when installing the necessary software on the raspberry pi is to update the software that is already installed. We will do this using the terminal. If this is your first time using a terminal, the Raspberry Pi documentation (https://www.raspberrypi.org/documentation/usage/terminal/) helps you move around and get to know the environment. Open a terminal and type in sudo apt update and hit enter. This will update the list of available packages and versions. After that, type in sudo apt upgrade. This will actually install newer versions of the packages already installed.
Installing the printer driver is the next step. Printer management in Linux can be done using CUPS. You might need to install it on your Raspberry Pi first. In a terminal, type in sudo apt install cups. The next step is to get the printer drivers. Maybe you get lucky and it is included in the official repositories. In a terminal, use apt search [printer name or manufacturer name] to look for it. Most printers will probably not be included in the repositories, so you need to get it from elsewhere. There might be a CD enclosed to the printer. On the website of the manufacturer, the most recent drivers should be available for download. Some manufacturers have different websites for different regions of the world and sadly, not all of them include the same information. If you have a Star printer, starasia.com seems to be the website with the newest downloadable drivers. Please check that you download printers for Linux. We used the CUPS drivers, not the JavaPOS drivers.
Next, you need to install the drivers. Please follow the instructions of the manufacturer. There might be a software manual for Linux available, which can come in handy. Please follow the instructions for Debian or Ubuntu - there are many different Linux distributions and not all of them are the same, so check first, if you have the right instructions on hand. In our manual the instructions started without stating that they are for Red Hat based systems and only on the next page we learned, that the instructions for Debian-based systems are different. The software manual should also state which packages need to be installed, for example we had to install “libcups2-dev”. You will probably need to sudo some commands. To save you from repeating our mistake: if you need to compile the drivers from the source code using make - make install needs to be sudoed. Just from the error message we couldn’t figure out what went wrong.
If not included in your installation manual you need to set up the printer in CUPS. To do that, navigate to localhost:631 in a browser. Click on “Administration” and then “Add printer” to setup the printer. There is also a help section. You need to authenticate as a user, see https://help.ubuntu.com/lts/serverguide/cups.html... (section “Web Interface”) for details. Choose the suitable ppd and paper size. You should also make it the default printer, as the software will print to the default printer. To do that, navigate to the page of the printer and from the “Administration” menu select “Set As Server Default”. From the “Maintenance” menu you can select “Print Test Page” for a first check if everything is set up correctly.
Another package you will need is python3-yaml, as the stories are saved in yaml files and the package is needed so the python code can interpret them. Use sudo apt install python3-yaml to install it.
Now we will finally start with the installation of the software that actually prints the stories and listens for input on the GPIO pins connected to the buttons. Open a terminal and navigate to the home directory if you are not already in it (this can be accomplished by typing in cd (for change directory)). As our code is on GitHub, you can copy it to your Raspberry Pi by using git clone https://github.com/fio-na/GrimmsKiste-1.git This will create a local repository on your Raspberry Pi of our code. If you get an error message because git is not installed, you can install it by typing in sudo apt install git.
The code contains some elements you may need to alter. First of all, the stories are saved in yaml files which are also in the git repository. If the path to your folder is not “/home/pi/GrimmsKiste-1”, you will need to change these paths in order to use the stories. Second, we print using subprocess and hand over terminal commands. This includes some options used by our printer driver which lets us determine whether the paper shall be cut after printing or not. These will probably not work for you (unless you also use a Star TSP printer). You will also notice that a number of lines only including one dot will be printed. We needed this, because otherwise parts of the story were not readable because the paper still stuck in the printer. And finally in the function format_text we use textwrap to get chunks of text no longer than 28 characters, because that’s how many fit into one line on our 80 mm paper. Please adjust these things to fit your setup.
Some files need to be made executable. To do this, navigate into the folder with the code you just downloaded. This should be cd ~/GrimmsKiste-1 if you followed along. In Linux file permissions are handled by chmod. chmod a+x Engin.py and chmod a+x shutdown-pi-and-restart-program.py makes those two files executable for all users.
Now we can test if the engine can run and functions properly and if the printer and buttons are set up correctly. Type in ./Engin.py to do that.
If everything is working well, the next step is to set up two systemd services. For more information, the archlinux wiki page (https://wiki.archlinux.org/index.php/Systemd) might help or the man page of systemd.service (https://www.freedesktop.org/software/systemd/man/systemd.service.html). The first systemd service will check every two seconds, if Engin.py is currently running, and if it isn’t it will start it. Therefore it also starts the program when the Raspberry Pi boots. Open a file in the systemd folder: sudo nano /etc/systemd/system/grimmskiste-restart.service Type in the following:
[Unit] Description=restarts Grimms Kiste every two seconds if it fails [Service] ExecStart=/home/pi/GrimmsKiste-1/Engin.py Restart=always RestartSec=2 [Install] WantedBy=multi-user.target
You need to edit the path at ExecStart, if your Engin.py is located elsewhere, e.g. if your username is different. To save a file in nano, you need to push ctrl + x, then type in y (for yes) and hit enter.
The other service will start the shutdown-pi-and-restart-program.py script, which listens on the shutdown and restart button. The restart button reads the process ID of Engin.py from a file and kills it, and because of the other systemd service Engin.py restarts after two seconds. The shutdown button simply sends a command to the Raspberry Pi that is shall shutdown now. Open another file using sudo nano /etc/systemd/system/grimmskiste.service and type in the following:
[Unit] Description=Controls two hardware buttons to shut down the raspberry pi or to kill the running program Grimms Kiste [Service] ExecStart=/home/pi/GrimmsKiste-1/shutdown-pi-and-restart-program.py [Install] WantedBy=multi-user.target
Again, you will need to edit the path at ExecStart, if it is different on your Pi. And again, you can save the file in nano using ctrl + x, then typing y and hitting enter.
Now you have the unit files for the systemd services, but they are not in use yet. Whenever you change unit files, type in sudo systemctl daemon-reload, so do that now. Then start both services using sudo systemctl start grimmskiste.service and sudo systemctl start grimmskiste-restart.service This will start the services for now. Use sudo systemctl status grimmskiste.service and sudo systemctl status grimmskiste-restart.service to check if they are up and running. In the output, there should be a line which includes “active (running)”, probably in the third line - if it isn’t, something went wrong. Journalctl might be able to help with more debugging information.
Using systemctl start only starts the services for now, but if you want them to start every time the Raspberry Pi boots, you need to enable them. This is done by sudo systemctl enable grimmskiste.service and sudo systemctl enable grimmskiste-restart.service.
- Now you should test all buttons if everything is running correctly. Test the shutdown button as well and check if everything is still running properly after the reboot. If so, you don’t need the screen, keyboard etc. and your program should run every time you plug the Raspberry Pi into the socket.
Step 4: Introduction to YAML:
Important: The fields in purple must not be renamed. The names of the individual lists are an exception. Each story gets its own YAML file with all choices. The structure is the same as for the file start.yaml
Colon: If you want to use colons in the text you have to make a > after message. The text is then lowered one line and indented with two blank lines.
Tabs: Don’t use tabs and please make sure there are no tabs at the end of a message, this will result in the parser not being able to read the file.
_default_question: The question entered here is taken if no field with „question" has been entered in the history.
_prompt: This field is printed out when the reader has to make an entry.
Both fields may only exist once in the start.yaml file and may not be used in other files.
start: start is the name of the first list of the start page. The names must not be duplicated in all other lists. In the template, this field is called the „Name of the story" and must be changed for each story.
Message: This field contains the story and must stand in one line. question: Used when a question other than the _default_question is to be used. If the field is not used, it must be deleted. (optional)
Actions: The „actions“ list contains the selection options. A maximum of 4 options can be entered here.
Label: The label is printed as a selection option.
Next: This is the name of the next selection option to be called.
end: A list with only a message marks the end of a story.The fields actions, label and next have to be deleted
Add more stories:
As explained above, each new story gets its own .yaml file. To do this, open the folder “Grimms Box" and copy the file template.yaml. You can also find it in our GitHub repo (https://github.com/fio-na/GrimmsKiste-1). Rename the file to the title of the story and open it.
In the new file you, add the manufacturer and the date and change the field “The name of the story" to the title (see fig. 4: The name of the story here is HP1). Then fill in message, question, label and next. Once you have done this, copy the data structure (as shown in Fig. 4) and paste it below the last next. The title will now be changed to one key used in “next” in the first part (as shown in fig. 4 HP1 would then be HP2 or gang2, depending on which option is edited first). Then message, question, label and next are filled in again. Do this for all the choices/actions until the whole story is in the file. At all ends the last list has to contain only a message. All others fields in the final list have to be deleted. After that the file must be saved.
Procedure in short:
- Open the Grimms Box folder
- Copy the Vorlage.yaml and rename it to the title of the story.
- Open this new file.
- Copy data structure (fig. 4)
- Change the name from History to Selection name
- Enter the text of the story in the message field,
- Insert suitable label.
- Enter the name of the next selection option in next.
- Repeat steps 4 through 9 until the story is finished.
- At all ends: The last list contains only a message.
- Save the file.
Add your new story to the start page:
start.yaml is the start page for Grimm's box. However, this file must first be able to access the new stories. Therefore, the new stories must be added to this file first.
Per actions you can only create 4 labels, next, because Grimm's box has only 4 buttons to choose from. Therefore, if, as in the example start.yaml file, 4 labels and next fields are already assigned, the 4th label must be named “More stories" or “More" and a second data structure (here:S2; with message, question, actions, label, next) must be appended and renamed. Then you add the new story with label and next and name it appropriately. Finally, it must be saved.
Procedure in short:
- Open start.yaml
- Fill in fields appropriately.
- The fields actions, label and next must be copied and pasted.
Maintain the main file “Engin.py”:
Finally, the story has to be added to the main file “Engin.py". For this only the file path of the new YAML file must be entered into the file list. The path is enclosed in quotation marks and separated from the others by a comma.
Procedure in short:
- Open Engine.py.
- Copy the file path of the YAML file
- Copy path to filelist
- Separate the paths by commas.
Step 5: Instructions for Use
To start Grimm’s Box, connect the printer to the Raspberry Pi (there’s a little hole for the cables), plug the printer and the Raspberry Pi into the socket and turn the printer on. The Raspberry Pi starts on its own when plugged in. Wait for it to boot. The software is supposed to start on its own.
There is a button to shutdown the Raspberry Pi and a button to restart the story software, in case someone just leaves without finishing the story. Both need to be pushed at least 3 seconds. This is to ensure that they aren’t pushed accidentally but you can change the timing in the shutdown-pi-and-restart-program.py file. Please use the shutdown button, just unplugging isn’t good for the Raspberry Pi. With the current setup you can’t see whether the Raspberry Pi is on or off so you need to check if it still reacts to other buttons if you want to be sure.
Restarting the program takes some time, as you need to push the button at least 3 seconds and the process in the background only checks every 2 seconds if the program is running, so the whole process until it prints again can take 6 seconds. Just give it a little time. The restart button can also be used, if any problem occurs. Maybe a restart might fix it. If it doesn’t, connecting the Raspberry Pi to a screen etc. and running the program from the terminal might produce error messages you can look up on the internet. The buttons used for the stories need to be pushed at least 0.1 seconds, but it is very rare that someone pushes them less than that.
If the story is finished, the paper is cut and the program starts again automatically. But to give the reader some time to read the end it waits for 3.5 seconds plus the 2 seconds needed to notice the program is not running and restarting. The 3.5 seconds can be edited in the Engin.py file.
Buttons pushed less than 1.7 seconds after the last push will not be accepted. We implemented this because the Raspberry Pi is a lot faster than the printer and pushing two buttons would result in an action being chosen before the reader could see the options.