DEV Community

Cover image for R2D2 Creation with Codey πŸ€– Ep.4

R2D2 Creation with Codey πŸ€– Ep.4

Episode 4: The All-Seeing Eye

"Impressive. Most Impressive." πŸ‘οΈ

Darth Vader enters β€” wait, no. Wrong side.

Luke Skywalker stands at the workbench, holding an HC-SR04 ultrasonic sensor up to the light.

LUKE: "I've always wondered how he knew. How R2 always knew when something was coming. When an obstacle was in the way. When the Death Star trench was approaching. He sees things. Feels them. Before anyone else does."

R2-D2 beeps softly, as if this is a deeply personal topic.

LUKE: "Today we give him that. The sensor eye. And this timeβ€”" he gestures at the screen "β€”Codey's going to show us something called Auto Error Fixing. Because I have a feeling we're going to need it."

From somewhere unseen, a voice floats through the Force.

VADER: "Your lack of a level-shifted data pin... disturbs me."

LUKE: "We're on 5V. We'll be fine."

πŸ—‚οΈ SIPOC β€” The Sensor Eye System

Suppliers Inputs Process Outputs Customers
You (the maker) "Add HC-SR04 on pins 9/10 and PIR on pin 2, react with beeps and dome color changes" Codey writes sensor code, integrates with sound and dome systems from previous episodes Unified firmware: sense β†’ respond with light + sound R2-D2 β€” who now reacts to the world around him
HC-SR04 Sensor 5V power, TRIG pulse from Arduino Emits ultrasonic pulse, measures return echo time Distance in centimetres The code β€” which decides how close is "too close"
PIR Motion Sensor 5V power, GPIO input to Arduino Digital HIGH when motion detected A HIGH signal on the interrupt pin The code β€” which triggers the alert sequence
Auto Error Fixing A compilation error from incorrect code Codey reads the error log, rewrites the offending lines, recompiles Fixed code that compiles successfully You β€” who get working firmware without decoding C++ error messages
Vision Feature A photo of your breadboard Codey reads the image and identifies component placement A verification report: "Wiring looks correct" or specific mismatches You β€” who confirm wiring before upload

The Components πŸ”§

C-3PO enters with a tray of precisely arranged components.

C-3PO: "Today we add perception to R2-D2's capabilities. The HC-SR04 ultrasonic sensor β€” which I should note operates at 5V and is therefore perfectly compatible with the Arduino UNO without any level shifting, which is a relief β€” and the HC-SR501 PIR motion sensor, also 5V compatible. I have pre-sorted them by height to prevent any confusion."

R2-D2 beeps something that sounds like "nobody asked you to sort them."

Component Quantity Notes
Arduino UNO R3 1 Our trusted base
HC-SR04 ultrasonic sensor 1 5V, TRIG + ECHO pins
HC-SR501 PIR sensor 1 5V, single digital output
10kΞ© resistor 1 PIR output pull-down (some modules need it)
Jumper wires 6
USB cable 1

Plus the buzzer from Episode 2 and NeoPixel ring from Episode 3 β€” we are building on the complete system.

The Codey Prompt β€” Building on What We Have πŸ’¬

Han Solo points at the screen.

HAN: "Here's the thing about AI coding tools β€” you don't start from scratch every time. You tell it what already exists and what you want to add. Context is everything. Same in the smuggling business."

LUKE: "You're comparing Codey to smuggling?"

HAN: "I'm saying context matters. Do you want the lecture or the sensor?"

Open your Codey project (from Episode 3 milestone). In Agent mode:

We're continuing the R2-D2 build from the previous episodes.
Existing systems:
  - Piezo buzzer on pin 8 (tone-based sounds)
  - NeoPixel ring (12 LEDs) on pin 6 (dome animations)

Add these sensor systems:
  1. HC-SR04 ultrasonic sensor
     - TRIG on pin 9, ECHO on pin 10
     - Measure distance every 150ms (non-blocking)
     - If distance < 30cm: trigger alert animation + alert sound
     - If distance < 15cm: trigger full RED dome + rapid alert beeps

  2. PIR motion sensor on pin 2 (interrupt-capable)
     - On motion detected: trigger scan animation for 3 seconds
     - Then return to idle

Extend animations.h with these reactive behaviors.
Keep the state machine approach.
Use millis() everywhere β€” no delay().

Enter fullscreen mode Exit fullscreen mode

Generated Code Addition to animations.h

// ── Sensor additions (append to animations.h) ───────────────────

// ── HC-SR04 ─────────────────────────────────────────────────────
#define TRIG_PIN   9
#define ECHO_PIN   10

unsigned long lastSonarMs  = 0;
float         lastDistance = 999.0f;

float readDistance() {
  // Non-blocking: only trigger if enough time has passed
  unsigned long now = millis();
  if (now - lastSonarMs < 150) return lastDistance;
  lastSonarMs = now;

  // Send 10Β΅s TRIG pulse
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Read echo duration (timeout 30ms = ~5m max range)
  long duration = pulseIn(ECHO_PIN, HIGH, 30000UL);
  if (duration == 0) return 999.0f;

  // Convert to centimetres
  lastDistance = (duration * 0.0343f) / 2.0f;
  return lastDistance;
}

// ── PIR Motion Sensor ────────────────────────────────────────────
#define PIR_PIN   2

volatile bool motionDetected = false;

void IRAM_ATTR onMotion() {
  motionDetected = true;
}

// ── Reactive behaviour in updateAnimations() ─────────────────────
// (replaces/extends the existing updateAnimations function)

void updateAnimationsSensors() {
  unsigned long now = millis();

  // ── Check PIR first (interrupt-driven, higher priority) ─────
  if (motionDetected) {
    motionDetected = false;
    currentState   = SCAN;
    stateStartMs   = now;
    Serial.println("Motion detected β€” scan mode!");
  }

  // ── Check HC-SR04 distance ─────────────────────────────────
  float dist = readDistance();

  if (dist < 15.0f) {
    // Very close β€” full red alert
    if (currentState != ALERT) {
      currentState = ALERT;
      stateStartMs = now;
      tone(BUZZER_PIN, 2637); // C6 β€” high alert tone
    }
    // Override: set all LEDs red while this close
    for (int i = 0; i < NUMPIXELS; i++) {
      ring.setPixelColor(i, ring.Color(BRIGHTNESS, 0, 0));
    }
    ring.show();
    return;
  } else if (dist < 30.0f) {
    // Approaching β€” amber warning
    if (currentState == IDLE) {
      currentState = ALERT;
      stateStartMs = now;
    }
  } else {
    noTone(BUZZER_PIN); // Silence if moved away
  }

  // ── Normal state machine ────────────────────────────────────
  updateAnimations(); // existing function handles the rest
}

Enter fullscreen mode Exit fullscreen mode

Updated r2d2-dome.ino

// r2d2-dome.ino β€” updated for sensor eye
#include <Adafruit_NeoPixel.h>
#include "animations.h"

void setup() {
  Serial.begin(9600);
  initAnimations();

  // Sensor pins
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(PIR_PIN,  INPUT);

  // PIR interrupt β€” fires on rising edge (motion start)
  attachInterrupt(digitalPinToInterrupt(PIR_PIN), onMotion, RISING);

  Serial.println("R2-D2 sensor eye online!");
}

void loop() {
  updateAnimationsSensors(); // new unified call
}

Enter fullscreen mode Exit fullscreen mode

Auto Error Fixing in Action πŸ› οΈ

And then it happens.

LUKE: "I tried to compile andβ€”"

Compilation Error:
  animations.h:47: error: 'IRAM_ATTR' was not declared in this scope
  animations.h:47: note: 'IRAM_ATTR' is an ESP32 attribute, not available on AVR

Enter fullscreen mode Exit fullscreen mode

LUKE: "What does that mean? I justβ€”"

Before Luke can panic, the screen updates automatically.

CODEY AUTO ERROR FIX:

I see the error! IRAM_ATTR is an ESP32-specific macro for placing
interrupt handlers in IRAM (fast memory). The Arduino UNO uses
an ATmega328P β€” it doesn't have IRAM at all.

For Arduino UNO, the interrupt handler just needs the ISR() attribute,
which I used in the function signature. I'll remove IRAM_ATTR.

Fixed:
  Before: void IRAM_ATTR onMotion() {
  After:  void onMotion() {

Recompiling...

Enter fullscreen mode Exit fullscreen mode
βœ“ Compilation successful (after auto-fix)
  Board:   Arduino UNO R3
  Sketch:  r2d2-dome.ino + animations.h
  Size:    9,104 bytes (28% of flash)

Enter fullscreen mode Exit fullscreen mode

LUKE: "It... fixed it. By itself."

HAN: "Never tell me the odds."

LUKE: "That's not the sameβ€”"

HAN: "The AI fixed its own mistake without you having to understand why. That's what matters."

The Wiring Diagram β€” Three Systems Now 🧭

Click Wiring Diagram. The diagram now shows all three systems:

R2-D2 Sensor Eye + Dome + Sound β€” Wiring Diagram
════════════════════════════════════════════════════════════

[Arduino UNO R3]

  POWER RAIL:
    5V  ─────────┬── NeoPixel 5V
                 β”œβ”€β”€ HC-SR04 VCC
                 β”œβ”€β”€ PIR Sensor VCC
                 └── (100Β΅F cap +)
    GND ─────────┬── NeoPixel GND
                 β”œβ”€β”€ HC-SR04 GND
                 β”œβ”€β”€ PIR Sensor GND
                 └── (100Β΅F cap βˆ’)

  SIGNALS:
    Pin 6  ──── (470Ξ©) ──── NeoPixel DIN
    Pin 8  ──── (100Ξ©) ──── Piezo Buzzer +
    Pin 9  ─────────────── HC-SR04 TRIG
    Pin 10 ─────────────── HC-SR04 ECHO
    Pin 2  ─────────────── PIR Sensor OUT

Color code:
  RED    = 5V / power rail
  BLACK  = GND rail
  GREEN  = NeoPixel data (pin 6)
  ORANGE = Buzzer signal (pin 8)
  BLUE   = HC-SR04 TRIG (pin 9)
  PURPLE = HC-SR04 ECHO (pin 10)
  YELLOW = PIR output (pin 2)
  GREY   = Through resistors

Connection Table:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ From               β”‚ To                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Arduino 5V         β”‚ NeoPixel Ring: 5V                β”‚
β”‚ Arduino 5V         β”‚ HC-SR04: VCC                     β”‚
β”‚ Arduino 5V         β”‚ PIR HC-SR501: VCC                β”‚
β”‚ Arduino 5V         β”‚ 100Β΅F Cap: + (long leg)          β”‚
β”‚ Arduino GND        β”‚ NeoPixel Ring: GND               β”‚
β”‚ Arduino GND        β”‚ HC-SR04: GND                     β”‚
β”‚ Arduino GND        β”‚ PIR HC-SR501: GND                β”‚
β”‚ Arduino GND        β”‚ 100Β΅F Cap: βˆ’ (short leg)         β”‚
β”‚ Arduino Pin 6      β”‚ Resistor 470Ξ© β†’ NeoPixel DIN     β”‚
β”‚ Arduino Pin 8      β”‚ Resistor 100Ξ© β†’ Piezo (+)        β”‚
β”‚ Arduino Pin 9      β”‚ HC-SR04: TRIG                    β”‚
β”‚ Arduino Pin 10     β”‚ HC-SR04: ECHO                    β”‚
β”‚ Arduino Pin 2      β”‚ PIR HC-SR501: OUT                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Enter fullscreen mode Exit fullscreen mode

C-3PO: "Seven signals on eight wires plus the power rail. The color-coded system makes it genuinely manageable. Download the PDF immediately β€” this is the most complex wiring diagram we have produced so far and I do not trust organic memory."

Vision Feature: "Is My Breadboard Wired Correctly?" πŸ‘οΈ

Luke takes a photo of his assembled breadboard.

LUKE: "Before I upload β€” can I check this with Codey? Just to be sure?"

Click the Vision icon in Codey (Pro feature). Upload the breadboard photo.

Codey responds:

I can see your breadboard. Here's what I observe:

βœ“ HC-SR04 ultrasonic sensor connected:
  - VCC to 5V rail β€” correct
  - GND to GND rail β€” correct
  - TRIG appears connected to the digital pin area (looks like pin 9) β€” correct
  - ECHO appears connected to pin 10 β€” correct

βœ“ PIR sensor:
  - VCC and GND connections look correct
  - Signal wire appears to go to pin 2 β€” correct

⚠️ One potential issue:
  I notice what looks like the NeoPixel data wire may not have the
  470Ξ© resistor in line β€” it appears to connect directly. Check that
  the resistor is seated in the breadboard between pin 6 and the DIN
  input. A direct connection may cause LED flickering or data errors.

Everything else looks correctly laid out!

Enter fullscreen mode Exit fullscreen mode

Luke examines the breadboard.

LUKE: "The resistor... it's in the wrong row. It's not actually connected to anything."

R2-D2 beeps in the tone of "I could have told you that."

LUKE: "Vision just saved R2's dome lights."

What's Next: The Holographic Projector πŸ“½οΈ

Obi-Wan's presence fills the workshop like warm light.

OBI-WAN: "You have given R2-D2 his lights. His sounds. His sense of the world around him. But the moment that first made the galaxy fall in love with this droid β€” do you remember it, Luke?"

LUKE: "Help me, Obi-Wan Kenobi. You're my only hope."

OBI-WAN: "In Episode 5, we give Artoo his projector. The SSD1306 OLED display β€” small, crisp, I2C wired β€” will show R2's status, messages, and a recreation of that famous message. Milestones and Rollback will save us if anything goes wrong."

R2-D2 beeps the opening notes of the Princess Leia theme.

πŸ”— Resources

  • HC-SR04 with Arduino: Search "HC-SR04 Arduino tutorial"
  • PIR HC-SR501: Search "HC-SR501 Arduino interrupt"
  • Codey Online Vision: codey.online β€” Pro feature
  • Auto Error Fixing: built into all Codey plans

πŸ€– R2D2 Creation with Codey β€” building the galaxy's greatest droid, one episode at a time. May the Force β€” and the cloud compiler β€” be with you.

Top comments (0)