Arduino Uno Magic Light Cup Module
This project demonstrates how to control an RGB LED using an Arduino Uno, creating a "magic light cup" effect. The LED changes colors based on the RGB values set in the code. This project is perfect for adding a colorful, interactive element to your Arduino projects.
How It Works
The magic light cup (KY-027) is a teaching module sold in pairs. Each board carries a tilt switch and an LED, and the trick is in how they are cross-wired: tilting one cup "pours" light into the other. It is a demonstration of reading an input on one module and driving a PWM output on another.
Each module exposes three pins — a signal input for the LED, a signal output from the tilt switch, and power. The illusion of liquid light comes from PWM fading rather than simple on/off switching: as one LED dims, the other brightens in step, so brightness appears to flow between them.
Because the effect depends on smooth brightness control, the LED pins must be on PWM-capable outputs. On the Arduino Uno those are D3, D5, D6, D9, D10 and D11.
The tilt switch inside is the same mercury or ball type used in the KY-017, so it bounces as it settles and benefits from the same debouncing treatment.
Components Needed
- Arduino Uno
- Magic Light Cup Module module
- Arduino Uno
- USB cable for programming and power
- Arduino Uno
Wiring to the Arduino Uno
Each cup needs two signal connections plus power. Put both LED pins on PWM-capable outputs — on this board D3, D5, D6, D9, D10 and D11 — and the two tilt outputs on any digital pins. All four share the same 5 V and GND rails.
The LEDs on these carriers include series resistors, so they connect directly to a GPIO. Current draw is modest, well within what a pin can source.
Mount the two modules so they can be tilted independently; the effect only reads properly when each can be rotated on its own.
| Connection | Arduino Uno pin | Function |
|---|---|---|
| Cup A — LED | D9 | PWM brightness for the first cup |
| Cup A — tilt | D2 | Tilt state of the first cup |
| Cup B — LED | D10 | PWM brightness for the second cup |
| Cup B — tilt | D3 | Tilt state of the second cup |
| VCC / GND | 5V / GND | Shared supply for both modules |
Build and Upload
Open the Arduino IDE and create a new sketch.
Copy and paste the provided Arduino code into the sketch.
Upload the code to the Arduino Uno.
Open the serial monitor with a baud rate of 9600.
Observe the RGB LED changing colors (red, green, blue) every second, with RGB values printed to the Serial Monitor.
Example Code
Pouring light between two cups by cross-fading their LEDs on tilt. Upload it with the board set to Arduino Uno and open the Serial Monitor at 9600 baud.
const int LED_A = 9;
const int TILT_A = 2;
const int LED_B = 10;
const int TILT_B = 3;
int level = 128; // 0 = all in B, 255 = all in A
const int STEP = 4;
void setup() {
Serial.begin(9600);
pinMode(LED_A, OUTPUT);
pinMode(LED_B, OUTPUT);
pinMode(TILT_A, INPUT_PULLUP);
pinMode(TILT_B, INPUT_PULLUP);
}
void loop() {
// Tilting a cup pours its light towards the other
if (digitalRead(TILT_A) == LOW && level > 0) level -= STEP;
if (digitalRead(TILT_B) == LOW && level < 255) level += STEP;
level = constrain(level, 0, 255);
analogWrite(LED_A, level);
analogWrite(LED_B, 255 - level);
delay(20); // sets how fast the light "flows"
}
Applications
A magic light cup module turns up in a wide range of projects. These are the uses where it is the right choice rather than a compromise:
- Teaching PWM and analog output in a visually obvious way
- Interactive art installations and desk toys
- Demonstrating tilt sensing without needing an accelerometer
- Turn-taking indicators in two-player games
- Introducing the idea of coupled inputs and outputs to beginners
Working with the Arduino Uno
The Arduino Uno is built around the ATmega328P and runs on 5 V logic with 2 KB of SRAM and 32 KB of program flash. These details change how this circuit is wired and what the sketch can do, so they are worth stating plainly before you build.
The Uno runs at 5 V, so most hobby sensor modules connect directly with no level shifting.
With only 2 KB of SRAM, avoid large buffers and prefer the F() macro for constant strings.
The single hardware UART is shared with the USB connection, so heavy Serial printing competes with uploads.
| Arduino Uno characteristic | Value | Why it matters here |
|---|---|---|
| Logic voltage | 5 V | Matches most hobby modules directly |
| ADC resolution | 10-bit (0–1023) | Sets how finely an analog reading can be resolved |
| Analog inputs | A0–A5 (six channels) | Determines how many analog sensors can share the board |
| PWM outputs | D3, D5, D6, D9, D10 and D11 | Needed for brightness, speed and tone control |
| I²C pins | A4 (SDA) and A5 (SCL) | Fixed by hardware — wiring copied from another board may not match |
| Interrupt pins | D2 and D3 only | Required for counting fast or asynchronous events |
| Serial | a single hardware UART shared with USB | Monitor runs at 9600 baud by default |
Troubleshooting
Most problems with this module fall into a handful of categories. Work through these before suspecting the part itself:
- The LEDs only switch on and off instead of fading — they are on non-PWM pins. Move them to
PWM-capableoutputs. - Light pours in only one direction — one tilt switch is mounted at the wrong angle or its pull-up is missing.
- The fade is jerky — reduce STEP and shorten the delay so brightness changes in finer increments.
- Both LEDs stay lit at half brightness — neither tilt switch is being read as LOW; check
INPUT_PULLUPis set. - Code written for an ESP board gives odd analog values — the Arduino Uno uses a 10-bit ADC returning 0–1023; rescale any constant taken from a 12-bit example.
- An I²C sensor is not found after copying wiring from another Arduino — on the Arduino Uno I²C is on A4 (SDA) and A5 (SCL).
Taking It Further on the Arduino Uno
Once the basic reading works, where you go next depends very much on which board you are using. These are the directions that suit the Arduino Uno specifically:
The Uno’s shield ecosystem is its real advantage. Once the circuit works on a breadboard, a prototyping shield turns it into something permanent that still stacks with a data-logging or Ethernet shield without rewiring.
Logging to an SD card via a shield is the natural next step, since the Uno has no onboard storage and no network. Timestamp each reading with a DS3231 real-time clock so the log survives power cuts with correct times.
Because SRAM is limited to 2 KB, keep logged strings short and write them out immediately rather than buffering. Building a long String in memory is the most common cause of an Uno sketch that runs for hours and then freezes.
Notes and Practical Limits
Human brightness perception is logarithmic, so a linear PWM ramp looks like it changes quickly at the dim end and barely at all when bright. Squaring the level before writing it produces a visually smoother pour.
The 0–255 range used here matches the standard Arduino analogWrite() resolution.