diff --git a/Cargo.lock b/Cargo.lock
index 553347bfd5d33308cc69730c9e656d96654ef781..ffa3e66f7b8eae671360cf56f869d94c1e274e8b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,12 @@
 # It is not intended for manual editing.
 version = 4
 
+[[package]]
+name = "anyhow"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+
 [[package]]
 name = "byteorder"
 version = "1.5.0"
@@ -25,6 +31,15 @@ dependencies = [
  "wasi",
 ]
 
+[[package]]
+name = "ioctl-rs"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7970510895cee30b3e9128319f2cefd4bde883a39f38baa279567ba3a7eb97d"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "libc"
 version = "0.2.169"
@@ -88,11 +103,55 @@ dependencies = [
  "getrandom",
 ]
 
+[[package]]
+name = "serial"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1237a96570fc377c13baa1b88c7589ab66edced652e43ffb17088f003db3e86"
+dependencies = [
+ "serial-core",
+ "serial-unix",
+ "serial-windows",
+]
+
+[[package]]
+name = "serial-core"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f46209b345401737ae2125fe5b19a77acce90cd53e1658cda928e4fe9a64581"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "serial-unix"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f03fbca4c9d866e24a459cbca71283f545a37f8e3e002ad8c70593871453cab7"
+dependencies = [
+ "ioctl-rs",
+ "libc",
+ "serial-core",
+ "termios",
+]
+
+[[package]]
+name = "serial-windows"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15c6d3b776267a75d31bbdfd5d36c0ca051251caafc285827052bc53bcdc8162"
+dependencies = [
+ "libc",
+ "serial-core",
+]
+
 [[package]]
 name = "sierpinski-plotter"
 version = "0.1.0"
 dependencies = [
+ "anyhow",
  "rand",
+ "serial",
 ]
 
 [[package]]
@@ -106,6 +165,15 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "termios"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.14"
diff --git a/Cargo.toml b/Cargo.toml
index 20c0473d38a75bd0501941e8db62e9fe40205b43..7ac979a26f1fc0986c1a5747094b6705ae372526 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,4 +4,6 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
+anyhow = "1.0.95"
 rand = "0.8.5"
+serial = "0.4.0"
diff --git a/src/main.rs b/src/main.rs
index 7c6317fb14f72f0649601e8dc52800dc6cae416b..6c3ff8356a79271990dc73e235f6d0723d4ffd7e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,11 @@
+use std::{
+    env,
+    io::{Read, Write},
+    time::Duration,
+};
+
 use rand::{rngs::ThreadRng, thread_rng, Rng};
+use serial::SerialPort;
 
 struct TriangleIterator {
     points: [(u32, u32); 3],
@@ -45,10 +52,38 @@ impl Iterator for TriangleIterator {
     }
 }
 
-fn main() {
+fn main() -> anyhow::Result<()> {
+    let args: Vec<_> = env::args().collect();
+    if args.len() != 2 {
+        println!("Usage: {} /dev/tty***", args[0]);
+        return Ok(());
+    }
+
+    let mut ser = serial::open(&args[1])?;
+    ser.reconfigure(&|settings| {
+        settings.set_baud_rate(serial::BaudRate::Baud9600)?;
+
+        Ok(())
+    })?;
+    ser.set_timeout(Duration::from_secs(3600))?;
+
     let triangle = TriangleIterator::new(10300, 7650);
 
+    write!(&mut ser, "IN; SP 5; VS 40;")?;
+
+    let mut buf = [0];
     for (x, y) in triangle.take(10_000) {
-        println!("({}, {})", x, y);
+        // wait until our buffer is empty
+        write!(&mut ser, "OA;")?;
+        loop {
+            ser.read_exact(&mut buf)?;
+            if buf == *b"\r" {
+                break;
+            }
+        }
+
+        write!(&mut ser, "PU {} {}; PD;", x, y)?;
     }
+
+    Ok(())
 }