Automated Mailbox – Dec07‐01  Final Report – December 10 th , 2007                                  Client:   Iowa State University    Contact Name:   Dr. Greg Smith     Advisor:   Dr. Degang James Chen    Team Members:  Mario Limonciello  Major: Electrical Engineering  Role: Team Leader  Tyler Clifton   Major: Electrical Engineering  Role: Communication Coordinator  Steve Walker   Major: Electrical Engineering  Role: Team Member   Yee Quan Wong   Major: Electrical Engineering  Role: Team Member    DISCLAIMER: This document was developed as a part of the requirements of an electrical and computer  engineering  course  at  Iowa  State  University,  Ames,  Iowa.  This  document  does  not  constitute  a  professional engineering design or a professional land surveying document. Although the information is  intended  to  be  accurate,  the  associated  students,  faculty,  and  Iowa  State  University  make  no  claims,  promises, or guarantees about the accuracy, completeness, quality, or adequacy of the information. The  user  of  this  document  shall  ensure  that  any  such  use  does  not  violate  any  laws  with  regard  to  professional  licensing  and  certification  requirements.  This  use  includes  any  work  resulting  from  this  student‐prepared document that is required to be under the responsible charge of a licensed engineer  or  surveyor.  This  document  is  copyrighted  by  the  students  who  produced  this  document  and  the  associated  faculty  advisors.  No  part  may  be  reproduced  without  the  written  permission  of  the  senior  design course coordinator. 

 

Table of Contents  1.0 

Summary ........................................................................................................................................... 5 

2.0 

Project Plan ....................................................................................................................................... 6 

2.1 

Problem Statement ....................................................................................................................... 6 

2.2 

Concept Sketch/Mockup ............................................................................................................... 6 

2.3 

System Block Diagram ................................................................................................................... 8 

2.4 

System Description ....................................................................................................................... 8 

2.5 

Operating Environment .............................................................................................................. 11 

2.6 

User Interface Description .......................................................................................................... 11 

2.7 

Functional Requirements ............................................................................................................ 12 

2.8 

Non‐functional Requirements .................................................................................................... 12 

2.9 

Market Survey ............................................................................................................................. 13 

2.10 

Deliverables ................................................................................................................................. 14 

3.0 

Project Design ................................................................................................................................. 15  3.1.1 

Common Parts ..................................................................................................................... 15 

3.1.2 

Transmitter Specific ............................................................................................................ 16 

3.1.3 

Common Code Libraries ...................................................................................................... 16 

3.1.4 

Receiver Specific Code ........................................................................................................ 17 

3.1.5 

Transmitter Specific Code ................................................................................................... 17 

3.2 

Work Structure ............................................................................................................................ 18 

3.2.1 

Incremental Design ............................................................................................................. 18 

3.2.2 

Electrical & Mechanical Drawing ........................................................................................ 19 

3.3 

Resource Requirements .............................................................................................................. 19 

3.4 

Project Schedule ......................................................................................................................... 20 

4.0 

Project Testing ................................................................................................................................ 20 

4.1 

Transmission Test ........................................................................................................................ 20 

4.2 

Logic Test..................................................................................................................................... 20 

4.3 

LED Intensity Test ........................................................................................................................ 20 

4.4 

Battery Test ................................................................................................................................. 21 

4.5 

Temperature Test ....................................................................................................................... 21 

5.0 

Future Work for Commercialization ............................................................................................... 21 

6.0 

Closing Thoughts ............................................................................................................................. 22  ii   

 

  7.0 

References ...................................................................................................................................... 23 

8.0 

Appendices ...................................................................................................................................... 25 

8.1 

Appendix A: USI‐SPI Code ........................................................................................................... 25 

8.2 

Appendix B: Common NRF24LO1 Code ...................................................................................... 29 

8.3 

Appendix C: Transmitter NRF24L01 Code ................................................................................... 37 

8.4 

Appendix D: Receiver NR424L01 Code ....................................................................................... 44 

8.5 

Appendix E: Transmitter Main Code ........................................................................................... 52 

8.6 

Appendix F: Receiver Main Code ................................................................................................ 55 

8.7 

Appendix G: Schematics .............................................................................................................. 57 

8.7.1 

Transmitter ......................................................................................................................... 57 

8.7.2 

Receiver ............................................................................................................................... 58 

8.8 

Appendix H: Mechanical Drawings ............................................................................................. 59 

8.9 

Appendix I: Project Schedules ..................................................................................................... 62 

   

 

iii     

 

Table of Figures    Figure 1:  Diagram of different mailbox logic states ..................................................................................... 7  Figure 2: Mailbox with mock detection and in‐home indicator ................................................................... 7  Figure 3: Block diagram of Automated Mailbox system. .............................................................................. 8  Figure 4: Visual block diagram of sending signal .......................................................................................... 9  Figure 5: Visual block diagram of receiving a signal ................................................................................... 10  Figure 6: Smart Home's Mail Chime ........................................................................................................... 13     

 

iv     

 

1.0 Summary  For  most  people  walking  to  an  empty  mailbox  is  inconvenient.    The  time  spent,  weather,  or  user’s  disabilities are reasons why making the trip between their home and mailbox may seem undesirable.      Demographically, the elderly may have health issues that benefit from the ability to predetermine the  presence of mail.  The mailbox may be located at the end of their driveway or across the street.  The  solution  avoids  multiple  trips  to  their  mailbox  by  informing  the  user  of  their  mailbox’s  status.    This  system  initiates  a  check  for  mail  once  the  door  has  been  opens  and  closes  in  sequence.    If  the  Automated Mailbox detects mail, the user’s in‐home receiver provides a notification that the mailbox is  not empty.    The Automated Mailbox system consists of two microcontrollers, two transceivers, light emitting diodes,  comparators,  photodetectors,  switches,  resistors,  and  power  sources.    The  entire  system  is  preassembled  and  ships  with  a  mailbox.    The  microcontroller  and  transceiver  components  provide  a  means  of  control  and  communication.    The  wireless  setup  is  a  modern  method  for  notifying  users,  as  well as a smart feature for this product.  The Automated Mailbox performs a check for the presence of  mail by emitting light over an array of photodetectors.  A predetermined voltage–voltage with no mail  present–acts  as  a  control  voltage  compared  with  the  voltage  due  to  the  detection  system.    A  comparator sends a resulting signal to the microcontroller, which communicates with the transceiver to  perform the transmission.    A  switch  is  incorporated  into  the  mailbox’s  flag  to  provide  a  method  for  not  alerting  when  a  user  is  sending  mail.    The  flag  switch  will  still  trigger  the  microcontroller  to  wake  up,  but  the  IR  detection  system will not be enabled.    The  system  also  detects  when  the  outside  power  source  needs  a  replacement.    Low  power  circuitry  performs  a  voltage  level  check  during  each  transmitting  process.    This  is  performed  by  a  simple  comparator circuit to check if the voltage is less than 66% of the rated requirement.  Once the power  source reaches this level, a notification informs the user that a replacement may be in order.    A  microcontroller  located  within  the  in‐home  receiver  handles  the  notification  for  the  Automated  Mailbox.  Once a signal reaches the transceiver in the in‐home receiver, the microcontroller handles the  information and powers the corresponding LED(s).    Competitors  develop  systems  with  less  effective  checking  routines.    One  competitor  employs  a  detection method to notify the user once the door of the mailbox becomes open.  This product “chimes”  until  the  door  closes.    This  may  issue  false  signals  during  harsh  winds,  children’s  play,  or  faulty  equipment.     This  project’s  design  process  utilizes  a  top‐down  engineering  approach.    The  design  is  presented  in  incremental block diagrams and detailed circuit schematics.  These diagrams come from design software  such as Cadence Capture CIS and flowchart software such as Microsoft Visio.  Using these diagrams as a  blueprint, the individual components assemble easily.  Software design for the microcontroller was all  done in C.      

5     

 

2.0 Project Plan   

2.1 Problem Statement  During  harsh  seasons,  many  people,  especially  the  elderly,  do  not  enjoy  traveling  to  their  mailbox  multiple times a day to check for mail.  There may be a variety of hazards, especially during the extreme  seasons.  For example, in the winter the driveway may be icy, making it easy for someone to slip and fall.   During the summer, the extreme heat may cause the individual to get heat sickness or poisoning.  It is  much easier to avoid these conditions if a system provides notification when there is mail in the mailbox  before making the journey outside.      

2.2 Concept Sketch/Mockup  Figure 1:  Diagram of different mailbox logic states is a concept sketch for receiving mail and performing  next step operations.  The key process after receiving mail consists of checking the status of the mailbox  door  and  flag.    Both  components  are  monitored  by  magnetic  switches,  which  can  interrupt  the  microcontroller.    The  microcontroller  monitors  for  the  door  to  be  closed.    Regardless  of  the  door’s  status, if the flag is changed, the microcontroller will wake up and send an update on the battery status.   If the door is closed and the flag is down, the system detects the presence of mail and transmits a signal  pending the results.      The  detection  system  uses  a  matrix  of  infrared  LEDs  on  the  ceiling  of  the  mailbox.    The  placement  criterion for the infrared LEDs consists of maximizing the surface area coverage.  The area of the ceiling  panel  provides  a  basis  of  coverage  by  mathematically  spacing  the  LEDs  given  this  information.    The  photodetectors are placed in a similar matrix, but  using the area of the mailbox’s floor.  As the infrared  light from the diodes is detected by the photodetectors, a voltage is formed from the photons’ energy.   This voltage is compared to a control voltage to determine the mailbox’s status.  Figure 2: Mailbox with  mock detection and in‐home indicator is a concept mockup of this process.   

6     

 

 

  Figure 1:  Diagram of different mailbox logic states 

 

Figure 2: Mailbox with mock detection and in‐home indicator 

 

  7   

 

 

 

2.3 Syste em Block Diaagram  Figure 3:  Block diagram m of Automated Mailbox  system. provides an overvview of all of  the steps thaat are  processed d for the syste em.     

  Figure 3: Block diagram m of Automated d Mailbox system m.   

2.4 Syste em Descriptiion  As it has b been describe ed, the Autom mated Mailbo ox is broken up into two sm maller subsysttems.    The in n  home receiver and outtdoor transmitter both shaare common libraries and similar comp ponents.  The basic subsystem co onsists of a power source,, LEDs, a micrrocontroller, aand an RF transmitter.  For the  specific ap pplication use ed, these are connected in n different fasshions that arre described m more in detaiil  later on.  The transmitter is interrupt driven b by changes upon the magn netic switch inputs.  When n the interrup pts  are triggeered, the micrrocontroller w will awaken.  It then uses IR LEDs and ph hotodetectorrs and a voltage  comparattor to determine if anythin ng is breakingg the path of IR.  The micro ocontroller then communiccates  with the R RF transmitte er using a stan ndard SPI protocol.  The acctual handshaaking between the two RF  transmitteers is then co oncealed from m the code baase, making th his a much sim mpler device..  See Figure 4 4:  Visual blo ock diagram o of sending sign nal for a flow wchart of this eexchange.  Like the trransmitter, th he receiver exxposes the RFF device to an n SPI interfacee.  Instead of being driven by  external interrupts on switches, it receives an interrupt from the RF devicee to indicate that it needs to  he data receivved.  Two outtput pins are then enabled d depending u upon the dataa that was  process th received.  See Figure 5 5: Visual blockk diagram of rreceiving a siggnal for moree information.  8     

   

  Figure 4: Visual block diagram of sending signal 

 

9     

 

Receiving Signal Transceiver

Microcontroller

LED

  Figure 5: Visual block diagram of receiving a signal 

 

 

10     

 

2.5 Operating Environment  The  transceiver  and  detector  are  both  installed  within  the  mailbox.    The  system  is  durable  enough  to  resist bending and being bumped from contents in the mailbox.  The detection system withstands harsh  weather  conditions  and  is  resistant  to  rainwater,  snow,  or  dust  when  the  mailbox  is  opened.    The  bottom  of  the  mailbox  is  sealed  to  prevent  exposure  to  these  elements.    Neither  the  transceiver  nor  detection  system  withstands  being  thrown  or  dropped,  but  they  can  endure  a  slip  off  a  table  from  several  feet  off  the  ground  and  still  function.    The  transceiver  and  detection  system  withstand  temperatures from ‐10 °F to 120 °F.  The  operating  temperature  for  the  receiver  is  room  temperature,  60  °F  to  80  °F.    The  receiver's  indicators are visible in both a bright and dimly lit room. The receiver is sealed such that it is resistant to  light, dust, and water exposure. 

2.6 User Interface Description  ƒ

Mailbox Door  The mailbox  door is the interface for the user and mail carrier.  The system is activated when the  door is closed.  This action is done whenever mail is inserted in or removed from the mailbox.  Once  the door is closed, the microcontroller activates from the falling edge of the magnetic switches and  proceeds with the detection process. 

ƒ

Mailbox Flag  The  flag  interface  differentiates  between  outgoing  and  incoming  mail.    The  flag  must  be  put  up  whenever mail is being sent out.  When the flag is in the up position, the microcontroller receives an  input notifying it that the mail is outgoing. This prevents the system from sending a mail detection  signal to the receiver. 

ƒ

In‐home Receiver  The in‐home receiver interface notifies the user of the mailbox’s status: mail present or low battery.   The user’s in‐home receiver is connected to a 120 VAC outlet.  No further action is necessary after  this  connection  has  been  made.    Once  a  mail  present  or  low  battery  status  occurs,  an  LED  illuminates on the in‐home receiver informing the user of this condition. 

 

 

11     

 

2.7 Functional Requirements  The following requirements have been determined necessary for the system to function as described in  the problem statement.    ƒ The system shall detect the presence of incoming mail.  ƒ The system must be able to sense the flag switch position to differentiate incoming or outgoing mail.  ƒ The system must be able to alert users when incoming mail is present instead of outgoing mail.   

2.8 Non‐functional Requirements  These requirements are not absolutely necessary for this project’s functionality.  They are not explicitly  defined in the problem statement, but are in our problem solution.  ƒ Power 

ƒ

1. The communication and detection system located within the mailbox shall be powered by four  AA batteries.  This provides a total of six volts to the system.  2. The in‐home receiving unit must be powered by standard 120 VAC outlets.     Space  1. The circuits and system components must consume less than 

ƒ

ƒ

ƒ ƒ

ƒ

1  of the mailbox’s total space.  5

Transmitting and Receiving  1. Transmission must be able to occur with fifty feet separation.   2. The transmission shall not interfere with other systems operating at the same frequency.  Operating temperature  1. The system components must be able to withstand harsh Iowa conditions ranging from 0 °F to  120 °F.  Size  1. The overall mail box dimensions shall be around 7”H x 18”L.  Weight  1. The  Automated  Mailbox  detector  system  must  be  light  enough  to  mount  on  a  mailbox  ceiling  without exerting excessive stress on the mailbox.  2. The switches must be light enough to mount on a mailbox flag without causing it to break.   3. The  other  mailbox  mounted  components  must  be  light  enough  to  mount  within  a  mailbox  without compromising the existing mailbox structure and post.  Cost  1. The cost of building the system must not exceed $150. 

The cost of the complete system must be competitively priced and profitable compared to other market    alternatives. 

12     

 

2.9 Market Survey  In our analysis of similar products, the only one we were able to find was the ‘Figure 6: Smart Home's  Mail Chime’.  This device sends a signal to the house at all times the door is left open.  This has the  distinct disadvantage that it will not actually detect whether an item is in the mailbox.  If somehow the  door is ajar, the device will continually send a signal to the house.  Mail Chime ‐ $49.99  http://www.smarthome.com/74661.html  ƒ Dimensions:    1. Sensor:  4‐1/4" x 1‐1/2" x 1"  2. Receiver:  4‐1/4" x 3‐1/4" x 1"  ƒ Range:  300 foot  ƒ What’s included:  1. Mail Chime Receiver  2. Sensor with 12‐volt A23 battery installed  3. AC adapter  4. Double‐faced tape  5. Instructions  ƒ Only works on mailboxes that have a door that opens from a vertical to a horizontal position. 

    Figure 6: Smart Home's Mail Chime 

 

  13     

 

2.10

Deliverables 

ƒ Mailbox with detection and communication system  ƒ In‐home receiver with communication and notification system  ƒ User documentation    The end product provides users with notification of mail presence in their mailbox.  A detection system  is placed within the mailbox, which uses infrared identification and photodetectors to determine their  mailbox’s status.  The outside unit hosts a power source within its structure.  Once triggered, a signal is  transmitted from the mailbox to an in‐home receiver.  The in‐home receiver is powered by standard 120  VAC  outlets.    The  receiver  has  two  states  to  inform  the  user  about  the  condition  of  the  system.   Notification  is  done  by  LEDs  placed  within  the  receiver  housing  to  indicate  low  battery  and/or  mail  present.      User  documentation  is  included  with  the  purchase  of  each  Automated  Mailbox  system.    This  documentation gives the user basic directions for operation, installation, as well as contact support.   

 

14     

 

3.0 Project Design  Using the basic System Description, we choose adequate parts that would meet both our Functional and  Non Functional requirements.  Because of the way this project was designed, many of the same model  numbers were used in both the receiver and the transmitter.   

3.1.1 Common Parts  •

Microcontroller 

  The microcontroller is used to control all other components in the design.  For this project the  team chose an Atmel AVR ATTiny2313. The team’s microcontroller has an 8‐bit architecture with  2 Kbytes of in‐system programmable Flash memory. There are also 128 Bytes of Data EPPROM  and 128 Bytes of SRAM. It can operate at voltages ranging from 1.8 ‐ 5.5 V.  Atmel AVR series  microcontrollers  support  programming  in  either  assembly  or  embedded  C  programming  languages.   The  device  is  also  capable  of  communicating  in  SPI  format  with  other  hardware  devices indirectly via a USI interface.  This will be described more in detail later.  •

Transceiver 

  The  transceivers  are  responsible  for  wireless  communication  between  the  mailbox  and  household.   All  transmissions  occur  on  a  range  of  channels  operating  at  2.4  GHz.    These  transceivers utilize registers when transmitting data.  The transceiver used is the MiRF v2, which  is based upon the Nordic nRF24L01, Single Chip 2.4 GHz Transceiver.  The transceivers use an SPI  interface for programming and communication, which is compatible with the microcontrollers.   The SPI specification allows for two or more devices on a bus to communicate, designating one  as a master with the rest being slave devices.  The microcontroller is the master device, allowing  it to control the timing, clocking, and functionality of the transceiver.   The  MiRF v2  simplifies  many of the  complicated steps with regard to  clocking data, adding an  antenna,  and  setting  up  additional  features  supported  by  the  Nordic  nrF24L01.   The  only  pins  available  to  the  Nordic  are  the  standard  SPI  pins  and  power.  Upon  initial  power,  the  microcontroller  sends  a  set  of  configuration  data  to  the  transceiver  via  SPI.   The  transceiver  powers  up  after  processing  the  configuration  data.   Once  the  transceiver  is  ready,  it  sends  a  signal to the  microcontroller indicating  that it  can begin  processing data.   From this point, the  microcontroller controls all data transfers to and from the transceiver.  •

LED 

  LEDs  are  used  to  provide  notification  to  a  user  regarding  their  mailbox’s  status.    This  status  is  either mail is present or low batteries.  These LEDs are powered by the microcontroller in the in‐ home receiver unit.  The microcontroller will determine when the usage of an LED is necessary. 

15     

 

3.1.2 Transmitter Specific  •

Magnetic Switches 

  The  magnetic  switches  are  comprised  of  two  sections  that  function  like  the  inverse  of  an  ordinary switch.  When the two contacts of the switch are touching, the circuit will appear to be  an open circuit.  When the two contacts are separated, the circuit will close and allow current to  flow.  It does not dissipate power unless the mailbox door is open.  When the door is open, a  minimal  amount  of  power  is  dissipated.    This  dissipation  is  not  enough  to  affect  the  battery  significantly.  It conserves the battery while not in use.   •

IR LEDs 

  Infrared  LEDs  are  used  for  the  detection  process.   They  are  powered  by  the  microcontroller  within  the  mailbox.   These  LEDs  are  governed  by  the  microcontroller  in  the  detection  system,  thus determining when their usage is necessary.  •

Photodetectors 

  The photodetectors will detect infrared light from the IR LEDs.  The photodetectors are located  on  the  bottom  of  the  mailbox.    When  mail  is  present,  there  is  blockage  of  photodetectors,  causing a lower voltage.  This lower voltage notifies the microcontroller that mail is present.   •

Voltage Regulator 

  The voltage regulator regulates the voltage from the supply, such that the voltage seen by the  devices  is  unaffected  by  the  degradation  of  the  batteries.    The  voltage  regulator  operates  by  stepping a 6V (4‐AA) input down to a 3.3V output.  •

Comparator 

  The comparator interprets voltages caused by current from the photodetector over a resistor.  It  compares  two  voltages  at  the  +  and  –  terminal.    When  the  comparator  sees  a  voltage  of  2.8  volts, it tells the microcontroller that there is no mail present.  Once the voltage drops below 2.8  volts, it notifies the microcontroller that mail is present. 

3.1.3 Common Code Libraries  Because both the microcontrollers need to communicate via SPI to their respective RF Transceivers, a lot  of code was shared between the two microcontrollers.  The microcontrollers don’t directly have an SPI  interface,  so  one  has  to  be  implemented  via  the  USI  (universal  serial  interface)  available  on  the  microcontroller.    Atmel document AVR319 was very useful for this procedure.  This document shows how to implement  USI on some of the bigger microcontrollers such as the ATMega8.  There is not documentation on the  16     

  internet  to  indicate  one  way  or  the  other  if  this  is  supported  on  the  ATTiny2313.    We  did  manage  to  implement such an interface by slight modifications to Atmel’s code.  See Appendix A for the USI‐>SPI  Code.    The  other  common  piece  of  code  that  had  to  be  handled  was  how  to  communicate  between  the  SPI  interfaces  of  the  transceivers  and  the  USI‐SPI  interface  of  the  microcontroller.    Luckily,  Brennen  Ball  provides a very rudimentary library that implements some of the more important functions available to  the NRF24L01.  This library is rather sizable however, and when compiled on a microcontroller takes up  15x the size of a ATTiny2313’s flash memory.  To get around this, the library had to be first customized  to  all  the  pins  and  interrupts  of  the  ATTiny2313,  followed  by  being  stripped  of  all  unnecessary  functionality.    Because of this, both the microcontrollers end up using different versions of the library.  See Appendix B  Appendix C and Appendix D for this code.   

3.1.4 Receiver Specific Code  The code used on the receiver is very straightforward, especially after the USI‐>SPI and NRF24L01 code  is properly implemented and functioning.  It simply exploits the interrupt functionality of the NRF24L01  library to decide when to turn on and off different LEDs.  See Appendix E for this code. 

3.1.5 Transmitter Specific Code  The code used on the transmitter is much more complicated.  Since the transmitter needs to be able to  go into a low power mode, this code needs to properly manage all the devices attached to it and be  aware of what pins and components are actually active.  Also, this code needs to work directly off  interrupts instead of within the main while () loop.  This is because normally that while () loop is not  being executed.  Instead the CPU clock will typically be sleeping waiting for one of the magnetic switches  to trip an interrupt and wake the code back up.  The details for this code can be seen in Appendix F. 

 

 

17     

 

3.2 Work Structure  To  accomplish  this  project,  the  different  aspects  of  the  project  had  to  be  divided  among  group  members.    Since  all  parts  are  directly  related  to  one  another,  members  had  to  be  sure  to  share  any  complications encountered along the way.   

3.2.1 Incremental Design  During  each  step  of  the  design,  incremental  milestones  were  created  to  verify  that  no  errors  were  encountered within that subsection.  For example with the code testing, a list of 4 tests was created to  both ensure functionality and to debug or narrow down any possible problems.  • Interrupt Test  Interrupts are urgent to counter functionality as well as SPI functionality.  To make sure the  microcontroller’s fuses were set appropriately, code was placed inside of an interrupt service  routine.  The only way that this code could be executed would be if the ISR was properly being  called.  • Counter Test  The next test was to ensure that the timer was being properly utilized.  Since the USI‐>SPI code  was highly dependent upon timer overflow, this was urgent.  To test it, a timer was set to  perform something that would have normally happened within the main loop inside an interrupt  service routine instead.  • SPI Test  When first porting over the code from the AVR319 document, it had to be tested to make sure it  was  properly  transmitting  SPI  commands.    To  verify  this,  the  SPI  output  (MOSI  pin)  was  connected  to  the  SPI  input  (MISO  pin)  on  the  same  microcontroller.    When  a  command  was  written out the MOSI pin, there was verification in place to make sure it was properly read back  on the MISO pin.  • Debug SPI Commands  As a final test, using an oscilloscope, the commands were watched to make sure that they were  being properly transmitted.    By  following  this  organized  design,  testing,  and  verification  structure  we  have  been  able  to  identify  bottlenecks in the design before they actually became troublesome.  The exact same procedures have  been in use heavily for this design. 

 

 

18     

 

3.2.2 Electrical & Mechanical Drawing  Early in the development cycle, electrical drawings were produced.  As choices of components changed,  so have these schematics.  The most updated drawings are available in Appendix G.    A  mechanical  drawing  was  not  produced  until  the  very  last  step  in  the  development  process.   Mechanical  was  a  very  low  priority,  and  consequently  held  off  until  the  very  end.    The  mechanical  drawing is available in Appendix H. 

3.3 Resource Requirements  The  necessary  costs  for  all  the  parts  are  summarized  in  Table  1  and  Table  2.    The  spending  limit  was  $150, and the team is well within this limit. 

Part

Cost per item

Quantity

Total Cost (with Free Parts)

Total Cost (without Free Parts)

Battery (9V)

$4.00

1

$4.00

$4.00

Microcontroller

$1.79

2

$0

$3.58

RF Transceiver

$29.95

2

$59.90

$59.90

Photodetector

$0.25

9

$0

$2.25

IR LED

$0.30

3

$0

$0.90

Magnetic Switch

$3.50

2

$0

$7.00

20-Pin Retention Socket

$0.69

1

$0.69

$0.69

25 Pin D-Sub Connector Hood

$1.79

1

$1.79

$1.79

25 Pin D-Sub Connector

$1.89

1

$1.89

$1.89

PCB

$1.79

1

$1.79

$1.79

$70.06

$83.79

Total Table 1: Electrical Part Costs 

Part

Cost per item

Screws

Quantity

Total Cost

Provided

20

$0

$7.48 $8

1 1

$7.48 $8

Transmitter housing

$8

1

$8

Plexiglas

$6

1

$6

Power Cord

$5

1

$5

Mailbox Receiver housing

Total

$34.80 Table 2: Mechanical Part Costs 

 

  19     

 

3.4 Project Schedule  Throughout the project’s lifetime, the team has attempted to work as closely to the schedule as  possible.  During the first semester, it was followed very strictly with little deviation.  For second  semester, as the team got overwhelmed the schedule began to slip.  Thankfully, due to all group  members putting in extra time, it was recovered by the end.  See Appendix I for the schedules. 

4.0 Project Testing  For every step of the project, testing was essential to verifying project functionality and performance.   Incrementally testing each component and subsystem ensured an easy resolution.  After completing the  design, testing was used to determine which of the project’s functional and nonfunctional requirements  had been met. 

4.1 Transmission Test  A test had been developed for determining the maximum range of transmission.  The group attempted  to use the device at different ranges in order to find where it began to drop off.  By performing this test  earlier in the product’s design, the group discovered that the initial range was only ten feet.  This limitation was due to the on board ceramic antennas that were initially in use.  To solve the  problem, the group replaced these antennas with larger external antennas.  This increased the range to  approximately 50 feet. 

4.2 Logic Test  When the project was initially planned, the group made choices for how it should be performing,  interacting, and reacting.  This was all implemented in code throughout design.  After design was  complete, the group verified that each of these interactions worked correctly.  To make sure these were sensible; the group asked outside members how they would expect the project  to function.  Using input from possible clients, some of the behavior was adjusted. 

4.3 LED Intensity Test  To determine how accurate the device was, the intensity of the LEDs was varied.  As battery voltage  decreased, the possible intensity also decreased, and results recorded.  This allowed the group to determine the most ideal area to notify a user of a low battery and also  verified the requirement of being able to detect mail. 

 

 

20     

 

4.4 Battery Test  One of the requirements was that the end product would have a significant battery life.  Unfortunately,  the group didn’t have the time to verify exact numbers on battery life.  Instead, approximations were  made.  Using the average charge of 650 mAH for each one of the three AA batteries, approximately 2.5 months  of battery life was estimated.  The group took this a little further then, and came up with a list of items that could be done to improve  battery life:  • • • • •

Switching LED types  Optimized Code  Adding an external clock  Deeper sleep modes  Integrating more functionality into microcontroller 

4.5 Temperature Test  Another requirement was that the mailbox be able to withstand harsh conditions of Iowa winters and  summers.  To test the cold environment, the mailbox was brought outdoors during the winter.  To test  the hot environment, a blow dryer was used to heat up components.  Unfortunately, several of the semiconductors ended up being susceptible to temperature extremes on  either end.  To solve this, additional circuitry for temperature adjustment is needed. 

5.0 Future Work for Commercialization  The group conducted a usability study with an industrial engineering student.  Through this study, a  variety of items were found that should be done before this product is ready to be used by the general  public.  • • • • • • • • •

Directional high gain antennas  Rubber seals for the opening of the mailbox  Using set screws with o‐rings instead of Velcro to mount items  Using polycarbonate for the ceiling instead of cardboard  Build a custom flag with an embedded switch  Use a solid foam pad instead of Styrofoam to mount devices on the bottom  To avoid wire breakage, use notched plexiglass  Provide insulation for battery box  Create temperature hysteresis control system 

 

  21     

 

6.0 Closing Thoughts  During  extreme  hot  or  cold  seasons,  many  people,  especially  the  elderly,  are  scared  to  travel  to  their  mailbox multiple times to check for mail.  Rather than continuously fear encountering dangers on their  trip  to  and  from  the  mailbox,  it  is  much  easier  for  the  person  to  be  notified  that  there  is  mail  in  the  mailbox before making the journey outside.    The aim of this project is to create a product that will notify the user when an object has been placed in  the  mailbox.  Once  something  has  been  inserted  into  the  mailbox,  the  user  will  receive  an  alert  on  a  receiver located in the safety of their household.  They can then travel outside only when necessary, and  only have to make a single journey.  After the user obtains the item from the mailbox, the device resets  the receiver in the household, indicating the mailbox is now empty.    The product is easily implemented in an existing mailbox and is very easy to use.  An equal participation  is  required  among  the  team  members  to  guarantee  the  successful  completion  of  this  project.    With  plenty of design time, money to purchase components, and technical resources to improve the design,  an automated mailbox design has been developed.  The device transmits a signal back to the house to  let the user know the new status of the mailbox.  The device also interprets the status of the mail flag to  determine  if  the  user  is  attempting  to  send  a  letter.  The  automated  mailbox  is  a  simple,  low  cost  solution for alerting the user about received mail. 

 

 

22     

 

7.0 References  [1] Choosing a Microcontroller. 7 Feb. 2007 .  [2] Choosing a Microcontroller for Embedded System Applications. 7 Feb. 2007  .  [3] Clearwater Tech. "GE Security." Clearwater Tech. Clearwater Tech Industries. 7 Feb. 2007  .  [4] Fairchild Semiconductor. "Fairchild Semiconductor ‐ Site Search." Fairchild Semiconductor. 2006. 02  Feb. 2007  .  [5] Fairchild Semiconductor. "QEE113 Plastic Infarred Light Emmiting Diode." Fairchild Semiconductor.  30 Apr. 2002. 2 Feb. 2007  .  [6] Fairchild Semiconductor. "QSE773 Plastic Silicon Pin Photodiode." Fairchild Semiconductor. 2000.  Fairchild Semiconductor Corporation. 03 Feb. 2007  .  [7] Freescale. "MC33493 Product Summary Page." Freescale. Freescale Semiconductor Industries. 27  Jan. 2007 .  [8] Freescale. "MC33592 Product Summary Page." Freescale. Freescale Semiconductor Industries. 7 Feb.  2007 .  [9] Hewes, John. "Light Emmiting Diodes." The Electronics Club. 2007. 25 Jan. 2007  .  [10] How to choose a MicroController. 7 Feb. 2007  .  [11] How to choose a Microcontroller for a wireless senior Electrical and Computer Engineering Design  Project . 7 Feb. 2007  .  [12] Paschotta, Rüdiger. "Encyclopedia of Laser Physics and Technology ‐ Photodetectors." RP Photonics.  11 Nov. 2006. 25 Jan. 2007 

23     

  [13] Real Elliot, The. Weblog entry. 16 Nov. 2006. Ghetto Programming: Getting started with AVR  microprocessors on the cheap. 7 Feb. 2007  .  [14] Refikh, M. "How to Build Your Own Wireless Receiver and Transmitter Device." E‐DSP. 11 Mar.  2006. 25 Jan. 2007 < http://www.e‐dsp.com/how‐to‐build‐your‐own‐wireless‐receiver‐and‐ transmitter‐device‐create‐rf‐in‐your‐embedded‐application/>.  [15] SmartHome. "Basic Sensor of Alarm System." SmartHome. SmartHome Industries. 7 Feb. 2007  .  [16] Pin Interrupts. 14 November 2007   

 

[17] .d90 file format. 14 November 2007   

 

[18] Interrupt syntax for different C compilers. 14 November 2007   

 

[19] Using the USI Module for SPI Communication. 14 November 2007   

 

[20] diyembedded.com. 14 November 2007   

 

 

 

24     

 

8.0 Appendices  8.1 Appendix A: USI‐SPI Code  // This file has been prepared for Doxygen automatic documentation generation. /*! \file ******************************************************************** * * Atmel Corporation * * \li File: spi_via_usi_driver.c * \li Compiler: IAR EWAAVR 3.10c * \li Support mail: [email protected] * * \li Supported devices: All devices with Universal Serial Interface (USI) * capabilities can be used. * The example is written for ATmega169. * * \li AppNote: AVR319 - Using the USI module for SPI communication. * * \li Description: Example on how to use the USI module for communicating * with SPI compatible devices. The functions and variables * prefixed 'spiX_' can be renamed to be able to use several * spi drivers (using different interfaces) with similar names. * Some basic SPI knowledge is assumed. * * $Revision: 1.4 $ * $Date: Monday, September 13, 2004 12:08:54 UTC $ ****************************************************************************/ #include #include

/* USI port and pin definitions. */ #define USI_OUT_REG PORTB #define USI_IN_REG PINB #define USI_DIR_REG DDRB #define USI_CLOCK_PIN PB7 #define USI_DATAIN_PIN PB5 #define USI_DATAOUT_PIN PB6

//!< USI port output register. //!< USI port input register. //!< USI port direction register. //!< USI clock I/O pin. //!< USI data input pin. //!< USI data output pin.

/* Speed configuration: * Bits per second = CPUSPEED / PRESCALER / (COMPAREVALUE+1) / 2. * Maximum = CPUSPEED / 64. */ #define TC0_PRESCALER_VALUE 256 //!< Must be 1, 8, 64, 256 or 1024. #define TC0_COMPARE_VALUE 1 //!< Must be 0 to 255. Minimum 31 with prescaler CLK/1.

/* Prescaler value converted to bit settings. */ #if TC0_PRESCALER_VALUE == 1 #define TC0_PS_SETTING (1<
25     

  #endif

/*! \brief Data input register buffer. * * Incoming bytes are stored in this byte until the next transfer is complete. * This byte can be used the same way as the SPI data register in the native * SPI module, which means that the byte must be read before the next transfer * completes and overwrites the current value. */ unsigned char storedUSIDR;

/*! \brief Driver status bit structure. * * This struct contains status flags for the driver. * The flags have the same meaning as the corresponding status flags * for the native SPI module. The flags should not be changed by the user. * The driver takes care of updating the flags when required. */ struct usidriverStatus_t { unsigned char masterMode : 1; //!< True if in master mode. unsigned char transferComplete : 1; //!< True when transfer completed. unsigned char writeCollision : 1; //!< True if put attempted during transfer. }; volatile struct usidriverStatus_t spiX_status; //!< The driver status bits.

/*! \brief Timer/Counter 0 Compare Match Interrupt handler. * * This interrupt handler is only enabled when transferring data * in master mode. It toggles the USI clock pin, i.e. two interrupts * results in one clock period on the clock pin and for the USI counter. */ ISR(TIMER0_COMPA_vect) { USICR |= (1<
/*! \brief USI Timer Overflow Interrupt handler. * * This handler disables the compare match interrupt if in master mode. * When the USI counter overflows, a byte has been transferred, and we * have to stop the timer tick. * For all modes the USIDR contents are stored and flags are updated. */ ISR(USI_OVERFLOW_vect) { // Master must now disable the compare match interrupt // to prevent more USI counter clocks. if( spiX_status.masterMode == 1 ) { TIMSK &= ~(1<
/*! \brief

Initialize USI as SPI master.

26     

  * * This function sets up all pin directions and module configurations. * Use this function initially or when changing from slave to master mode. * Note that the stored USIDR value is cleared. * * \param spi_mode Required SPI mode, must be 0 or 1. */ void spiX_initmaster( char spi_mode ) { // Configure port directions. USI_DIR_REG |= (1<
/*! \brief Initialize USI as SPI slave. * * This function sets up all pin directions and module configurations. * Use this function initially or when changing from master to slave mode. * Note that the stored USIDR value is cleared. * * \param spi_mode Required SPI mode, must be 0 or 1. */ void spiX_initslave( char spi_mode ) { // Configure port directions. USI_DIR_REG |= (1<
/*! * * * * *

\brief

Put one byte on bus.

Use this function like you would write to the SPDR register in the native SPI module. Calling this function in master mode starts a transfer, while in slave mode, a byte will be prepared for the next transfer initiated by the master device. If a transfer is in progress, this function will set the write collision flag

27     

  * and return without altering the data registers. * * \returns 0 if a write collision occurred, 1 otherwise. */ char spiX_put( unsigned char val ) { // Check if transmission in progress, // i.e. USI counter unequal to zero. if( (USISR & 0x0F) != 0 ) { // Indicate write collision and return. spiX_status.writeCollision = 1; return; } // Reinit flags. spiX_status.transferComplete = 0; spiX_status.writeCollision = 0; // Put data in USI data register. USIDR = val; // Master should now enable compare match interrupts. if( spiX_status.masterMode == 1 ) { TIFR |= (1<
/*! \brief Get one byte from bus. * * This function only returns the previous stored USIDR value. * The transfer complete flag is not checked. Use this function * like you would read from the SPDR register in the native SPI module. */ unsigned char spiX_get() { return storedUSIDR; }

/*! \brief Wait for transfer to complete. * * This function waits until the transfer complete flag is set. * Use this function like you would wait for the native SPI interrupt flag. */ void spiX_wait() { do {} while( spiX_status.transferComplete == 0 ); }

// end of file

   

 

28     

 

8.2 Appendix B: Common NRF24LO1 Code  /***************************************************************************** * * File: spi1.h * * Copyright S. Brennen Ball, 2006-2007 * Mario Limonciello, 2007 * * The author provides no guarantees, warantees, or promises, implied or * otherwise. By using this software you agree to indemnify the author * of any damages incurred by using it. * *****************************************************************************/ #ifndef _SPI_H_ #define _SPI_H_ #include #ifndef #define #endif #ifndef #define #endif #ifndef #define #endif

bool bool unsigned char false false 0 true true !false

unsigned char spi1_send_read_byte(unsigned char byte); #endif //_SPI_H_   /****************************************************************************** * * File: nrf24l01.h * * Copyright S. Brennen Ball, 2006-2007 * Mario Limonciello, 2007 * * The author provides no guarantees, warantees, or promises, implied or * otherwise. By using this software you agree to indemnify the author * of any damages incurred by using it. * *****************************************************************************/ #ifndef NRF24L01_H_ #define NRF24L01_H_ #include #ifndef #define #endif #ifndef #define #endif #ifndef #define #endif

bool bool unsigned char false false 0 true true !false

///////////////////////////////////////////////////////////////////////////////// // SPI function requirements // // The user must define a function to send one byte of data and also return the // resulting byte of data data through the SPI port. The function used here // has the function prototype //

29     

  // unsigned char spi_send_read_byte(unsigned char byte); // // This function should take the argument unsigned char byte and send it through // the SPI port to the 24L01. Then, it should wait until the 24L01 has returned // its response over SPI. This received byte should be the return value of the // function. // // You should also change the include file name below to whatever the name of your // SPI include file is. ////////////////////////////////////////////////////////////////////////////////// #include "spi1.h" #define spi_send_read_byte(byte) spi1_send_read_byte(byte)

///////////////////////////////////////////////////////////////////////////////// // Delay function requirements // // The user must define a function that delays for the specified number of // microseconds. This function needs to be as precise as possible, and the use // of a timer module within your microcontroller is highly recommended. The // function used here has the prototype // // void delay_us(unsigned int microseconds); // // You should also change the include file name below to whatever the name of your // delay include file is. ////////////////////////////////////////////////////////////////////////////////// #define F_CPU 100000UL // Sets up the default speed for delay.h #include #define delay_us(microseconds) _delay_us(microseconds)

////////////////////////////////////////////////////////////////////////////////// // IO pin definitions // // Below you will find several definitions and includes. The first is an #include // for your microcontroller's include file to allow you to use register names // rather than numbers. The next three are to allow you to control the pins on // the 24L01 that aren't automatically handled by SPI. These are CE, CSN, and // IRQ. // // The general format of these defines is a define for the IO register the pin is // attached to. The second define is a mask for the pin. For example, say that // your CE pin is tied to an IO port with the register name IOPORT1. Also, let's // say that the IO port is 8-bits wide, and you have attached the pin to pin 0 of // the port. Then your define would look like this: // // #define nrf24l01_CE_IOREGISTER IOPORT1 // #define nrf24l01_CE_PINMASK 0x01 // // If you have defines in your include file for individual IO pins, you could use // this define in this file, as well. Using the previous example, assume that in // your microcontroller's include file, pin 0 of IOPORT1 has a define like this // // #define IOPORT1_PIN0 0x01 // // Then, you could make your defines for the CE pin in this file look like this: // // #define nrf24l01_CE_IOREGISTER IOPORT1 // #define nrf24l01_CE_PINMASK IOPORT1_PIN0 // // You should also change the include file name below to whatever the name of your // processor's register definition include file is. ///////////////////////////////////////////////////////////////////////////////////// #include #include //defines for uC pins CE pin is connected to //This is used so that the routines can send TX payload data and // properly initialize the nrf24l01 in TX and RX states. //Change these definitions (and then recompile) to suit your particular application.

30     

 

//pb3 on attiny2313 #define nrf24l01_CE_IOREGISTER #define nrf24l01_CE_PINMASK

PORTB _BV(PB3)

//defines for uC pins CSN pin is connected to //This is used so that the routines can send properly operate the SPI interface // on the nrf24l01. //Change these definitions (and then recompile) to suit your particular application. //Pb4 on attiny2313 #define nrf24l01_CSN_IOREGISTER #define nrf24l01_CSN_PINMASK

PORTB _BV(PB4)

//defines for uC pins IRQ pin is connected to //This is used so that the routines can poll for IRQ or create an ISR. //Change these definitions (and then recompile) to suit your particular application. #define nrf24l01_IRQ_IOREGISTER PINB #define nrf24l01_IRQ_PINMASK _BV(PB2)

//////////////////////////////////////////////////////////////////////////////////// // SPI commands // // The following are defines for all of the commands and data masks on the SPI // interface. //////////////////////////////////////////////////////////////////////////////////// //SPI command defines #define nrf24l01_R_REGISTER 0x00 #define nrf24l01_W_REGISTER 0x20 #define nrf24l01_R_RX_PAYLOAD 0x61 #define nrf24l01_W_TX_PAYLOAD 0xA0 #define nrf24l01_FLUSH_TX 0xE1 #define nrf24l01_FLUSH_RX 0xE2 #define nrf24l01_REUSE_TX_PL 0xE3 #define nrf24l01_NOP 0xFF //SPI command data mask defines #define nrf24l01_R_REGISTER_DATA #define nrf24l01_W_REGISTER_DATA

0x1F 0x1F

//////////////////////////////////////////////////////////////////////////////////// // Register definitions // // Below are the defines for each register's address in the 24L01. //////////////////////////////////////////////////////////////////////////////////// #define nrf24l01_CONFIG 0x00 #define nrf24l01_EN_AA 0x01 #define nrf24l01_EN_RXADDR 0x02 #define nrf24l01_SETUP_AW 0x03 #define nrf24l01_SETUP_RETR 0x04 #define nrf24l01_RF_CH 0x05 #define nrf24l01_RF_SETUP 0x06 #define nrf24l01_STATUS 0x07 #define nrf24l01_OBSERVE_TX 0x08 #define nrf24l01_CD 0x09 #define nrf24l01_RX_ADDR_P0 0x0A #define nrf24l01_RX_ADDR_P1 0x0B #define nrf24l01_RX_ADDR_P2 0x0C #define nrf24l01_RX_ADDR_P3 0x0D #define nrf24l01_RX_ADDR_P4 0x0E #define nrf24l01_RX_ADDR_P5 0x0F #define nrf24l01_TX_ADDR 0x10 #define nrf24l01_RX_PW_P0 0x11 #define nrf24l01_RX_PW_P1 0x12 #define nrf24l01_RX_PW_P2 0x13 #define nrf24l01_RX_PW_P3 0x14 #define nrf24l01_RX_PW_P4 0x15 #define nrf24l01_RX_PW_P5 0x16 #define nrf24l01_FIFO_STATUS 0x17

31     

  //////////////////////////////////////////////////////////////////////////////////// // Default register values // // Below are the defines for each register's default value in the 24L01. Multi-byte // registers use notation B, where "B" represents "byte" and is the byte // number. //////////////////////////////////////////////////////////////////////////////////// #define nrf24l01_CONFIG_DEFAULT_VAL 0x08 #define nrf24l01_EN_AA_DEFAULT_VAL 0x3F #define nrf24l01_EN_RXADDR_DEFAULT_VAL 0x03 #define nrf24l01_SETUP_AW_DEFAULT_VAL 0x03 #define nrf24l01_SETUP_RETR_DEFAULT_VAL 0x03 #define nrf24l01_RF_CH_DEFAULT_VAL 0x02 #define nrf24l01_RF_SETUP_DEFAULT_VAL 0x0F #define nrf24l01_STATUS_DEFAULT_VAL 0x0E #define nrf24l01_OBSERVE_TX_DEFAULT_VAL 0x00 #define nrf24l01_CD_DEFAULT_VAL 0x00 #define nrf24l01_RX_ADDR_P0_B0_DEFAULT_VAL 0xE7 #define nrf24l01_RX_ADDR_P0_B1_DEFAULT_VAL 0xE7 #define nrf24l01_RX_ADDR_P0_B2_DEFAULT_VAL 0xE7 #define nrf24l01_RX_ADDR_P0_B3_DEFAULT_VAL 0xE7 #define nrf24l01_RX_ADDR_P0_B4_DEFAULT_VAL 0xE7 #define nrf24l01_RX_ADDR_P1_B0_DEFAULT_VAL 0xC2 #define nrf24l01_RX_ADDR_P1_B1_DEFAULT_VAL 0xC2 #define nrf24l01_RX_ADDR_P1_B2_DEFAULT_VAL 0xC2 #define nrf24l01_RX_ADDR_P1_B3_DEFAULT_VAL 0xC2 #define nrf24l01_RX_ADDR_P1_B4_DEFAULT_VAL 0xC2 #define nrf24l01_RX_ADDR_P2_DEFAULT_VAL 0xC3 #define nrf24l01_RX_ADDR_P3_DEFAULT_VAL 0xC4 #define nrf24l01_RX_ADDR_P4_DEFAULT_VAL 0xC5 #define nrf24l01_RX_ADDR_P5_DEFAULT_VAL 0xC6 #define nrf24l01_TX_ADDR_B0_DEFAULT_VAL 0xE7 #define nrf24l01_TX_ADDR_B1_DEFAULT_VAL 0xE7 #define nrf24l01_TX_ADDR_B2_DEFAULT_VAL 0xE7 #define nrf24l01_TX_ADDR_B3_DEFAULT_VAL 0xE7 #define nrf24l01_TX_ADDR_B4_DEFAULT_VAL 0xE7 #define nrf24l01_RX_PW_P0_DEFAULT_VAL 0x00 #define nrf24l01_RX_PW_P1_DEFAULT_VAL 0x00 #define nrf24l01_RX_PW_P2_DEFAULT_VAL 0x00 #define nrf24l01_RX_PW_P3_DEFAULT_VAL 0x00 #define nrf24l01_RX_PW_P4_DEFAULT_VAL 0x00 #define nrf24l01_RX_PW_P5_DEFAULT_VAL 0x00 #define nrf24l01_FIFO_STATUS_DEFAULT_VAL 0x11 //////////////////////////////////////////////////////////////////////////////////// // Register bitwise definitions // // Below are the defines for each register's bitwise fields in the 24L01. //////////////////////////////////////////////////////////////////////////////////// //CONFIG register bitwise definitions #define nrf24l01_CONFIG_RESERVED 0x80 #define nrf24l01_CONFIG_MASK_RX_DR 0x40 #define nrf24l01_CONFIG_MASK_TX_DS 0x20 #define nrf24l01_CONFIG_MASK_MAX_RT 0x10 #define nrf24l01_CONFIG_EN_CRC 0x08 #define nrf24l01_CONFIG_CRCO 0x04 #define nrf24l01_CONFIG_PWR_UP 0x02 #define nrf24l01_CONFIG_PRIM_RX 0x01 //EN_AA #define #define #define #define #define #define #define #define #define

register bitwise definitions nrf24l01_EN_AA_RESERVED 0xC0 nrf24l01_EN_AA_ENAA_ALL 0x3F nrf24l01_EN_AA_ENAA_P5 0x20 nrf24l01_EN_AA_ENAA_P4 0x10 nrf24l01_EN_AA_ENAA_P3 0x08 nrf24l01_EN_AA_ENAA_P2 0x04 nrf24l01_EN_AA_ENAA_P1 0x02 nrf24l01_EN_AA_ENAA_P0 0x01 nrf24l01_EN_AA_ENAA_NONE 0x00

//EN_RXADDR register bitwise definitions

32     

  #define #define #define #define #define #define #define #define #define

nrf24l01_EN_RXADDR_RESERVED nrf24l01_EN_RXADDR_ERX_ALL nrf24l01_EN_RXADDR_ERX_P5 nrf24l01_EN_RXADDR_ERX_P4 nrf24l01_EN_RXADDR_ERX_P3 nrf24l01_EN_RXADDR_ERX_P2 nrf24l01_EN_RXADDR_ERX_P1 nrf24l01_EN_RXADDR_ERX_P0 nrf24l01_EN_RXADDR_ERX_NONE

0xC0 0x3F 0x20 0x10 0x08 0x04 0x02 0x01 0x00

//SETUP_AW register bitwise definitions #define nrf24l01_SETUP_AW_RESERVED 0xFC #define nrf24l01_SETUP_AW 0x03 #define nrf24l01_SETUP_AW_5BYTES 0x03 #define nrf24l01_SETUP_AW_4BYTES 0x02 #define nrf24l01_SETUP_AW_3BYTES 0x01 #define nrf24l01_SETUP_AW_ILLEGAL 0x00 //SETUP_RETR register bitwise definitions #define nrf24l01_SETUP_RETR_ARD 0xF0 #define nrf24l01_SETUP_RETR_ARD_4000 0xF0 #define nrf24l01_SETUP_RETR_ARD_3750 0xE0 #define nrf24l01_SETUP_RETR_ARD_3500 0xD0 #define nrf24l01_SETUP_RETR_ARD_3250 0xC0 #define nrf24l01_SETUP_RETR_ARD_3000 0xB0 #define nrf24l01_SETUP_RETR_ARD_2750 0xA0 #define nrf24l01_SETUP_RETR_ARD_2500 0x90 #define nrf24l01_SETUP_RETR_ARD_2250 0x80 #define nrf24l01_SETUP_RETR_ARD_2000 0x70 #define nrf24l01_SETUP_RETR_ARD_1750 0x60 #define nrf24l01_SETUP_RETR_ARD_1500 0x50 #define nrf24l01_SETUP_RETR_ARD_1250 0x40 #define nrf24l01_SETUP_RETR_ARD_1000 0x30 #define nrf24l01_SETUP_RETR_ARD_750 0x20 #define nrf24l01_SETUP_RETR_ARD_500 0x10 #define nrf24l01_SETUP_RETR_ARD_250 0x00 #define nrf24l01_SETUP_RETR_ARC 0x0F #define nrf24l01_SETUP_RETR_ARC_15 0x0F #define nrf24l01_SETUP_RETR_ARC_14 0x0E #define nrf24l01_SETUP_RETR_ARC_13 0x0D #define nrf24l01_SETUP_RETR_ARC_12 0x0C #define nrf24l01_SETUP_RETR_ARC_11 0x0B #define nrf24l01_SETUP_RETR_ARC_10 0x0A #define nrf24l01_SETUP_RETR_ARC_9 0x09 #define nrf24l01_SETUP_RETR_ARC_8 0x08 #define nrf24l01_SETUP_RETR_ARC_7 0x07 #define nrf24l01_SETUP_RETR_ARC_6 0x06 #define nrf24l01_SETUP_RETR_ARC_5 0x05 #define nrf24l01_SETUP_RETR_ARC_4 0x04 #define nrf24l01_SETUP_RETR_ARC_3 0x03 #define nrf24l01_SETUP_RETR_ARC_2 0x02 #define nrf24l01_SETUP_RETR_ARC_1 0x01 #define nrf24l01_SETUP_RETR_ARC_0 0x00 //RF_CH register bitwise definitions #define nrf24l01_RF_CH_RESERVED 0x80 //RF_SETUP register bitwise definitions #define nrf24l01_RF_SETUP_RESERVED 0xE0 #define nrf24l01_RF_SETUP_PLL_LOCK 0x10 #define nrf24l01_RF_SETUP_RF_DR 0x08 #define nrf24l01_RF_SETUP_RF_PWR 0x06 #define nrf24l01_RF_SETUP_RF_PWR_0 0x06 #define nrf24l01_RF_SETUP_RF_PWR_6 0x04 #define nrf24l01_RF_SETUP_RF_PWR_12 0x02 #define nrf24l01_RF_SETUP_RF_PWR_18 0x00 #define nrf24l01_RF_SETUP_LNA_HCURR 0x01 //STATUS register bitwise definitions #define nrf24l01_STATUS_RESERVED #define nrf24l01_STATUS_RX_DR

33     

0x80 0x40

  #define #define #define #define #define #define #define #define #define #define #define #define

nrf24l01_STATUS_TX_DS nrf24l01_STATUS_MAX_RT nrf24l01_STATUS_RX_P_NO nrf24l01_STATUS_RX_P_NO_RX_FIFO_NOT_EMPTY nrf24l01_STATUS_RX_P_NO_UNUSED nrf24l01_STATUS_RX_P_NO_5 nrf24l01_STATUS_RX_P_NO_4 nrf24l01_STATUS_RX_P_NO_3 nrf24l01_STATUS_RX_P_NO_2 nrf24l01_STATUS_RX_P_NO_1 nrf24l01_STATUS_RX_P_NO_0 nrf24l01_STATUS_TX_FULL

0x20 0x10 0x0E 0x0E 0x0C 0x0A 0x08 0x06 0x04 0x02 0x00 0x01

//OBSERVE_TX register bitwise definitions #define nrf24l01_OBSERVE_TX_PLOS_CNT 0xF0 #define nrf24l01_OBSERVE_TX_ARC_CNT 0x0F //CD register bitwise definitions #define nrf24l01_CD_RESERVED 0xFE #define nrf24l01_CD_CD 0x01 //RX_PW_P0 register bitwise definitions #define nrf24l01_RX_PW_P0_RESERVED 0xC0 //RX_PW_P0 register bitwise definitions #define nrf24l01_RX_PW_P0_RESERVED 0xC0 //RX_PW_P1 register bitwise definitions #define nrf24l01_RX_PW_P1_RESERVED 0xC0 //RX_PW_P2 register bitwise definitions #define nrf24l01_RX_PW_P2_RESERVED 0xC0 //RX_PW_P3 register bitwise definitions #define nrf24l01_RX_PW_P3_RESERVED 0xC0 //RX_PW_P4 register bitwise definitions #define nrf24l01_RX_PW_P4_RESERVED 0xC0 //RX_PW_P5 register bitwise definitions #define nrf24l01_RX_PW_P5_RESERVED 0xC0 //FIFO_STATUS register bitwise definitions #define nrf24l01_FIFO_STATUS_RESERVED 0x8C #define nrf24l01_FIFO_STATUS_TX_REUSE 0x40 #define nrf24l01_FIFO_STATUS_TX_FULL 0x20 #define nrf24l01_FIFO_STATUS_TX_EMPTY 0x10 #define nrf24l01_FIFO_STATUS_RX_FULL 0x02 #define nrf24l01_FIFO_STATUS_RX_EMPTY 0x01 //////////////////////////////////////////////////////////////////////////////////// // Function declarations // // Below are all function definitions contained in the library. Please see // nrf24l01.c for comments regarding the usage of each function. //////////////////////////////////////////////////////////////////////////////////// //initialization functions void nrf24l01_initialize(unsigned char config, unsigned char opt_rx_standby_mode, unsigned char en_aa, unsigned char en_rxaddr, unsigned char setup_aw, unsigned char setup_retr, unsigned char rf_ch, unsigned char rf_setup, unsigned char * rx_addr_p0, unsigned char * rx_addr_p1, unsigned char rx_addr_p2, unsigned char rx_addr_p3, unsigned char rx_addr_p4, unsigned char rx_addr_p5,

34     

  unsigned char * tx_addr, unsigned char rx_pw_p0, unsigned char rx_pw_p1, unsigned char rx_pw_p2, unsigned char rx_pw_p3, unsigned char rx_pw_p4, unsigned char rx_pw_p5); void nrf24l01_initialize_debug(bool rx, unsigned char p0_payload_width, bool enable_auto_ack); void nrf24l01_initialize_debug_lite(bool rx, unsigned char p0_payload_width); //power-up, power-down functions void nrf24l01_power_up(bool rx_active_mode); void nrf24l01_power_up_param(bool rx_active_mode, unsigned char config); void nrf24l01_power_down(); void nrf24l01_power_down_param(unsigned char config); //SPI commands defined by the spec //for regnumber values, see section above titled "register definitions" //all functions return the STATUS register unsigned char nrf24l01_write_register(unsigned char regnumber, unsigned char * data, unsigned int len); unsigned char nrf24l01_read_register(unsigned char regnumber, unsigned char * data, unsigned int len); unsigned char nrf24l01_write_tx_payload(unsigned char * data, unsigned int len, bool transmit); unsigned char nrf24l01_read_rx_payload(unsigned char * data, unsigned int len); unsigned char nrf24l01_flush_tx(); unsigned char nrf24l01_flush_rx(); unsigned char nrf24l01_reuse_tx_pl(); unsigned char nrf24l01_nop(); //RX/TX setting functions void nrf24l01_set_as_rx(bool rx_active_mode); void nrf24l01_set_as_rx_param(bool rx_active_mode, unsigned char config); void nrf24l01_rx_standby_to_active(); void nrf24l01_rx_active_to_standby(); void nrf24l01_set_as_tx(); void nrf24l01_set_as_tx_param(unsigned char config); //register-oriented get/set functions for commonly-used registers during operation unsigned char nrf24l01_get_config(); void nrf24l01_set_config(unsigned char config); unsigned char nrf24l01_get_rf_ch(); void nrf24l01_set_rf_ch(unsigned char channel); unsigned char nrf24l01_get_status(); unsigned char nrf24l01_get_observe_tx(); void nrf24l01_set_rx_addr(unsigned char * address, unsigned int len, unsigned char rxpipenum); void nrf24l01_set_tx_addr(unsigned char * address, unsigned int len); void nrf24l01_set_rx_pw(unsigned char payloadwidth, unsigned char rxpipenum); unsigned char nrf24l01_get_rx_pw(unsigned char rxpipenum); unsigned char nrf24l01_get_fifo_status(); //auto-ack and pipe-related functions bool nrf24l01_aa_enabled(unsigned char rxpipenum); void nrf24l01_aa_enable(unsigned char rxpipenum); void nrf24l01_aa_disable(unsigned char rxpipenum); bool nrf24l01_rx_pipe_enabled(unsigned char rxpipenum); void nrf24l01_rx_pipe_enable(unsigned char rxpipenum); void nrf24l01_rx_pipe_disable(unsigned char rxpipenum); unsigned char nrf24l01_get_plos_cnt(); void nrf24l01_clear_plos_cnt(); void nrf24l01_clear_plos_cnt_param(unsigned char rf_ch); unsigned char nrf24l01_get_arc_cnt(); //utility functions bool nrf24l01_cd_active(); void nrf24l01_clear_flush(); unsigned char nrf24l01_get_rx_pipe(); unsigned char nrf24l01_get_rx_pipe_from_status(unsigned char status); void nrf24l01_get_all_registers(unsigned char * data); //interrupt check/clear functions

35     

  bool bool bool bool void void void void

nrf24l01_irq_pin_active(); nrf24l01_irq_rx_dr_active(); nrf24l01_irq_tx_ds_active(); nrf24l01_irq_max_rt_active(); nrf24l01_irq_clear_all(); nrf24l01_irq_clear_rx_dr(); nrf24l01_irq_clear_tx_ds(); nrf24l01_irq_clear_max_rt();

//FIFO_STATUS check functions bool nrf24l01_fifo_tx_reuse(); bool nrf24l01_fifo_tx_full(); bool nrf24l01_fifo_tx_empty(); bool nrf24l01_fifo_rx_full(); bool nrf24l01_fifo_rx_empty(); //IO void void void void void bool bool

interface-related functions nrf24l01_transmit(); nrf24l01_clear_ce(); nrf24l01_set_ce(); nrf24l01_clear_csn(); nrf24l01_set_csn(); nrf24l01_ce_pin_active(); nrf24l01_csn_pin_active();

//low-level functions for library use only unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata); void nrf24l01_spi_send_read(unsigned char * data, unsigned int len, bool copydata); #endif /*NRF24L01_H_*/

   

 

36     

 

8.3 Appendix C: Transmitter NRF24L01 Code  /****************************************************************************** * * File: nrf24l01.c * * Copyright S. Brennen Ball, 2006-2007 * Mario Limonciello, 2007 * * The author provides no guarantees, warantees, or promises, implied or * otherwise. By using this software you agree to indemnify the author * of any damages incurred by using it. * *****************************************************************************/ #include "nrf24l01.h" //initializes only the CONFIG register and pipe 0's payload width //the primary purpose of this function is to allow users with microcontrollers with // extremely small program memories to still be able to init their 24L01. This code // should have a smaller footprint than the above init functions. //when using this method, the 24L01 MUST have its default configuration loaded // in all registers to work. It is recommended that the device be reset or // have its power cycled immediately before this code is run. //in normal circumstances, the user should use nrf24l01_initialize() rather than this // function, since this function does not set all of the register values. void nrf24l01_initialize_debug_lite(bool rx, unsigned char p0_payload_width) { unsigned char config; config = nrf24l01_CONFIG_DEFAULT_VAL; if(rx != false) config |= nrf24l01_CONFIG_PRIM_RX; nrf24l01_write_register(nrf24l01_RX_PW_P0, &p0_payload_width, 1); nrf24l01_power_up_param(true, config); } //powers up the 24L01 with all necessary delays //this function takes the existing contents of the CONFIG register and sets the PWR_UP //the argument rx_active_mode is only used if the user is setting up the // 24L01 as a receiver. If the argument is false, the receiver will remain in // standby mode and not monitor for packets. If the argument is true, the CE // pin will be set and the 24L01 will monitor for packets. In TX mode, the value // of this argument is insignificant. //note: if the read value of the CONFIG register already has the PWR_UP bit set, this function // exits in order to not make an unecessary register write. void nrf24l01_power_up(bool rx_active_mode) { unsigned char config; nrf24l01_read_register(nrf24l01_CONFIG, &config, 1); if((config & nrf24l01_CONFIG_PWR_UP) != 0) return; config |= nrf24l01_CONFIG_PWR_UP; nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); delay_us(1500); if((config & nrf24l01_CONFIG_PRIM_RX) == 0) nrf24l01_clear_ce(); else { if(rx_active_mode != false) nrf24l01_set_ce(); else nrf24l01_clear_ce();

37     

  } } //powers up the 24L01 with all necessary delays //this function allows the user to set the contents of the CONFIG register, but the function // sets the PWR_UP bit in the CONFIG register, so the user does not need to. //the argument rx_active_mode is only used if the user is setting up the // 24L01 as a receiver. If the argument is false, the receiver will remain in // standby mode and not monitor for packets. If the argument is true, the CE // pin will be set and the 24L01 will monitor for packets. In TX mode, the value // of this argument is insignificant. void nrf24l01_power_up_param(bool rx_active_mode, unsigned char config) { unsigned char test, test2; config |= nrf24l01_CONFIG_PWR_UP; nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); delay_us(1500); if((config & nrf24l01_CONFIG_PRIM_RX) == 0) nrf24l01_clear_ce(); else { if(rx_active_mode != false) nrf24l01_set_ce(); else nrf24l01_clear_ce(); } } //powers down the 24L01 //this function takes the existing contents of the CONFIG register and simply // clears the PWR_UP bit in the CONFIG register. //note: if the read value of the CONFIG register already has the PWR_UP bit cleared, this // function exits in order to not make an unecessary register write. void nrf24l01_power_down() { unsigned char config; nrf24l01_read_register(nrf24l01_CONFIG, &config, 1); if((config & nrf24l01_CONFIG_PWR_UP) == 0) return; config &= (~nrf24l01_CONFIG_PWR_UP); nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); nrf24l01_clear_ce(); } //powers down the 24L01 //this function allows the user to set the contents of the CONFIG register, but the function // clears the PWR_UP bit in the CONFIG register, so the user does not need to. void nrf24l01_power_down_param(unsigned char config) { config &= (~nrf24l01_CONFIG_PWR_UP); nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); nrf24l01_clear_ce(); }

//sets up the 24L01 as a transmitter //this function takes the existing contents of the CONFIG register and simply // clears the PRIM_RX bit in the CONFIG register. //note: if the read value of the CONFIG register already has the PRIM_RX bit cleared, this

38     

  // function exits in order to not make an unecessary register write. void nrf24l01_set_as_tx() { unsigned char config; nrf24l01_read_register(nrf24l01_CONFIG, &config, 1); if((config & nrf24l01_CONFIG_PRIM_RX) == 0) return; config &= (~nrf24l01_CONFIG_PRIM_RX); nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); nrf24l01_clear_ce(); } //sets up the 24L01 as a transmitter //this function allows the user to set the contents of the CONFIG register, but the function // clears the PRIM_RX bit in the CONFIG register, so the user does not need to. void nrf24l01_set_as_tx_param(unsigned char config) { config &= ~(nrf24l01_CONFIG_PRIM_RX); if((config & nrf24l01_CONFIG_PWR_UP) != 0) nrf24l01_power_up_param(false, config); else nrf24l01_power_down_param(config); } //executes the W_REGISTER SPI operation //unsigned char regnumber indicates the register number assigned by the nrf24l01 specification. // For regnumber values, see section titled "register definitions" in nrf24l01.h. //unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1, // and TX_ADDR. The size of data should be set according to the user-specified size of the address // length for the register the address is being sent to. //unsigned int len is always the size of unsigned char * data. For example, if data is declared as // data[6], len should equal 6. //returns the value of the STATUS register unsigned char nrf24l01_write_register(unsigned char regnumber, unsigned char * data, unsigned int len) { return nrf24l01_execute_command(nrf24l01_W_REGISTER | (regnumber & nrf24l01_W_REGISTER_DATA), data, len, false); } //executes the R_REGISTER SPI operation //unsigned char regnumber indicates the register number assigned by the nrf24l01 specification. // For regnumber values, see section titled "register definitions" in nrf24l01.h. //unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1, // and TX_ADDR. The size of data should be set according to the user-specified size of the address // length for the register the address is being read from. //unsigned int len is always the size of unsigned char * data. For example, if data is declared as // data[6], len = 6. //returns the value of the STATUS register unsigned char nrf24l01_read_register(unsigned char regnumber, unsigned char * data, unsigned int len) { return nrf24l01_execute_command(regnumber & nrf24l01_R_REGISTER_DATA, data, len, true); } //executes the W_TX_PAYLOAD operation //unsigned char * data is the actual payload to be sent to the nrf24l01. //unsigned int len is the length of the payload being sent (this should be sized // according to the payload length specified by the receiving nrf24l01).

39     

  //if bool transmit is true, the nrf24l01 immediately transmits the data in the payload. // if false, the user must use the nrf24l01_transmit() function to send the payload. //returns the value of the STATUS register unsigned char nrf24l01_write_tx_payload(unsigned char * data, unsigned int len, bool transmit) { unsigned char status; status = nrf24l01_execute_command(nrf24l01_W_TX_PAYLOAD, data, len, false); if(transmit == true) nrf24l01_transmit(); return status; } //executes the FLUSH_TX SPI operation //this funciton empties the contents of the TX FIFO //returns the value of the STATUS register unsigned char nrf24l01_flush_tx() { return nrf24l01_execute_command(nrf24l01_FLUSH_TX, NULL, 0, true); } //executes the REUSE_TX_PL SPI operation //this funciton allows the user to constantly send a packet repeatedly when issued. //returns the value of the STATUS register unsigned char nrf24l01_reuse_tx_pl() { return nrf24l01_execute_command(nrf24l01_REUSE_TX_PL, NULL, 0, true); } //executes the FLUSH_TX SPI operation //this funciton does nothing //returns the value of the STATUS register unsigned char nrf24l01_nop() { return nrf24l01_execute_command(nrf24l01_NOP, NULL, 0, true); } //transmits the current tx payload void nrf24l01_transmit() { nrf24l01_set_ce(); delay_us(10); nrf24l01_clear_ce(); } //clears the pin on the host microcontroller that is attached to the 24l01's CE pin void nrf24l01_clear_ce() { nrf24l01_CE_IOREGISTER &= ~nrf24l01_CE_PINMASK; } //sets the pin on the host microcontroller that is attached to the 24l01's CE pin void nrf24l01_set_ce() { nrf24l01_CE_IOREGISTER |= nrf24l01_CE_PINMASK; } //returns true if CE is high, false if not bool nrf24l01_ce_pin_active() { if((nrf24l01_CE_IOREGISTER & nrf24l01_CE_PINMASK) != 0) return true; else return false; } //sets the pin on the host microcontroller that is attached to the 24l01's CSN pin void nrf24l01_clear_csn() {

40     

  nrf24l01_CSN_IOREGISTER &= ~nrf24l01_CSN_PINMASK; } //clears the pin on the host microcontroller that is attached to the 24l01's CSN pin void nrf24l01_set_csn() { nrf24l01_CSN_IOREGISTER |= nrf24l01_CSN_PINMASK; } //returns true if CSN is high, false if not bool nrf24l01_csn_pin_active() { if((nrf24l01_CSN_IOREGISTER & nrf24l01_CSN_PINMASK) != 0) return true; else return false; } //sets the TX address in the TX_ADDR register //unsigned char * address is the actual address to be used. It should be sized // according to the tx_addr length specified to the nrf24l01. //unsigned int len is the length of the address. Its value should be specified // according to the tx_addr length specified to the nrf24l01. void nrf24l01_set_tx_addr(unsigned char * address, unsigned int len) { nrf24l01_write_register(nrf24l01_TX_ADDR, address, len); } //returns the value of the CONFIG register unsigned char nrf24l01_get_config() { unsigned char data; nrf24l01_read_register(nrf24l01_CONFIG, &data, 1); return data; } //sets the value of the CONFIG register void nrf24l01_set_config(unsigned char config) { nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); } //unsigned char channel is the channel to be changed to. void nrf24l01_set_rf_ch(unsigned char channel) { unsigned char data; data = channel & ~nrf24l01_RF_CH_RESERVED; nrf24l01_write_register(nrf24l01_RF_CH, &data, 1); } //clears the PLOS_CNT field of the OBSERVE_TX register //this function makes a read of the current value of RF_CH and // simply writes it back to the register, clearing PLOS_CNT void nrf24l01_clear_plos_cnt() { unsigned char data; nrf24l01_read_register(nrf24l01_RF_CH, &data, 1); nrf24l01_write_register(nrf24l01_RF_CH, &data, 1); } //returns the status of the CD register (true if carrier detect [CD] is // active, false if not) bool nrf24l01_cd_active() { unsigned char data;

41     

  nrf24l01_read_register(nrf24l01_CD, &data, 1); return data; } //return the value of the status register unsigned char nrf24l01_get_status() { return nrf24l01_nop(); } //returns true if TX_REUSE bit in FIFO_STATUS register is set, false otherwise bool nrf24l01_fifo_tx_reuse() { unsigned char data; nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1); return (bool)(data & nrf24l01_FIFO_STATUS_TX_REUSE); } //returns true if TX_FULL bit in FIFO_STATUS register is set, false otherwise bool nrf24l01_fifo_tx_full() { unsigned char data; nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1); return (bool)(data & nrf24l01_FIFO_STATUS_TX_FULL); } //returns true if TX_EMPTY bit in FIFO_STATUS register is set, false otherwise bool nrf24l01_fifo_tx_empty() { unsigned char data; nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1); return (bool)(data & nrf24l01_FIFO_STATUS_TX_EMPTY); } //returns true if IRQ pin is low, false otherwise bool nrf24l01_irq_pin_active() { if((nrf24l01_IRQ_IOREGISTER & nrf24l01_IRQ_PINMASK) != 0) return false; else return true; } //returns true if TX_DS interrupt is active, false otherwise bool nrf24l01_irq_tx_ds_active() { return (nrf24l01_get_status() & nrf24l01_STATUS_TX_DS); } //returns true if MAX_RT interrupt is active, false otherwise bool nrf24l01_irq_max_rt_active() { return (nrf24l01_get_status() & nrf24l01_STATUS_MAX_RT); } //clear all interrupts in the status register void nrf24l01_irq_clear_all() { unsigned char data = nrf24l01_STATUS_RX_DR | nrf24l01_STATUS_TX_DS | nrf24l01_STATUS_MAX_RT; nrf24l01_write_register(nrf24l01_STATUS, &data, 1); } //clears only the TX_DS interrupt

42     

  void nrf24l01_irq_clear_tx_ds() { unsigned char data = nrf24l01_STATUS_TX_DS; nrf24l01_write_register(nrf24l01_STATUS, &data, 1); } //clears only the MAX_RT interrupt void nrf24l01_irq_clear_max_rt() { unsigned char data = nrf24l01_STATUS_MAX_RT; nrf24l01_write_register(nrf24l01_STATUS, &data, 1); } //flush both fifos and clear interrupts void nrf24l01_clear_flush() { nrf24l01_flush_tx(); nrf24l01_irq_clear_all(); } //low-level spi send function for library use //the user should not call this function directly, but rather use one of the 8 SPI data instructions unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata) { unsigned char status; nrf24l01_clear_csn(); status = instruction; nrf24l01_spi_send_read(&status, 1, true); nrf24l01_spi_send_read(data, len, copydata); nrf24l01_set_csn(); return status; } //low-level spi send function for library use //the user should not call this function directly, but rather use one of the 8 SPI data instructions void nrf24l01_spi_send_read(unsigned char * data, unsigned int len, bool copydata) { unsigned int count; unsigned char tempbyte; for(count = 0; count < len; count++) { if(copydata != false) data[count] = spi_send_read_byte(data[count]); else { tempbyte = data[count]; spi_send_read_byte(tempbyte); } } }

 

 

43     

 

8.4 Appendix D: Receiver NR424L01 Code  /****************************************************************************** * * File: nrf24l01.c * * Copyright S. Brennen Ball, 2006-2007 * * The author provides no guarantees, warantees, or promises, implied or * otherwise. By using this software you agree to indemnify the author * of any damages incurred by using it. * *****************************************************************************/ #include "nrf24l01.h" //initializes only the CONFIG register and pipe 0's payload width //the primary purpose of this function is to allow users with microcontrollers with // extremely small program memories to still be able to init their 24L01. This code // should have a smaller footprint than the above init functions. //when using this method, the 24L01 MUST have its default configuration loaded // in all registers to work. It is recommended that the device be reset or // have its power cycled immediately before this code is run. //in normal circumstances, the user should use nrf24l01_initialize() rather than this // function, since this function does not set all of the register values. void nrf24l01_initialize_debug_lite(bool rx, unsigned char p0_payload_width) { unsigned char config; config = nrf24l01_CONFIG_DEFAULT_VAL; if(rx != false) config |= nrf24l01_CONFIG_PRIM_RX; nrf24l01_write_register(nrf24l01_RX_PW_P0, &p0_payload_width, 1); nrf24l01_power_up_param(true, config); } //powers up the 24L01 with all necessary delays //this function takes the existing contents of the CONFIG register and sets the PWR_UP //the argument rx_active_mode is only used if the user is setting up the // 24L01 as a receiver. If the argument is false, the receiver will remain in // standby mode and not monitor for packets. If the argument is true, the CE // pin will be set and the 24L01 will monitor for packets. In TX mode, the value // of this argument is insignificant. //note: if the read value of the CONFIG register already has the PWR_UP bit set, this function // exits in order to not make an unecessary register write. void nrf24l01_power_up(bool rx_active_mode) { unsigned char config; nrf24l01_read_register(nrf24l01_CONFIG, &config, 1); if((config & nrf24l01_CONFIG_PWR_UP) != 0) return; config |= nrf24l01_CONFIG_PWR_UP; nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); delay_us(1500); if((config & nrf24l01_CONFIG_PRIM_RX) == 0) nrf24l01_clear_ce(); else { if(rx_active_mode != false) nrf24l01_set_ce(); else nrf24l01_clear_ce(); }

44     

  } //powers up the 24L01 with all necessary delays //this function allows the user to set the contents of the CONFIG register, but the function // sets the PWR_UP bit in the CONFIG register, so the user does not need to. //the argument rx_active_mode is only used if the user is setting up the // 24L01 as a receiver. If the argument is false, the receiver will remain in // standby mode and not monitor for packets. If the argument is true, the CE // pin will be set and the 24L01 will monitor for packets. In TX mode, the value // of this argument is insignificant. void nrf24l01_power_up_param(bool rx_active_mode, unsigned char config) { unsigned char test, test2; config |= nrf24l01_CONFIG_PWR_UP; nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); delay_us(1500); if((config & nrf24l01_CONFIG_PRIM_RX) == 0) nrf24l01_clear_ce(); else { if(rx_active_mode != false) nrf24l01_set_ce(); else nrf24l01_clear_ce(); } } //powers down the 24L01 //this function takes the existing contents of the CONFIG register and simply // clears the PWR_UP bit in the CONFIG register. //note: if the read value of the CONFIG register already has the PWR_UP bit cleared, this // function exits in order to not make an unecessary register write. void nrf24l01_power_down() { unsigned char config; nrf24l01_read_register(nrf24l01_CONFIG, &config, 1); if((config & nrf24l01_CONFIG_PWR_UP) == 0) return; config &= (~nrf24l01_CONFIG_PWR_UP); nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); nrf24l01_clear_ce(); } //powers down the 24L01 //this function allows the user to set the contents of the CONFIG register, but the function // clears the PWR_UP bit in the CONFIG register, so the user does not need to. void nrf24l01_power_down_param(unsigned char config) { config &= (~nrf24l01_CONFIG_PWR_UP); nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); nrf24l01_clear_ce(); } //takes a 24L01 that is already in RX standby mode and puts it in active RX mode void nrf24l01_rx_standby_to_active() { nrf24l01_set_ce(); } //takes a 24L01 that is already in active RX mode and puts it in RX standy mode

45     

  void nrf24l01_rx_active_to_standby() { nrf24l01_clear_ce(); } //executes the W_REGISTER SPI operation //unsigned char regnumber indicates the register number assigned by the nrf24l01 specification. // For regnumber values, see section titled "register definitions" in nrf24l01.h. //unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1, // and TX_ADDR. The size of data should be set according to the user-specified size of the address // length for the register the address is being sent to. //unsigned int len is always the size of unsigned char * data. For example, if data is declared as // data[6], len should equal 6. //returns the value of the STATUS register unsigned char nrf24l01_write_register(unsigned char regnumber, unsigned char * data, unsigned int len) { return nrf24l01_execute_command(nrf24l01_W_REGISTER | (regnumber & nrf24l01_W_REGISTER_DATA), data, len, false); } //executes the R_REGISTER SPI operation //unsigned char regnumber indicates the register number assigned by the nrf24l01 specification. // For regnumber values, see section titled "register definitions" in nrf24l01.h. //unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1, // and TX_ADDR. The size of data should be set according to the user-specified size of the address // length for the register the address is being read from. //unsigned int len is always the size of unsigned char * data. For example, if data is declared as // data[6], len = 6. //returns the value of the STATUS register unsigned char nrf24l01_read_register(unsigned char regnumber, unsigned char * data, unsigned int len) { return nrf24l01_execute_command(regnumber & nrf24l01_R_REGISTER_DATA, data, len, true); } //executes the R_RX_PAYLOAD instruction //unsigned char * data is the actual payload that has been received by the nrf24l01. // The user must size data according to the payload width specified to the nrf24l01. // This variable is filled by this function, so individual byte values need not be // initialized by the user. //unsigned int len is the length of the payload being clocked out of the nrf24l01 (this // should be sized according to the payload length specified to the nrf24l01). //returns the value of the STATUS register unsigned char nrf24l01_read_rx_payload(unsigned char * data, unsigned int len) { unsigned char status; nrf24l01_clear_ce(); status = nrf24l01_execute_command(nrf24l01_R_RX_PAYLOAD, data, len, true); nrf24l01_set_ce(); return status; } //executes the FLUSH_TX SPI operation //this funciton does nothing //returns the value of the STATUS register unsigned char nrf24l01_nop() { return nrf24l01_execute_command(nrf24l01_NOP, NULL, 0, true); } //executes the FLUSH_RX SPI operation //this funciton empties the contents of the RX FIFO

46     

  //returns the value of the STATUS register unsigned char nrf24l01_flush_rx() { return nrf24l01_execute_command(nrf24l01_FLUSH_RX, NULL, 0, true); } //clears the pin on the host microcontroller that is attached to the 24l01's CE pin void nrf24l01_clear_ce() { nrf24l01_CE_IOREGISTER &= ~nrf24l01_CE_PINMASK; } //sets the pin on the host microcontroller that is attached to the 24l01's CE pin void nrf24l01_set_ce() { nrf24l01_CE_IOREGISTER |= nrf24l01_CE_PINMASK; } //returns true if CE is high, false if not bool nrf24l01_ce_pin_active() { if((nrf24l01_CE_IOREGISTER & nrf24l01_CE_PINMASK) != 0) return true; else return false; } //sets the pin on the host microcontroller that is attached to the 24l01's CSN pin void nrf24l01_clear_csn() { nrf24l01_CSN_IOREGISTER &= ~nrf24l01_CSN_PINMASK; } //clears the pin on the host microcontroller that is attached to the 24l01's CSN pin void nrf24l01_set_csn() { nrf24l01_CSN_IOREGISTER |= nrf24l01_CSN_PINMASK; } //returns true if CSN is high, false if not bool nrf24l01_csn_pin_active() { if((nrf24l01_CSN_IOREGISTER & nrf24l01_CSN_PINMASK) != 0) return true; else return false; } //sets the RX address in the RX_ADDR register that is offset by rxpipenum //unsigned char * address is the actual address to be used. It should be sized // according to the rx_addr length that is being filled. //unsigned int len is the length of the address. Its value should be specified // according to the rx_addr length specified to the nrf24l01. //unsigned char rxpipenum is the pipe number (zero to five) whose address is being // specified. If an invalid address (greater than five) is supplied, the function // does nothing. void nrf24l01_set_rx_addr(unsigned char * address, unsigned int len, unsigned char rxpipenum) { if(rxpipenum > 5) return; nrf24l01_write_register(nrf24l01_RX_ADDR_P0 + rxpipenum, address, len); } //sets the RX payload width on the pipe offset by rxpipenum //unsigned char payloadwidth is the length of the payload for the pipe referenced in // rxpipenum. It must be less than or equal to 32. If an invalid payload width is // specified, the function does nothing. //unsigned char rxpipenum is the pipe number (zero to five) whose address is being // specified. If an invalid address (greater than five) is supplied, the function // does nothing.

47     

  void nrf24l01_set_rx_pw(unsigned char payloadwidth, unsigned char rxpipenum) { if((rxpipenum > 5) || (payloadwidth > 32)) return; nrf24l01_write_register(nrf24l01_RX_PW_P0 + rxpipenum, &payloadwidth, 1); } //gets the RX payload width on the pipe offset by rxpipenum //unsigned char rxpipenum is the pipe number (zero to five) whose address is being // specified. If an invalid address (greater than five) is supplied, the function // does nothing. unsigned char nrf24l01_get_rx_pw(unsigned char rxpipenum) { unsigned char data; if((rxpipenum > 5)) return; nrf24l01_read_register(nrf24l01_RX_PW_P0 + rxpipenum, &data, 1); return data; } //returns the value of the CONFIG register unsigned char nrf24l01_get_config() { unsigned char data; nrf24l01_read_register(nrf24l01_CONFIG, &data, 1); return data; } //sets the value of the CONFIG register void nrf24l01_set_config(unsigned char config) { nrf24l01_write_register(nrf24l01_CONFIG, &config, 1); } //returns the current RF channel in RF_CH register unsigned char nrf24l01_get_rf_ch() { unsigned char data; nrf24l01_read_register(nrf24l01_RF_CH, &data, 1); return data; } //unsigned char channel is the channel to be changed to. void nrf24l01_set_rf_ch(unsigned char channel) { unsigned char data; data = channel & ~nrf24l01_RF_CH_RESERVED; nrf24l01_write_register(nrf24l01_RF_CH, &data, 1); } //returns the current PLOS_CNT value in OBSERVE_TX register unsigned char nrf24l01_get_plos_cnt() { unsigned char data; nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1); return ((data & nrf24l01_OBSERVE_TX_PLOS_CNT) >> 4); } //clears the PLOS_CNT field of the OBSERVE_TX register

48     

  //this function makes a read of the current value of RF_CH and // simply writes it back to the register, clearing PLOS_CNT void nrf24l01_clear_plos_cnt() { unsigned char data; nrf24l01_read_register(nrf24l01_RF_CH, &data, 1); nrf24l01_write_register(nrf24l01_RF_CH, &data, 1); } //clears the PLOS_CNT field of the OBSERVE_TX register //this function allows the user to set the RF_CH register by using // the argument in the function during the PLOS_CNT clearing process void nrf24l01_clear_plos_cnt_param(unsigned char rf_ch) { nrf24l01_write_register(nrf24l01_RF_CH, &rf_ch, 1); } //returns the current ARC_CNT value in OBSERVE_TX register unsigned char nrf24l01_get_arc_cnt() { unsigned char data; nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1); return (data & nrf24l01_OBSERVE_TX_ARC_CNT); } //returns the status of the CD register (true if carrier detect [CD] is // active, false if not) bool nrf24l01_cd_active() { unsigned char data; nrf24l01_read_register(nrf24l01_CD, &data, 1); return data; } //return the value of the status register unsigned char nrf24l01_get_status() { return nrf24l01_nop(); } //returns true if RX_FULL bit in FIFO_STATUS register is set, false otherwise bool nrf24l01_fifo_rx_full() { unsigned char data; nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1); return (bool)(data & nrf24l01_FIFO_STATUS_RX_FULL); } //returns true if RX_EMPTYE bit in FIFO_STATUS register is set, false otherwise bool nrf24l01_fifo_rx_empty() { unsigned char data; nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1); return (bool)(data & nrf24l01_FIFO_STATUS_RX_EMPTY); } //returns true if IRQ pin is low, false otherwise bool nrf24l01_irq_pin_active() { if((nrf24l01_IRQ_IOREGISTER & nrf24l01_IRQ_PINMASK) != 0) return false; else

49     

  return true; } //returns true if RX_DR interrupt is active, false otherwise bool nrf24l01_irq_rx_dr_active() { return (nrf24l01_get_status() & nrf24l01_STATUS_RX_DR); } //returns true if MAX_RT interrupt is active, false otherwise bool nrf24l01_irq_max_rt_active() { return (nrf24l01_get_status() & nrf24l01_STATUS_MAX_RT); } //clear all interrupts in the status register void nrf24l01_irq_clear_all() { unsigned char data = nrf24l01_STATUS_RX_DR | nrf24l01_STATUS_TX_DS | nrf24l01_STATUS_MAX_RT; nrf24l01_write_register(nrf24l01_STATUS, &data, 1); } //clears only the RX_DR interrupt void nrf24l01_irq_clear_rx_dr() { unsigned char data = nrf24l01_STATUS_RX_DR; nrf24l01_write_register(nrf24l01_STATUS, &data, 1); } //clears only the MAX_RT interrupt void nrf24l01_irq_clear_max_rt() { unsigned char data = nrf24l01_STATUS_MAX_RT; nrf24l01_write_register(nrf24l01_STATUS, &data, 1); } //returns the current pipe in the 24L01's STATUS register unsigned char nrf24l01_get_rx_pipe() { return nrf24l01_get_rx_pipe_from_status(nrf24l01_get_status()); } unsigned char nrf24l01_get_rx_pipe_from_status(unsigned char status) { return ((status & 0xE) >> 1); } //flush both fifos and clear interrupts void nrf24l01_clear_flush() { nrf24l01_flush_rx(); nrf24l01_irq_clear_all(); } //low-level spi send function for library use //the user should not call this function directly, but rather use one of the 8 SPI data instructions unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata) { unsigned char status; nrf24l01_clear_csn(); status = instruction; nrf24l01_spi_send_read(&status, 1, true); nrf24l01_spi_send_read(data, len, copydata);

50     

  nrf24l01_set_csn(); return status; } //low-level spi send function for library use //the user should not call this function directly, but rather use one of the 8 SPI data instructions void nrf24l01_spi_send_read(unsigned char * data, unsigned int len, bool copydata) { unsigned int count; unsigned char tempbyte; for(count = 0; count < len; count++) { if(copydata != false) data[count] = spi_send_read_byte(data[count]); else { tempbyte = data[count]; spi_send_read_byte(tempbyte); } } }

   

 

51     

 

8.5 Appendix E: Transmitter Main Code  /****************************************************************************** * * DEC0701: Automated Mailbox * Transmitter Code * File: main.c * * Copyright S. Mario Limonciello, 2007 * * The author provides no guarantees, warantees, or promises, implied or * otherwise. By using this software you agree to indemnify the author * of any damages incurred by using it. * *****************************************************************************/ #include #include #define F_CPU 100000UL #include #include

// Defines pins, ports, etc to make programs easier to read // Sets up the default speed for delay.h //power management functionality

//basic nomenclature: //Setting up a DDRX register: //When setting particular bits high, those become output.

Setting low makes them inputs

//Output on a PORTX pin: //If the DDRX register is set high, setting a pin high causes output //Sample on leading rising edge, setup on trailing falling edge #define SPIMODE 0 void void void void void

check_and_send(void); SetupInterrupts(void); InitLED(void); InitSPI(void); PowerManage(void);

static unsigned char data; int main() { /* initialized to 0x10 to send once when starting */ data = 0x10; /* Disable unnecessary parts for better power management */ PowerManage(); /* Prepare interrupts for SPI and edge detection */ SetupInterrupts(); /* SPI Driver Initialization */ spiX_initmaster(SPIMODE); //makes us master SPI device DDRB |= _BV(PB4) | _BV(PB3); //setup CSN,CE for output /* enable port D's GPIO for output on the IR LEDS */ DDRD= _BV(PD0) | _BV(PD5); while(1) { //If we have been interrupted, do stuff if (data & 0x10) check_and_send(); } return(0); } ISR(INT0_vect) { data |= 0x10;

52     

  } ISR_ALIAS(INT1_vect,INT0_vect); void check_and_send(void) { //Turn on the Voltage regulator PORTD |= _BV(PD0) | _BV(PD5);

//wait for 6 seconds before running this to make sure the door //is fully closed if it was opened _delay_ms(6000); //only do the processing if the mailbox is closed if (!(PIND & _BV(PD2))) { /* Turn on the transmitter */ nrf24l01_power_up(); //wait for 6 seconds before running this to make sure the //transmitter is powered up _delay_ms(6000); /* initialize our mirf v2 for tx */ nrf24l01_initialize_debug_lite(0, 1); //check what the current flag status is. //only do the IR led stuff if its down if (!(PIND & _BV(PD3))) { if (PIND & _BV(PD1)) data |= 0x01; //item else data &= ~(0x01); //no item } else { data &= ~(0x01); //no item } //always check for battery and transmit this if (PIND & _BV(PD4)) data |= 0x02; //low battery else data &= ~(0x02); //no low battery //flush the TX fifo in case we have a failed transmission from before nrf24l01_flush_tx(); //send payload _delay_us(130); //wait for the other 24L01 to come from standby to RX nrf24l01_write_tx_payload(&data, 1, 1); //wait for payload to be sent while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()) && !nrf24l01_irq_max_rt_active()); nrf24l01_irq_clear_all(); //clear interrupts again //Turn off the transmitter nrf24l01_power_down(); } //don't run again until we get another interrupt data &= ~(0x10); //Turn off voltage regulator _delay_ms(1000); PORTD &= ~_BV(PD0) & ~_BV(PD5); //go into sleep mode

53     

  sleep_mode(); } void SetupInterrupts(void) { //Door Switch (Triggers when switch goes high->low) PCMSK |= _BV(PIND2); // tell pin change mask to listen to pd2 MCUCR |= _BV(ISC01); // interrupt on INT0 pin falling edge (sensor triggered) GIMSK |= _BV(INT0); // enable PCINT interrupt in the general interrupt mask //Flag Switch (Triggers PCMSK |= _BV(PIND3); // MCUCR |= _BV(ISC10); // GIMSK |= _BV(INT1); // sei();

when switch changes) tell pin change mask to listen to pd3 interrupt on INT1 pin any edge (sensor triggered) enable PCINT interrupt in the general interrupt mask

//turns on interrupts generally

} void PowerManage(void) { //Disable analog comparator ACSR |= (1<
   

 

54     

 

8.6 Appendix F: Receiver Main Code  /****************************************************************************** * * DEC0701: Automated Mailbox * Receiver Code * File: main.c * * Copyright S. Mario Limonciello, 2007 * * The author provides no guarantees, warantees, or promises, implied or * otherwise. By using this software you agree to indemnify the author * of any damages incurred by using it. * *****************************************************************************/

#include #include #define F_CPU 100000UL #include

// Defines pins, ports, etc to make programs easier to read // Sets up the default speed for delay.h

//basic nomenclature: //Setting up a DDRX register: //When setting particular bits high, those become output.

Setting low makes them inputs

//Output on a PORTX pin: //If the DDRX register is set high, setting a pin high causes output //Sample on leading rising edge, setup on trailing falling edge #define SPIMODE 0 int main() { unsigned char data = 0x00; /* SPI Initialization */ spiX_initmaster(SPIMODE); //makes us master SPI device sei(); //turns on interrupts for SPI DDRB |= _BV(PB4) | _BV(PB3); //setup CSN,CE for output //initialize our mirf v2 for rx nrf24l01_initialize_debug_lite(1, 1); //setup LEDs //enable port D's GPIOs for output on the LEDS DDRD= _BV(PD4) | _BV(PD5); //debugging LED. Turns on while we receive data. DDRD |= _BV(PD0); //

SetupInterrupts(); while(1) { //turn off debugging LED PORTD &= ~_BV(PD0); //wait until a packet has been received while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active())); //once we get an interrupt: //debug code to make sure that we are actually receiving //We will flash as data is received _delay_ms(500); if (PORTD & _BV(PD0)) PORTD &= ~_BV(PD0); else PORTD |= _BV(PD0);

55     

  nrf24l01_read_rx_payload(&data, 1); //read the packet into data nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01 nrf24l01_flush_rx();//clear the FIFO in case we had any data sitting _delay_us(130); //wait for the other 24L01 to come from standby to RX //got mail //turn on PD4 if (data & 0x01) PORTD |= _BV(PD4); //turn off PD4 else PORTD &= ~_BV(PD4); //low battery //turn on PD5 if (data & 0x02) PORTD |= _BV(PD5); //turn off PD5 else PORTD &= ~_BV(PD5); } return(0); } unsigned char spi1_send_read_byte(unsigned char byte) { //do SPI stuff spiX_put(byte); spiX_wait(); return spiX_get(); }

56     

 

8.7 Appendix G: Schematics  8.7.1 Transmitter 

  57     

 

8.7.2 Receiver 

58     

 

8 Appendix H: Mechanical Drawings  8.8  

  Figure 7: Color Mailbox diagram 

59     

 

  Figure 8: Mailbox Diagram 

60     

   

  Figure 9: Styrofoam Mount 

  Figure 10: Plexiglass 

   

  61     

 

8 Appendix I: Project Schedu 8.9 ules  T The dates for the  four major milesstones were as fo ollows: 

Plaanning

Feb. 2 27, 2007 D Design

May 2, 2007 Implementtation & Testing

Dec. 3, 2007 Docum mentation

Dec. 1 12, 2007  

62     

 

Automated Mailbox – Dec07‐01

Automated Mailbox detects mail, the user's in-home receiver provides a notification that the mailbox is not empty. ..... "Basic Sensor of Alarm System.

987KB Sizes 3 Downloads 54 Views

Recommend Documents

Automated Mailbox
Hitachi primarily because Atmel is less feature filled then the other microcontrollers. The Intel and .... //see "Photodiode Test Diagram.png" for hookup information.

3dcards-illustrated-mailbox-msl212.pdf
Sign in. Loading… Whoops! There was a problem loading more pages. Retrying... Whoops! There was a problem previewing this document. Retrying.

'Stellar Mailbox Extractor for Exchange Server' by Stellar Data ...
Mar 10, 2017 - Converts Exchange database (EDB file) to Outlook data (PST) files ... Now recover deleted files from hard disk drive and similar storage devices ...

Automated
programmedhomeprofitsandprogrammedblogeasybucksnet1499501310645.pdf. programmedhomeprofitsandprogrammedblogeasybucksnet1499501310645.

AB-12 Designing a Mailbox Memory for Two 80C31 Microcontroll.pdf
AB-12 Designing a Mailbox Memory for Two 80C31 Microcontroll.pdf. AB-12 Designing a Mailbox Memory for Two 80C31 Microcontroll.pdf. Open. Extract.

mailbox love letter - teach me genealogy-type fields.pdf
There was a problem loading more pages. Retrying... Whoops! There was a problem previewing this document. Retrying... Download. Connect more apps... Try one of the apps below to open or edit this item. mailbox love letter - teach me genealogy-type fi

2018-01 FMP - Cluster Mailbox Maintenance ...
RECORD OF ACTION OF THE BOARD OF DIRECTORS. OF. FAIRWAY MEADOWS ... associated with their individually locking mailboxes. BE IT FURTHER ...

automated diagnosis
case of failures to the braking system). Most of the de- vices and systems nowadays have sophisticated electronic control and need control/diagnostic software (the evolu- tions of cars is paradigmatic but other domains such as the aerospace one are e

Connect to a second exchange mailbox in Outlook 2010.pdf ...
Connect to a second exchange mailbox in Outlook 2010.pdf. Connect to a second exchange mailbox in Outlook 2010.pdf. Open. Extract. Open with. Sign In.

automated reasoning
as programming language and as logical language [20, 43]. .... logic programming language. ..... In M D Agostino, D Gabbay, R Haehnle, and J Posegga, editors ...

Automated Tag Clustering.pdf
the tag clouds or the popular pages. We claim that account- ing for tag clusters by, for example, showing five semantically. more cohesive tag clouds is much ...

NNC Services Buyer Journey and Automated Marketing ...
NNC Services Buyer Journey and Automated Marketing Presentation_sept 2015.pdf. NNC Services Buyer Journey and Automated Marketing Presentation_sept ...

Automated Online News Content Extraction
These days, finding and browsing news is one of the most important internet activities. In this paper, a ... are being created and made available on the Web at a breath taking speed. .... Without RSS, users will have to check the site daily for new.

Guillaume Couillard/ Business Automated Systems ...
Program Operator terminates your affiliate status, or if your account is inactive in any continuous twelve month period. An affiliate may terminate this agreement at any time, and for any reason, by writing to - or emailing - the Program Operator at