Built-in project · Arduino Uno R3

Send a heartbeat on an Arduino Uno

Two Unos, each with an nRF24L01 radio, a button and a red LED: press the button on one and the heart on the other beats lub-dub, and the sender glows when it arrives. The whole build, an Arduino Uno and 8 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Advanced Runs in your browser. Free, and no account needed.

Send a heartbeat · Arduino Uno R3live0.000 s 0.00x
Press the button on the left board, then the one on the right
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Send a heartbeat: a pair of these, one for you and one for someone you
// love. Press the button on yours and the heart on theirs beats twice, lub-dub,
// and yours glows once to say it got there.
//
//   radio     nRF24L01: CE -> pin 7, CSN -> pin 8, SCK -> 13, MOSI -> 11,
//             MISO -> 12, VCC -> 3V3 (never 5 V), GND -> GND
//   button    pin 2 -> button -> GND        (INPUT_PULLUP, pressed reads LOW)
//   heart     pin 5 -> 220 ohms -> red LED -> GND
//
// Both boards run this same sketch. Each one listens all the time, and only
// stops listening for the moment it sends. They share one address, so either
// can start, and the radio that hears the packet answers it in hardware:
// radio.write() returns true only when that answer comes back. That one bool
// is how the sender knows the heartbeat arrived.
//
// The radios reach across a house, not across a city. For two homes far
// apart the same idea runs over Wi-Fi on an ESP32, but the heartbeat and the
// lub-dub are the same.
//
// Things to try. Press the button on the left board, then on the right one.
// Delete one board and press again: the sender says nobody answered.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

const int BUTTON_PIN = 2;
const int HEART_PIN = 5;

RF24 radio(7, 8);   // CE, CSN
const byte address[6] = "HEART";

bool wasPressed = false;
int sent = 0;

void fade(int peak, int ms) {
  for (int v = 0; v <= peak; v += 15) {
    analogWrite(HEART_PIN, v);
    delay(ms / 34);
  }
  for (int v = peak; v >= 0; v -= 15) {
    analogWrite(HEART_PIN, v);
    delay(ms / 34);
  }
  digitalWrite(HEART_PIN, LOW);
}

void beat() {
  fade(255, 250);   // lub
  delay(80);
  fade(150, 200);   // dub
}

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(HEART_PIN, OUTPUT);
  radio.begin();
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(address);
  radio.openReadingPipe(1, address);
  radio.startListening();
  Serial.println("Heartbeat ready: press the button to send one");
}

void loop() {
  bool pressed = digitalRead(BUTTON_PIN) == LOW;
  if (pressed && !wasPressed) {
    sent++;
    char message[8] = "beat";
    radio.stopListening();
    bool heard = radio.write(&message, sizeof(message));
    radio.startListening();
    Serial.print("Heartbeat ");
    Serial.print(sent);
    if (heard) {
      Serial.println(" sent and received");
      fade(60, 300);   // a soft glow: it got there
    } else {
      Serial.println(": nobody answered");
    }
    delay(50);
  }
  wasPressed = pressed;

  if (radio.available()) {
    char message[8] = "";
    radio.read(&message, sizeof(message));
    Serial.println("A heartbeat for you");
    beat();
  }
}
sketch.ino · Arduino Uno R3
// Send a heartbeat: a pair of these, one for you and one for someone you
// love. Press the button on yours and the heart on theirs beats twice, lub-dub,
// and yours glows once to say it got there.
//
//   radio     nRF24L01: CE -> pin 7, CSN -> pin 8, SCK -> 13, MOSI -> 11,
//             MISO -> 12, VCC -> 3V3 (never 5 V), GND -> GND
//   button    pin 2 -> button -> GND        (INPUT_PULLUP, pressed reads LOW)
//   heart     pin 5 -> 220 ohms -> red LED -> GND
//
// Both boards run this same sketch. Each one listens all the time, and only
// stops listening for the moment it sends. They share one address, so either
// can start, and the radio that hears the packet answers it in hardware:
// radio.write() returns true only when that answer comes back. That one bool
// is how the sender knows the heartbeat arrived.
//
// The radios reach across a house, not across a city. For two homes far
// apart the same idea runs over Wi-Fi on an ESP32, but the heartbeat and the
// lub-dub are the same.
//
// Things to try. Press the button on the left board, then on the right one.
// Delete one board and press again: the sender says nobody answered.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

const int BUTTON_PIN = 2;
const int HEART_PIN = 5;

RF24 radio(7, 8);   // CE, CSN
const byte address[6] = "HEART";

bool wasPressed = false;
int sent = 0;

void fade(int peak, int ms) {
  for (int v = 0; v <= peak; v += 15) {
    analogWrite(HEART_PIN, v);
    delay(ms / 34);
  }
  for (int v = peak; v >= 0; v -= 15) {
    analogWrite(HEART_PIN, v);
    delay(ms / 34);
  }
  digitalWrite(HEART_PIN, LOW);
}

void beat() {
  fade(255, 250);   // lub
  delay(80);
  fade(150, 200);   // dub
}

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(HEART_PIN, OUTPUT);
  radio.begin();
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(address);
  radio.openReadingPipe(1, address);
  radio.startListening();
  Serial.println("Heartbeat ready: press the button to send one");
}

void loop() {
  bool pressed = digitalRead(BUTTON_PIN) == LOW;
  if (pressed && !wasPressed) {
    sent++;
    char message[8] = "beat";
    radio.stopListening();
    bool heard = radio.write(&message, sizeof(message));
    radio.startListening();
    Serial.print("Heartbeat ");
    Serial.print(sent);
    if (heard) {
      Serial.println(" sent and received");
      fade(60, 300);   // a soft glow: it got there
    } else {
      Serial.println(": nobody answered");
    }
    delay(50);
  }
  wasPressed = pressed;

  if (radio.available()) {
    char message[8] = "";
    radio.read(&message, sizeof(message));
    Serial.println("A heartbeat for you");
    beat();
  }
}

Parts list

11 parts, plus the jumper wires. Every one is in the editor's parts bin.

How it is wired

21 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • Ground: Arduino Uno R3 (1) pin GND; 2.4 GHz radio, nRF24L01+ (1) pin GND
  • Arduino Uno R3 (1) pin 13; 2.4 GHz radio, nRF24L01+ (1) pin SCK
  • Arduino Uno R3 (1) pin 12; 2.4 GHz radio, nRF24L01+ (1) pin MISO
  • Arduino Uno R3 (1) pin 11; 2.4 GHz radio, nRF24L01+ (1) pin MOSI
  • Arduino Uno R3 (1) pin 8; 2.4 GHz radio, nRF24L01+ (1) pin CSN
  • Arduino Uno R3 (1) pin 7; 2.4 GHz radio, nRF24L01+ (1) pin CE
  • Arduino Uno R3 (1) pin 5; Resistor, 220 Ω (1) pin 1
  • Arduino Uno R3 (1) pin 2; Pushbutton (1) pin 1a
  • Arduino Uno R3 (1) pin 3V3; 2.4 GHz radio, nRF24L01+ (1) pin VCC
  • Ground: Arduino Uno R3 (1) pin GND; Arduino Uno R3 (2) pin GND; Pushbutton (1) pin 2a; LED, red (1) pin C; Pushbutton (2) pin 2a; LED, red (2) pin C
  • Arduino Uno R3 (2) pin 13; 2.4 GHz radio, nRF24L01+ (2) pin SCK
  • Arduino Uno R3 (2) pin 12; 2.4 GHz radio, nRF24L01+ (2) pin MISO
  • Arduino Uno R3 (2) pin 11; 2.4 GHz radio, nRF24L01+ (2) pin MOSI
  • Arduino Uno R3 (2) pin 8; 2.4 GHz radio, nRF24L01+ (2) pin CSN
  • Arduino Uno R3 (2) pin 7; 2.4 GHz radio, nRF24L01+ (2) pin CE
  • Arduino Uno R3 (2) pin 5; Resistor, 220 Ω (2) pin 1
  • Arduino Uno R3 (2) pin 2; Pushbutton (2) pin 1a
  • Arduino Uno R3 (2) pin 3V3; 2.4 GHz radio, nRF24L01+ (2) pin VCC
  • Ground: Arduino Uno R3 (2) pin GND; 2.4 GHz radio, nRF24L01+ (2) pin GND
  • Resistor, 220 Ω (1) pin 2; LED, red (1) pin A
  • Resistor, 220 Ω (2) pin 2; LED, red (2) pin A

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.