The Blue Box

2 blue boxes on a green background, the box on the left has a sticky note attached on the top face saying "Press when sad". A button can be seen poking out of the top hole behind the sticky note. The second box also has a hole in the top face.

Top view of the Blue Box, with power off and sticky note on top labeling what the button does

Why did I make this?

Sometimes I get bouts of profound melancholia that are extremely debilitating and greatly affect my ability to be productive and get things done in my day to day life. Though trial and error I've found that moving around and talking to friends generally helps with lessening how badly it affects me or makes it go away entirely. The Blue Box is my attempt at making a physical device that reminds me of these things and help me blunt the worst parts of the melancholic moods. 

2 blue boxes on a green background, the box on the left has a sticky note attached on the top face saying "Press when sad". A button can be seen poking out of the top hole behind the sticky note. The second box also has a hole in the top face.

Each box is 6 in x 6 in x 4 in.  The electronic components inside consist of LEDs, an Arduino, a breadboard, a LoRa radio module, and a buzzer.

2 blue boxes on a green background, the box on the left has a sticky note attached on the top face saying "Press when sad". A button can be seen poking out of the top hole behind the sticky note. The second box also has a hole in the top face. The box on the left has go outside cut onto its front face

A picture from a different angle, this time to show the "Go Outside" that's cut onto the front face

2 blue boxes on the left and right, the front face on the left blue box has "You're not alone, go talk to friends" cut on its front face

On the opposite side of the main body, "You're not alone, go talk to friends"  is laser cut on its front face

2 blue boxes on the left and right, the front face on the left blue box has "You're not alone, go talk to friends" cut on its front face, and a green wire can be seen sticking out of the top holes

The green wire sticking out of the top of both boxes' holes serve as the antenna for both modules to communicate with each other

20240227_222343.mp4

In this video, I show myself pressing the one button on the main body. This makes the LEDs inside the main body light up, and sends a radio signal to the external module. The external module receives the radio signal and lights up its own LEDs, as well as activating a buzzer.

Process

In the frame there is a battery, Arduino Uno, and breadboard. The breadboard has a buzzer and LED on it that are currently making sound and lit up respectively.

Testing the circuit for the external module my roommate is meant to carry around

In frame there is an Arduino Uno and breadboard. On the breadboard is a green LED and a button which I am currently pressing

Testing the circuit for the main body, this is a stripped down version of it

2 pieces of laser cut red acryllic on the left, the top and bottom edges have square teeth, the right has a cardboard box held together with blue masking tape

Initial stages of prototype the physical design of the blue box, the cardboard model to show dimensions, and the red acrylic to get familiar with the laser cutting process

A picture of the schematic for this project, it has two arduino unos, the radios, and a battery loop for turning on and off the circuit

Before I built anything, I made the schematic for how this project should roughly function in terms of circuits and electric connections. It helped me immensely in the rest of the project for development because I could now test the circuits to make sure they were working as planned.

The biggest part of this project process was getting the radios to work with each other. It wasn't too bad in the end when I put everything together but it did take more time than I wished it to. The fabrication process itself was also about as hard as I expected it to be. I've never built anything before out of acrylic, or laser cut anything before this semester. It took some time to get used to and I'm still not entirely confident in designing to be lasercut even now. Learning Fusion 360 to a sufficient level to CAD something that will slide together is a skill I'll need to practice. Given that this was only the second time ever I had to fabricate something and the first time I had to do it myself, this project turned out better than I expected. Once I actually got going and in the thick of it, none of the skills that had initially seemed daunting to learn seemed hard anymore. They were simply necessary.

Discussion

"Make roommate’s box smaller, current is a hefty thing to carry around". I also want to make the box's design more compact, but with the skillset and time I had to do this project, that really wasn't something I could do feasibly. I suppose that if I were to revisit this project with that idea in mind I would switch over to an Arduino nano so that there wouldn't need to be as much space inside the box to hold all the electronics.
"If you don't use radio, you could use wifi and ping your roommates phone".  This is a really interesting idea that I think also has a lot of potential if I want to explore this route instead. It is true that the best part is no part, and getting rid of an external box that my roommate would need to carry around would certainly meet that criteria. Given how essential phones are to our lives now, it's the next best thing to a guarantee that my roommate would see the pings. I don't know how I feel about having another point of contact with my roommate having the same endpoint on his end though.

I have mixed feelings on this project and how it turned out, to be completely honest. I'm happy that I managed to get a form of it working, but it wasn't the form I was hoping for. I was hoping that at the end of the process I would have a thing ready to use just like how my ideation laid it out. It would be something that my roommate could carry around and the thing would just work over long distances and through walls. That unfortunately wasn't what I got, what with the range of the final result being much too short for actual functionality. Ultimately, the Blue Box in its current form does not solve the problem I designed it to solve, so it did not satisfy my own goals.  I might come back to this project and redesign it so that it can, but that's not something I'll be doing this semester. The build process was very educational though. Through fabricating the two boxes, I familiarized myself with the Ideate laser printers, Fusion 360, and the Long Range radios for the Arduino. I'm glad to have these tools in my back pocket now because they'll almost certainly be useful for any future projects I intend to do.  This project was also good in terms of experience with how much work it took to actually build the boxes and get the electronics up and running. I now have a better sense of scope and how much effort it will take to do or build a particular thing, which I'm very grateful for.

I've already discussed in previous paragraphs what I would do with the second iteration of the project, but I'll lay it out explicitly here. The second iteration will do away with the roommate module entirely, the main box will instead ping my roommate's phone directly. The main box will also be substantially smaller, and I hope to achieve this by using the Arduino Nano instead of the Uno. I'll also redo the main box so that the main form is instead a cylinder, the better to hold it with. The button would also be much bigger and have a cover, so that pressing it isn't risky or uncomfortable.

Technical information

Project Code

/* Allen Zhu

   Carnegie Mellon University

   Physical Computing (60-223) Spring 2024

   Project 2: The Blue Box, a trinket to help me not be sad


   Sample/template code taken from Professor Robert Zacharias

   LoRa code taken from Adafruit's website found here: https://learn.adafruit.com/adafruit-rfm69hcw-and-rfm96-rfm95-rfm98-lora-packet-padio-breakouts/rfm9x-test

This code is freely available under the CC-by-SA 4.0 DEED license

  

   This Arduino sketch is to help a LoRa transmitter module transmit an on/off signal to its receiver module, see Blue Box External Module for more details.


   Structuring this Arduino sketch so that the loop contains four basic elements:

     1) read inputs (gather information from the world)

     2) compute and make decisions based on those inputs

     3) drive outputs (effect different actuators in the world)

     4) report information back to the user


 Pin mapping:


   Arduino pin | role  | details

   ------------------------------------

   2             output  interrupt pin for LoRa

   9~            output  radio reset pin

   10~           output  CS pin, connects to SPI chip select

   11~           output  MOSI pin, connects to SPI MOSI

   12            output  MISO pin, connects to SPI MISO

   13            output  SCLK pin, connects to SPI clock


*/


/*

------------------------------------LoRa Setup------------------------------------

*/


// importing libraries

#include <SPI.h>

#include <RH_RF95.h>


// pinout setup for LoRa

#define RFM95_CS 10  // reset and CS pins can be any pin

#define RFM95_RST 9

#define RFM95_INT 2  // the IRQ pin should be an interrupt pin. On an UNO this is pin #2 or pin #3.


// Setting frequency of the LoRa module

#define RF95_FREQ 915.0  // note: must match RX's freq!


// Singleton instance of the radio driver

RH_RF95 rf95(RFM95_CS, RFM95_INT);  // instantiating radio with custom pin numbers


// Blinky on receipt

#define LED 13


void setup() {


 // setting up pins

 pinMode(LED, OUTPUT);

 pinMode(RFM95_RST, OUTPUT);

 digitalWrite(RFM95_RST, HIGH);


 // startup text

 Serial.begin(9600);

 delay(100);

 Serial.println("Arduino LoRa RX Test!");


 // manual reset

 digitalWrite(RFM95_RST, LOW);

 delay(10);

 digitalWrite(RFM95_RST, HIGH);

 delay(10);


 //checking if radio initialization was successful

 while (!rf95.init()) {

   Serial.println("LoRa radio init failed"); // it failed

   while (1);

 }

 Serial.println("LoRa radio init OK!"); //it succeeded


 // Frequency for this project is 915 MHz

 if (!rf95.setFrequency(RF95_FREQ)) {

   Serial.println("setFrequency failed");

   while (1);

 }

 Serial.print("Set Freq to: ");

 Serial.println(RF95_FREQ);


 // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on


 // The default transmitter power is 13dBm, using PA_BOOST.

 // setting transmitter power to 23 here, LoRa range is from 5 to 23 dBm:

 rf95.setTxPower(23, true);

}


int16_t packetnum = 0;  // packet counter, we increment per xmission


void loop() {

  // 1) read inputs (gather information from the world) (unnecessary)

 // 2) compute and make decisions based on those inputs (unnecessary)


 // sending the signal to the receiver


 delay(2000); // Wait 2 seconds between transmits, could also 'sleep' here!

 Serial.println("Transmitting..."); // Send a message to rf95_server



 // 3) drive outputs (effect different actuators in the world)


 // the actual message itself to be transmitted

 //char radiopacket[20] = "On      "; the former message to be sent

 int onSignal = 1; // the signal to be sent

 packetnum++;


 Serial.print("Sending "); Serial.println(onSignal);

 //radiopacket[19] = 0;



 // 4) report information back to the user


 Serial.println("Sending..."); delay(10);

 rf95.send(onSignal, 10);


 Serial.println("Waiting for packet to complete..."); delay(10);

 rf95.waitPacketSent();

}



//EXTERNAL MODULE CODE



/*  Allen Zhu

   Carnegie Mellon University

   Physical Computing (60-223) Spring 2024

   Project 2: The Blue Box, a trinket to help me not be sad


   Sample/template code taken from Professor Robert Zacharias

   LoRa code taken from Adafruit's website found here: https://learn.adafruit.com/adafruit-rfm69hcw-and-rfm96-rfm95-rfm98-lora-packet-padio-breakouts/rfm9x-test

  

   This Arduino sketch is to help a LoRa receiver module receive an on/off signal from the transmitter module, see main body sketch for more details.


   Structuring this Arduino sketch so that the loop contains four basic elements:

     1) read inputs (gather information from the world)

     2) compute and make decisions based on those inputs

     3) drive outputs (effect different actuators in the world)

     4) report information back to the user


  Pin mapping:


   Arduino pin | role  | details

   ------------------------------------

   4             output  LED pin

   5             output  buzzer pin

   2             output  interrupt pin for LoRa

   9~            output  radio reset pin

   10~           output  CS pin, connects to SPI chip select

   11~           output  MOSI pin, connects to SPI MOSI

   12            output  MISO pin, connects to SPI MISO

   13            output  SCLK pin, connects to SPI cloc

*/

/*

------------------------------------LoRa Setup------------------------------------

*/

// importing libraries

#include <SPI.h>

#include <RH_RF95.h>


// pinout setup for LoRa

#define RFM95_CS 10  // reset and CS pins can be any pin

#define RFM95_RST 9

#define RFM95_INT 2  // the IRQ pin should be an interrupt pin. On an UNO this is pin #2 or pin #3.


//pinout setup for everything else

#define LEDPIN 4

#define BUZZERPIN 5


// Setting frequency of the LoRa module

#define RF95_FREQ 915.0  // note: must match TX's freq!


// Singleton instance of the radio driver

RH_RF95 rf95(RFM95_CS, RFM95_INT);  // instantiating radio with custom pin numbers


// Blinky on receipt

#define LED 13


void setup() {


 // setting up pins

 pinMode(LED, OUTPUT);

 pinMode(LEDPIN, OUTPUT);

 pinMode(BUZZERPIN, OUTPUT);

 pinMode(RFM95_RST, OUTPUT);

 digitalWrite(RFM95_RST, HIGH);


 // startup text

 Serial.begin(9600);

 delay(100);

 Serial.println("Arduino LoRa RX Test!");


 // manual reset

 digitalWrite(RFM95_RST, LOW);

 delay(10);

 digitalWrite(RFM95_RST, HIGH);

 delay(10);


 //checking if radio initialization was successful

 while (!rf95.init()) {

   Serial.println("LoRa radio init failed");  // it failed

   while (1)

     ;

 }

 Serial.println("LoRa radio init OK!");  //it succeeded


 // Frequency for this project is 915 MHz

 if (!rf95.setFrequency(RF95_FREQ)) {

   Serial.println("setFrequency failed");

   while (1)

     ;

 }

 Serial.print("Set Freq to: ");

 Serial.println(RF95_FREQ);


 // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on


 // The default transmitter power is 13dBm, using PA_BOOST.

 // setting transmitter power to 23 here, LoRa range is from 5 to 23 dBm:

 rf95.setTxPower(23, true);

}


int16_t packetnum = 0;  // packet counter, we increment per xmission


int radioWorks = 0;


void loop() {



  // 1) read inputs (gather information from the world)

  if (rf95.available())

 {

   // Should be a message for us now  

   uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];

   uint8_t len = sizeof(buf);

  


   // 2) compute and make decisions based on those inputs

  

   if (rf95.recv(buf, &len)) // receiving the transmitted message

   {

    

     //declaring variables for ease of data manipulation


     radioWorks = 1;


     digitalWrite(LED, HIGH);

     RH_RF95::printBuffer("Received: ", buf, len);

     Serial.print("Got: ");

     Serial.println((char*)buf);

     Serial.print("RSSI: "); // RSSI is signal strength, -15 is the likely highest you'll see, larger number = stronger signal

     Serial.println(rf95.lastRssi(), DEC);

    

   

     //  3) drive outputs (effect different actuators in the world)

    

     // Send a reply

     uint8_t data[] = "And hello back to you";

     rf95.send(data, sizeof(data));

     rf95.waitPacketSent();

    

     // 4) report information back to the user

     Serial.println("Sent a reply");

     digitalWrite(LED, LOW);

   }

   else

   {

     Serial.println("Receive failed");

   }


  

   

 }


 // 2) compute and make decisions based on those inputs


 if (radioWorks == 1) {

    

     // 3) drive outputs (effect different actuators in the world)


     digitalWrite(LEDPIN, HIGH);

     digitalWrite(BUZZERPIN, HIGH);

     delay(3000);

     digitalWrite(LEDPIN, LOW);

     digitalWrite(BUZZERPIN, LOW);


     radioWorks = 0;

   }

  

}