Motion-Activated Thermal Printer
Motion-Activated Thermal Printer
What I wanted to learn, and why it interested me: I wanted to learn how to use a thermal receipt printer to explore an interactive method of displaying fun art.
Final outcome: a motion-activated thermal printer that prints a message, date and time, and an image in a receipt format designed for visitors to my house.
Images of final creative/exploratory output
Final creative output: when the radar motion sensor detects motion, the thermal printer will print out a receipt with the help of an RTC.
Final setup with a 12V power supply, Arduino Uno, breadboard, thermal printer, radar motion detector, and RTC.
Final printed receipt design
Process images from development towards creative/exploratory output
Testing out the motion detector.
Testing how to print bitmap images from a the thermal printer.
Process and reflection:
My project began with the rough idea of creating an interactive project that I can place in my house for visitors. I wanted to explore a new type of sensor and explore different ways for displaying fun art. While researching inspo for the receipt design, I thought that it would be interesting to add a real-time clock module to implement as part of my receipt.
Printing images and a straight horizontal line was surprisingly the most difficult part of the process. As for printing out the image, I needed to download a separate software (Processing) to convert my image into a bitmap. This process was a bit complex, but once I had figured out the workflow, it was interesting to play with. As for printing a horizontal line on the receipt, I'm still not quite sure why it does not print a series of dashes. However, I was able to find a way to work around it by printing out dotted lines instead.
Overall, I'm proud of the final outcome. It's satisfying to see how a simple technical experiment could turn into a tangible, playful interaction! In the future, I hope to explore more about how to install the receipt printer in my house and test out the exact sensitivity of the motion detector.
Technical details
Block Diagram: real time clock and a radar motion detector as input controlled with an Arduino, then outputs receipts through a thermal printer
Electric Schematic: the real time clock and radar motion detector is wired to the Arduino Uno via a solderless breadboard, and the thermal printer uses a 9V external power supply.
/*
60-223 Intro to Physical Computing, fall 2025
Domain-specific Skill Building exercise: [Motion-Activated Thermal Printer]
[This Arduino sketch connects to a thermal printer, a motion sensor, and a real-time clock module. When the motion sensor detects movement, the printer automatically prints a custom "receipt". Each printout includes a message, the current date and time from the RTC, and a small image.]
Pin mapping:
Arduino pin | role | details
------------------------------
2 input motion detector
6 output thermal printer
Sketch written by ChatGPT on 10/04/2025
Released to the public domain by the author, January 2024
Robert Zacharias, rzachari@andrew.cmu.edu
*/
#include "Adafruit_Thermal.h"
#include "SoftwareSerial.h"
#include <Wire.h>
#include "RTClib.h"
// Define pins for the printer
#define TX_PIN 6
#define RX_PIN 5
SoftwareSerial mySerial(RX_PIN, TX_PIN);
Adafruit_Thermal printer(&mySerial);
// Motion sensor pin
#define MOTION_PIN 2
// RTC object
RTC_DS3231 rtc;
// Include generated bitmap header
#include "IMG_4535_imresizer.h" // Defines IMG_4535_width, IMG_4535_height, IMG_4535_data
bool printed = false; // Ensure we print only once per motion event
void setup() {
pinMode(MOTION_PIN, INPUT); // Motion sensor output
mySerial.begin(19200);
printer.begin();
// Initialize RTC
if (!rtc.begin()) {
while (1); // RTC not found
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
// Motion detected is HIGH
if (digitalRead(MOTION_PIN) == HIGH) {
if (!printed) {
DateTime now = rtc.now();
// ===== HEADER =====
printer.justify('C'); // Centered text
printer.setSize('L'); // Large text for main heading
printer.println("HEY!");
printer.setSize('S'); // Small text for subheading
printer.println("Yutong's house :)");
// Date & time on one line, small centered text
String dateTimeStr = String(now.month()) + "/" + String(now.day()) + "/" + String(now.year()) + " " +
String(now.hour()) + ":" + (now.minute() < 10 ? "0" : "") + String(now.minute()) + ":" +
(now.second() < 10 ? "0" : "") + String(now.second());
printer.println(dateTimeStr);
// Full-width dotted line
printer.justify('C');
printer.setSize('S');
printer.println("................................");
// ===== BODY =====
printer.setSize('M'); // Medium text for product label
printer.justify('L'); // Left aligned
printer.println("PRODUCT");
// Print bitmap
printer.printBitmap(IMG_4535_imresizer_width, IMG_4535_imresizer_height, IMG_4535_imresizer_data);
// ===== TOTAL =====
printer.setSize('M'); // Medium text
printer.justify('R'); // Right aligned
printer.println("TOTAL $$$$");
// ===== SIGNATURE SECTION =====
printer.justify('L');
printer.setSize('M');
printer.println("SIGNATURE");
printer.justify('C');
printer.setSize('S');
printer.println("................................");
printer.println(); // Empty line for signature
printer.println(); // Empty line for signature
printer.println(); // Empty line for signature
printer.println("................................");
// ===== THANK YOU NOTE =====
printer.println(); // Empty line
printer.setSize('S'); // Smallest text
printer.justify('C'); // Centered
printer.println("SEE YOU AGAIN?");
printer.println(); // Empty line
// Advance paper
printer.feed(2);
printed = true; // Prevent multiple prints per motion
}
} else {
printed = false; // Reset flag when no motion
}
}