This project dates back to the early summer of 2021, when my father unexpectedly sent out an email to my brothers and myself reminiscing about a "magic painting" that used to hang in the bar that he and my mother frequented during their courtship. The magic painting was a shadowbox (basically a diorama) that showed a sailing ship on a clear sun-drenched sea. However, at hourly intervals, the painting would come alive: the sky would darken, lightning would flash, thunder would roar, and soon the ship was rocking in a heavy squall. My dad proposed that we recreate this magic painting. I volunteered to do the automation part if he'd do the woodwork.
Later that summer I visited my dad at the family cottage in Maine. I brought down a big box of electronics and mechanical gear -- an Arduino Nano microcontroller, a variety of LEDs, speakers, motors, gears and solderable breadboards. Using his wood-working shop, we built the frame that holds the boat, and jigsawed the boat and a cut-out of waves from scrap plywood. I then proceeded to mount an electric motor to rock the boat, a speaker wired directly to one of the Nano PWMs to emit thunder sounds, and a set of LEDs wired to a shift-register to create the lightning effects.
It turns out the first design was awful. The electric motor I chose span too fast and was noisy. The LEDs were weak and unevenly lit, and the sound was faint. I brought the thing back to my home in Toronto and after many weekends of tinkering made the following changes:
- replaced the motor with a slower and quieter one
- replaced the individual LEDs with an addressable 21-unit RGB strip, plus a couple of individual LEDs in the corners to create the effect of lightning coming in from an angle
- added a real-time clock module to know when it was bedtime and put the thing to sleep so that it wouldn't bother people in the middle of the night
- added an audio amplifier to beef up the sound
- added micro-SD card reader to hold a variety of sound effects of thunder, waves, rain, creaking timbers, gulls calling and a ship's bell to ring in the morning when the painting wakes up
- added ball tilt sensor mounted on the back of the boat so that the controller knows when to turn off the motor after the storm has stopped
How it works
Here's the innards of the thing with the frame opened and the wave cutout removed:
The electric motor is mounted on the bottom right corner. It spins a wooden disk with an arm attached to it that rocks the boat up and down on a pivot. At the top is the LED strip, which is used both for the ambient lighting as well as to make lightning flashes. There are also two white LEDs mounted in the top corners that shine down at an angle to enhance the lightning illusion, as well as a red LED mounted on the top mast. Below the boat you can see the battery for the realtime clock. The amplifier and speaker are mounted on the left wall, and you can see the L298N motor driver just below the prow of the ship.
There are so many wires in the bottom left corner that you can't actually see the Arduino, shift register, or microSD card module. Unfortunately, because of the trial-and-error way I designed the boat, I ended up using a lot of individual pins and jumpers. If I were to do it all over again, I would make a proper circuit design on a prototyping board and use ribbon cables to connect to the various modules.
The Arduino is programmed in Sketch C++. For the storm sequence, I developed a simple data structure that describes the time and nature of each event. In the code excerpt below, the first number is the relative time in millis to start the event, the second is a code indicating what type of event to start, and the third is a parameter such as the lighting effect to use or the rate to run the motor at:
Script StormScript[] = {
{500, stormsound, 0},
{5000, light_transition, TWILIGHT},
{5000, lightning, left},
{8000, mast_light_transition, ON},
{9000, lightning, left},
{15000, motor_speed, 60},
{17250, lightning, left},
{20000, light_transition, STORMLIGHT},
...
};
This system is simple and extensible, and at one point I had ambitions of detecting special days and running alternative scripts. For example, on the 4th of July the ship could play the 1812 Overture and use the LED strip to simulate fireworks. Unfortunately the Nano's free memory was already running pretty low at this point and I thought better of the effort required to implement this.
Lessons learned
I found the most challenging part of the project was managing the audio amplifier. It's a prebuilt amplifier module I found on Amazon based on the lm386 chip. I originally wired its ground to a common ground used by the Arduino, micro-SD module, and realtime clock, but it picked up a tremendous amount of electrical noise. After many failed attempts to quiet the noise using various combinations of caps, resistors and ferrite cores, I discovered that simply attaching the amplifier's ground pin directly to the power supply's ground fixed the problem completely.
Another lesson I learned is to not draw the input power to the LED strip from the Arduino's 5V pin. When the LED was fully lit it drew too much power from the microcontroller and caused it to crash randomly. I fixed this problem by taking the LED strip's VCC input to the 5V regulated voltage from the L298 DC motor bridge used to drive the electric motor. I also used a hefty power supply that provided 12V@5 amps.
Wrapping up
The ship is now programmed to play the storm script every hour after it is turned on between the hours of 8 am and 10 pm (adjusted for daylight savings time, of course!). At night it dims and becomes a nightlight. Between storms the ship plays various seaside sounds of gulls calling at random intervals of ~10 minutes. I am very grateful to freesound.org for its amazing collection of user-contributed sound samples.
My dad's 90th birthday is coming up in a few weeks and guess what he's getting for a present?
Comments