Projects

You Have Mail - RF Wireless Mailbox Monitor

Liam Davies

Issue 55, February 2022

This article includes additional downloadable resources.
Please log in to access.

Log in

Sitting at your front door waiting for that package to arrive? We’ve got you sorted with this Arduino-powered Wireless Mailbox Monitor. Comes complete with a mini kitchen top mailbox that opens automatically and displays how many items have arrived!

BUILD TIME: 6 hours (excluding 3d printing)
DIFFICULTY RATING: Intermediate

We start this project with a story that every maker will be able to relate to. Picture this: You’ve just ordered a rather extensive quantity of electronic parts and gadgets online and are patiently waiting for them to arrive in the mail. Days and weeks pass, to no avail.

But then, disaster strikes. The postie finally puts your package of goodies in the mailbox and, of course, it immediately begins to rain, soaking your precious parts and whatever else was in there. The last time we checked, electronics and water don’t mix super well. And we’ll take a guess and say neither do envelopes, bills or newspapers.

Now that our sob story is over with, it should now be clear that this project was born out of necessity! Bottom line? We want to know right away when mail arrives! If we are blessed with the luxury of online email notifications without actually opening the inbox, we should be able to do the same with real mail - it’s only fair.

The Broad Overview

There are two main parts to this project - the detector and the receiver. The detector unit essentially sits in or near your mailbox and continually checks whether new mail has been inserted. If it detects that there is new mail, it goes ahead and uses a radio module to chat to the receiver.

The receiver unit, waiting patiently in the kitchen, bedroom or home office, perks up and hears the detector report a new item. We built the receiver in the shape of a mailbox, of course.

Because we couldn't resist over-engineering this project, when new mail arrives, the front mailbox ‘door’ automatically swings open thanks to a mini servo hidden inside, and a 7-segment display lights up with the number of items received. This is, of course, a purely aesthetic addition, but the noise of the servo will also alert anyone around that new mail has arrived.

Once the reset button is pressed on either the sender or receiver unit, the mini mailbox closes back up and the LED display turns off. Simple, but effective and useful - hopefully!

We're aiming to design this project so that it's useful for properties where it’s not an “on your doorstep” type situation to fetch your mail. Many rural properties have their mailboxes at the end of very long driveways - i.e. out of walking distance - which is an important factor in designing this project.

How It Works

Fundamentally, this project is quite simple. We detect mail being inserted into the mailbox, send a signal to the receiver, and then light up our mail indicator. Easy, right?

As with any ‘simple’ engineering task, there are a million different ways of doing it wrong. The first solution we came up with for this project was to use a simple limit switch to detect when any weight is present in the mailbox. There is nothing wrong with this dead-simple approach, but because it’s effectively a binary sensor (i.e. there is mail, or there isn’t), we can’t know how many items have been inserted!

The second approach to this is to use a system that detects when an item is inserted.

This system works similarly to the vending machine project in Issue 43, where we used an infrared emitter and detector to create a coin detector. Like the coins, envelopes and packages are typically white or grey in colour so they reflect enough light to produce a substantial change in a nearby detector. When an item is not being inserted into the mailbox, the opposite surface of the mailbox is hopefully dark enough to be differentiable from a package.

Since we detect when an item is inserted, rather than the permanent presence, we need to make sure we’re polling all the time.

What about when we take the mail items out? Since we’re only detecting the action of inserting mail, we won’t know when it’s taken out. For this reason, we’re adding reset buttons to both the detector and display unit so the mail ‘count’ can be reset back to zero. Regardless, if you’re building this project, and don’t care about the particular number of items received, feel free to build it just with the simple limit switch!

RF Module

We opted to use a pair of RF modules from Jaycar that claim a range of up to 1km. We found later in testing it doesn’t quite reach this value, but it's nonetheless practical for what this project is designed for. These modules are based on the nifty NRF905 chipset, which can switch between 433/868/915MHz transmission bands. Here in Australia, we have an IoT sub-gigahertz band of 915-928MHz - this is typically known as the ISM (Industrial Scientific Medical) band, so within reasonable restrictions, it’s free to use. However, the antenna included with the units are tuned for 433MHz, so we’re going to leave it as-is for the best performance.

These modules aren’t super expensive, and they have quite a few nice inbuilt features that make reliable wireless communication practical. Each communication consists of a preamble, a target address, the payload - the data you actually want to deliver up to 32 bytes - and a CRC checksum for ensuring the data sent is actually correct. It also has a clever ‘retransmit’ feature that is designed to avoid dropped data packets by repeatedly sending the payload data if the sender doesn’t receive a reply.

If you’re not experienced or interested in the nitty-gritty of these wireless communication details, don’t worry. We’ll be putting to use a fantastic library by Zakkemble that handles this complicated stuff, and lets us focus on transmitting data.

In our opinion, the main issue with using these modules with Arduinos is the rather large amount of pins used to control them. With the limited GPIO real-estate on the Uno and Nano boards, there aren't many pins left over after connecting the 8 required and 2 optional digital pins to the NRF905 module. If you have many other sensors to interface with, it’s probably best to look elsewhere. But, if you’re building a similar project to this, you should have no trouble getting it to work.

Power

Unless you are in possession of a secret infinite energy device (in which case you should totally tell us about it), chances are you will need to consider how to power the mailbox monitor. The display unit - the bit that stays inside - is pretty easy to power, only requiring a USB power source. The outside unit with the detector will either require a mains power source (with a 5V adaptor) or a battery, as we’ll be using.

Because we need to save energy on the detector side, we need to ensure that we’re not running the Arduino Nano and Radio Module all the time. Both of those things suck power!

We’ve had this dilemma for many of our battery-powered projects, such as the car entertainment unit and last month’s GPS tracker, both of which used Raspberry Pi’s and a MOSFET to turn it on and off when power is not required.

However, since Arduinos are very good at managing power, we could utilise the inbuilt Deep Sleep functionality to enable and disable processing at any time. We just need a trigger input to wake it up. This, of course, should be triggered by inserting mail. As we discussed in the previous section, we’re using an IR detector and emitter.

Our first thought was to use the analog comparator inbuilt to the Arduino Uno and Nano, which is a feature that few makers actually remember exists! On pins 6 and 7, it’s possible to connect two analog inputs and, within software, generate digital functionality depending on which side has the higher voltage.

We experimented for quite a while with this system, but unfortunately, once the Arduino is put to sleep, it requires an interrupt or Watchdog timer to wake it back up - something the inbuilt analog comparator can’t generate. So, we opted to design a circuit especially for waking the Arduino up with a MOSFET instead, while saving power and keeping the mailbox monitor responsive. Sit tight and we’ll show you how that’s all set up in the main build!

The Prototype Build:

Parts Required:JaycarAltronicsPakronics
2 x Arduino Nano or Compatible BoardXC4414Z6372ARD-A000005
1 x RF Transmitter & ReceiverXC4522Z6354-
1 x Double-sided Perfboard #-Element14: 3769960-
1 x 40-long Female HeaderHM3230P5390ADA3366*
1x 40-long Male HeaderHM3212P5430DF-FIT0084*
1x Tactile PushbuttonSP0601S1120DF-FIT0179
1 x 7-Segment Common Cathode LED DisplaysZD1855Z0190-
1 x Infrared EmitterZD1945Z0880ADA387
1 x Infrared PhototransistorZD1950Z1613-
1 x LM393 ICZL3393Z2558-
1 x 1MΩ 25-turn TrimpotRT4658R2394A-
1 x 180Ω Resistor*RR0554R0540SS110990043
7 x 220Ω Resistors*RR0556R0542SS110990043
1 x 390Ω Resistors*RR0562R0548SS110990043
6 x 470Ω Resistors*RR0564R0550SS110990043
6 x 1kΩ Resistors*RR0572R0558SS110990043
3 x 10kΩ Resistors*RR0596R0582SS110990043

Parts Required:

Our prototype build will primarily ensure that the wireless communication between the mail detector (Client) and mail display (Server) are working correctly, however, we’ll be also adding the LED displays and detectors for both units.

First up, we slotted an Arduino Nano into the breadboard and a small breakout board next to it. This breakout board we made splits apart the closely-spaced block of pins from the RF module into breadboard-compatible pins. It’s not essential, but it makes wiring substantially easier. Regarding the Arduino itself, we used some Arduino Nano clones with USB-C ports, but any version will work.

Since many of the digital pins on the RF module are not 5V compatible, we need to step them down to 3.3V with a simple resistor divider. We used a 470Ω and a 1kΩ resistor on each of the CE, TXE, PWR, SI, CSN and SCK pins. The 1kΩ is connected to ground on each, and the 470Ω is connected between the pin and the target Arduino pin. The DR and AM pins are optional, which generate interrupts when a data packet has been received or the incoming address matches, respectively. We opted to use them as they may be handy in our code later.

Because there are so many connections, we’ve used Dupont jumpers for this. It, unfortunately, makes it harder to look at and understand, but it’s not practical to use this many solid core wires. Never fear though, the Fritzing we have shows how the radio modules are connected.

At this point, both the receiver and transmitter are exactly identical, so you’ll need to build two with the same wiring. Double check the wiring because it’s very easy to get it wrong and scratch your head wondering why one side doesn’t work later. From this point, we’ll build both the client and server unit separately.

Server

The server is the simpler of these two sub-builds and just needs a 7-segment display and a reset button. Let’s get to it!

This is probably one of the most common and straightforward ways to display numerical characters, so we saw no reason to make this project any more complex. This is a simple 7-segment display unit from Jaycar and runs in a Common Cathode configuration - meaning the negative side of each LED is connected together. There are two Ground points on the display, one on the top-middle pin and one on the bottom-middle pin.

The other pins are used for the actual LED segments, eight in total. Since we’re not interested in using the decimal point, we’re not connecting it to leave seven. Not that we have an option, because we don't have many GPIO pins left! We’re using analog pins A0-A5 and D6 for the segments, which we connected in series with a 220Ω resistor each.

The server prototype build is pretty simple, and we only now need to add a reset button for resetting the mail count back to zero. This isn’t a hard reset button, meaning we don’t actually reset the Arduino. However, strictly speaking, we’re not using it as a digital input either. Since there aren’t any digital pins left on the Arduino, thanks to the RF module and 7-segment display gobbling them all up, we need to use an analog pin.

A quirk of the Arduino Nano compared to the Uno, in particular, is that it has two extra analog pins broken out, A6 and A7. Unfortunately, these can’t be used as outputs, or even as digital inputs. They are analog input only! This catches newcomers out all the time on the Arduino Forums, you have been warned! So, we can hook up our button to it, but it must have an external 10kΩ pulldown attached to make it readable. In code, we can simply check if the analog value is substantially above 0.

Client

The first thing we added to the Client-side of the Mailbox Monitor was the infrared emitter and detectors, which is essentially just an infrared LED and a phototransistor each. We opted to use a 10kΩ resistor with the phototransistor and a 390Ω with the Infrared LED. We also hooked up an LM393 to compare and output a digital voltage if the phototransistor sees a large amount of Infrared light. The LM393 needs a 5V and Ground wire.

To act as a sensitivity adjustment, we added a 1MΩ 10-turn potentiometer that allows to create a finely-adjustable threshold voltage. Like the LM393, it needs 5V and Ground to create an adjustable voltage on its wiper.

Finally, we connected the potentiometer and the phototransistor to the LM393 on its non-inverting (3) and inverting (2) pins respectively. Now, the LM393 will output a signal on Pin 1 that will be high if the Infrared LED is not above the threshold, and low if it is - i.e. active low.

We then popped in a jumper wire to run the signal back to the Arduino Nano on Pin D2. Note that we had to move the RF module on D2 to D5, so that we could use the Interrupt Wakeup pin.

The Code

While we’ll be writing a more extensive program for the final build, we feel it's important to show how the critical parts of the project are implemented before we add some more complex functionality later on. There is quite a lot of it, so it’s been shortened - the rest can be found in the project files as usual.

void setup() {
  Serial.begin(115200);
  Serial.println(F("Client starting..."));
  SPI.begin();
  transceiver.begin(SPI, 10000000, 10, 7, 9, 8, 
4, 3, 5, nRF905_int_dr, nRF905_int_am);
  transceiver.events(
    nRF905_onRxComplete,
    nRF905_onRxInvalid,
    NULL,
    NULL
  );
  transceiver.setListenAddress(RXADDR);
  transceiver.setTransmitPower(NRF905_PWR_10);
  transceiver.powerDown();
  Serial.println(F("Client started"));
}

Our startup function for the client - the mail detector - is mostly detected towards setting up the RF radio module. It’s nice and fast since it runs on SPI, but there is a number of additional statements required to ensure it operates at max power, but doesn’t suck power when the Arduino is in sleep mode. The pin assignments in the transceiver.begin() line are a combination of the hardware (non-changeable) SPI pins and additional data pins for features like targeting certain addresses and avoiding transmission collisions - if a neighbour decides to open their garage with a 433MHz remote fob, for example.

void loop() {
  sendMessage('M');
  ADCSRA = 0;
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
  noInterrupts();
  attachInterrupt(0, mailEvent, FALLING);
  EIFR = bit (INTF0);    
  interrupts();
    sleep_cpu ();  
}

The main loop may look a little gibberish to those who haven’t experimented with register programming, but essentially all we’re doing is sending a message to the server and going back to sleep until the signal from the LM393 wakes up the Arduino again with an interrupt. We also turn off the ADC while asleep to save some precious power. The Arduino spends most of its time asleep, in the sleep_cpu() function, until a low signal (i.e. an envelope passing over top of the Infrared detector) is detected on Interrupt pin 0 (D2). It then continues where it left off, and sends another message.

After uploading, we can confirm that waving a piece of paper over the top of the detector powers up the Arduino, sends a signal to the server (whose code we’re not showing here, but is similar) and the 7-segment display is incremented. It then goes back to sleep and power draw is reduced.

The point of the prototype build is to experiment and confirm a basic working principle of the concept, and while most of the build is effective, we need to change the way the Arduino wakes up and goes back to sleep. Let’s dig into the main build and we’ll show you why.

The Main Build:

Additional Parts Required:JaycarAltronicsPakronics
2 x Domed Pushbutton IP67SP0656S0960SS110990055
2 x LM7555 CMOS 555 Timer ICsZL3455Z2021-
1 x FQP30N06L N-Channel MOSFET (Or equivalent)ZT2468Z1537-
3 x 8-Pin IC SocketsPI6500P0550-
2 x 5mm LED BezelsHP1103H1554ADA2172
1 x 2k2Ω Resistor*RR0580R0566SS110990043
1 x 560kΩ Resistor*RR0638R0624SS110990043
1 x 680kΩ Resistor*RR0640R0626SS110990043
1 x 10µF Capacitor*RE6075R4767DF-FIT0117
1 x S8550 PNP Transistor (or equivalent)*ZT2328Z1030DF-FIT0322
1 x 100nF Ceramic Capacitor*RC5360R2865DF-FIT0118
1x 40-long Female Header StripHM3230P5390ADA3366*
1x 40-long Male Header StripHM3212P5430DF-FIT0084*
1m x 16-way Splittable IDC Ribbon CableWM4502W2616-
1 x Cable Gland 4-8mmHP0724H4312AADA761
1 x 9V BatterySB2423S4931PAKR-A0113
1 x 9V Battery SnapPH9234P0455ADA80
1 x USB-C Power CableWC7755P1989ADA4474
1 x SG90 ServoYM2758Z6392DF-SER0006
OPTIONAL:---
2 x 8mm Neodymium Magnets* (For mounting onto metal mailboxes)---

Additional Parts Required:

*Quantity required, may only be sold in packs. Mounting hardware, adhesives, cable ties, heatshrink, paperclips and whiteboard marker may also be required.

While most of the circuitry is similar to the prototype build, such as the radio modules, we need to change up a couple of things to improve the practicality of the device, starting with the question of power.

Power Circuitry

We obviously can’t hook up the 9V battery straight to the Arduino, it’d kill the onboard regulators and microprocessor. We typically use a 7805 5V regulator for this, but since this would waste about 45% of the battery power (1 - 5V/9V = 0.444) due to the linear nature of the regulator, we’re using a DC-DC Buck converter. While it’s more expensive, it should keep the power usage down and keep the 9V battery lasting a while.

Unfortunately, a standard Arduino Nano isn’t exactly power efficient even in sleep mode. Since the onboard USB controller chip and power LEDs are always running, we saw about 30mA of power draw even in deep sleep mode. There is another power sucker that requires some thought here - the Infrared LED. Even though our microcontroller may be turned off, at full chat, the Infrared LED will draw 20mA and drain the 9V battery in less than a day flat! So we need to be very careful with power management here. This took a lot of thought to come up with something that also wouldn’t sacrifice sensitivity, minimises false positives, and keep the Arduino on long enough to send its radio data.

Besides running the LED at a lower current and potentially losing sensitivity to letters being inserted, there is an alternative solution of running the LED on a very low duty cycle. By turning it on and off very fast, but only keeping it on. For example, 1% of the time, will reduce the power usage to just 200μA. However, we need to ensure the frequency we’re driving it at is high enough that we don’t miss an item being inserted into the mailbox.

We came up with a cool little circuit using just one LM393 comparator IC and two LM7555 low-power timer ICs. These are both low-power and very affordable. This circuit could be used anywhere there’s a need to have very low-power detection functionality. We spent a ton of time refining this circuit to get it working well!

We put together a prototype of this low-power circuit on a breadboard and did a quick experiment of just how much power we could save while not affecting the performance or responsiveness.

Compared to the 80mA or so power usage by the Arduino and Radio Module, we reduced the ‘sleeping current’ to 1mA with this circuit. We’re covering the sensor in the photo shown to simulate the inside of a mailbox. When placed in an environment with direct sunlight, the phototransistor registers the infrared emissions of the Sun as an envelope - which is not really avoidable, unfortunately, aside from keeping the sensor out of the Sun’s path.

Working out the maths, the resultant power draw should now keep the mailbox monitor alive for around a month. This still isn’t perfect, but could be improved dramatically by adding a very small solar panel or some more 9V batteries.

The first part of the circuit is the LM7555 chip in astable mode - essentially running it so that it cycles between ON and OFF rapidly. This is configured to blink at less than 1% duty cycle. The circuit we assembled on a perfboard uses some 8-pin IC sockets to make the chips removal, with a 2.2kΩ and 560kΩ resistor for timing the ON and OFF periods of the duty cycle respectively.

This signal will go straight to the infrared LED through a PNP transistor, so that the LM7555 doesn’t supply all the current to the LED by itself. We’ll hook the LED up later in the build.

We found a 100nF ceramic capacitor works pretty well for creating a suitable frequency, oscillating at around 30Hz which should be high enough to detect when an item is inserted.

We also need to process the signal coming from the phototransistor. Since it will be pulsed due to the infrared LED pulsing, we need to transform it into a signal that can be used to turn on the Arduino. If we hooked this signal straight up to a MOSFET to turn the Arduino on, it would turn on for a couple of milliseconds then turn off again!

The first stage of this process is to create a digital signal from the analog phototransistor input, which we’ll do by using the LM393 in the exact same way as the Prototype build, together with a 1MΩ potentiometer for sensitivity adjustment. Again, we’re using an IC socket to make it removable.

However, this will still give us a pulsed digital signal! We need to maintain this signal for at least a couple of seconds to allow the Arduino to wake up and transmit a mail signal. We initially thought about doing this with a capacitor and the other channel of the LM393 comparator, however, in practice, the capacitor either discharges too fast or doesn’t react quick enough to a positive signal on the phototransistor.

So, we used another LM7555 in monostable mode to generate a one-shot pulse of around 10-15 seconds on detection of a pulse from the LM393, giving the Arduino enough time to send a radio signal and then go back to sleep. For this, we used a 10µF capacitor and a 560kΩ resistor. Either of these components can be easily changed to generate a different ‘on-time’ for the Arduino.

Finally, we slotted in an N-channel MOSFET and connected all the external wires so that we can wire it into the rest of the detector unit.

This small circuit took some thinking to get everything to fit - it isn’t exactly spacious inside the detector box! Speaking of which, let’s get to printing that.

3D Prints

Transmitter

We’re going to guess you won’t have the exact green mailbox we have! So, we’ve provided the STL models in the project files which can be adapted to mount in any area you’d like. The front half of the box can be screwed onto just about anywhere, but the 40mm x 40mm square pole ours was mounted onto can be clamped on with an additional rear bracket. We don’t like permanently mounting projects, so there isn’t a need to drill holes unless there is no way to access the mailbox container with the detector LED cables.

Mother nature is a cruel force, and will force you to protect your precious electronics against weather, large temperature changes, humidity and redback spiders at the very least. Depending on your installation, you will need to change parts of the project to keep the electrons in and the H2O out.

The easiest way to do this is to use a rubber gasket or sheet to create a water-tight fit between the two halves of the 3D printed enclosures, then screw into it and clamp it tight.

We absolutely love these little 4-8mm cable glands to use with the detector LED cable, which are IP68 rated. Just slide the cable through, twist tight and secure it into the 3D printed enclosure. It’s purposely placed on the underside so water doesn’t drip into the cable entryway.

Before we screw everything together though, let’s pop in the main build electronics. The 9V battery and its power clip can be slid into the rear area, which should be nice and snug against the inbuilt brackets. We also had to build a small board attachment for the radio module to step the 5V down to 3.3V.

The board attachment isn’t super complex, but it does get pretty tedious having to deal with each of the 10 I/O lines for the radio module. You can find more details and specific connections in the included schematics.

Detector

The detector is mounted separately inside the mailbox, away from the rest of the electronics to save space and prevent the surrounding metal acting as a faraday cage for the Radio antenna. The detector itself is a small plastic enclosure where the infrared emitter and detector sit, separated by ≈2cm and by an angle of 15° to create a light path that appropriately reflects on objects above. Our detector was designed with a metal mailbox in mind, so instead of screws or double-sided tape we’re using two 8mm neodymium magnets to secure the detector to the box. They’re quite strong and won’t move even with a good knock. We had to experiment with three separate prototypes to get the magnet distance and LED distance right.

The LEDs are secured in two 5mm LED holders, and we used a cut-up USB cable as the power cable. Only three cables are needed for this, so even a three-core wire will do just fine here. We’re using a shared ground between the detector and emitter, both of which have a signal wire connected to their opposite legs. If you’re worried about weather sealing, you may wish to add some hot-glue or epoxy to the inside to insulate the electronics. After popping it onto the inside of the mailbox, run the cable in a way that won’t get caught by items inside or wick water down towards the transmitter box.

Receiver

Putting together our mini mailbox is the fun part! There are four different parts to 3D print; the mailbox body, the front door, the mailbox underside and the base for the whole thing. The prints have quite tight tolerances so you may need to either adjust dimensions or modify print parameters to get everything fitting together nicely. In particular, we had some ‘elephant-footing’ where the first layer of filament is slightly pressed into the build plate, expanding it out. Good for grip, not good for tight-tolerance printing!

Most of the brains are stored in the base, so only the servo and the 7-segment display is placed in the mailbox.

We first put together a cool little armature system for the door opening sequence. Since it’s not practical to mount a servo directly to the door hinge, we need to use an arm mounted further back in the mailbox. The servo is press-fit into the underside of the mailbox, which due to the poor printing tolerances required some rubber mallet and filing work to get it in there. Once it's in there though, it’s definitely not coming out again!

There isn’t a lot of force being applied on the servo arm itself, so we opted to use an unfolded paper clip as the control arm. This is a fairly common strategy with DIY remote control aircraft for aileron and rudder control! Just pop the paper clip through one end of the one-sided servo horn (should be included with the servo) and the other through the hole in the door. There should be enough travel room to slide the metal paper clip up and down through the slot.

The armature of the servo is fairly forgiving. After modelling and simulating the joint in Fusion 360, we figured out that the 180° degree movement of the servo is more than enough to drop down and lift up the front door. You may wish to experiment with the right length of metal between the servo and door. Don’t worry if the start and stop points of the servo arm aren't exactly 0° or 180°, since we’ll be setting start and stop limits in software anyway.

For the hinge of the door itself, we’re once again using an unfolded paper clip, pushed straight through. You may need to use a 1mm or 1.5mm drill bit to help clear out the hole if your 3D printer didn’t do a good job with it.

The other electronic part that the mailbox houses is the 7-segment display that will light up according to how many mail detection events have been recorded. We used some IDE cable to bundle the 10 wires together (7 for the segments, 1 for the optional decimal point, and 2 for the common grounds). We used some short solder joints and used some heatshrink to keep it all neat and tidy. ››

›› Finally, we press-fitted the 7-segment display into the front of the mailbox. Depending on the tolerance, you may wish to file the edges down so it’s a snug fit, while not being overly loose.

With our mailbox put together, we need to put it on the pole that will connect it to the base. You’re free to use a 3D printed tube for this, but we opted against because poles with small contact areas often lead to weak prints. Instead, we chopped up a whiteboard marker, pulled out the ink cartridge, and used the white tube as the pole. We had to use a Dremel with a cutting bit and a drill bit to get a clean cut and to allow the wires to travel smoothly through the tube.

After routing the servo head and 7-segment display wires through the tube, it can be inserted into both the mailbox base and the underside print. The servo header and the display wires should have plenty of room to move inside the tube and keeps them out of the way so they’re not an eyesore.

The base itself includes three holes; one for the mailbox post, one for the radio antenna and one for a reset button.

Because there isn’t a lot of room underneath the base, we opted to hard-solder everything onto the Arduino so take your time soldering.

First up, added 220Ω resistors to each of the 7 display wires to limit the current, adding heatshrink to prevent shorting. After that, we inserted the resistors directly into the A0-A5 and D6 pins on the Arduino Nano - no headers used here to save space. Be very careful not to bend the leads because resistors are horrible strain relief points and will break very quickly. The ground wires are also soldered together, then added to the Ground pin of the Arduino Nano.

Next, we worked on connecting the RF module to the Arduino. Again, to save space it’s soldered directly to the pins, but we had to use an intermediary circuit board to step down six of the ten data lines to 3.3V rather than 5V. This consisted of 470Ω resistors in series with 1kΩ resistors, just like the prototype build.

We also used this board to share the two ground pins on the Arduino Nano to the other components that required it, namely the servo and the RF module. Speaking of which, we chose to mount it to the underside of the base with the antenna sticking upwards, parallel with the letterbox pole.

We added a 10kΩ resistor to the reset button to act as a pulldown, and then we stuck everything to the bottom of the base. Alright, let's get to the code! ››

The Code

Much of the code for the final build is similar to the prototype build, so we won’t be showing it again. The main difference with how we’re running the main build transmitter is that we’re no longer using a software sleep, we’re using a MOSFET to turn it on and off, so the Arduino just sees it as a fresh boot every time a new mail item is inserted. We can do most of our work in the setup function. In fact, there isn’t any code at all in the loop() function, it’s completely empty. It is important that both the setup() and loop() functions are included as the compiler will fail without them.

  transceiver.setListenAddress(RXADDR);
  transceiver.setTransmitPower(NRF905_PWR_10);
  while(packetStatus == PACKET_NONE || 
packetStatus == PACKET_INVALID) {
    //Send a mail signal to begin with.
    sendMessage('M');
    Serial.println("Transmission attempt...");
    delay(500);
  }
  bool sentReset = false;
  while(1) {
    //If we've pressed the reset button, 
    //send a reset signal.
    if(!digitalRead(RESET_PIN) && !sentReset) {
      sentReset = true;
      Serial.println("Sending Reset Signal.");
      while(packetStatus == 
PACKET_NONE || packetStatus == PACKET_INVALID) {
        sendMessage('R');
        Serial.println("Transmission attempt...");
        delay(500);
      }
    }
  }

This is where the vast majority of our transmitter logic happens. Since we need to send a message right as we boot up, we immediately set the transmitter at its power and keep trying to send messages until a packet makes its way through to the receiver. As we mentioned, the NRF905 radios are clever and are able to check that they actually receive a reply, so we don’t have to worry about missing a piece of mail.

The message we send is fairly simple, an ‘M’ for a mail item and a ‘R’ for a reset signal, which tells the receiver to reset the mail count back to zero. Keen readers will notice that we’ve left an infinite ‘while’ loop in the code, and this is okay since we’re only waiting to see if the user resets the unit. We don’t care about doing any other logic since the low-power board will shut the Arduino down after a few seconds anyway.

The receiver code is a bit more substantial, since it needs to keep track of mail events, control the mailbox servo and also display the item count on the 7-segment display.

byte digitPins[] = {A3,A4,A5,5,A2,A0,A1};
byte numbers[][7] = {
 {0,1,1,1,1,1,1}, // 0
 {0,0,0,1,1,0,0}, // 1
 {1,0,1,1,0,1,1}, // 2
 {1,0,1,1,1,0,1}, // 3
 {1,1,0,1,1,0,0}, // 4
 {1,1,1,0,1,0,1}, // 5
 {1,1,1,0,1,1,1}, // 6
 {0,0,1,1,1,0,0}, // 7
 {1,1,1,1,1,1,1}, // 8
 {1,1,1,1,1,0,1}, // 9
};

To make the 7-segment display work, here are the data fields for controlling which segments are lit up with each number. Essentially, we have a field for which segments are connected to which pin, and a field with the correct segments to light up for each number 0-9. We can light up a number on the display like this:

for(int i = 0; i <= 7; i++) {
      digitalWrite(digitPins[i], (currentMail 
> 0) ? numbers[currentMail][i] : 0);
}

In other words, if the current mail is above zero, we turn on the display and write the appropriate data field to each segment.

void loop() {
  while(packetStatus == PACKET_NONE) {
    updateDigitDisplay();
  }
  if(packetStatus != PACKET_OK)
  {
    packetStatus = PACKET_NONE;
    Serial.println(F("Invalid packet!"));
    transceiver.RX();
  }
  else
  {
    packetStatus = PACKET_NONE;
    char buffer[PAYLOAD_SIZE];
    Serial.println("Received packet: ");
    transceiver.read(buffer, sizeof(buffer));
    char output[PAYLOAD_SIZE];
    strcpy(output, buffer);
    Serial.println(output);
    Serial.print("n");
    Serial.println("-----------------");
     if(output[0] == 'M') {
      currentMail++;  
    } else if (output[0] == 'R') {
      currentMail = 0;
    }
    while(!transceiver.
TX(NRF905_NEXTMODE_RX, true));
  }
}

Finally, here is our loop function that continually waits for new mail, replies, and then increments the mail counter when a packet is received. This communication system is very basic, consisting of a super simple protocol of essentially two letters, but it can be expanded to send any type of data conveniently.

Testing

The main problem we end up having with many projects that have any form of wireless communication is reliability. With the mailbox monitor mounted and hooked up, we left it outside and ran some range tests. We found a range of about 20-30m (in an urban environment with many houses nearby) was the most reliable. Even though wireless communication has improved by orders of magnitude over the past decade, it is impossible to expect all data to be sent successfully over radio. However, the simple re-transmitting function for this project greatly improves the reliability, ensuring that no mail item is missed even at longer distances.

Functionally, it is, of course, a quite simple project, but it’s effective, fun to use, and a cool coffee table gadget. It does what it was designed to do, but one thing that we’ll have to test is battery life of the transmitter. We estimate it will last a month, although that may vary with how many times it has to wake up throughout the day. Replacing the 9V battery is not the easiest task in the world, so if we were to do this project again we’d definitely put it in a better spot.

We’ll also have to see how well this project holds up in the weather. Because we spent a bit of time experimenting and modifying the enclosure prototypes, all of the 3D printing should be fairly water-tight - it won’t survive an apocalypse, of course, but it’s good enough for us.

Where To From Here?

We don’t expect everyone reading this to be interested in building a mailbox monitor, but as usual, hopefully, you learned something and are able to adapt it to your application. We showed off quite a few different techniques for power saving and communication in this project, so we’d like to see what’s possible.

We have featured long-range LoRa before, however, the NRF905 modules we picked up aren’t quite powerful enough to be placed in that box. Admittedly, we aren’t doing any favours for the module, testing it in an urban environment with house walls, competing for communication channels and signal-attenuating metal everywhere. They’re not bad modules and substantially outshine WiFi, making them suitable for local communication with that extra bit of range.

An interesting application for these modules would be a radio-based node network. For larger houses and properties where it’s not practical or economical to place the now-popular WiFi mesh routers everywhere, it would be possible to use RF modules to relay IoT data as needed. Garden greenhouses, weather stations, security gadgets, and of course mailbox monitors could be connected to one network without using valuable WiFi bandwidth.