Bella Italia

Tim
2021-12-06

Table of contents

One of the best things about doing a PhD in Germany (imho) is the tradition, that your research group makes some form of graduation hat for you. You are “awarded” this hat after your successful defense and can keep it as a reminder to all the blood, sweat and tears you invested into getting that degree. Usually, that hat highlights some major aspects of your PhD work and then also features a ton of funny pictures and anecdotal jokes on it. Conceptually, it looks a little bit like a traditional American mortarboard hat. However, usually they are crafted out of cardboard and way too much glue. In 2021, a very dear friend of mine successfully (duhh, of course) her PhD, so of course she had to have to most amazing of PhD hats. Since the creation of these hats strongly benefits from everything you learned in Arts & Crafts class in primary school (and potentially knowledge in 3D printing and electronics as well), I was very much looking to this moment for at least 1.5 years. So we assembled a group of friends, former and current coworkers and other creative people to make this hat stand out. Below, I’ll highlight some of the aspects that wouldn’t have possible without 3D printing.

An image of an PhD hat.
The final hat, right before the ceremony.

The Microscope

Gif of the fluorescence microscope in action.
The light sequence of the “microscope”.

One of the many things she did extensively during her PhD was fluorescence microscopy of organoids. During this, a light source with a defined wavelength is used to excite fluorescence proteins in the sample. These then emit light of a different wavelength which is recorded. This can for example be used to verify the presence or localisation of proteins within a cell.

For this particular representation of it, a stylised microscope shines “green” light (should be 561 nm) on something that looks more like a brain than an organoid, which then in turn glows red from the inside. This represents the excitation and emission wavelengths of mCherry which she used in her work.

The WB Chamber

Gif of the animation displayed in the WB chamber.
Animation of the gel front separating.

Another thing she extensively did during her PhD was the quantification of proteins using western blots (WB). The method separates proteins by size by moving them through a gel using current as the driving force. Personally, I think the concept of western blots is quite cool and useful, but extremely annoying to do in practise. And she must’ve done hundreds. Poor girl.

Shown is an animation of of the gel front slowly separating into the respective bands per lane. The band pattern in this case is completely randomised each time the animation plays. Inbetween “gel runs”, the chamber sometimes displayed short greetings from friends.

The Coffee Pot

An ibrik.
A symbol for all the coffee we had.

And lastly, also most importantly, a turkish coffee pot (an ibrik?) also made it onto the hat. During our time as coworkers, it was tradition to always have amazing freshly brewed espresso after the mediocre cafeteria food. This completely spiraled out of proportion and at times we had several different coffee blends and roasts as well as chocolate to pair it with to choose from. To satisfy the scientsits in us, we of course recorded our results (see here).

While we usually prepared the coffee in a moka pot, we also sometimes used one of these turkish coffee pots. Which usually boiled over so that the entire office smelled like burned coffee grounds for the rest of the day.

3D printing

I use Fusion360 to design my components for 3D printing. It’s really amazing for everything that has clearly defined dimensions, even if the definition is an educated guess. For the components I took inspiration from Google Images and then just guessed and adjusted the dimensions until it looked good enough. Another benefit of Fusion360 is the strong internal rendering engine, which, despite not being the most amazing, still produces great looking previews.

Electronics

Since I had several of these at home, the entire project is powered by a Wemos D1 Mini, a variant of the ubiquitous ESP8266 board. Wemos produces several different shields which you can stack on top of the actual ESP8266 board to make more complex projects. Since this particular project was meant to be portable and had to function without a cable running from PhD hat to wall socket, I also used a Wemos Battery Shield and a 3.7 V 18650 battery. The battery shield allowed me to power the ESP8266 through the battery as well as to recharge the battery itself.

The “fluorescence microscope” uses 2 Lumetheus 5mm LEDs. Their data sheet recommends a voltage of up to 2.4 V with an operating current of 30 mA. I’m toggling these by using the ESP8266 GPIOs to trigger one BC547 NPN transistor and a 47 Ohm resistor per LED. This allows me to go beyond the rather low current output of the GPIOs so that the LEDs are actually bright enough to be visible.

The western blot chamber houses two 0.96″ OLED displays with 128×64 pixels each. These require 3.3 V and are adressed using SDA and SCL. I have am splitting the signal coming from the ESP8266 inside the chamber so that both displays receive and display the same signals.

Wiring diagram of the electronics inside the hat.
Wiring diagram of the electronics inside the hat. The Wemos boards were soldered onto a perfboard on which most wires and components are routed. The components are then adressed using wires that are routed from the top of the hat through the baseplate into a case. For the backside of the perfboard, click here.

Code

The code running the entire thing is displayed below. Basically, the entire hat cycles through the same 3 steps over and over again:

  1. First, the green LED shines for 3 seconds
  2. Then, the red LED shines for 3 seconds
  3. Finally, the western blot chamber displays a randomised event. This event can be either:
    • A simple text-based greeting that one of the contributing people wished for.
    • If the greeting was longer than a single line, I created a 128×64 image and converted it to C++ byte array using this online tool. The byte array could then directly be displayed on the OLED screens.
    • Or, to pay hommage to the science behind the chamber, a gel animation is displayed. For this, the band pattern is randomly generated on the fly, using the noise on the analog A0 pin as the random seed.
// Libraries
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <Fonts/FreeMono9pt7b.h>


bool const debug = false;
const long interval = 3000;


// Variables for the blinking microscope 
bool const microscope = true;
const byte green_LED = D5;
const byte red_LED = D6;


// Variables for the WB chamber
bool const chamber = true;
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Images
const unsigned char bitmap_hand [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xdf, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x9f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf8, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xe0, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const unsigned char bitmap_giuacchi [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x0f, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x3f, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xe0, 0x00, 0xc4, 0x08, 0x3e, 0x01, 0xe0, 0x78, 0x4f, 0x06, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xc0, 0x00, 0xc4, 0x08, 0x7f, 0x07, 0xf1, 0xfc, 0x7f, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xc1, 0xf0, 0xc4, 0x08, 0x41, 0x86, 0x11, 0x84, 0x71, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xc1, 0xf0, 0xc4, 0x08, 0x3f, 0x8c, 0x03, 0x00, 0x60, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xc0, 0x30, 0xc4, 0x08, 0x7f, 0x8c, 0x03, 0x00, 0x40, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xe0, 0x30, 0xc4, 0x08, 0xc1, 0x8c, 0x03, 0x00, 0x40, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x60, 0x30, 0xc4, 0x18, 0xc1, 0x8c, 0x03, 0x00, 0x40, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x78, 0x30, 0xc6, 0x38, 0xc3, 0x86, 0x11, 0x84, 0x40, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x3f, 0xf0, 0xc7, 0xf8, 0x7f, 0x87, 0xf1, 0xfc, 0x40, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x0f, 0xc0, 0xc3, 0xc8, 0x3d, 0x81, 0xe0, 0x78, 0x40, 0x86, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xc1, 0xe0, 0xc0, 0x83, 0xc0, 0x78, 0x01, 0x81, 0x07, 0x81, 0x02, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xc7, 0xf0, 0xc1, 0x8f, 0xf1, 0xfc, 0x01, 0x83, 0x1f, 0xc1, 0x02, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xc6, 0x18, 0x41, 0x8c, 0x31, 0x84, 0x00, 0x83, 0x18, 0x61, 0x02, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xcc, 0x18, 0x61, 0x18, 0x19, 0x80, 0x00, 0xc6, 0x30, 0x61, 0x02, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xcc, 0x0c, 0x63, 0x1f, 0xf8, 0xe0, 0x00, 0x46, 0x30, 0x31, 0x02, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xcc, 0x0c, 0x33, 0x1f, 0xf8, 0x1c, 0x00, 0x64, 0x30, 0x31, 0x02, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xcc, 0x18, 0x36, 0x18, 0x00, 0x06, 0x00, 0x6c, 0x30, 0x61, 0x06, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0xc6, 0x18, 0x36, 0x0c, 0x11, 0x06, 0x00, 0x38, 0x18, 0x61, 0x8e, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0xc7, 0xf0, 0x1c, 0x0f, 0xf1, 0xfe, 0x00, 0x38, 0x1f, 0xc1, 0xfe, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0xc3, 0xe0, 0x1c, 0x03, 0xe0, 0xf8, 0x00, 0x18, 0x0f, 0x80, 0xf2, 0x0c, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char bitmap_vaffanculo [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x30, 0x06, 0x00, 0x07, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 
  0x00, 0x18, 0x0c, 0x00, 0x0f, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 
  0x00, 0x18, 0x0c, 0x00, 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 
  0x00, 0x18, 0x0c, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 
  0x00, 0x0c, 0x18, 0x7c, 0x3f, 0xfe, 0x3e, 0x04, 0xf0, 0x1e, 0x10, 0x21, 0x83, 0xc0, 0x60, 0x00, 
  0x00, 0x0c, 0x18, 0xfe, 0x3f, 0xfe, 0x7f, 0x07, 0xf8, 0x7f, 0x10, 0x21, 0x8f, 0xe0, 0x60, 0x00, 
  0x00, 0x06, 0x30, 0x83, 0x0c, 0x30, 0x41, 0x87, 0x18, 0x61, 0x10, 0x21, 0x8c, 0x30, 0x60, 0x00, 
  0x00, 0x06, 0x30, 0x7f, 0x0c, 0x30, 0x3f, 0x86, 0x08, 0xc0, 0x10, 0x21, 0x98, 0x30, 0x60, 0x00, 
  0x00, 0x06, 0x30, 0xff, 0x0c, 0x30, 0x7f, 0x84, 0x08, 0xc0, 0x10, 0x21, 0x98, 0x18, 0x60, 0x00, 
  0x00, 0x03, 0x61, 0x83, 0x0c, 0x30, 0xc1, 0x84, 0x08, 0xc0, 0x10, 0x21, 0x98, 0x18, 0x60, 0x00, 
  0x00, 0x03, 0x61, 0x83, 0x0c, 0x30, 0xc1, 0x84, 0x08, 0xc0, 0x10, 0x61, 0x98, 0x30, 0x00, 0x00, 
  0x00, 0x03, 0xe1, 0x87, 0x0c, 0x30, 0xc3, 0x84, 0x08, 0x61, 0x18, 0xe1, 0x8c, 0x30, 0x00, 0x00, 
  0x00, 0x01, 0xc0, 0xff, 0x0c, 0x30, 0x7f, 0x84, 0x08, 0x7f, 0x1f, 0xe1, 0x8f, 0xe0, 0x60, 0x00, 
  0x00, 0x01, 0xc0, 0x7b, 0x0c, 0x30, 0x3d, 0x84, 0x08, 0x1e, 0x0f, 0x21, 0x87, 0xc0, 0x60, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup() {

  if (debug) {
    Serial.begin(115200);
  }

  // New random seed each iteration of the sketch
  randomSeed(analogRead(0));


  // Turn off Wifi to save battery
  WiFi.mode(WIFI_OFF);

  if (microscope) {
    pinMode(green_LED, OUTPUT);
    pinMode(red_LED, OUTPUT);
  }
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setRotation(2);
  display.setFont(&FreeMono9pt7b);
  display.display();
  delay(1000);

}

// the loop function runs over and over again forever
void loop() {

  if (chamber) {
    display.clearDisplay();
    display.display();    
  }

  if (microscope) {

    delay(500);
    digitalWrite(green_LED, HIGH);
    delay(interval);
    digitalWrite(green_LED, LOW);
    digitalWrite(red_LED, HIGH);
    delay(interval-200);
    digitalWrite(red_LED, LOW);
    delay(500);
    
  }

  if (chamber) {

    int chamber_choice = random(12);

    if (chamber_choice == 1) {

      draw_text_static("Cazzo!");
      
    } else if (chamber_choice == 2) {

      draw_text_static("Coffice!?");
      
    } else if (chamber_choice == 3) {

      draw_bitmap(bitmap_hand);
      
    } else if (chamber_choice == 4) {

      draw_text_static("WALLERA");
      
    } else if (chamber_choice == 5) {

      draw_bitmap(bitmap_vaffanculo);
      
    } else if (chamber_choice == 6) {

      draw_bitmap(bitmap_giuacchi);
      
    } else {
      
      draw_gel();
      
    }
  }
}

void draw_rectangle(int i) {
  
  display.clearDisplay();
  display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
  display.display();      // Show initial text
  delay(100);

}

void draw_text_static(const char *text) {

  int16_t x1, y1;
  uint16_t w, h;
  int scale_factor = 1;
  int x_offcenter_compensation = 3;
  int y_offcenter_compensation = 3;
  int i = 20;
  
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h); // calc width of new string
  display.setCursor((display.width()/2) - (w/2) - x_offcenter_compensation, (SCREEN_HEIGHT / 2) + (h/2) - y_offcenter_compensation);
  display.print(text);
  display.display();
  delay(5000);
  
}

void draw_bitmap(const uint8_t *bitmap) {
  
  display.clearDisplay();
  display.drawBitmap(0, 0, bitmap, 128, 64, WHITE);
  display.display();
  delay(5000);
  
}

void draw_gel(void) {

  int x_min = 8;
  int w_max = 110;
  int y_min = 3;
  int h_max = 59;

  int n_lanes = 4;
  int lane_thickness = 5;
  int lane_padding = 5;
  float lane_width = (float) (((w_max - x_min) - (n_lanes-1) * lane_padding) / n_lanes);

  // Generate random bands for each lane, but make it sparse
  int bands[n_lanes+1][h_max+51];
  for (int i = 0; i <= n_lanes; i++) {
    for (int j = 1; j <= (h_max+50); j++) {
      if (((j / 3) & 1) == 0) {
        int tmp = random(20);
        if (tmp == 0) {
          bands[i][j] = 0;
        } else {
          bands[i][j] = 1;
        }
      }
    }
  }
  
    
  // Draw front
  for (int j = 1; j <= h_max; j++) {
    display.clearDisplay();
    for (int i = 1; i <= n_lanes; i++) {
      
      display.drawRect(round(x_min + lane_padding + (lane_width + lane_padding) * (i-1)), 
                       y_min + lane_padding, 
                       round(lane_width), 
                       lane_thickness, WHITE);
      
    }
    for (int i = 1; i <= n_lanes; i++) {
      
      display.fillRect(round(x_min + lane_padding + (lane_width + lane_padding) * (i-1)), 
                       y_min + lane_padding + j, 
                       round(lane_width), 
                       lane_thickness, WHITE);
      
    }
    for (int i = 1; i <= n_lanes; i++) {
      for (int k = 1; k <= j; k++) {
        if (bands[i][k] == 0) {
          display.fillRect(round(x_min + lane_padding + (lane_width + lane_padding) * (i-1)), 
                 y_min + lane_padding + k, 
                 round(lane_width), 
                 lane_thickness-2, WHITE);
        }
      }
    }
    
    display.display();
    delay(200);
  }

  // Clean array
  memset(bands, 1, sizeof(bands));

}

Leave a comment