Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This IoT Code Guidebook is a supplement the IoT Project Guidebook.
During the summer of 2022, we will be updating the code documentation for our IoT project to match the new IoT kit.
Expect frequent updates to this documentation!
This guidebook contains a series of IoT code tutorials to help you get familiar with using your IoT electronics kit to build smart devices and program apps for them.
In addition, this guidebook contains coding references to help show and explain how to create a device app and web app that interact with each other through the internet. There are also references that show and explain how to connect specific inputs and outputs to your device and how to add code in your device app to control the inputs and outputs.
Finally, this guidebook also contains links to external resources, such as an online code editor (web IDE) for creating your device app, programming language references, and additional experiments for learning how to use your IoT kit.
Be sure to check out the recommended prerequisite knowledge that will help ensure students are successful with the IoT code tutorials and IoT project.
HOW TO COPY CODE: When using these coding tutorials and references, you can copy a code block by clicking the copy icon displayed in the upper-right corner of the code block.
This guidebook is tailored for an IoT electronics kit called the SparkFun Inventor's Kit for Photon, which will simply be referred to as the Photon kit.
SparkFun sells a variety of other sensors and outputs that can be used with the Photon kit. If possible, it is highly recommended to add an ultrasonic sensor to the kit for more design possibilities.
NOTE: Your instructor may have provided you with a different IoT electronics kit. If your IoT kit uses Arduino, then you can still use this guidebook to help get familiar with using your IoT kit to build smart devices and program apps for them. The Photon kit is programmed using a language called Wiring that is nearly identical to Arduino. In addition, the Photon circuit board is similar to an Arduino circuit board (though there are a few differences).
FYI: This IoT code tutorial focuses on coding web apps (using JavaScript) that interact with a Photon device. However, it is also possible to code native mobile apps for iOS and Android (using Objective-C, Swift, or Java) that interact with a Photon device.
Copyright © 2016-2021 Michael Frontz and Jim Lyst, Indiana University School of Informatics and Computing at IUPUI
This material is part of the Computing by Design high school computer science curriculum developed for the Informatics Diversity-Enhanced Workforce (iDEW) program, an award-winning community partnership in central Indiana that is broadening student participation in computing and helping students develop the skills essential for success in the 21st century workplace. The iDEW program is managed by the Indiana University School of Informatics and Computing at IUPUI.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. You are free to use, share, or adapt this material for noncommercial purposes as long as you provide proper attribution and distribute any copies or adaptations under this same license.
GOAL: Identify the other components in your Photon kit and their purposes (inputs, outputs, connectors, and cables)
TASK: Review the information below, and then complete this assignment by finding each component in your Photon kit & identifying its name and function.
Your Photon kit includes these physical inputs, which can be connected to your circuit board:
Push Buttons – detects if button is being pushed (kit has red, yellow, green & blue buttons)
Trimpot Dial – detects position of dial (can be turned clockwise or counter-clockwise)
Motion Sensor – detects if something is moving in nearby environment
Magnetic Switch – detects if something is open or closed (such as door, window, etc.)
Photocell (Light Sensor) – measures amount of light in environment
Humidity & Temperature Sensor – measures relative humidity & temperature of air
Soil Moisture Sensor – measures amount of moisture in soil (or similar material)
Accelerometer – measures acceleration or tilt in 3 dimensions; can also detect taps or bumps
The following is not a standard part of the Photon kit, but your teacher may have added it:
Ultrasonic Sensor – measures distance to nearest object
Your Photon kit includes these physical outputs, which can be connected to your circuit board:
LED Lights – produces light (kit has red, yellow, green & blue LED lights)
Speaker – produces sound (tone) at any frequency from 20Hz to 20kHz
Servo Motor – rotates to any angle from 0° to ~180°
Micro OLED Display – displays text and simple graphics in monochrome
Your Photon kit includes these components to help connect inputs and outputs to your circuit board:
Breadboard – provides additional pins to help connect and power your inputs and outputs
Jumper Wires – help connect inputs and outputs to pins on breadboard and circuit board
Resistors – help limit electric current for certain inputs or outputs (such as LED lights, etc.)
Your Photon kit will include one or more cables to provide power to your circuit board:
USB to Micro-USB Cable – powers circuit board by connecting to USB port or charger
9V to Barrel Jack Adapter – powers circuit board by connecting to 9V battery
Only one power source (Micro-USB or Barrel Jack) needs to be connected.
USB to Barrel Jack: SparkFun sells a USB to Barrel Jack Adapter cable which is a great alternative to the cables included in the kit. This cable connects a USB port (computer, charger, etc.) to the barrel jack. If using this cable, the Photon's VIN pin will supply ~5 volts.
The product page for the SparkFun Inventor's Kit for Photon provides links to details about each part included in the kit. (Click the "Includes" tab on the product page to see the links to the parts.)
In this second tutorial, you'll program a "Hello World" app for your IoT device.
The goals of this second tutorial are to help you:
Verify your Photon device connects to Wi-Fi and the Particle Cloud service
Understand how to use Particle Build to create Photon device apps
Create a Hello World app to learn how to program your Photon device
When learning a new programming language, the first step that many people take is to create what is called a "Hello World" program. Traditionally, this program simply displays the text "Hello World" on the screen and only requires a few lines of code. The purpose is to demonstrate that you can create a simple yet functional program in the new coding language. It's the first step before creating more complex programs.
However, your Photon circuit board does not have a built-in screen. Your Photon kit does have a micro OLED screen that can be connected to the Photon – but that would require connecting 7 different jumper wires and coding a more complex app. Eventually, you'll be able to do this – but we need something much simpler for your first Photon app.
The good news is your Photon circuit board has a built-in blue LED light (D7) that can be controlled by your device's app. You won't have to connect any extra parts or wires yet – and you can program a simple app that makes the built-in LED blink on and off repeatedly, as a way of saying "Hello World."
All the apps that run on your Photon device will be coded using Particle's version of the open-source Wiring programming language framework for microcontrollers.
The Particle firmware on your Photon runs a modified version of the Wiring language with a few minor differences, as well as some additional methods (functions) customized for the Photon hardware.
One example of a minor difference:
In the original Wiring language, the analogRead()
method reads the value of an analog input pin and returns the value as an integer (whole number) between 0-1023.
In the Particle firmware, the analogRead()
method does the same thing but returns the value as an integer between 0-4095 (providing a higher level of precision).
The Particle firmware contains additional methods (functions) that are not part of the original Wiring language. For example, there are methods which are used to make the Photon interact with Particle Cloud. There are methods which can be used to control built-in hardware components on the Photon circuit board (such as the Wi-Fi module, RGB light, etc.).
WIRING VS. ARDUINO: Arduino is another programming language framework for microcontrollers. It turns out that Arduino is based on Wiring, so the two languages are nearly identical (though there are some differences). In most cases, a program originally written in Arduino will work on your Photon with only minor revisions. So once you've learned how to program in one of these languages, you've basically learned both.
WIRING VS. C++: Wiring (like Arduino) is a programming framework written in C++, so you can also directly incorporate C++ code within your device app.
Having a basic conceptual understanding of electric circuits is very helpful, so students can better understand how to correctly connect the parts in their IoT electronics kit (and how to troubleshoot connection issues) – however, it is NOT required:
Atoms and Electrons
Static Electricity vs. Current Electricity
Conductors vs. Insulators
Closed Circuit vs. Open Circuit
Voltage, Current, and Resistance
Series Circuit vs. Parallel Circuit
Being able to solve quantitative equations involving circuits (Ohm's Law, etc.) is NOT required.
The IoT tutorials will provide a limited explanation of circuits, which should be sufficient for using the IoT kit to create devices.
Previous experience building and programming devices using an Arduino electronics kit – such as a robotics kit, etc. – is very helpful. However, it is NOT required. The IoT tutorials will assume that students have no prior experience in building or programming physical computing devices.
Previous experience and familiarity with the following Arduino development concepts is very helpful before programming IoT device apps – however, it is NOT required:
Variables – declaring data type (int
, float
, boolean
, String
, etc.) and name (unique identifier), assigning and changing values, converting data type, global vs. local scope
Program Functions – setup()
function, loop()
function, creating custom functions, calling a custom function, passing arguments into a function, returning value from a function
Input/Output Functions – such as: pinMode()
, digitalRead()
, digitalWrite()
, analogRead()
, analogWrite()
, tone()
, etc.
Libraries and Objects – including external library file in device app, constructing new object using defined class in library, using object properties and methods
Comparison Operators – such as: >
, <
, ==
, !=
, etc.
Logical Operators (NOT, AND, OR): !
, &&
, ||
Conditional Statements using if
and else
Loops – such as: for
, while
, etc.
Previous experience and familiarity with these web development concepts is highly recommended before programming IoT web apps – however, mastery is NOT required:
Tag syntax for common HTML elements – such as: <div>
, <h1>
, <h2>
, <p>
, <span>
, <a>
,<img>
, <button>
, <input>
, <ul>
, <li>
, etc.
Nesting of HTML elements within other elements
Use of class
and id
attributes for HTML elements
Loading external files – such as: CSS style sheets, JavaScript files, images, other web pages, etc.
CSS selectors for HTML elements, classes, and ids
Common properties used in styles – such as: background-color
, color
, font-size
, margin
, padding
, border
, width
, height
, display
, etc.
Variables – declaring names (unique identifiers), assigning and changing values, data types (numbers, strings, boolean, etc.), global vs. local scope
Functions – creating functions, calling a function, passing arguments into a function, returning value from a function
Objects – constructing new object using defined class, using object properties and methods
Comparison Operators – such as: >
, <
, ==
, !=
, etc.
Logical Operators (NOT, AND, OR): !
, &&
, ||
Conditional Statements using if
and else
Loops – such as: for
, while
, etc.
Events – such as: onclick
, onchange
, etc.
jQuery selectors for HTML elements, classes, and ids
jQuery syntax for basic functions – such as: .html()
, .show()
, .hide()
, .addClass()
, .removeClass()
, etc.
GOAL: Understand how to create electronic circuits by connecting components to the Photon circuit board (use of power pins, I/O pins, jumper wires, and breadboard)
TASK: Review the information below to begin to understand how to use the components in your Photon kit to create electronic circuits, and answer the questions in this document.
Each input and output connected to your Photon circuit board must form an electronic circuit, which is a continuous path that conducts electricity from the positive (+) terminal of a power source, through the input or output, and back to the negative (-) terminal of the power source.
An electronic circuit is a special type of electric circuit. Here are the two key differences:
The current in an electric circuit could be only a few volts, or it could be hundreds of volts (or more). Some electric circuits operate on direct current (DC), while others use alternating current (AC).
Electronic circuits always operate on low voltage direct current.
Electric circuits transfer electricity to components (such as: light bulbs, motors, etc.) that transform some of the electrical energy into other types of energy (such as: light, motion, etc.) in order to perform a useful physical task.
Electronic circuits have special components with semiconductors that use electrical signals to process and transfer information.
The electronic circuits in your IoT devices will actually do both: they will perform a useful physical task by processing and transferring information.
Each input and output connected to your Photon should have its own circuit – i.e., its own separate path to conduct electricity without having to travel through another input or output. These are called parallel circuits. Using parallel circuits has these advantages:
Parallel circuits ensure each input and output receives its full voltage from the circuit board (because the voltage is not being split with another input or output on the same circuit).
Parallel circuits allow each input and output to be independently controlled by the circuit board.
For each parallel circuit, most of the conductive path will consist of jumper wires and the breadboard (via its internal metal strips). The rest of the conductive path will include the input or output itself (via its internal wires or circuitry) and the circuit board (via its power pins, I/O pins, and other internal circuitry).
AVOID SHORT CIRCUITS: Do NOT try this, but if you were to connect a wire directly from the positive side of a power source to the negative side (without any input or output in the middle), you would create a short circuit that leads to excessive current flow.
Short circuits can possibly: burn up your wire, damage your circuit board, damage your USB power supply, damage or drain your battery, etc.
The power for your circuits will be supplied by the Photon circuit board, which itself must receive power from another source.
The Photon circuit board can receive power through either one of its power supply ports:
Barrel Jack: A barrel jack adapter can be plugged in to provide power from an external supply such as a battery, outlet, etc.
Micro-USB: A Micro-USB cable can be plugged in to provide power from a computer's USB port or a USB charger.
CHOOSE ONE: Only one power source (barrel jack or Micro-USB) needs to be connected to the Photon circuit board.
CAUTION: Be careful when plugging or unplugging the Micro-USB cable to avoid breaking the Micro-USB port on the Photon. Be sure the correct side of the cable is facing up.
The Photon circuit board can supply power to inputs and outputs through these pins:
I/O Pins: These pins can supply 3.3 volts (by reducing the incoming voltage from the USB or barrel jack power source). Only certain inputs and outputs will get their power from an I/O pin.
3.3V: This pin supplies 3.3 volts (by reducing the incoming voltage from the USB or barrel jack power source).
V-USB: If a power source is connected to the Micro-USB port, this pin supplies ~5 volts.
VIN: If a power source is connected to the barrel jack, this pin supplies the same voltage as the external source (which could range from 4.5-15 volts). For example, if a 9V battery with adapter were plugged into the barrel jack, this pin would supply 9 volts. If a USB adapter were plugged into the barrel jack, this pin would supply ~5 volts.
GND: This pin acts as the ground (negative terminal) when powering inputs and outputs. The Photon circuit board has 3 available GND pins.
CAUTION: The inputs and outputs in your Photon kit have different power requirements:
Certain inputs and outputs (such as: micro OLED display, etc.) require only 3.3 volts of power – using a higher voltage could damage these components.
Certain inputs and outputs (such as: servo motor, etc.) require 5 volts or more – using a lower voltage could prevent these components from working.
A breadboard has a large number of additional pins (plugs) that are useful for connecting inputs and outputs to your circuit board. First, your inputs and outputs connect to pins in the breadboard, and then jumper wires are used to help connect those breadboard pins to specific pins on your circuit board.
One purpose of using a breadboard is it allows you to connect multiple inputs and outputs to some of the same power supply pins – while still ensuring each input and output has its own parallel circuit.
For example, the Photon circuit board has only one V-USB pin to supply 5V of power, but your device might have multiple inputs and outputs that require 5V – so the breadboard can be used to allow these components to share this one V-USB pin.
To understand how a breadboard works and is used, you need to understand the "anatomy" of your breadboard. The image on the left below shows an external view of your breadboard, while the image on the right shows what's inside the breadboard:
First, let's examine the external view of your breadboard. While the breadboard might seem like one large rectangle of holes, it actually consists of 4 smaller rectangular sections:
On the far left is a power rail consisting of two columns of pins: one column is labeled as positive (+) and the other column is labeled as negative (-).
In the left center is a set of terminal strips consisting of rows of pins: each row is numbered (from 1-30) and the pins within each row are lettered (from A-E).
In the right center is another set of terminal strips consisting of rows of pins: each row is numbered (from 1-30) and the pins within each row are lettered (from F-J). Notice there is a divide between the left set of terminal strips and the right set of terminal strips.
On the far right is another power rail consisting of two columns of pins: one column is labeled as positive (+) and the other column is labeled as negative (-).
Inside the breadboard, there are metal strips underneath the pin holes. The image of the internal view shows these metal strips – and makes it easier to visualize the 4 separate sections of the breadboard. (The red arrows are pointing to the metal strips under the power rails.)
When you plug a wire into a breadboard pin, the wire makes contact with the specific metal strip underneath that pin hole location. If another wire is plugged into another pin along the same metal strip, the metal strip will allow electricity to be conducted between the wires. If the wires are touching different metal strips, then the wires are NOT connected to each other.
These metal strips inside the breadboard act like additional wires. While these metal strips may be "hidden" inside your breadboard, they become part of your circuits as you connect inputs and outputs.
Here are some examples to help explain further how the terminal strips and power rails work:
If you were to plug a wire into pin A of row 1 and then plug another wire into pin E of row 1, these wires would be connected because they're touching the same metal strip.
If you were to plug a wire into pin A of row 1 and then plug another wire into pin F of row 1, these wires would NOT be connected because they're touching different metal strips. Remember that the terminal strip rows on the left and right sides are separate from each other.
If you were to plug a wire into pin A of row 1 and then plug another wire into pin A of row 2, these wires would NOT be connected because they're touching different metal strips. Remember that the terminal strip rows are separate from each other.
If you were to plug a wire into a pin of the positive (+) column of the left power rail and then plug another wire into another pin in the positive (+) column of the left power rail, these wires would be connected because they're touching the same metal strip.
If you were to plug a wire into a pin of the positive (+) column of the left power rail and then plug another wire into a pin of the negative (-) column of the left power rail, these wires would NOT be connected because they're touching different metal strips.
If you were to plug a wire into a pin of the positive (+) column of the left power rail and then plug another wire into a pin of the positive (+) column of the right power rail, these wires would NOT be connected because they're touching different metal strips.
Certain inputs or outputs can be connected directly to pins on the Photon circuit board. However, in most cases, you'll need to use the breadboard to help connect some (or all) of your inputs and outputs.
Each input or output has at least 2 wires that must be connected (one for positive and the other for negative). Some inputs or outputs have additional wires used for sending or receiving signals.
The wires for inputs and outputs connect to the pins of different terminal strips. Then jumper wires are used to connect each of these terminal strips directly (or indirectly) to its corresponding power pin or I/O pin on the Photon circuit board.
Here are two basic rules for connecting inputs and outputs to the breadboard:
Different wires for the same component should NOT connect to pins in the same terminal strip. For example, the temperature sensor has 4 wires that should connect to different terminal strips.
Jumper wires are the only exception to this rule: a jumper wire is supposed to share a terminal strip with a wire of an input or output in order to connect it directly (or indirectly) to its corresponding power pin or I/O pin on the circuit board.
Wires for different components should NOT connect to pins in the same terminal strip. For example, the wires of a push button and LED light should connect to different terminal strips.
Resistors are the only exception to this rule: a resistor is supposed to share a terminal strip with a wire of an input or output because the purpose of the resistor is to limit the amount of electric current flowing through the input or output to prevent damaging them. The LED lights and photocell (light sensor) in your Photon kit require the use of resistors.
Think of each power rail like a power strip you might use at home or school: you first have to plug the power strip into an outlet, and then the power strip can provide power to other devices plugged into it. Since your breadboard has two power rails (far left and far right), it's like having two power strips.
Some IoT devices won't need to use either power rail on the breadboard. However, most IoT devices will use one of the power rails. A few IoT devices might need to use both power rails (e.g., if your device has multiple components needing 3.3V as well as multiple components needing 5V).
In order to use a power rail on the breadboard to supply power to inputs or outputs, you must first use jumper wires to connect the power rail to power pins on the Photon circuit board:
The positive (+) column of the power rail would connect to a positive (+) pin on the Photon board (such as the 3.3V pin, V-USB pin, or VIN pin – do NOT connect a power rail to an I/O pin).
The negative (-) column of the power rail would connect to a negative (-) pin on the Photon board (i.e., any one of the GND pins).
Sometimes you might only need to connect the negative (-) column of a power rail. This is because every input and output needs to connect back to GND (and there are only 3 GND pins available on the Photon board). Since certain inputs and outputs use their I/O pin as their voltage source (+), sometimes it might not be necessary to connect and use the positive (+) column of the power rail.
Once a power rail has been connected to power pins on the Photon circuit board, you can use jumper wires to connect multiple inputs and outputs to this same power rail:
Use a jumper wire to connect the terminal strip for the ground (-) wire of the input or output to any negative (-) pin in the power rail.
For inputs or outputs that don't get power from their I/O pin, use a jumper wire to connect the terminal strip for the power (+) wire of the input or output to any positive (+) pin in the power rail (as long as the power rail is supplying the correct voltage required by the input or output).
All of this information about using jumper wires and the breadboard to connect inputs and outputs to the circuit board will really only make sense once you have hands-on experience building some practice devices. Tutorials 2, 3, and 4 will help provide that experience.
SparkFun has tutorials that provide more information about circuits and breadboards:
In this first tutorial, you'll become familiar with your team's IoT electronics kit.
The goals of this first tutorial are to help you:
Understand the features of your Photon circuit board (pins, ports, buttons, LED lights)
Identify the other components in your Photon kit and their purposes (inputs, outputs, connectors, and cables)
Understand how to create electronic circuits by connecting components to the Photon circuit board (using power pins, I/O pins, jumper wires, and breadboard)
This guidebook is tailored for an IoT electronics kit called the SparkFun Inventor's Kit for Photon, which will simply be referred to as the Photon kit.
SparkFun is a company that sells products to help people build and program electronics devices. Photon is a Wi-Fi enabled microcontroller (small computer) from a company called Particle that sells IoT hardware and services that help inventors and other companies create their own IoT products.
SparkFun created its own Photon kit by incorporating the Photon P1 microcontroller into an easy-to-use circuit board and packaged it with a set of inputs, outputs, wires, and other parts to help you start inventing your own IoT devices. It is also possible to purchase additional parts (sensors, motors, etc.) that can be used with this Photon kit.
NOTE: Your instructor may have provided you with a different IoT electronics kit. If your IoT kit is programmed using Arduino or Wiring, then you may still be able to use (or modify) the tutorials and references in this coding guidebook.
WI-FI NETWORK: Photon devices are relatively easy to setup to connect to home Wi-Fi networks or mobile hotspot devices. Photon devices running firmware version 0.7.0 or higher can be setup to connect to WPA2 Enterprise Wi-Fi networks (such as those typically found in schools, universities, and corporations). Teachers may need to coordinate with their school's IT administrator to follow Particle's guide to WPA2 Enterprise Setup.
GOAL: Understand the features of your Photon circuit board (pins, ports, buttons, LED lights)
TASK: Review the information below as you examine the circuit board in your Photon kit, and answer the questions in this document.
The SparkFun Photon kit contains a printed circuit board (PCB) that incorporates the Particle Photon P1 microcontroller, which will act like the “brain” of your IoT device. This circuit board also has various pins, ports, buttons, and LED lights. SparkFun refers to this circuit board as the Photon RedBoard (because of its color).
You can connect various inputs (such as: sensors, buttons, etc.) and outputs (such as: motors, lights, etc.) to the pins on the circuit board to create a device. Then you can control your device by programming an app that will run on the Photon microcontroller.
Photon P1 Microcontroller
Input/Output Pins
Power Supply Ports and Pins
Buttons
LED Lights
A microcontroller is a small computer on a single integrated circuit that contains a processor (CPU), memory, storage, and programmable input/output pins. The Photon microcontroller also has an integrated Wi-Fi chip and antenna, which makes it great for IoT devices.
CPU: 32-bit 120Mhz ARM Cortex M3
Memory: 128KB RAM
Storage: 1MB Flash
Wi-Fi: 2.4GHz 802.11b/g/n
Compared to the tech specs of a "regular" computer, a microcontroller is much less powerful – it has a slower processor, less memory, and less storage. This is because microcontrollers are used in devices that have dedicated functions (such as: automobile engine control systems, medical devices, office machines, appliances, etc.). These dedicated devices typically don’t require as much computing power.
A microcontroller is controlled by its firmware, which acts as its operating system. Periodically, your Photon will need to update its firmware. If this is necessary, the firmware update will occur automatically when you download a new app to your Photon over Wi-Fi.
A microcontroller is designed to store only one app, which will run automatically. If you need to change your Photon device's app, the new app has to be downloaded over Wi-Fi (and will replace the old app). You will have to code the apps for your Photon – though you'll get some practice and help to do so.
When the Photon is powered on, it will automatically try to connect to Wi-Fi (using a programmed list of Wi-Fi network logins). Once the Photon is connected to Wi-Fi, it will automatically try to connect to Particle Cloud, which is a cloud service that Particle provides for all of its microcontroller devices. All of the Photon's internet communications are routed through Particle Cloud.
Particle Cloud can be used to:
Code and store all your different Photon device apps (using online Particle Build code editor)
Update the app stored on your Photon device
Update the firmware on your Photon device
Send and receive data between your Photon device app and your web app
Manage your Photon device remotely
The Photon circuit board has numerous I/O pins used to connect various inputs (such as: sensors, buttons, etc.) and outputs (such as: motors, lights, etc.). These I/O pins have small plugs that allow you to easily connect (and disconnect) the wires for inputs and outputs.
The circuit board has a set of digital pins labeled as: D0, D1, D2, D3, D4, D5, D6, D7. Digital pins are used to connect inputs or outputs that use binary values (such as: HIGH or LOW, etc.). For example:
Digital Input: A motion sensor detects either "motion" or "no motion."
Digital Output: A LED light can be set to be "on" or "off."
The circuit board has a set of analog pins labeled as: A0, A1, A2, A3, A4, A5. Analog pins are used to connect inputs or outputs that use a range of values (such as: 0-255, etc.) For example:
Analog Input: A photocell can detect a range of values based on the amount of light measured.
Analog Output: A speaker can produce a range of tones that have different frequencies.
TWIN PINS: Analog pins A2, A3, A4, and A5 are each represented by two pins on the Photon board. The duplicate pins are labeled as: SS/A2, SCK/A3, MISO/A4, MOSI/A5.
If you use one of these pins, you should not use its twin. For example, you could connect a part to either A2 or SS/A2 (choose only one), but you could not connect two different parts to these twin pins at the same time.
Any analog pin can be used for analog inputs. However, only certain pins can be used for analog outputs. (Confusingly, some of the pins capable of analog output are labeled as digital pins.)
The Photon uses pulse-width modulation (PWM) to make a digital output signal (which has only two values: HIGH or LOW) act like an analog output signal (which has a range of values). Certain outputs (such as: speaker, servo motor, etc.) require a connection to an I/O pin capable of PWM.
These Photon pins can be used as analog outputs using PWM: A4, A5, D0, D1, D2, D3, RX, TX, WKP.
The circuit board also has I/O pins with "special" labels. Most of these "special" pins are used to connect with parts that require specific data communication protocols:
SPI Pins: SS/A2, SCK/A3, MISO/A4, MOSI/A5
SPI stands for "Serial Peripheral Interface"
For example, a Micro OLED display would be connected using the SPI pins.
I2C Pins: SDA/D0, SCL/D1
I2C stands for "Inter-Integrated Circuit"
For example, an accelerometer would be connected using the I2C pins.
UART Pins: RX, TX
UART stands for "Universal Asynchronous Receiver-Transmitter"
For example, a fingerprint scanner would be connected using the UART pins.
However, any of these "special" pins can also be used as "regular" I/O pins.
The Photon circuit board must receive power from an external power source (such as: USB, battery, or outlet). The Photon circuit board will then supply power to any connected inputs and outputs.
The Photon circuit board can receive power through either one of its power supply ports:
Barrel Jack: A barrel jack adapter can be plugged in to provide power from an external supply such as a battery, outlet, etc.
Micro-USB: A Micro-USB cable can be plugged in to provide power from a computer's USB port, USB charger, etc.
POWER ON/OFF: The Photon circuit board does not have an "on/off" switch. As soon as a power source is connected to the USB port or barrel jack, the Photon will power on and start running. To turn off the Photon, you have to disconnect its power source.
The Photon circuit board can supply power to connected inputs and outputs through these pins:
I/O Pins: These pins can supply 3.3 volts (by reducing the incoming voltage from the USB or barrel jack power source). Certain inputs and outputs (but not all) get their power from an I/O pin.
3.3V: This pin supplies 3.3 volts (by reducing the incoming voltage from the USB or barrel jack power source).
V-USB: If a power source is connected to the Micro-USB port, this pin supplies ~5 volts.
VIN: If an external power supply is connected to the barrel jack, this pin supplies the same voltage as the external supply (which could range from 4.5-15 volts). For example, if a 9V battery adapter were plugged into the barrel jack, this pin would supply 9 volts. If a USB adapter were plugged into the barrel jack, this pin would supply ~5 volts.
GND: This pin acts as the ground (negative terminal) when powering inputs and outputs. The Photon circuit board has 3 available GND pins.
A breadboard can be used to connect multiple inputs and outputs to the same power supply pins. Section 1.3 of this tutorial will explain how this works.
The Photon circuit board has two built-in buttons used for special purposes:
Mode: This button is used to switch your Photon between different modes such as: Connected, Listening, Safe, and Device Firmware Upgrade. Normally, you will not need to use this button.
Reset: This button can be used to restart your Photon – forcing it to reconnect to the internet and restart its device app. Occasionally, you might use this button to restart your app.
The Photon circuit board has three built-in LED lights:
Power: This red LED indicates the Photon is receiving power (from the barrel jack or USB). If this LED is off, then no power source is connected (or the Photon device is damaged).
RGB: This LED changes its color and activity pattern to indicate the current mode and connection status of the Photon device.
D7: This blue LED is connected to the D7 pin and can be controlled by your Photon device app, which can be helpful for testing purposes.
Whenever you connect a power source to the Photon (or restart it using the Reset button), the Photon should power on, connect to Wi-Fi, connect to Particle Cloud, and start running its device app.
During this startup process, the RGB color will change from green to cyan (light blue) and the RGB activity will change from "blinking" (fast blinking) to "breathing" (slow blinking).
Whenever the device app or firmware on the Photon is updated, the RGB will blink pink during the download and installation. Once the update is complete, the Photon will automatically restart itself.
If your Photon device displays one of these other RGB patterns, then the Photon has encountered an issue or has been placed into a different mode. Consult your teacher to troubleshoot your device.
The SparkFun Photon RedBoard Hookup Guide provides more details about this circuit board.
Now that your Photon is connected to Wi-Fi and Particle Cloud, your team will log in to Particle Build, the code editor that will be used to create your "Hello World" app.
Particle Build is an online code editor (web IDE) provided by Particle. Particle Build is part of the Particle Cloud platform. You will use Particle Build to code and store all your Photon device apps.
The Photon device itself can only store and run one app at a time. However, you can create and save multiple apps in Particle Build. When you need to update the specific app stored on your Photon device, you'll do this in Particle Build – and your Photon will download the new app over Wi-Fi.
Your team will need a Particle account to log in to Particle Build. However, your teacher will most likely provide your team with an existing Particle account login (email & password) that's already associated with your specific Photon device. Every Photon has a unique device ID it uses to communicate with Particle Cloud, and each device ID can only be associated with one Particle account.
One person on your team should log in to using your team's Particle account login.
Once you're logged in, you'll see the Particle Build code editor, which defaults to the "Code" menu and shows a blank app template.
The user interface for Particle Build is divided into 4 sections:
On the far left is a vertical navigation bar with icons.
On the middle left is a menu panel showing options for the current navigation selection.
On the right side is the code editor panel showing the code for your current app.
On the bottom of the code editor panel is a horizontal status bar that displays messages.
If you hover your mouse pointer over an icon in the navigation bar, the icon's name will be displayed. Here is a summary of the navigation icons from top to bottom:
The middle menu panel can be toggled between "show" and "hide" by clicking the same navigation icon repeatedly.
In the left navigation bar, click the Code icon.
The middle menu panel will become hidden.
Click the Code icon again to show the menu panel again.
In general, you'll probably want to keep the menu panel shown – but if you want extra space for your code editor panel, you can temporarily hide the menu panel.
In the left navigation bar, click the Devices icon.
The middle menu panel will list your Particle devices. You should see a device name listed under P1 (because your device is a Photon P1). Your device's connection status is shown as a colored dot to the right of its name. If your device is connected to Wi-Fi and Particle Cloud, the dot should be cyan (light blue) and "breathing" (slowly blinking) – just like the RGB LED on your Photon circuit board.
Click the drop-down arrow to the right of the device's connection status dot. This will show additional information about your device:
You'll see the device ID, which is a unique ID used by your device to interact with Particle Cloud. Later when you create web apps to interact with your device, you'll need your device ID.
You'll see the firmware version that is currently saved on your device. If an updated version is available, your device's firmware will be automatically updated the next time you flash an app.
If you wanted to double-check your device and its connection (imagine you had multiple devices), an easy way is to signal it from Particle Build.
Click the Signal button. Particle Cloud will send a signal to your device over Wi-Fi. Your Photon's RGB LED will respond by cycling through a rainbow of colors.
Click the button again to stop signaling your device. Your Photon's RGB will return to breathing cyan.
In the left navigation bar, click the Code icon to return to your list of apps.
You'll add a variable in your app code to represent the built-in LED light.
Your "Hello World" app will make the Photon's built-in blue LED light turn on and off in a blinking pattern. This will be accomplished by sending separate "on" and "off" signals to the LED's pin.
Each I/O pin on the Photon circuit board is identified by a pin number (such as: A0, A1, A2, D0, D1, D2, etc.). In this case, the Photon's built-in blue LED light is connected to pin D7 (via internal circuitry).
When coding a Photon device app, you will typically create a global variable to store a pin number for each input or output connected to your Photon. This will help make your code easier to understand because the variable names help identify each input or output.
You'll need to create a global variable to store the pin number of the built-in LED. Add this code statement to your app by inserting it (as a separate line of code) before the setup()
function:
HOW TO COPY CODE: When using this IoT code guidebook, you can copy a code block simply by clicking the copy icon displayed in the upper right of the code block.
This code statement does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this case, the variable will be called LED
. You get to decide what to name your variables. Choose names that will make sense to anyone reviewing your code.
It assigns a value to the variable. In this case, the variable's value will be equal to D7
, which is the pin number for the Photon's built-in LED light.
Notice that this code statement ends with a . Typically, each code statement in your app will end with a semi-colon. The semi-colon separates code statements, similar to how periods separate sentences in written English.
The exceptions to ending with a semi-colon are certain statements (such as functions, conditionals, loops, etc.) that use to enclose other code statements. However, within the curly braces, each code statement ends with a semi-colon.
Although you can actually list multiple code statements on the same line (because their semi-colons will separate them), each code statement is traditionally listed on its own separate line to make it easier to read the code.
The Particle Build code editor does NOT autosave your work as you type, so be sure to periodically save your code.
Save your app code by clicking the Save icon in the left navigation bar.
You get to decide what to name each variable in your app's code. However, here are a few rules and recommendations to help you name your variables:
Each global variable must have a unique name.
Variable names must be one word (no spaces allowed).
Variable names can contain lowercase letters, uppercase letters, numbers, and certain special characters (such as underscores, etc.) – but the name cannot start with a number.
Make each variable's name concise yet descriptive, so it will be easy to read and understand.
Example of variable name that's concise yet descriptive: button
Example of variable name that's too concise: b
Example of variable name that's too descriptive: greenbuttonthatturnslighton
Examples of variable names using underscores: red_light
, motion_sensor
Examples of variable names using camelCase: redLight
, motionSensor
If you have multiple inputs or outputs of the same type (multiple LED lights, multiple buttons, etc.), add an adjective or number to their variable names to help identify them in your app code.
Examples of variable names with adjectives: redLED
, blueLED
Examples of variable names with numbers: button1
, button2
Next you'll add commands in your app code to turn the LED on and off in a repeating pattern.
Your app can receive signals from inputs using the digitalRead()
or analogRead()
methods, depending on whether the values being received will be digital or analog.
Your app can send signals to outputs using the digitalWrite()
or analogWrite()
methods, depending on whether the values being sent will be digital or analog.
DIGITAL VS. ANALOG: Digital inputs and outputs use binary values (such as: HIGH vs. LOW, etc.). Analog inputs and outputs use a range of values (such as: 0-255, etc.)
The LED can be controlled as a digital output that is either "on" or "off".
You'll need to send an "on" signal to the LED pin. Add this code to your app by inserting it within the loop()
function (between the curly braces):
The digitalWrite()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D7
, etc.) or a variable that stores a pin number. In this case, the variable LED
is listed (which has a value equal to D7
).
The signal value, which can be HIGH
or LOW
. Your Photon uses this value to send an electrical signal through the pin: HIGH
is a signal of 3.3 volts which represents "on," while LOW
is a signal of 0 volts which represents "off." In this case, the signal was set to HIGH
because you want to turn on the LED light.
You'll want to leave the LED turned on for a short amount of time before you send the "off" signal.
Because the Photon's app code runs very fast, there will be certain situations where you'll want to insert delays into the code, in order to allow time for certain events to occur. Typically, these delays are intended to give people time to perceive the event and/or respond to the event.
Your app can use the delay()
method to insert a time delay. It acts like a timer that makes the app wait before performing the next line of code.
You'll need to add a delay after the LED has been turned on. Add this code to your app by inserting it (as a separate line of code) within the loop()
function (after the digitalWrite()
statement):
The delay()
method requires one parameter inside its parentheses:
The time value, which can be an integer number (whole number) or a variable that stores an integer. The value represents the number of milliseconds for the delay (1000 ms = 1 second). In this case, the delay was set to 1000
ms (1 second).
Next, you'll send an "off" signal to the LED pin. Add this code to your app by inserting it (as a separate line of code) within the loop()
function (after the delay()
statement):
You can see that the second parameter in this digitalWrite()
statement was set to LOW
, which represents "off" for a digital output.
When all the code within the loop()
function has been performed, the loop()
will automatically repeat itself. Since the first line of code in your loop()
turns on the LED, you'll want to add another delay to leave the LED turned off for a short amount of time before the loop()
repeats itself.
Add this code to your app by inserting it within the loop()
function (after the second digitalWrite()
statement):
Now, the code within your loop()
function should perform these tasks (in order):
Turn On LED light
Wait 1 second
Turn Off LED light
Wait 1 second
Repeat
REPEATING LOOP: You don't need to add a command to make the loop()
function repeat – it automatically repeats itself after its last line of code has been performed.
Next you'll add a command in your app code to designate the LED pin as an output.
A variety of inputs and outputs can be connected to the I/O pins on your Photon circuit board. Your app code needs to identify which I/O pins are being used and whether each of these pins will be used for an input or output. This is referred to as setting the pin modes.
You'll need to set the pin mode for the built-in LED that you'll be using. Add this code to your app by inserting it within the setup()
function (between the curly braces):
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D7
, etc.) or a variable that stores a pin number. In this case, the variable LED
is listed (which has a value equal to D7
).
The mode value, which can be INPUT
, INPUT_PULLUP
, or OUTPUT
. Your Photon uses this value to change the electrical behavior of the pin, so the pin can either receive signals from an input or send signals to an output. In this case, the mode was set to OUTPUT
because your app will be sending "on" and "off" signals to the LED light.
At this point, your app code should look similar to this:
Notice that the pinMode()
statement shown in the app code above is indented (using the tab key). This is a useful practice when adding code statements within curly braces because it helps make the code easier to read and understand – especially if your app contains many code statements nested within each other.
The Particle Build code editor does NOT check your code syntax as you type, so be sure to periodically verify your code to check for errors.
Verify your app code by clicking the Verify icon in the left navigation bar. (Particle Build will first save your code before verifying it.)
While Particle Build is verifying your code, it will display the message "Compiling code" in the status bar at the bottom of the code editor panel. When the verification process is complete, the status bar will indicate the results:
If your code compiled without any errors, the status bar will display a success message.
If your code contains an error, the status bar will display an error message with a description of the error and a link to the specific line number in your code where the error was detected (though sometimes the root cause of the error occurs on a previous line). You'll want to fix the error and then try verifying your code again.
MULTIPLE ERRORS: Sometimes your app code might contain multiple errors. However, Particle Build will stop verifying the code at the first error that is detected. Once you fix that error and verify the code again, you might see a new error message for another error that occurs later in the code.
Let's title your new app template, and learn about the basic code structure for Photon device apps.
In the Code menu panel, you'll notice that your current app doesn't have a title yet.
It's recommended to give each app a unique title. Particle Build will allow you to save different apps that have the same title – but this could get confusing, so try to use unique app titles.
NOTE: You cannot have any blank spaces in an app's title. If you want to visually separate words in your app's title, just use a hyphen or an underscore.
Enter hello-world
as your app's title.
You'll see the app's title show up in the "My Apps" list.
HOW TO RENAME APP: If you wanted to change the title of your current app, just click the title to enter a different title.
Your code editor should show the basic structure for a new Photon device app:
Every Photon device app must have one (and only one) setup()
function. You can add lines of code between this function's opening and closing curly braces.
The setup()
function will run one time when your app first starts (which is when your Photon is first powered on – or is restarted using its Reset button).
The code added within the setup()
function typically sets pin modes for the device's inputs and outputs, initializes settings for certain inputs and outputs, or performs other "setup" actions that need to occur at the start of the program.
Even if you didn't add any code within the setup()
function, your app must still have this function.
Every Photon device app must have one (and only one) loop()
function. You can add lines of code between this function's opening and closing curly braces.
After the setup()
function is done running, the loop()
function will start to run. When all the code within the loop()
function has been performed, the loop()
function will automatically run itself again. It keeps running in an endless loop (until the device is restarted or powered off).
The code added within the loop()
function performs the main tasks of your program.
Even if you didn't add any code within the loop()
function, your app must still have this function.
Besides having the required setup()
and loop()
functions, your Photon device apps will typically have some or all of the following:
Comments
Libraries
Global Variables
Custom Functions
Any comments in the app are ignored when the program is compiled and uploaded to your device.
Some device apps might include (i.e., import) one or more library files. A library is a file of pre-built code that provides additional functions that your program can utilize. For example, certain inputs and outputs have their own code library with functions to make it easier to control the input or output.
Your device app will typically have code that declares global variables which store data used in your program's functions, such as pin numbers for sensors, etc.
Global variables are usually listed before the setup()
function (to make it easier to read the code).
You can also add your own custom functions to your device app. Each custom function must have a unique function name.
Custom functions are used to contain code that performs specific tasks or subtasks. Custom functions are optional, but they can help break up your code into smaller modules that are easier to understand (and easier to re-use). So rather than listing all your main program code within the loop()
function, you can subdivide some or all the code into custom functions.
The code within a custom function is only run if and when that custom function is "called" (by listing the function's name) within the setup()
or loop()
function. A custom function can also be "called" within another custom function.
Custom functions are usually listed after the loop()
function (to make it easier to read the code).
Let's start your Photon to verify it connects to Wi-Fi and Particle Cloud.
Start your Photon by powering on the circuit board:
Connect a power cable into the barrel jack or Micro-USB port on the circuit board, and connect the other end of the cable to a power source (such as: battery, computer USB port, etc.).
CHOOSE ONE: Only one power source (barrel jack or Micro-USB) needs to be connected.
REMINDER: The Photon circuit board does not have an "on/off" switch. As soon as a power source is connected to its barrel jack or Micro-USB port, the Photon will power on and start running. To turn off the Photon, you have to disconnect its power source.
Once the circuit board has power, you should see its red Power LED light turn on.
You should also see the RGB LED light turn on – it will blink green while the Photon automatically tries to connect to Wi-Fi.
Once the Photon has successfully connected to Wi-Fi and Particle Cloud, the RGB LED will be cyan (light blue) and "breathing" (slowly blinking).
CONNECTION ISSUES: If your Photon is having issues (can't connect to Wi-Fi, etc.), you'll see a (such as: breathing green, breathing pink, etc.). You may have to consult with your teacher to troubleshoot your device.
When your Photon is powered on (or restarted), it will automatically try to connect to a Wi-Fi network. It does this by using its saved list of Wi-Fi logins (network names and passwords). Every Photon can be programmed to store login information for up to 5 different Wi-Fi networks.
A brand new Photon will not have any Wi-Fi logins saved yet. However, the Photon provided to you by your teacher will most likely already have a Wi-Fi login programmed into it.
Once your Photon is connected to Wi-Fi, the Photon will automatically try to connect to Particle Cloud, which is a cloud service that Particle provides for all of its microcontroller devices. All of your Photon's internet communications are routed through Particle Cloud.
Particle Cloud can be used to:
Code and store all your different Photon device apps (using Particle Build code editor)
Update the app stored on your Photon device
Update the firmware on your Photon device
Send and receive data between your Photon device app and your web app
Manage your Photon device remotely
In this third tutorial, you'll create a "Smart Light" device and program its apps.
The goals of this third tutorial are to help you:
Practice connecting physical inputs and outputs to your Photon device
Program a Photon app that controls your device's physical inputs and outputs
Program a web app that interacts with your Photon device through Particle Cloud
The smart light bulb was introduced in 2012. Today, there are several companies that offer smart light bulb systems.
From the outside, a smart light bulb looks like a regular light bulb. However, what seems like a simple light bulb is actually a full-fledged IoT device: inside the bulb are multiple LED lights wired to a microcontroller circuit board that connects to your Wi-Fi network.
The smart light interacts with a mobile app that allows you to control an individual light or a group of lights. The mobile app might offer features such as:
Remotely turn the light(s) on or off
Set automatic timers to turn the light(s) on or off at specific times
Adjust the brightness of the light(s)
Change the color of the light(s)
Sync the light(s) to music, movies, or games
Control the light(s) using a voice assistant (such as: Alexa, Siri, etc.)
For this tutorial, you'll create a prototype of a Smart Light device using one LED. Your device will include a button to manually turn the light on or off. You'll program a Photon device app to control the LED using the button. You'll also program a web app that interacts with your Photon device over the internet to monitor the light's status and to allow you to remotely turn the light on or off.
A variable's name cannot be one of the .
If your variable name combines multiple words, you can make the name easier to read by either using an underscore between words – or using "" (lowercase letters, but new words start with an uppercase letter).
VOID: Why is listed before the setup()
and loop()
functions? This is because each function in your Photon device app must declare a data type (such as: integer, boolean, etc.) for the data value returned by the function. In this case, void
indicates the function does NOT return any data value.
Comments are optional notes that you can insert to help explain or clarify portions of the code to anyone reviewing the program. Comments can be or .
Particle Build has a Libraries menu where you can search for existing libraries (or upload your own library file that you've created). When you select a library to be added to your app, Particle Build will automatically insert an statement for the library at the beginning of your app code.
SETUP NEW DEVICE: The Photon device provided to you by your teacher should already be setup with a Wi-Fi login and Particle account that you will use. If not, then the Photon will need to be by programming it with a Wi-Fi login, creating a Particle account, and adding the device to your account by claiming its device ID.
RGB Color
RGB Activity
Photon Device Status
Green
Blinking
Trying to connect with Wi-Fi
Cyan (light blue)
Blinking
Connected to Wi-Fi + Trying to connect with Particle Cloud
Cyan (light blue)
Breathing
Connected to Wi-Fi and Particle Cloud (device app running)
Pink
Blinking
Receiving new device app or new firmware over Wi-Fi
RGB Color
RGB Activity
Photon Device Status
Green
Breathing
Connected to Wi-Fi – but could not connect to Particle Cloud
Blue (dark blue)
Breathing
Could not connect to Wi-Fi
Blue (dark blue)
Blinking
Listening Mode (ready to add new Wi-Fi login)
Pink
Breathing
Safe Mode (does not run device app)
White
Breathing
Device's Wi-Fi module has been turned off
Orange-Yellow
Blinking
DFU Mode (ready for manual device firmware upgrade)
Red
Blinking
Firmware crash error
Next, you'll modify your app code to make the button toggle the LED on or off with each button press – similar to how a light switch normally works.
You'll add a global variable that track the LED's current status ("off" or "on"). Whenever the button is pressed, this variable will be checked, in order to toggle the LED to the opposite status.
Declare a global variable to store the LED's status by adding this code statement before the setup()
function:
This code statement declares a variable named lightStatus
which has a data type of String
, which is the data type used for storing text. The initial value of this variable is made equal to "off"
.
USE DOUBLE QUOTES: Use double quotation marks to enclose your text when assigning the value of a String variable:
CORRECT (double quotes): String myText = "Hello World";
INCORRECT (single quotes): String myText = 'Hello World';
Since the lightStatus
was initially set to "off"
, let's be sure the LED is turned off when the app starts by adding this code statement within the setup()
function (after setting the LED pin mode):
Let's create a custom function named toggleLight()
that will be "called" (performed) whenever the button is pressed.
The toggleLight()
custom function will check the current value of lightStatus
("off" or "on") and then toggle the LED and lightStatus
to the opposite status.
Add the toggleLight()
function after the loop()
function (after its closing curly brace):
Now you can "call" (perform) this custom function whenever the button is pushed. A function is "called" by simply listing the function's name as a code statement.
Replace all the existing code within the loop()
function (everything inside its curly braces) with this code instead:
Now when the button is pressed, the toggleLight()
function will be called, performing the code within that custom function.
Notice that a brief delay()
of 175 milliseconds was included. This is necessary to give people just enough time to release the button after pressing it:
If there is no delay (or the delay is too brief), the device will seem unpredictable because the loop()
will repeat so quickly that it toggles the light multiple times for the same button press.
If the delay is too long, the device will seem unresponsive because the button has to be held down longer before the button press is detected.
So this delay()
value shouldn't be too brief or too long – it needs to be just right. A value between 150-200 ms should work well for most people. You can test your button's behavior, and then adjust the specific value higher or lower to make your button seem more responsive.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar.
Once your Photon has downloaded the app and restarted, the updated app will start running:
Confirm that the LED light toggles between "on" and "off" each time the button is pressed. (If you hold the button down, you'll see the LED continuously toggles between on and off.)
You may notice that occasionally a button press isn't detected immediately. This is normal because there will be occasions when you press the button while the Photon happens to be in the middle of the delay()
period. However, if the button seems very unresponsive, you can adjust the delay()
value in your app code, and then flash the updated app to your device to test the new value.
At this point, your Photon device should be operating similar to a normal light that can be switched on and off.
Next, you'll add code in your Smart Light device app to control the LED using the push button.
The basic steps to use a push button in your app code are:
Declare a global variable to store the I/O pin number for the button.
Set the pin mode for the button pin in the setup()
function.
Use a digitalRead()
statement to check whether the button is currently pressed, and add code statements that should be performed if the button is pressed (or not pressed).
Declare a global variable to store the I/O pin number for the button by adding this code statement before the setup()
function:
If you connected your button to a different I/O pin other than D2
, then modify this code statement to list the correct pin number for your button.
Set the pin mode for your button pin by adding this code statement within the setup()
function (between the curly braces):
The digitalRead()
method is used to check whether a button is currently pressed.
The digitalRead()
method will return a value of either LOW
or HIGH
:
LOW
indicates that the button is currently pressed.
HIGH
indicates that the button is NOT currently pressed.
A variable named buttonState
will store the value returned by the digitalRead()
method.
An if statement will be used to turn on the LED if the button is being pressed (if buttonState
has a value equivalent to LOW
).
An else statement will be included to turn off the LED if the button is not being pressed.
Replace all the existing code within the loop()
function (everything inside its curly braces) with this code instead:
COPY CODE: Remember that you can copy a code block in this guidebook simply by clicking the copy icon in the upper right of the code block.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar.
Once your Photon has downloaded the app and restarted, the updated app will start running:
Confirm that the LED light that you connected to your Photon circuit board turns on when you press (and hold) the button – and turns off when the button is released.
Of course, nobody would want to continually press a button to keep a light turned on – however, this is a good way to verify that your button is connected correctly. In the next step, you'll modify the app code so the LED light toggles on or off with each button press.
If the LED does not turn on when the button is pressed, then there is a mistake in your app code – or a mistake in your wiring connection – or a mistake in both.
If the LED light is turned off and pressing the button has no effect, then verify that one of the button's legs is connected (via a jumper wire) to the same I/O pin number that is assigned to the button
variable in your app code. If necessary, change either your wiring or your code, so the pin numbers match. If you revised your code, flash the updated app to your device.
If that still doesn't solve the issue, then double-check all your button wiring by referring back to the connection instructions.
Icon | Name | Purpose |
Flash | Flashes the current app to your Photon device over Wi-Fi (The app will first be saved and verified. If there are errors in the app, it will not be flashed.) |
Verify | Complies the current app to check for errors (The app will first be saved.) |
Save | Saves the current app in Particle Build |
Code | Lists all your saved apps. Click an app's title to open it in the code editor. |
Libraries | Lists libraries that can be included in your app to add functionality |
Help | Lists quick help for device (might not be available for your Photon) |
Docs | Opens new tab with Particle Reference Documentation for your device |
Devices | Lists your devices. You can view the device ID, and signal device over Wi-Fi. (If you have multiple devices, you can select which device to flash apps to.) |
Console | Opens new tab with Console showing your device's events in Particle Cloud |
Settings | Provides options to: log out, change password, or get your access token. |
Next, you'll create a web app that will interact with your Smart Light device through Particle Cloud.
Your web app will consist of an HTML file namedindex.html
, a CSS file named style.css
, and a JavaScript file named script.js
.
Particle Build is only used to code your Photon device app. You'll need to use a different code editor to create the HTML, CSS, and JS files for your web app. Consult your teacher to determine which code editor will be most appropriate to use for your web app files.
Copy this HTML, and paste it into a blank HTML file named index.html
:
COPY CODE: When using this IoT code guidebook, you can copy a code block simply by clicking the copy icon displayed in the upper right of the code block.
This HTML does three main things:
It loads a CSS stylesheet file.
It loads three JavaScript files.
It displays a "card" with the light's name, the light's status, and a button that can be clicked to remotely toggle the light on or off.
In the <head>
section, line 7 of the HTML has a <link>
tag to load a CSS stylesheet file. The CSS stylesheet will be used to modify the appearance of certain HTML elements in your web app.
At the moment, your web app CSS file named style.css
is either blank or hasn't been created yet.
At the bottom of the <body>
section, lines 16-18 of the HTML contain <script>
tags to load three JavaScript files into your web app:
Particle API JS library: particle.min.js
jQuery JS library: jquery.min.js
Your web app JS file: script.js
The Particle API JS library contains methods to allow your web app to interact with your Photon device through Particle Cloud. You'll use Particle methods in your web app JS file.
The jQuery JS library contains methods that make it easy to modify the content and style of your web app by dynamically changing its HTML and CSS. You'll use jQuery methods in your web app JS file.
At the moment, your web app JS file named script.js
is either blank or hasn't been created yet.
In the <body>
section of your web app, lines 10-15 of the HTML display an <h1>
heading and then a <div>
section that will become a "card" displaying the following information:
The name of the light, which is simply named Light 1
in this case, but this could be changed to something more specific such as Desk Light
, Hall Light
, etc.
The status of the light, which has been displayed using the placeholder text of Connecting...
. Once the web app has connected to Particle Cloud, your web app JS will dynamically change this placeholder text to display the actual light status as either ON
or OFF
.
A button to toggle the light on or off, which has been given a placeholder label of Wait
. Once the web app has connected to Particle Cloud, your web app JS will dynamically change this button label to either Turn Off
(if the light is currently on) or Turn On
(if the light is currently off).
HTML: If you want to learn more about HTML or need a quick reference, check out the W3Schools HTML Tutorial and Reference.
If you preview the web app at this point, it's very plain (because there's no CSS in the style.css
file) and it doesn't function yet (because there's no JS in the code.js
file).
Your last step is to modify the "Hello World" app, as some extra practice.
In Particle Build, modify the code within the loop()
function to change the LED blinking pattern. Here are some possible options your team could choose:
Make the D7 LED blink faster
Make the D7 LED blink slower
Make the D7 LED blink in a different pattern (such as two quick blinks followed by a longer pause)
It's recommended to add a comment at the very beginning of your code to list a title for your app, plus any other information that might be helpful to you or to anyone else reviewing the program code.
For example, this comment could list your app's title, your team's information (team name and/or team members), your teacher's name, and your class period.
Add a block comment at the beginning of your app code before the setup()
function:
Modify this comment to list your specific information. Check with your teacher to find out if there is other information that should be listed within this block comment.
Flash your modified app to your Photon to confirm it does what you intended it to do.
Your teacher may want to see your modified app code running on your Photon.
If you need to download a copy of your app code to your computer in order to submit it to your teacher, there are two different download icons shown in the Code Menu panel:
The first icon (cloud with download arrow) to the right of "Current App" is used to download the compiled version of the app (firmware binary).
The second icon (angle brackets with download arrow) to the right of "Files" is used to download a zip file containing your app source code (.ino
file).
Click the second download icon to download a zip file containing your app source code:
In this case, the zip file will be named hello-world.zip
. You'll need to uncompress the zip file to get your app source code file, which will be named hello-word.ino
. If necessary, this .ino
file can be opened in a text editor on your computer.
UNCOMPRESS ZIP: To uncompress a zip file downloaded to your computer:
On a Windows computer, right-click the zip file, and select "Extract All." Browse to the destination folder where you want to save the uncompressed file, and click "Extract."
On a Mac computer, just double-click the zip file.
In the next tutorial, you'll start connect an input and output to your Photon to create a "Smart Light" device.
Next, you'll use the "Hello World" app as starter code for your "Smart Light" device app. You'll use this code to verify that you connected the LED correctly.
One person on your team should log in to Particle Build using your team's Particle account login.
Once you're logged in, you should see a new app template in the code editor. (If not, just click the "Create New App" button in the Code menu panel.)
Enter smart-light
as your app's title.
You'll use the hello-world
app as starter code for your smart-light
app:
COPY CODE: When using this IoT code guidebook, you can copy a code block simply by clicking the copy icon displayed in the upper right of the code block.
Copy the "Hello World" code above.
In the code editor panel, select all the existing code in the smart-light
app, and then replace it by pasting in the copied code.
Save your smart-light
app code by clicking the Save icon in the left navigation bar.
You'll need to make a few changes to the app code:
Modify the comment block: Change Hello World
to Smart Light Device
, and be sure your team info, teacher's name, and class period are correctly listed.
Modify line 7 that declares the LED
variable: Change the variable's value from D7
to D0
(or whichever pin number your LED is connected to). This will allow your app to control your LED.
Be sure your Photon device is connected to Wi-Fi and Particle Cloud.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar. (Particle Build will first save and verify your code before flashing it to your device.)
Once your Photon has downloaded the new app and restarted, the updated app will start running:
Confirm that the LED light that you connected to your Photon circuit board blinks on and off in a repeating pattern (with the light turning on for 1 second and then turning off for 1 second). The blue D7 light should be turned off.
If the LED light that you connected is not blinking, then there is a mistake in your app code – or a mistake in your wiring connection – or a mistake in both.
If the blue D7 light is blinking, then check your app code to verify whether you changed the pin number assigned to the LED
variable. If necessary, revise your code, and flash the updated app to your device.
Otherwise, verify that the LED light's positive leg (the bent leg) is connected (via a jumper wire) to the same I/O pin number that is assigned to the LED
variable in your app code. If necessary, change either your wiring or your code, so the pin numbers match. If you revised your code, flash the updated app to your device.
If that still doesn't solve the issue, then double-check all your wiring by referring back to the connection instructions.
Next, you'll add the CSS for your web app's stylesheet.
Copy this CSS, and paste it into a blank CSS file named style.css
:
As you can see, this CSS has style declarations for 4 types of elements in your HTML:
The CSS for body
styles the <body>
section in your HTML.
The CSS for .card
styles elements in your HTML that have class="card"
. The <div>
element has this class.
The CSS for .light-on
styles any elements in your HTML that have class="light-on"
. Currently, no elements have this class. However, your web app JS will add this class to the <div>
element if your light is turned on (changing the card's background color to yellow) and will remove this class if your light is turned off (changing the card's background color back to gray).
The CSS for button
styles the <button>
element in your HTML.
CSS: If you want to learn more about CSS or need a quick reference, check out the W3Schools CSS Tutorial and Reference.
If you preview the web app at this point, you can see how the CSS has changed the appearance of the web app, but it still doesn't function yet (because there's still no JS in the code.js
file).
Next, you'll add JavaScript code to allow your web app to interact with your Photon device through Particle Cloud. Remember that the web app will perform these two tasks:
The web app will display whether the LED light is currently turned on or off. The web app will do this by getting the current value of the lightStatus
variable in your Photon device app.
The web app will display a button that can be clicked to remotely turn the LED light on or off. The web app will do this by calling the toggleLight()
function in your Photon device app.
The Particle API JS library defines a class named Particle()
which you'll use to create an object. An object is a special type of variable that has its own methods (functions) and properties (variables).
Copy this JavaScript code statement, and paste it into a blank JS file named script.js
:
This will create a new Particle()
object and assign it to a global variable named particle
. Your web app JS will use this object's methods to interact with Particle Cloud.
In order for a web app to interact with a Photon device through Particle Cloud, the web app must provide the Photon's device ID and access token with each request. This ensures your web app interacts with the correct device – and prevents unauthorized apps from accessing your device.
You will declare global variables in your web app JS to store your Photon device ID and access token. You'll need to get their values from your Particle Build account.
Add this JS code to your script.js
file, and modify it to list your Photon device ID and access token:
IMPORTANT: You must modify this code to replace "0000"
with your actual Photon device ID and access token. Otherwise, your web app will not work properly.
Your Photon's unique device ID is listed in the Devices menu of your Particle Build account:
Click the Devices icon in the left navigation bar.
In the Devices menu panel, click the drop-down arrow to the right of your Photon device name.
Select and copy the device ID.
Paste the device ID into your JS code as the value for myDevice
(the device ID must be listed within quotation marks).
Your Photon's unique access token is listed in the Settings menu of your Particle Build account:
Click the Settings icon in the left navigation bar.
In the Settings menu panel, select and copy the access token.
Paste the access token into your JS code as the value for myToken
(the access token must be listed within quotation marks).
Your web app JS will use the particle.getVariable()
method to get the value of a Photon device variable stored as a cloud variable in Particle Cloud.
Add this JS code to your script.js
file:
This adds a custom function named checkLights()
to your JS. Inside this custom function is a call to the particle.getVariable()
method.
The particle.getVariable()
method requires your Photon device ID, the name of the cloud variable, and your Photon access token:
myDevice
is the global variable that stores your Photon device ID
"lightStatus"
is the name of the cloud variable whose value you want to get.
myToken
is the global variable that stores your Photon access token
When Particle Cloud returns the value of your cloud variable, the value gets temporarily stored in a local variable called: data.body.result
In your Photon device app, the lightStatus
variable has a value of either "on"
or "off"
. Therefore, in your web app JS, data.body.result
will also be one of these values.
Inside the particle.getVariable()
method are JS and jQuery code statements (lines 4-13 above) that were added to perform actions based on the value returned for the Photon variable.
An if-else statement is used to determine whether data.body.result
has a value equivalent to "on"
or "off"
. Then jQuery statements (which start with $
) are used to dynamically change the information displayed in the "card" by targeting specific id selectors:
$("#light1")
targets the HTML element with id="light1"
which is the <div>
element that represents the "card" displaying the information for the light. The jQuery statements either add or remove the light-on
CSS class (which changes the card's background color to yellow).
$("#light1-status")
targets the HTML element with id="light1-status"
which is an <h2>
element. The jQuery statements change this element's HTML to list either ON
or OFF
.
$("#light1-button")
targets the HTML element with id="light1-button"
which is the <button>
element that can be clicked to remotely turn the light on or off. The jQuery statements change this element's HTML to list either Turn Off
or Turn On
as the button's label.
JAVASCRIPT: If you want to learn more about JS or need a quick reference, check out the W3Schools JavaScript Tutorial and Reference.
JQUERY: If you want to learn more about jQuery or need a quick reference, check out the W3Schools jQuery Tutorial and Reference.
If your web app needs to continuously monitor the value of a Photon variable, you can use the window.setInterval()
method to automatically call a JS function at a set time interval (such as every 5 seconds, etc.).
Add this JS code statement to your script.js
file:
The window.setInterval()
method requires two parameters inside its parentheses (in this order):
The name of the JS function to be called, which should be the name of the custom function in your JS that contains the particle.getVariable()
method for the variable you need to monitor. The function's name should be listed without a set of parentheses. In this case,checkLights
is the name of the function.
The time interval between calls, which will be the amount of time between each call to the JS function. The time interval is specified in milliseconds (1000 ms = 1 second). In this case, the interval was set to 200
ms (every 0.2 seconds).
Your web app JS will use the particle.callFunction()
method to call a function in your Photon device app by calling its cloud function reference in Particle Cloud.
Add this JS code to your script.js
file:
This adds a custom function named toggleLight1()
to your JS. Inside this custom function is a call to the particle.callFunction()
method.
The particle.callFunction()
method requires your Photon device ID, the name of the cloud function, an argument (a String parameter for the Photon function), and your Photon access token:
myDevice
is the global variable that stores your Photon device ID
"toggleLight"
is the name of the cloud function that you want to call (which will call its corresponding function in your Photon device app)
"data"
is the String parameter that will be passed into the Photon device function. If this text parameter isn't actually used within the Photon function, then it can be any text string enclosed within double quotation marks – even an empty text string of ""
will work.
myToken
is the global variable that stores your Photon access token
The <button>
in your web app HTML contains an onclick event attribute that will run this toggleLight1()
function whenever the button in the web app is clicked.
Be sure your Photon device is connected to Wi-Fi and Particle Cloud.
Refresh your web app, and test it with your Photon device to make sure they interact correctly:
Verify that your web app displays the current status of your Smart Light. Use the push button connected to your Photon device to turn the LED light on or off. Verify that your web app updates automatically to show the correct light status.
Verify that your web app can remotely turn your Smart Light on and off. Click the button in your web app, and verify that your Photon device automatically toggles the LED light on or off.
In the next tutorial, you'll modify your "Smart Light" device into a "Smart Security" device by adding a motion sensor and speaker to your existing LED light and push button. Then you'll program a new Photon app and new web app for the modified device.
Next, you'll add code in your Smart Security device app to control the speaker.
The basic steps to control a speaker in your app code are:
Declare a global variable to store the I/O pin number for the speaker.
Set the pin mode for the speaker pin in the setup()
function.
Use tone()
statements to produce sounds.
Declare a global variable to store the I/O pin number for the speaker by adding this code statement before the setup()
function:
If you connected your speaker to a different I/O pin other than D1
, then modify this code statement to list the correct pin number for your speaker.
Set the pin mode for your speaker pin by adding this code statement within the setup()
function (between the curly braces):
The speaker will be used to produce an "alarm sound" if the motion sensor detects motion.
The tone()
method is used to produce a sound of a specific frequency (pitch) for a specific duration of time. The speaker can produce tones ranging in frequency from 20Hz (very low pitch) to 20KHz (very high pitch), covering the full range of sounds that humans can hear.
Add this code statement within your checkMotion()
custom function (inside the curly braces of the if
statement that checks the value of motionState
– add the code before the delay()
):
The tone()
method requires three parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D1
, etc.) or a variable that stores a pin number. In this case, the variable named speaker
is listed.
The frequency for the tone, which can be an integer value (whole number) or a variable that stores an integer. The value can be between 20-20000 hertz. Lower numbers will have a lower pitch, while higher numbers will have a higher pitch. In this case, the frequency will be 1000
hertz, which will be a "less annoying" pitch than what an alarm sound would typically use.
The duration for the tone, which can be an integer number (whole number) or a variable that stores an integer. The value represents the number of milliseconds that the tone will be played (1000 ms = 1 second). In this case, the duration will be 250
ms (0.25 seconds), which will be a much shorter duration than what an alarm sound would typically use.
Be sure your Photon device is connected to Wi-Fi and Particle Cloud.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar. (Particle Build will first save and verify your code before flashing it.)
Once your Photon has downloaded the new app and restarted, the updated app will start running:
Press the button to "arm" your Smart Security device. (This simulates having entered a passcode into a keypad to arm the device.) The LED light should turn on when the device is in "armed" mode. Confirm that the speaker produces an alarm sound when motion is detected. The sensor should be able to detect motion in the environment up to 10 feet away.
Press the button again to "disarm" the device (the LED should turn off). Because of the 2 second delay required when motion is detected, you may have to press the button more than once (or hold the button down slightly longer). Once the device is in "disarmed" mode, confirm that motion near the sensor does not produce an alarm sound.
Physical buttons that people can push are used as inputs on many different types of devices. Your Photon kit should have a set of 4 push buttons with different cap colors: red, yellow, green, and blue.
In this step, your team will connect a push button to your Photon circuit board using the breadboard.
You'll need these components:
1 push button (could be any color, but use same color as your LED)
2 jumper wires (use two different colors to help identify them)
Follow these instructions explaining how to connect the button. The button can be connected to almost any I/O pin, but connect it to the D2 pin (which will match the wiring diagram).
Next you'll flash your "Hello World" app to your Photon device to run the app.
Be sure your Photon is powered on and connected to Wi-Fi and Particle Cloud.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar. (Particle Build will first save and verify your code before flashing it.)
Your Photon will download the app from Particle Cloud over Wi-Fi and store the app in your Photon's flash memory. While this is occurring, you should see that the RGB light on your Photon's circuit board will blink pink.
Once the download is complete, your Photon will automatically restart itself. You'll see the RGB light on your Photon blink green while it tries to reconnect to Wi-Fi. Once your Photon has reconnected to Wi-Fi and Particle Cloud, the RGB will be "breathing" cyan (light blue).
Once your Photon has downloaded the new app and restarted, your new app will automatically start running:
Confirm that the blue D7 LED light on your Photon's circuit board blinks on and off in a repeating pattern (with the light turning on for 1 second and then turning off for 1 second).
If so, then you've successfully programmed the "Hello World" app for your Photon device. Your teacher may want to see your Photon device to confirm that your team's app is working.
APP ISSUES: If the app doesn't work correctly (such as: D7 LED doesn't turn on, D7 LED doesn't turn off, etc.), then double-check your app code in Particle Build. If necessary, consult with another team or your teacher to figure out what the issue might be.
Next, you'll modify your Smart Light device app to allow a web app to interact with your Photon through the internet.
All of your Photon's internet communications are routed through the Particle Cloud service, which offers these ways that a web app can interact with a Photon device through Particle Cloud:
A web app can get the value of a Photon device variable
A web app can call a custom function on a Photon device
A web app can get event notifications from a Photon device
The web app that you'll be creating for your Smart Light device will perform these two tasks:
The web app will display whether the LED light is currently turned on or off. The web app will do this by getting the current value of the lightStatus
variable in your Photon device app.
The web app will display a button that can be clicked to remotely turn the LED light on or off. The web app will do this by calling the toggleLight()
function in your Photon device app.
You'll need to add some code to your Photon device app that will allow your web app to get the value of the lightStatus
variable and to call the toggleLight()
function.
In order for a web app to get the value of Photon device variable, your Photon device app must share the variable through Particle Cloud using the Particle.variable()
method.
Share the lightStatus
variable through Particle Cloud by adding this code statement within the setup()
function of your Photon app:
This Particle.variable()
code statement creates a "cloud variable" that stores the value of your Photon device variable. Whenever the value of the device variable changes in your Photon app, the value stored in the cloud variable will be automatically synced to match.
The Particle.variable()
method requires two parameters inside its parentheses (in this order):
The cloud variable name, which can be up to 12 characters in length. If possible (for simplicity), make your cloud variable name match your device variable name. However, the cloud variable is allowed to have a different name. The cloud variable name must be listed within double quotation marks. In this case, "lightStatus"
will be the name of the cloud variable (which matches the device variable name).
The Photon device variable name, which is the variable in your Photon app whose value will be shared in Particle Cloud. In this case, you're sharing the value of the lightStatus
variable.
In order for a web app to call a function that runs on your Photon device, your Photon device app must share the function through Particle Cloud using the Particle.function()
method.
Share the toggleLight()
function through Particle Cloud by adding this code statement within the setup()
function of your Photon app:
This Particle.function()
code statement creates a "cloud function" that is a reference to the custom function in your Photon device app. Whenever your web app calls the cloud function, the corresponding device function in your Photon app will automatically be called.
The Particle.function()
method requires two parameters inside its parentheses (in this order):
The cloud function name, which can be up to 12 characters in length. If possible (for simplicity), make your cloud function name match your device function name. However, the cloud function is allowed to have a different name. The cloud function name must be listed within double quotation marks without parentheses after its name. In this case, "toggleLight"
will be the name of the cloud function (which matches the device function name).
The Photon device function name, which is the custom function in your Photon device app that will be shared through Particle Cloud. List the function name without parentheses after its name. In this case, you're sharing the toggleLight
function in your Photon app.
A Photon device function that is shared through Particle Cloud must do the following:
The Photon function must accept a String parameter when the function is called.
The Photon function must return an integer value when the function is performed.
Currently, the toggleLight()
function does not do these things – but you can easily modify the function to work with Particle Cloud with these minor changes:
Change toggleLight()
to toggleLight(String data)
. This adds a parameter inside the parentheses that will be accepted when the function is called: String
is the data type for the parameter (a text string), and data
is the name of a local variable that will store the parameter value (the text string). If desired, you could use a different name other than data
.
In front of the function name, change void
to int
. This indicates that the function will return an integer value (whole number), instead of no value (which is what void
represents).
Add the code statement return 1;
inside the function at the end before the closing curly brace. This code statement will return an integer value of 1 whenever the function is performed. This is the simplest way to ensure the function returns an integer value.
Your custom function should look like this now:
You might notice that there aren't any code statements within the curly braces of the toggleLight()
function that actually use the data
parameter variable. That's actually okay – the function does have to accept a String parameter, but it doesn't have to use the parameter inside in the function.
However, depending on what a custom function is supposed to do, the text string passed into the data
parameter could be used to decide what action(s) are performed within the custom function. In this case, you won't do that, but it is an option that's available.
Once a custom function in your Photon device app has been modified to be shared through Particle Cloud, your Photon app (and your web app) must include a text string when calling the function.
In your Photon app, there's just one code statement that calls the toggleLight()
function. Inside the loop()
function, there is an if
statement that calls the toggleLight()
function when the button is pushed (buttonState == LOW
):
Inside this if
statement, change toggleLight();
to toggleLight("data");
In this case, "data"
will be the text string passed into the parameter when this function is called. However, since this function doesn't actually do anything with the parameter value, this text string could be any text listed within double quotation marks – even an empty text string of ""
would work.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar.
Once your Photon has downloaded the app and restarted, the updated app will start running. You shouldn't notice any visible changes in the device's behavior, but your Photon app will now be sharing the lightStatus
variable and toggleLight()
function with Particle Cloud.
Confirm that the LED light still toggles between "on" and "off" each time the button is pressed.
LEDs (light-emitting diodes) are small, bright, long-lasting, energy-efficient lights. Your Photon kit has a set of LED lights with different bulb colors: red, yellow, green, and blue.
In this first step, your team will connect an LED light to your Photon circuit board using the breadboard.
You'll need these components:
1 LED light (any color)
1 resistor
2 jumper wires (use two different colors to help identify them)
Follow these instructions explaining how to connect the LED. The LED can be connected to almost any I/O pin, but connect it to the D0 pin (which will match the wiring diagram).
In this fourth tutorial, you'll modify your "Smart Light" device into a "Smart Security" device and program new apps for the device.
The goals of this fourth tutorial are to help you:
Gain further experience by creating another practice IoT device and programming its apps
Become better prepared to create your own IoT device and apps for your team project
For decades, security systems have been used to monitor homes and businesses for emergencies (burglary, fire, flood, etc.). These systems use some combination of: motion sensors, door/window sensors, glass break sensors, video cameras, smoke detectors, flood sensors, etc. Today, many security systems are being connected to the internet to offer additional features.
You'll create a prototype of a Smart Security device by modifying your Smart Light device (which has an LED light and push button) to add a motion sensor and a speaker:
The LED light will be used to indicate whether the security system is currently "armed" (LED is on) or "disarmed" (LED is off).
The push button will be used to switch the security system between "armed" and "disarmed" mode. (The button will simulate a security system's keypad, which is used to enter a numeric passcode. For this prototype device, you'll simply press the button to toggle the system between modes, as if you had correctly entered a passcode.)
The motion sensor will detect whether something is moving within the surrounding area.
The speaker will be used to produce an alarm sound if motion is detected.
You'll use a copy of your Smart Light device app as starter code for your Smart Security device app. You'll modify the existing code controlling the LED and button before adding new code to control the motion sensor and speaker.
You'll also program a web app that interacts with your Photon over the internet to perform these tasks:
Monitor the security system's current mode ("armed" or "disarmed")
Remotely toggle the security system between "armed" or "disarmed" mode
Receive an event notification if the security system detects motion
View the date and time of the last motion event detected
Your Photon kit includes a small speaker that can produce tones or play simple music (note by note).
In this step, your team will connect the speaker to your Photon circuit board using the breadboard.
You'll need these components:
Speaker
2 jumper wires (use different colors to help identify them)
Follow these instructions explaining how to connect the speaker. The speaker can be connected to any I/O pin capable of PWM, but connect it to the D1 pin (which will be different from the wiring diagram).
NEED LED & BUTTON: Be sure the LED and button from your Smart Light device are still connected. If not, connect an LED to the D0 pin and connect a push button to the D2 pin.
Your Photon kit includes a motion sensor that uses passive infrared (PIR) light to detect movement in the surrounding environment up to 10 feet away.
In this step, your team will connect the motion sensor to your Photon circuit board using the breadboard.
You'll need these components:
Motion sensor (with 3-pin connector)
3 jumper wires (use different colors to help identify them; it may help to match the sensor wires)
Follow these instructions explaining how to connect the motion sensor. The sensor can be connected to almost any I/O pin, but connect it to the D3 pin (which will be different from the wiring diagram).
5V REQUIRED: The motion sensor requires 5V of power to operate, so the sensor's red wire must be connected to the VIN pin or V-USB pin, depending on your Photon's power source.
If your Photon is being powered through the barrel jack, connect to the VIN pin.
If your Photon is being powered through the Micro-USB port, connect to the V-USB pin.
Next, you'll use your Smart Light device app as starter code for your Smart Security device app. The LED and button code in the two apps will be nearly identical – you'll just make a few minor changes. After that, you'll be ready to start adding new code for the motion sensor and speaker.
One person on your team should log in to Particle Build using your team's Particle account login.
Once you're logged in, you should see a new app template in the code editor. (If not, just click the "Create New App" button in the Code menu panel.)
Enter smart-security
as your app's title.
You'll use your smart-light
app as starter code for your smart-security
app:
The Code menu panel lists all your saved apps under "My apps." Click on your smart-light
app to load its code into the code editor panel. (If the Code menu panel is not visible, just click the Code icon in the left navigation bar to show the Code menu panel.)
In the code editor panel, select all the existing code in your smart-light
app, and copy it.
In the Code menu panel, click on your smart-security
app listed under "My apps" to load it into the code editor panel. (If the Code menu panel is not visible, just click the Code icon in the left navigation bar to show the Code menu panel.)
Select all the existing code in your smart-security
app, and then replace it by pasting in the copied code from your other app.
Save your smart-security
app code by clicking the Save icon in the left navigation bar.
The LED and button code in the Photon app will remain essentially the same. You'll just make some minor changes to the lightStatus
variable and toggleLight()
function:
Change the name of lightStatus
to deviceMode
. There should be 6 places in the code where this change needs to be made.
The possible values for lightStatus
were "off"
or "on"
. Find the 3 places in the code where "off"
is listed, and change each one to "disarmed"
instead. There is 1 place in the code where "on"
needs to be changed to "armed"
instead.
Change the name of toggleLight
to toggleMode
. There should be 4 places in the code where this change needs to be made.
In the comments at the top of the code, change Smart Light Device
to Smart Security Device
.
These modifications do not change how the code functions – it just makes the code make more sense when you read it, since this app will control a Smart Security device (instead of a Smart Light).
Be sure your Photon device is connected to Wi-Fi and Particle Cloud.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar. (Particle Build will first save and verify your code before flashing it to your device.)
Once your Photon has downloaded the new app and restarted, the updated app will start running:
Confirm that the device still functions like the Smart Light did: the LED light should toggle between on and off each time the button is pressed. When the LED is turned on, it indicates the security system is in "armed" mode. When the LED is turned off, the security system is "disarmed."
In the next steps, you'll add code for the motion sensor and speaker to made the security system fully functional when it's "armed."
Next, you'll modify your Smart Security device app to allow a web app to interact with your Photon through the internet.
Remember that all your Photon's internet communications are routed through Particle Cloud, which provides these ways for your web app to interact with your Photon device:
A web app can get the value of a Photon device variable
A web app can call a custom function on a Photon device
A web app can get event notifications from a Photon device
The web app that you'll be creating for your Smart Security device will perform these tasks:
The web app will display whether the security device is currently armed or disarmed. The web app will do this by getting the value of the deviceMode
variable in your Photon device app.
The web app will display a toggle switch that can be clicked to remotely toggle the security device between armed and disarmed mode. The web app will do this by calling the toggleMode()
function in your Photon device app.
The web app will display a notification if the security device detects motion while the device is armed. The web app will also display the date and time when a motion event was last detected. The web app will do this by receiving event notifications sent from your Photon device app.
You'll need to add some code to your Photon device app to allow it to interact with your web app.
Your Photon app should have existing code statements from your Smart Light app which you modified that will share the deviceMode
variable and toggleMode()
function through Particle Cloud.
Be sure the following code statements are already listed within the setup()
function (do not add this code again if it already exists):
Your Photon device app can send an event notification using theParticle.publish()
method. This will create a "cloud event" in Particle Cloud that will stream the event notification to your web app.
By default, Particle Cloud will clear each cloud event after 60 seconds to prevent your web app from receiving outdated notifications.
An event notification can be sent with or without data:
An event notification sent without data acts like a simple alert that the event occurred.
An event notification sent with data will include additional information as a text string (up to 255 characters).
Particle Cloud will allow your Photon device to send about 1 event notification per second. If your device sends event notifications more frequently than this, Particle Cloud will intentionally slow down your event stream (with a 4-second delay), which can cause issues with your web app performance.
To prevent this, include a delay()
of at least 1 second after a Particle.publish()
statement (because a 1-second delay added by you is better than a 4-second delay added by Particle Cloud).
For your Smart Security device, your Photon app should send an event notification (without additional data) whenever the motion sensor detects motion.
Send an event notification through Particle Cloud by adding this code statement within your checkMotion()
custom function (after the tone()
statement but before the delay()
statement):
The Particle.publish()
method requires a parameter for the cloud event name, which can be up to 63 characters in length. The name must be listed within double quotation marks. In this case, "motion"
will be the name of the cloud event.
Since your code already has a delay()
statement on the next line for the motion sensor, this existing delay()
will also prevent your Photon app from sending event notifications too frequently.
Flash your app code to your Photon device by clicking the Flash icon in the left navigation bar.
Once your Photon has downloaded the app and restarted, the updated app will start running. You shouldn't notice any changes in the device's behavior, but your Photon app will now send a "motion"
event notification to Particle Cloud every time motion is detected while the device is armed.
Next, you'll add code in your Smart Security device app to control the motion sensor.
The basic steps to use a motion sensor in your app code are:
Declare a global variable to store the I/O pin number for the motion sensor.
Set the pin mode for the motion sensor pin in the setup()
function.
Use a digitalRead()
statement to check whether the sensor detects any motion, and add code statements that should be performed if motion is detected (or not detected).
Declare a global variable to store the I/O pin number for the motion sensor by adding this code statement before the setup()
function:
If you connected your motion sensor to a different I/O pin other than D3
, then modify this code statement to list the correct pin number for your motion sensor.
Set the pin mode for your motion sensor pin by adding this code statement within the setup()
function (between the curly braces):
The digitalRead()
method is used to check whether the sensor currently detects any motion.
The digitalRead()
method will return a value of either HIGH
or LOW
(which are treated as if they were int
values):
HIGH
indicates that motion is NOT currently detected.
LOW
indicates that motion is currently detected.
A variable named motionState
will store the value returned by the digitalRead()
method.
You'll add a custom function named checkMotion()
that will contain all this code.
Add this checkMotion()
custom function after the loop()
function (you can add it before or after the toggleMode()
function):
Inside the if
statement, you'll need to add code to do something if motion is detected. In the next step of this tutorial, you'll add code here to make an "alarm sound" using the speaker. Later, you'll also add code to send an event notification to the web app that you'll be creating.
You'll notice that a delay()
of 2 seconds is performed when motion is detected. This delay is needed to allow the sensor to capture a new "snapshot" of the environment before checking the sensor again.
The checkMotion()
function will only be performed if it is called within another function, such as the loop()
function. However, the motion sensor should only be checked if the device's mode is currently set to "armed"
.
Add this code within the loop()
function (after the closing curly brace of the existing if
statement that checks the value of buttonState
):
This code will only call the checkMotion()
function if the value of deviceMode
is equivalent to "armed"
.
Save your smart-security
app code by clicking the Save icon in the left navigation bar.
Next, you'll create a web app that will interact with your Smart Security device through Particle Cloud.
Your web app will consist of an HTML file namedindex.html
, a CSS file named style.css
, and a JavaScript file named script.js
.
Remember that Particle Build is only used to code your Photon device app. You'll need to use a different code editor to create the HTML, CSS, and JS files for your web app. Consult your teacher to determine which code editor will be most appropriate to use for your web app files.
, and paste it into a blank HTML file named index.html
.
The starter HTML contains blank lines where you'll add custom HTML for your specific web app.
Copy this HTML, and paste it into the blank lines within the <body>
of your starter HTML code:
COPY CODE: When using this IoT code guidebook, you can copy a code block simply by clicking the copy icon displayed in the upper right of the code block.
If you preview the web app at this point, it's very plain (because there's no CSS in the style.css
file) and it doesn't function yet (because there's no JS in the code.js
file).
is an online code editor (web IDE) provided by Particle. Particle Build is part of the Particle Cloud platform. You will use Particle Build to code and store all your Photon device apps.
The Photon device itself can only store and run one app at a time. However, you can create and save multiple apps in Particle Build. When you need to update the specific app stored on your Photon device, you'll do this in Particle Build – and your Photon will download the new app over Wi-Fi.
Your team will need a Particle account to log in to Particle Build. However, your teacher will most likely provide your team with an existing Particle account login (email & password) that's already associated with your specific Photon device. Every Photon has a unique device ID it uses to communicate with Particle Cloud, and each device ID can only be associated with one Particle account.
One person on your team should log in to Particle Build using your team's Particle account login.
Once you're logged in, you'll see the Particle Build code editor, which defaults to the "Code" menu and shows a blank app template.
The user interface for Particle Build is divided into 4 sections:
On the far left is a vertical navigation bar with icons.
On the middle left is a menu panel showing options for the current navigation selection.
On the right side is the code editor panel showing the code for your current app.
On the bottom of the code editor panel is a horizontal status bar that displays messages.
If you hover your mouse pointer over an icon in the navigation bar, the icon's name will be displayed. Here is a summary of the navigation icons from top to bottom:
The middle menu panel can be toggled between "show" and "hide" by clicking the same navigation icon repeatedly.
In general, you'll probably want to keep the menu panel shown – but if you want extra space for your code editor panel, you can temporarily hide the menu panel.
All the apps that run on your Photon device will be coded using Particle's version of the open-source programming language framework for microcontrollers.
The on your Photon runs a modified version of the Wiring language with a few minor differences, as well as some additional methods (functions) customized for the Photon hardware.
WIRING VS. ARDUINO: is another programming language framework for microcontrollers. It turns out that Arduino is based on Wiring, so the two languages are nearly identical (though there are some differences). In most cases, a program originally written in Arduino will work on your Photon with only minor revisions. So once you've learned how to program in one of these languages, you've basically learned both.
WIRING VS. C++: Wiring (like Arduino) is a programming framework written in C++, so you can also directly incorporate C++ code within your device app.
When you create a new device app in , a basic app template is provided that consists of an empty setup()
function and an empty loop()
function:
If you want an app template that provides more guidance, you can replace the default app template with the code below, which has some comments to explain each major section of your app:
COPY CODE: When using this IoT code guidebook, you can copy a code block simply by clicking the copy icon displayed in the upper right of the code block.
Every Photon device app must have one (and only one) setup()
function. You can add lines of code between this function's opening and closing curly braces.
The setup()
function will run one time when your app first starts (which is when your Photon is first powered on – or is restarted using its Reset button).
The code added within the setup()
function typically sets pin modes for the device's inputs and outputs, initializes settings for certain inputs and outputs, or performs other "setup" actions that need to occur at the start of the program.
Even if you didn't add any code within the setup()
function, your app must still have this function.
Every Photon device app must have one (and only one) loop()
function. You can add lines of code between this function's opening and closing curly braces.
After the setup()
function is done running, the loop()
function will start to run. When all the code within the loop()
function has been performed, the loop()
function will automatically run itself again. It keeps running in an endless loop (until the device is restarted or powered off).
The code added within the loop()
function performs the main tasks of your program.
Even if you didn't add any code within the loop()
function, your app must still have this function.
Besides having the required setup()
and loop()
functions, your Photon device apps will typically have some or all of the following:
Comments
Libraries
Global Variables
Custom Functions
It's a good idea to have at least one comment at the beginning of your app code to provide a name and/or description of your app.
Any comments in your app are ignored when the program is compiled and uploaded to your device.
Some device apps might include (i.e., import) one or more library files. A library is a file of pre-built code that provides additional functions that your program can utilize. For example, certain inputs and outputs have their own code library with functions to make it easier to control the input or output.
Your device app will typically have code that declares global variables which store data used in your program's functions, such as pin numbers for sensors, etc.
Global variables are usually listed before the setup()
function (to make it easier to read the code).
You can also add your own custom functions to your device app. Each custom function must have a unique function name.
Custom functions are typically used to contain code that performs specific tasks or subtasks. Having custom functions in your app is optional, but they can help break up your code into smaller modules that are easier to understand (and easier to re-use). So rather than listing all your main program code within the loop()
function, you can subdivide some or all of the code into custom functions.
The code within a custom function is only run if and when that custom function is "called" (by listing the function's name) within the setup()
or loop()
function. A custom function can also be "called" within another custom function.
Custom functions are usually listed after the loop()
function (to make it easier to read the code).
If you want to learn more about programming your Photon device, consult these references:
Next, you'll add JavaScript code to allow your web app to interact with your Photon device through Particle Cloud. Remember that the web app will perform these tasks:
The web app will display whether the security device is currently armed or disarmed. The web app will do this by getting the value of the deviceMode
variable in your Photon device app.
The web app will display a toggle switch that can be clicked to remotely toggle the security device between armed and disarmed mode. The web app will do this by calling the toggleMode()
function in your Photon device app.
The web app will display a notification if the security device detects motion while the device is armed. The web app will do this by receiving event notifications sent from your Photon device app.
, and paste it into a blank JS file named script.js
.
IMPORTANT: You must modify this JS code to . Otherwise, your web app will not work properly.
Copy this JS, and paste it after your modified starter JS:
This custom JS does 5 main things:
Stores an audio file in a JS global variable named alertSound
Sets a time interval to call a JS function named checkMode()
Adds a JS function named checkMode()
that will get the value of a Photon variable
Adds a JS function named toggleMode()
that will call a Photon function
Starts listening for "motion"
event notifications sent by your Photon device
The window.setInterval()
method will automatically call the function named checkMode()
every 500
ms (0.5 seconds).
The function named checkMode()
contains a call to the particle.getVariable()
method that will get the current value of the "deviceMode"
variable in your Photon app.
Inside the particle.getVariable()
method are JS and jQuery code statements (lines 8-15 above) that were added to perform actions based on the value returned for the Photon variable.
$("#system-mode")
targets the HTML element with id="system-mode"
. The jQuery statements change this element's HTML to display either ARMED
or DISARMED
.
$("input [name=toggle])
targets the <input>
element with name="toggle"
. The jQuery statements change its "checked"
property to either true
(checked) or false
(unchecked), which changes the toggle switch slider position.
Since the window.setInterval()
method will keep calling this function every 0.5 seconds, your web app will continuously monitor the current mode of your Smart Security device.
The function named toggleMode()
contains a call to the particle.callFunction()
method that will call the "toggleMode"
function in your Photon app to remotely switch your device's mode between "armed" and "disarmed".
The particle.getEventStream()
method is used to start listening for event notifications sent from your Photon app.
The particle.getEventStream()
method requires your Photon device ID, the name of your cloud event, and your Photon access token:
myDevice
is the global variable that stores your Photon device ID
"motion"
is the name of the cloud event that you want to receive notifications from
myToken
is the global variable that stores your Photon access token
If an event notification includes any data, this text string data gets temporarily stored in a local variable called: feed.data
Code statements added within the particle.getVariable()
method will be performed whenever an event notification is received.
In this case, JS and jQuery code statements (lines 29-33 above) were added that will perform these actions each time a new event notification is received:
Play the alertSound
Get the current date and time and store it in a variable named dateTime
Display the value of dateTime
in the HTML element with id="event-time"
Show the HTML element with id="motion-alert"
, wait for 1500
ms (1.5 seconds), and then fade out the element until it is hidden. This creates a visible "pop-up" notification in your web app.
NOTE: Since your Photon app is sending the "motion"
event notification without data, there aren't any JS or jQuery code statements using feed.data
(because no text string is being received).
Be sure your Photon device is connected to Wi-Fi and Particle Cloud.
Refresh your web app, and test it with your Photon device to make sure they interact correctly:
Verify that your web app displays the current mode ("armed" or "disarmed") of your Smart Security device. Use the push button connected to your Photon device to change the device mode. When the LED is turned on, the device is in "armed" mode. When the LED is turned off, the device is "disarmed." Verify that your web app updates automatically to show the correct device mode.
Verify that your web app can remotely change the device mode. Click the toggle switch in your web app, and verify that your Photon device automatically toggles modes (by checking the LED). It may take up to 2 seconds for the mode to switch due to the delay(2000)
in the Photon app.
While your Smart Security device is in "armed" mode, wave your hand over the motion sensor to trigger a motion event. Verify that your web app displays a motion notification pop-up (which will fade out after 1.5 seconds). Verify the web app displays the correct date and time for the last motion event notification.
Next, you'll add the CSS for your web app's stylesheet.
, and paste it into a blank CSS file named style.css
.
Copy this CSS, and add it after your starter CSS:
Your CSS should now have style declarations for several HTML elements:
The CSS for body
styles the <body>
section of your HTML.
The CSS for .card
styles elements in your HTML that have class="card"
. There are 2 <div>
elements that have this class. The first <div>
will be a "card" displaying information about your security system (current mode, toggle switch for mode, and time of last motion event). The second <div>
will be a "card" displaying a pop-up notification when motion is detected.
The CSS for #motion-alert
styles elements in your HTML that have id="motion-alert"
. The second <div>
has this id name and will be hidden (display: none
). When a motion event notification is received, your web app JS will use jQuery to briefly show this "card" and then hide it.
The rest of the CSS (for .switch
, .slider
, and input
) changes the checkbox input in your HTML to look and act like a toggle switch.
If you preview the web app at this point, you can see how the CSS has changed the appearance of the web app, but it still doesn't function yet (because there's still no JS in the code.js
file).
If you click your toggle switch, it will change appearance using CSS (but it requires JS to fully function).
An will be used to perform a set of actions if motion is detected (if motionState
has a value equivalent to LOW
).
VOID: Why is listed before the setup()
and loop()
functions? This is because each function in your Photon device app must declare a data type (such as: integer, boolean, etc.) for the data value returned by the function. In this case, void
indicates the function does NOT return any data value.
Comments are optional notes that you can insert to help explain or clarify portions of the code to anyone reviewing the program. Comments can be or .
Particle Build has a Libraries menu where you can search for existing libraries (or upload your own library file that you've created). When you select a library to be added to your app, Particle Build will automatically insert an statement for the library at the beginning of your app code.
A variable named alertSound
is declared that stores an audio file named "notification.wav"
. , and place it in the same folder as your web app files.
An if-else statement is used to determine whether data.body.result
has a value equivalent to "armed"
or "disarmed"
. Then jQuery statements (which start with $
) are used to dynamically change the information displayed in the first "card" by targeting specific :
The <input type="checkbox">
in your web app HTML contains an that will call this toggleMode()
function whenever the toggle switch in the web app is clicked.
If you have time and want to experiment with the other inputs and outputs in your Photon kit, you could explore the . (You can skip ahead to Experiment 3 or later.)
There are also references in this guidebook that show and explain how to connect and code each of the and included in your Photon kit.
Your team should now be ready to start thinking of possible ideas for .
In order for your web app to interact with your Photon device through Particle Cloud, you'll need to complete the following preparation steps:
Your web app HTML file needs to load several JS files (such as: Particle API JS library, etc.).
Your web app JS file needs to create a new Particle()
object.
Your web app JS file needs to declare variables to store your Photon device ID and access token.
Once these steps have been completed, you'll be ready to add code in your web app JS to read device variables, call device functions, and get device event notifications.
Your web app HTML file (index.html
) should include <script>
tags to load these JavaScript files:
Particle API JS library: particle.min.js
jQuery JS library: jquery.min.js
Your web app JS file: script.js
The Particle API JS library contains methods to allow your web app to interact with your Photon device through Particle Cloud. You'll use Particle methods in your web app JS file.
The jQuery JS library contains methods that make it easy to modify the content and style of your web app by dynamically changing its HTML and CSS. You'll use jQuery methods in your web app JS file.
JQUERY = OPTIONAL: Loading jQuery is optional. However, it will be much easier to code your web app JS if you can incorporate jQuery statements.
IMPORTANT: The <script>
tag in your HTML that loads the Particle API JS file (particle.min.js
) must be listed before the <script>
tag that loads your web app JS file (script.js
). Otherwise, if their order is reversed, your web app won't be able to interact with your Photon.
If possible, use a content delivery network (such as cdnjs or jsDelivr) to load the Particle API JS library and jQuery JS library.
Your web app JS file will be loaded as a local file from your web app folder (where your HTML and CSS files are located).
Add this to your web app HTML file within the <body>
section (just before the closing </body>
tag):
Alternatively, you could download local copies of the Particle API JS library and jQuery JS library. You will want the minified version of each file (min.js
), which has a smaller file size. If necessary, consult with your teacher to be sure you obtain the correct files.
Place the copies of the files into your web app folder (where your HTML and CSS files are located).
Add this to your web app HTML file within the <body>
section (just before the closing </body>
tag):
Be sure the file names listed in the <script>
tags match the file names in your web app folder.
Be sure your web app folder contains a JavaScript file named: script.js
This web app JS file will contain your JavaScript code to interact with your Photon device through Particle Cloud. Your JS code will also dynamically modify your HTML and CSS to display updated information from your Photon device.
The Particle API JS library defines a class called Particle()
that can be used to create an object variable with built-in methods (functions) to interact with a Photon device through Particle Cloud.
Your web app JS code must create a new Particle()
object, and assign it to a global variable, which is typically just named particle
.
Add this code statement at the beginning of your web app JS code:
In order for a web app to interact with a Photon device through Particle Cloud, the web app must provide a correct device ID and access token with each request. This ensures your web app communicates with the correct device – and prevents unauthorized apps from communicating with your device.
Your web app JS code will declare global variables to store your Photon device ID and access token. You'll get their values from your Particle Build account.
Add this code towards the beginning of your web app JS code, and then modify it:
IMPORTANT: You must modify this JS code to insert your actual Photon device ID and access token. Otherwise, your web app will not work properly.
Your Photon's unique device ID is listed in the Devices menu of your Particle Build account:
Click the Devices icon in the left navigation bar.
In the Devices menu panel, click the drop-down arrow to the right of your Photon device name.
Select and copy the device ID.
Paste the device ID into your JS code as the value for myDevice
(the device ID must be listed within quotation marks).
Your Photon's unique access token is listed in the Settings menu of your Particle Build account:
Click the Settings icon in the left navigation bar.
In the Settings menu panel, select and copy the access token.
Paste the access token into your JS code as the value for myToken
(the access token must be listed within quotation marks).
RESET TOKEN: If desired, you can reset your access token in the Settings menu of Particle Build. This generates a new random access token. However, your existing web apps will need to be updated with the new access token, in order to connect to Particle Cloud.
You can create a web app that interacts with your Photon device through Particle Cloud.
Your web app will consist of an HTML file namedindex.html
, a CSS file named style.css
, and a JavaScript file named script.js
.
If your web app will consist of a single screen, you can use the starter code below for your HTML, CSS, and JS files. Then you'll have to add your own code, as well as modify certain parts of the starter code.
If your web app will need multiple screens, use this other starter code instead.
You can use this starter code for your HTML file named index.html
:
COPY CODE: When using this IoT code guidebook, you can copy a code block simply by clicking the copy icon displayed in the upper right of the code block.
This HTML does three main things:
It loads a CSS stylesheet file.
It loads three JavaScript files.
It has blank lines where you'll add HTML for your specific web app.
In the <head>
section, there is a <link>
tag to load a CSS stylesheet file named style.css
that you'll use to modify the appearance of certain HTML elements in your web app.
At the bottom of the <body>
section, there are <script>
tags to load several JavaScript files into your web app:
Particle API JS library: particle.min.js
jQuery JS library: jquery.min.js
Your web app JS file: script.js
The Particle API JS library contains methods to allow your web app to interact with your Photon device through Particle Cloud. You'll use Particle methods in your web app JS file.
The jQuery JS library contains methods that make it easy to modify the content and style of your web app by dynamically changing its HTML and CSS. You'll use jQuery methods in your web app JS file.
In the <body>
section, there are several blank lines are where you will add HTML for your web app. (You can use more lines, obviously.) This is where you might display text, images, links, buttons, etc.
Your web app should consist of single HTML page. If you want different screens for your web app, then create a separate <div>
section for each screen, and give each <div>
a unique id name along with a class name shared by all the screen <div>
sections.
This will allow your web app JS to use jQuery code to show one screen while hiding the other screens. First, you use jQuery to hide()
all the screens (by selecting the class name), and then use jQuery to show()
one specific screen (by selecting its unique id name). To switch to a different screen, just hide()
all the screens again, and then show()
the new screen.
You can use this starter code for your CSS file named style.css
:
This CSS styles the <body>
section of your web app. However, you can modify this CSS if desired.
You'll typically want to add CSS to style other HTML elements in your web app, in order to produce the desired layout and appearance for your app's user interface.
You can use this starter code for your JS file named script.js
(be sure to modify):
IMPORTANT: You must modify this JS code to insert your actual Photon device ID and access token. Otherwise, your web app will not work properly.
This JS creates a new Particle()
object and assigns it to a global variable named particle
. This object has built-in methods (functions) that can be used to interact with your Photon device through Particle Cloud.
This JS also declares global variables to store your Photon device ID and access token. You must modify these lines to list your actual device ID and access token, which you will need to get from your team's Particle Build account.
Then you'll need to add the other necessary JS for your web app. Because your HTML file loaded the Particle API JS library and jQuery JS library, you can include Particle statements and jQuery statements within your JS code.
Review the reference section on Particle Cloud to learn how to make your web app JS interact with your Photon device app.
If you want to learn more about web development or need a quick reference, consult these tutorials and references from W3Schools:
Here are references for how to connect and code each physical input in your SparkFun Photon kit:
Ultrasonic Sensor (not standard part of SparkFun Photon kit, but your teacher may have added it)
OTHER SENSORS: There are references for other sensors such as RFID Reader, Fingerprint Scanner, and GPS Receiver in the old project guidebook. These references will eventually be transferred into this new code guidebook.
Icon | Name | Purpose |
Flash | Flashes the current app to your Photon device over Wi-Fi (The app will first be saved and verified. If there are errors in the app, it will not be flashed.) |
Verify | Complies the current app to check for errors (The app will first be saved.) |
Save | Saves the current app in Particle Build |
Code | Lists all your saved apps. Click an app's title to open it in the code editor. |
Libraries | Lists libraries that can be included in your app to add functionality |
Help | Lists quick help for device (might not be available for your Photon) |
Docs | Opens new tab with Particle Reference Documentation for your device |
Devices | Lists your devices. You can view the device ID, and signal device over Wi-Fi. (If you have multiple devices, you can select which device to flash apps to.) |
Console | Opens new tab with Console showing your device's events in Particle Cloud |
Settings | Provides options to: log out, change password, or get your access token. |
The defining feature of an IoT device is its ability to send and receive information through the internet. This allows an IoT device to interact with other apps or other IoT devices. For this project, you'll be creating a web app that interacts with your Photon device through the internet.
All of your Photon's internet communications are routed through the Particle Cloud service, which offers these ways that a web app can interact with a Photon device through Particle Cloud:
A web app can get the value of a Photon device variable
A web app can call a custom function on a Photon device
A web app can get event notifications from a Photon device
In order to make your Photon device interact with your web app, you'll need to add special code to both your Photon device app and your web app:
The Particle firmware on your Photon device has built-in cloud functions to allow your device to interact with a web app through Particle Cloud. You'll need to add code statements using these cloud functions in your Photon device app.
There is a Particle API JavaScript library that provides methods (functions) to allow your web app to interact with your Photon device app through Particle Cloud. You'll need to load this JS library in your web app's HTML file, and then add code statements using the library's methods in your web app's JavaScript file.
Your Photon device app can share a variable through Particle Cloud, so your web app can get the value of the variable.
For example, your Photon device app could measure the temperature of a room using a sensor, store the measurement in a variable, and share this variable's value through Particle Cloud, so your web app can get the variable's value and display it.
Your Photon device app will use the Particle.variable()
method to share the value of a device variable through Particle Cloud.
A "cloud variable" will be created to store the value of your device variable. Whenever the value of your device variable changes, the value stored in the cloud variable will be automatically synced to match.
Your web app will use the particle.getVariable()
method to get the value of your cloud variable.
Your Photon device app will use the Particle.variable()
method to share the value of a device variable through Particle Cloud by creating a cloud variable.
Add this code statement (be sure to modify) within the setup()
function of your Photon app:
The Particle.variable()
method requires two parameters inside its parentheses (in this order):
The cloud variable name, which can be up to 12 characters in length. If possible (for simplicity), make your cloud variable name match your device variable name. However, the cloud variable is allowed to have a different name. The cloud variable name must be listed within double quotation marks. Change "cloudVar"
to the actual name that you want to use for the cloud variable.
The Photon device variable name, which is the variable in your Photon device app whose value will be shared in Particle Cloud. Change deviceVar
to the actual name of the variable in your Photon app that you want to share.
Particle Cloud will let your Photon device share up to 20 cloud variables at one time. Each of your cloud variables in Particle Cloud has to be given a unique name (up to 12 characters in length).
If your Photon device app needs to share multiple variables, use a separate Particle.variable()
statement for each device variable being shared.
NOTE: The only data types that are allowed to be shared as cloud variables are:
int
(whole numbers)
double
(decimal numbers)
String
(text, up to 622 characters)
Be sure each Photon device variable being shared as a cloud variable uses one of these data types.
Your web app JS will use the particle.getVariable()
method to get the value of a Photon device variable stored as a cloud variable in Particle Cloud.
Add this code (be sure to modify) in your web app JS:
MODIFY CODE: You will need to make these changes to the example code above:
Change webFunction()
to the name you want to use for your custom function
Change "cloudVar"
to the name of your cloud variable whose value you want
Add code inside the particle.getVariable()
method to do something with the variable value returned as: data.body.result
This code adds a custom function named webFunction()
to your web app JS. This custom function contains a call to the particle.getVariable()
method, which will also contain code you'll add to perform action(s) based on the variable value returned by Particle Cloud.
Be sure to change webFunction()
to the actual name that you want to use for this JS function. For example, if the function is supposed to get the value of a temperature variable from your Photon device, you might name the function something like: getTemperature()
The particle.getVariable()
method requires your Photon device ID, the name of your cloud variable, and your Photon access token:
myDevice
is a global variable in your web app JS that should store your Photon device ID
"cloudVar"
is the name of your cloud variable, which must be listed inside double quotation marks. Be sure to change "cloudVar"
to the actual name of your cloud variable.
myToken
is a global variable in your web app JS that should store your Photon access token
When Particle Cloud returns the value of your cloud variable, this value gets temporarily stored in a local variable called: data.body.result
You will need to add code within the particle.getVariable()
method to do something with the value stored in data.body.result
.
For example, you could add code to:
Display the value in your web app (by using jQuery to modify the HTML)
Change the style of your web app based on the value (by using jQuery to modify the CSS)
Save the value in your web app (by assigning the value to a JS global variable)
If your web app needs to continuously monitor the value of a cloud variable, you can use the window.setInterval()
method to automatically call (perform) a function at a set time interval (such as every 0.5 seconds, etc.).
Add this code statement (be sure to modify) near the top of your web app JS:
The window.setInterval()
method requires two parameters inside its parentheses (in this order):
The name of the function to be called, which will be the name of the custom function in your JS that contains the particle.getVariable()
method for the variable you need to continuously monitor. The custom function's name should be listed without a set of parentheses. Change webFunction
to the name of your custom function.
The time interval between calls, which will be the amount of time between each call to the function. The time interval is specified in milliseconds (1000 ms = 1 second). In this case, the interval was set to 2000
ms (2 seconds). Change this value to an appropriate time interval for your web app.
If you want to get the values of multiple cloud variables at the same time, you can include separate calls to the particle.getVariable()
method within the same custom function:
If your web app needs to get different cloud variables at different times, then create separate custom functions to get each cloud variable individually:
Your Photon device app can share a custom function through Particle Cloud, so your web app can call the function to make it run on your Photon device.
For example, your Photon device app could share a custom function that toggles an LED light on or off, so your web app would be able to call this function to remotely turn the light on or off.
Your Photon device app will use the Particle.function()
method to share a custom function through Particle Cloud.
A "cloud function" will be created that acts like a reference to the custom function in your device app.
Your web app will use the particle.callFunction()
method to make the custom function run on your Photon device by calling its cloud function reference.
Your Photon device app will use the Particle.function()
method to share a custom function through Particle Cloud by creating a cloud function. In addition, you will also need to modify the custom function to work with Particle Cloud.
Add this code statement (be sure to modify) within the setup()
function of your Photon app:
The Particle.function()
method requires two parameters inside its parentheses (in this order):
The cloud function name, which can be up to 12 characters in length. If possible (for simplicity), make your cloud function name match your device function name. However, the cloud function is allowed to have a different name. The cloud function name must be listed within double quotation marks without parentheses after its name. Change "cloudFunc"
to the actual name that you want to use for the cloud function.
The Photon device function name, which is the custom function in your Photon device app that will be shared through Particle Cloud. List the function name without parentheses after its name. Change deviceFunc
to the actual name of the custom function in your Photon device app that you want to share.
Particle Cloud will let your Photon device share up to 15 cloud functions at one time. Each of your cloud functions in Particle Cloud has to be given a unique name (up to 12 characters in length).
If your Photon device app needs to share multiple functions, use a separate Particle.function()
statement for each device function being shared.
In order to share a custom function in your Photon device app with Particle Cloud, the custom function must be modified to do the following:
The custom function must accept a String parameter when the function is called.
The custom function must return an integer value when the function is performed.
For example, a typical custom function in your device app would have this generic format:
The code for this custom function would need to be modified to accept a String parameter (i.e., text) and return an integer value (i.e., whole number). Here's a modified version of the function:
Here are the 3 modifications that were made to the custom function:
String data
is listed inside the parentheses after the function name. This represents the parameter that the function will accept: String
is the data type for the parameter (i.e., text) , and data
is the name of a local variable that will receive and store the parameter value (text string). If desired, you could use a different variable name other than data
.
int
is listed in front of the function name (instead of void
), which indicates the function will return an integer value (whole number).
The code statement return 1;
is included inside the function (at the end before the closing curly brace), which will return an integer value of 1. This is the simplest way to have the function return a value.
IMPORTANT: Your custom function must have these modifications – even if your custom function doesn't do anything with the text passed into the data
parameter – and even if your device app doesn't do anything with the integer value returned by the custom function.
Once a custom function in your Photon device app has been modified to be shared through Particle Cloud, your Photon app (and your web app) must include a text parameter when calling the function.
If the custom function doesn't actually do anything with the parameter, then this text string parameter can be any text – even an empty text string of ""
will work.
For example, in your Photon app, a code statement to call the custom function would be:
deviceFunction
represents the name of the custom function. Change this to the name of your custom function.
"text"
represents the text string being passed into the function as a parameter. If this text parameter isn't actually used within the function, then it can be any text string enclosed within double quotation marks – even an empty text string of ""
will work.
As stated previously, the Photon device function being shared through Particle Cloud must accept a String parameter. The function doesn't actually have to do anything with this text data (other than receive it when the function is called).
However, depending on what your custom function does, the text string passed into the data
parameter could be used to decide what action(s) are performed within the custom function.
For example, imagine you created a custom function named turnLight()
to turn an LED light either on or off based on the value of a text string passed into the function as a parameter:
To turn on the LED, your Photon app (or your web app) would call turnLight()
and include"on"
as the parameter. In your Photon app, the code statement would be: turnLight("on");
To turn off the LED, your Photon app (or your web app) would call turnLight()
function and include "off"
as the parameter. In your Photon app, the code statement would be: turnLight("off");
Your web app JS will use the particle.callFunction()
method to make a custom function run on your Photon device by calling its cloud function reference in Particle Cloud.
Add this code (be sure to modify) in your web app JS:
MODIFY CODE: You will need to make these changes to the example code above:
Change webFunction()
to the name you want to use for your custom function
Change "cloudFunc"
to the name of your cloud function you want to call
If necessary, change "text"
to a different text parameter – only necessary if your Photon device function uses the text parameter to decide what actions are performed.
This code adds a custom function named webFunction()
to your web app JS. This custom function contains the particle.callFunction()
method.
Be sure to change webFunction()
to the actual name that you want to use for this JS function. If helpful, you could use the same name as the Photon device function being called. For example, if the JS function is supposed to call a function named toggleLight()
in your Photon device app, you could also name the JS function as toggleLight()
.
The particle.callFunction()
method requires your Photon device ID, the name of your cloud function, an argument (a String parameter for the Photon function), and your Photon access token:
myDevice
is a global variable in your web app JS that should store your Photon device ID
"cloudFunc"
is the name of your cloud function, which must be listed inside double quotation marks. Be sure to change "cloudFunc"
to the actual name of your cloud function.
"text"
is the String parameter that will be passed into the Photon device function. If this text parameter isn't actually used within the Photon function, then it can be any text string enclosed within double quotation marks – even an empty text string of ""
will work.
myToken
is a global variable in your web app JS that should store your Photon access token
Your web app will need a way to call the JS function which contains the particle.callFunction()
method that makes a function run on your Photon device.
One common way to do this is to add a button in your web app HTML that can be clicked by the user. The button should have an onclick event attribute that will call the JS function (which will in turn call your Photon function).
Add this to your web app HTML file within the <body>
section where you want the button to appear:
Change webFunction()
to the name of the JS function to be called when the button is clicked. This should be a JS function that contains a particle.callFunction()
method.
Change Button Label
to whatever text you want displayed in the button as its label. Be sure to use a label that will make sense to the user.
NOTE: You could use a different HTML element other than a button. Just be sure it will be clear to the user that the element is "clickable" (and it's clear what will happen when it is clicked).
Your Photon kit includes a "trimpot" (trimmable potentiometer) that can be rotated and used as a dial. A potentiometer is a variable resistor that can be adjusted by sliding, rotating, or another type of physical interaction. Potentiometers are used in various devices such as: joysticks and game controllers, control knobs and sliders, dimmer switches for lights, volume knobs for stereos, etc.
The trimpot dial can be rotated clockwise or counterclockwise approximately 270° (it does NOT rotate all the way around). The position of the dial can be measured and used as an input for a value that has a range from minimum to maximum.
The trimpot dial has 3 metal legs that will be inserted into pin holes on the breadboard.
To connect a trimpot dial to your Photon using the breadboard, you will need:
Trimpot
3 jumper wires (use different colors to help identify them)
3.3V MAXIMUM: Analog inputs, such as the trimpot, require 3.3V of power for accurate measurements. Connect the trimpot to the 3.3V pin on your Photon, or connect it to a positive power rail that's connected to the 3.3V pin.
TWIN PINS: Analog pins A2, A3, A4, and A5 are each represented by two pins on the Photon board. The duplicate pins are labeled as: SS/A2, SCK/A3, MISO/A4, MOSI/A5. If you use one of these pins, you cannot use its twin at the same time.
Here are the steps to connect the trimpot to your Photon using the breadboard:
Insert the three metal legs of the trimpot into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as an outer leg of the trimpot. Plug the other end of this jumper wire into the 3.3V pin on the Photon circuit board (or plug it into a positive power rail that's connected to the 3.3V pin via a different jumper wire).
Plug one end of a second jumper wire into the same terminal strip row as the middle leg of the trimpot. Plug the other end of this jumper wire into any analog I/O pin on the Photon circuit board.
Plug one end of the third jumper wire into the same terminal strip row as the other outer leg of the trimpot. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect a trimpot (ignore the wiring for the three push buttons):
Keep in mind that your connection can look different than this example diagram:
Your trimpot legs could be inserted into different row numbers. (The example connects the trimpot legs to rows 26-28 on the right side of the breadboard).
Your trimpot legs could be inserted into a different column of the breadboard. (The example connects the trimpot legs into column F of the terminal strip rows).
Your trimpot could connect (through a jumper wire) to a different analog I/O pin. (The example connects the trimpot to the A0 pin.)
Your trimpot could connect (through a jumper wire) either directly to the 3.3V pin or to a positive power rail on the breadboard that's connected to the 3.3V pin.
Your trimpot could connect (through a jumper wire) either directly to a GND pin or to a negative power rail that's connect to a GND pin. (There are three available GND pins.)
The basic steps to control a trimpot dial in your app code are:
Declare a global variable to store the I/O pin number for the trimpot.
Use the analogRead()
method to measure the trimpot dial position.
OPTIONAL: Use the map()
method to convert the trimpot reading to a custom range.
You should declare a global variable to store the I/O pin number that the trimpot is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the trimpot to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
This line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called trimpot
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to A0
. If necessary, modify this value to match the actual I/O pin that your speaker is connected to.
PIN MODE: Analog inputs do NOT need to have their pin mode set within the setup()
function. Their pin mode gets automatically set when the analogRead()
method is used.
The analogRead()
method is used to read the trimpot, which indicates the trimpot dial position.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
A local variable named trimpotRead
is declared that will have a data type of int
(integer). This variable is made equal to whatever value is returned by the analogRead()
method. You can change the name of this variable, but it will make sense if it's similar to the variable name used for the trimpot pin number.
The analogRead()
method requires one parameter insides its parentheses:
The I/O pin number, which can be the actual pin number (such as: A0
, etc.) or a variable that stores a pin number. In this example, the variable named trimpot
is listed. If necessary, change this to match the variable name for your trimpot's pin number.
The analogRead()
method will return an integer (whole number) value ranging from 0-4095:
If the dial is rotated all the way to the left (counterclockwise), the value will be 0.
If the dial is rotated all the way to the right (clockwise), the value will be 4095.
If the dial is rotated somewhere in-between, the value will be proportional to the dial's position. For example, if the dial is rotated exactly halfway, the value will be 2048.
You'll need to add code to do something with the reading stored as trimpotRead
. For example, this might be an if-else statement to perform certain actions based on whether trimpotRead
is greater than (or less than) one or more specific values.
In many cases, it may not be convenient to work with a value that ranges from 0-4095. Instead, it might be easier to have a value within a smaller custom range (such as: 0-10, 0-100, etc.) that makes more sense for your particular task.
The map()
function can be used to convert a value from its original range (such as 0-4095) into a new range of your choice. You decide the minimum and maximum values for the new range.
For example, if a trimpot dial were being used to control the brightness of an LED light, you might want the trimpot to return a value between 0-255 because the analogWrite()
method used to set the brightness of an LED requires a value in this range.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
As necessary, change the values assigned to minValue
and maxValue
to whatever numbers you want to use for your custom range. Also, the minValue
doesn't have to be zero.
Be sure to add code to do something with trimpotValue
. For example, this might be an if-else statement to perform certain actions based on whether trimpotValue
is greater than (or less than) one or more specific values.
NOTE: The code uses the round()
method to round the mapped value to the nearest integer because the map()
method returns a float
(decimal value). Also, inside the map()
method, the code intentionally adds 1 to the maxValue
because otherwise it is very difficult to get the maximum value even if the trimpot dial is turned clockwise all the way.
You could incorporate this code into a custom function called checkSensor()
that will read an analog sensor and return a value mapped to a custom range:
When calling the checkSensor()
function within the loop()
function, you will need to include values for these 3 parameters (in order) inside its parentheses:
the sensor's pin number, which will most likely be a variable that stores the pin number
the desired minimum value for the range, which should be an integer (whole number)
the desired maximum value for the range, which should be an integer (whole number)
The checkSensor()
function will return the mapped sensor value as an integer, which your code should store in a variable of data type int
.
For example, to call the checkSensor()
function within the loop()
function:
The checkSensor()
function could also be used to read other analog sensors, such as a light sensor:
Your Photon device app can send event notifications to your web app through Particle Cloud. The event notification can also include data (in the form of a text string).
For example, your Photon device could monitor a building using motion sensors. If a sensor detects motion, an event notification could be sent to your web app to alert you. The notification could also include data, such as the location of the specific motion sensor that was triggered.
Your Photon device app will use the Particle.publish()
method to send an event notification through Particle Cloud. The event notification can also include additional data (as text).
A "cloud event" will be created that sends the event notification to your web app.
Your web app will use the particle.getEventStream()
method to start listening for event notifications streamed through Particle Cloud.
By default, Particle Cloud will clear each cloud event after 60 seconds. This is to prevent your web app from receiving outdated notifications.
Your Photon device app will use the Particle.publish()
method to send an event notification through Particle Cloud to your web app. The event notification can be sent with or without data.
Particle Cloud will allow your Photon device to send about 1 event notification per second. If your device sends event notifications more frequently than this, Particle Cloud will intentionally slow down your event stream (with a 4-second delay), which can cause issues with your web app performance.
To prevent this, include a delay()
of at least 1 second after a Particle.publish()
statement (because a 1-second delay added by you is better than a 4-second delay added by Particle Cloud).
An event notification can be sent without any additional data. It acts like a simple alert of a specific event or condition occurring.
Add this code (be sure to modify) in your Photon app wherever an event notification should be sent (typically somewhere in the loop()
function or a custom function):
In this case, the Particle.publish()
method has just one parameter inside its parentheses:
The cloud event name, which can be up to 63 characters in length. The name must be listed within double quotation marks. Change "cloudEvent"
to the actual name that you want to use.
Alternatively, an event notification can be sent with additional data in the form of a text string.
Add this code (be sure to modify) in your Photon app wherever an event notification should be sent (typically somewhere in the loop()
function or a custom function):
In this case, the Particle.publish()
method has two parameters inside its parentheses:
The cloud event name, which can be up to 63 characters in length. The name must be listed within double quotation marks. Change "cloudEvent"
to the actual name that you want to use.
The event data, which is a text string that can be up to 255 characters in length. You can directly list the data as text within double quotation marks, or you can list the name of a String variable that stores the data. Change "data"
to the actual text data (or String variable name) that should be sent with the event notification.
Your web app JS will use the particle.getEventStream()
method to start listening for event notifications streamed through Particle Cloud.
Add this code (be sure to modify) in your web app JS:
MODIFY CODE: You will need to make these changes to the example code above:
Change "cloudEvent"
to the name of your cloud event whose value you want
Add code inside the particle.getEventStream()
method to do something when an event notification is received. If the event notification includes text data, the data is stored as: feed.data
The particle.getEventStream()
method requires your Photon device ID, the name of your cloud event, and your Photon access token:
myDevice
is a global variable in your web app JS that should store your Photon device ID
"cloudEvent"
is the name of your cloud event that you want to receive notifications from. The name must be listed inside double quotation marks. Be sure to change "cloudEvent"
to the actual name of your cloud event.
myToken
is a global variable in your web app JS that should store your Photon access token
If an event notification includes any data, this text data gets temporarily stored in a local variable called: feed.data
You will need to add code within the particle.getVariable()
method to do something when an event notification is received – and if applicable, do something with the text stored in feed.data
.
For example, you could add code to:
Display a message in your web app (by using jQuery to modify the HTML)
Change the style of your web app (by using jQuery to modify the CSS)
Save the text data in your web app (by assigning its value to a JS global variable)
Physical buttons that people can push are used as inputs on many different types of devices.
Your Photon kit has a set of 4 push buttons with different cap colors: red, yellow, green, and blue.
The buttons in your Photon kit are classified as momentary switches, which means they detect when they are being pressed or pushed. For example, the keys on a computer keyboard are momentary switches: they are only "on" when you press them (and they turn "off" when you release them).
This is different from maintained switches, which physically toggle between one state and another state. For example, a light switch is a maintained switch: pressing (or flipping) the switch will turn it on, and it will stay this way until pressed again (or flipped back).
However, you can make a push button act like a maintained switch by adding a global variable in your app code to track the button's current status ("on" or "off"), and then toggling this status in your code each time the button is pushed.
Each push button has 2 pairs of metal legs on opposite sides of its base. Unlike other components that connect to only one half of a breadboard, the push button has to connect to both halves of the breadboard across the gap in the middle. This is simply due to the width of the button – there isn't enough space to connect the push button plus jumper wires on one half of the breadboard.
To connect a push button to your Photon using the breadboard, you will need:
Push button
2 jumper wires (use different colors to help identify them)
Here are the steps to connect the push button to your Photon using the breadboard:
Place the push button along the middle divider of the breadboard, so one pair of legs will align with pin holes in column D on the left half of the breadboard, while the other pair of legs (on the opposite side) will align with pin holes in column G on the right half of the breadboard. If necessary, you can gently bend the metal legs to align them better with the pin holes.
Firmly press the button down to "snap" its base into place, so it's flat against the breadboard.
Plug one end of a jumper wire into the same terminal strip row as one of the button legs on the right half of the breadboard. Plug the other end of this jumper wire into an I/O pin on the Photon circuit board.
Plug one end of the other jumper wire into the same terminal strip row as the other button leg on the right half of the breadboard. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect a push button (you can ignore the wiring for the LED and resistor):
Keep in mind that your connection can look different than this example diagram:
Your button legs could be inserted into different row numbers. (The example connects the button legs to row 4 and row 6.)
Your button leg could connect (through a jumper wire) to a different I/O pin. (The example connects to the D2 pin.)
Your button could connect (through a jumper wire) either directly to a GND pin or to a negative power rail that's connect to a GND pin. (There are three available GND pins.)
The basic steps to use a push button in your app code are:
Declare a global variable to store the I/O pin number for the button.
Set the pin mode for the button pin in the setup()
function.
Use a digitalRead()
statement to check whether the button is currently pressed, and add code statements that should be performed depending on the result.
You should declare a global variable to store the I/O pin number that the button is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the button to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
This line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called button
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to D2
. If necessary, modify this value to match the actual I/O pin number that your button is connected to.
If you have multiple buttons connected to your Photon, then be sure to give each button a unique variable name by adding an adjective or number to the variable names. For example:
You need to set the pin mode for the button to be used as an input.
Add this code statement (modify if necessary) within the setup()
function:
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D2
, etc.) or a variable that stores a pin number. In this example, a variable named button
is listed. If necessary, change this to match the variable name for your button.
The mode value, which will always be INPUT_PULLUP
for a push button.
If you have multiple buttons connected to your Photon, then be sure to set the pin mode for each button pin variable. For example:
The digitalRead()
method is used to check whether a button is currently pressed.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
In the first code statement, a local variable named buttonState
is declared that will have a data type of int
(integer). This variable is made equal to whatever value is returned by the digitalRead()
method. You can change the name of this variable, but it will make sense if it's similar to the variable name used for the button pin number.
The digitalRead()
method requires one parameter insides its parentheses:
The I/O pin number, which can be the actual pin number (such as: D2
, etc.) or a variable that stores a pin number. In this example, the variable named button
is listed. If necessary, change this to match the variable name for your button's pin number.
The digitalRead()
method will return a value of either HIGH
or LOW
(which are treated as if they were int
values):
HIGH
indicates that the button is NOT currently pressed.
LOW
indicates that the button is currently pressed.
The condition listed inside the parentheses of the if statement checks whether the value of buttonState
is equivalent to LOW
:
If this condition is true, the code within the curly braces of the if
statement will be performed. You will need to add code statements within the curly braces that perform the actions you want.
If this condition is false (because the buttonState
is HIGH
), the code within the curly braces will NOT be performed. Optionally, you can add an else statement to perform a different set of code statements when the button is not pressed.
The soil moisture sensor in your Photon kit can be inserted into soil or similar materials (sand, etc.) to measure the amount of moisture in the material.
The moisture sensor is a variable resistor with two gold-plated legs that are inserted into soil. Moisture in the soil will conduct electricity from one sensor leg to the other. The amount of electricity conducted depends on the amount of soil moisture.
The soil moisture sensor in your Photo kit has a 3-pin screw terminal. You'll need to attach 3 jumper wires to the screw terminal. The back of the sensor has labels for the 3 pins: SIG, GND, VCC.
To attach jumper wires to the soil moisture sensor, you will need:
Soil moisture sensor with 3-pin screw terminal
3 jumper wires (use different colors to help identify them; recommend red, black, and yellow)
Small flat-head screwdriver (obtain from teacher, if necessary)
Use a small flat-head screwdriver to turn each screw counterclockwise until slightly loosened (but don't remove them). This creates openings on the top of the terminal to insert the jumper wires.
Insert one end of the first jumper wire (yellow) into the terminal slot for SIG. Then use the screwdriver tighten that terminal's screw (turn clockwise) until the jumper wire is held firmly.
Insert one end of the second jumper wire (black) into the terminal slot for GND. Then use the screwdriver tighten that terminal's screw (turn clockwise) until the jumper wire is held firmly.
Insert one end of the third jumper wire (red) into the terminal slot for VCC. Then use the screwdriver tighten that terminal's screw (turn clockwise) until the jumper wire is held firmly.
To connect a soil moisture sensor to your Photon using the breadboard, you will need:
Soil Moisture Sensor with 3 attached jumper wires
DUAL I/O PINS: The soil moisture sensor is connected to two different I/O pins. The sensor's SIG wire is connected to an analog I/O pin that will be used as an input to read data signals from the sensor. The sensor's VCC wire is connected to another I/O pin that will be used as an output to provide power to the sensor when taking a reading.
TWIN PINS: Analog pins A2, A3, A4, and A5 are each represented by two pins on the Photon board. The duplicate pins are labeled as: SS/A2, SCK/A3, MISO/A4, MOSI/A5. If you use one of these pins, you cannot use its twin at the same time.
Here are the steps to connect the soil moisture sensor to your Photon using the breadboard:
Plug the SIG jumper wire into any analog I/O pin on the Photon circuit board.
Plug the GND jumper wire into a pin hole connected to GND: either plug it into a negative power rail on the breadboard (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Plug the VCC jumper wire into any I/O pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect a soil moisture sensor:
Keep in mind that your connection can look different than this example diagram:
Your moisture sensor's SIG wire could connect to a different analog I/O pin. (The example connects to the A2 pin.)
Your moisture sensor's GND wire could connect either to a different GND pin or to a negative power rail connected to a GND pin. (There are three available GND pins.)
Your moisture sensor's VCC wire could connect to a different I/O pin. (The example connects to the D6 pin.)
Alternatively, you could connect the sensor's wires into different terminal strip rows on a breadboard, and then use 3 additional jumper wires to connect to the Photon circuit board.
Once the moisture sensor is connected to the Photon, insert the sensor legs into the soil (or similar material) where you need to take moisture measurements.
The basic steps to control a soil moisture sensor in your app code are:
Declare global variables to store the I/O pin numbers for the moisture sensor.
Set the pin mode for the sensor's power pin in the setup()
function, and turn off the sensor.
Use a sequence of digitalWrite()
and analogRead()
statements to briefly turn on the sensor and read the soil moisture.
OPTIONAL: Use the map()
method to convert the sensor reading to a custom range.
You should declare global variables to store the I/O pin numbers that the moisture sensor's SIG wire (data signal) and VCC wire (power) are connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the trimpot to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
Each line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variables will be called soil
and soilPower
. You can change the names, but choose names that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, soil
will be equal to A2
and soilPower
will be equal to D6
. If necessary, modify these values to match the actual I/O pins that your sensor's SIG and VCC wires are connected to.
You need to set the pin mode for the moisture sensor's power pin to be used as an output. Then you need turn off the power to the sensor until you're ready to actually take a sensor reading.
Add this code (modify if necessary) within the setup()
function:
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D6
, etc.) or a variable that stores a pin number. In this example, the variable named soiPower
is listed. If necessary, change this to match the variable name for your moisture sensor's power pin.
The mode value, which will always be OUTPUT
for an LED light because your app will send "on" and "off" signals (or brightness signals) to the LED light.
The digitalWrite()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D6
, etc.) or a variable that stores a pin number. In this example, the variable named soiPower
is listed. If necessary, change this to match the variable name for your moisture sensor's power pin.
The signal value, which can be HIGH
or LOW
. Your Photon uses this value to send an electrical signal through the pin: HIGH
is a signal of 3.3 volts which represents "on," while LOW
is a signal of 0 volts which represents "off." In this case, LOW
is being used to turn off the moisture sensor.
PIN MODE: Analog inputs do NOT need to have their pin mode set within the setup()
function. Their pin mode gets automatically set when the analogRead()
method is used. That's why there's no pinMode()
statement for the soil
pin.
A constant flow of electricity across the moisture sensor legs could cause them to corrode over time due to the natural salts and other minerals found in soil. The gold-plating on the sensors legs resist corrosion, but it's still better to only briefly turn on the sensor's power when taking a reading.
Reading the soil moisture always requires a sequence of four steps:
Turn on the sensor's power using the digitalWrite()
method.
Allow time for electricity to flow through the soil by using the delay()
method.
Read the soil moisture using the analogRead()
method.
Turn off the sensor's power using the digitalWrite()
method.
A local variable named soilRead
is declared that will have a data type of int
(integer). This variable is made equal to whatever value is returned by the analogRead()
method. You can change the name of this variable, but it will make sense if it's similar to the variable name used for the trimpot pin number.
The analogRead()
method requires one parameter insides its parentheses:
The I/O pin number, which can be the actual pin number (such as: A2
, etc.) or a variable that stores a pin number. In this example, the variable named soil
is listed. If necessary, change this to match the variable name for the pin number of your sensor's SIG wire.
The analogRead()
method will return an integer (whole number) value ranging from 0-4095:
When there is less moisture detected, the reading will have a lower value.
When there is more moisture detected, the reading will have a higher value.
You'll need to add code to do something with the reading stored as soilRead
. For example, this might be an if-else statement to perform certain actions based on whether soilRead
is greater than (or less than) one or more specific values.
Depending on the specific purpose of the moisture sensor in your device, you may need to gather some test values under different conditions (such as dry vs. wet) to see what the moisture values might actually be where your device will be used. This will help you determine which values to use in your code to make decisions. For example, if the moisture sensor will be used to send notifications when the soil is either too dry or too wet, what values will be used to decide this?
For example, the code below uses a value of 500
to decide whether the soil is too dry and a value of 3500
to decide whether the soil is too wet. However, you would need to gather test data to determine whether these values should be higher or lower.
In many cases, it may not be convenient to work with a value that ranges from 0-4095. Instead, it might be easier to have a value within a smaller custom range (such as: 0-10, 0-100, etc.) that makes more sense for your particular task.
The map()
function can be used to convert a value from its original range (such as 0-4095) into a new range of your choice. You decide the minimum and maximum values for the new range.
For example, if the moisture sensor were being used to automatically turn a sprinkler system on and off, you might want the sensor to return a value between 0-100 as an easier way to determine the relative soil moisture.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
As necessary, change the values assigned to minValue
and maxValue
to whatever numbers you want to use for your custom range. Also, the minValue
doesn't have to be zero.
Be sure to add code to do something with soilValue
. For example, this might be an if-else statement to perform certain actions based on whether soilValue
is greater than (or less than) one or more specific values.
NOTE: The code uses the round()
method to round the mapped value to the nearest integer because the map()
method returns a float
(decimal value). Also, inside the map()
method, the code intentionally adds 1 to the maxValue
because otherwise it is very difficult to get the maximum value even if the soil moisture is very high.
You could incorporate this code into a custom function called checkSoil()
that will read the soil moisture sensor and return a value mapped to a custom range:
If necessary, change the variable names for the sensor's pins to match your variable names. You can also change the values assigned to minValue
and maxValue
to whatever numbers you want to use for your custom range.
The checkSoil()
function will return the mapped sensor value as an integer, which your code should store in a variable of data type int
.
For example, to call the checkSoil()
function within the loop()
function:
The triple-axis accelerometer included in your Photon kit can be used to detect changes in motion or orientation in 3 dimensions (x, y, z).
Like the name implies, an accelerometer works by detecting acceleration – a change in motion. If a device with an accelerometer experiences a change in motion (i.e., speeding up, slowing down, or changing direction), the accelerometer can sense this change and measure the amount of acceleration in each of the 3 dimensions (x, y, z).
For example, fitness trackers use accelerometers to count steps by detecting changes in motion.
Your accelerometer is sensitive enough that it can be used to even tiny changes in motion caused by a nearby tap or bump. For example, if your Photon device is on a table, the accelerometer would be able to detect if you tapped the table with a finger.
Even if a device with an accelerometer is not moving, the accelerometer can detect the orientation (tilt) of the device by measuring the acceleration due to Earth's gravity, which is a constant downward force acting on all objects. The accelerometer can determine if the object is parallel to the Earth's surface or if it's tilted.
For example, smartphones and tablets use accelerometers to sense the orientation of the device, in order to change the screen's orientation to match.
Your accelerometer can be used to measure the tilt (in degrees) for pitch and roll:
Pitch is rotation on the Y-axis, which means an object is tilted up or down.
Roll is rotation on the X-axis, which means an object is tilted right or left.
NOTE: An accelerometer cannot measure yaw because Earth's gravity acts in the same direction as the Z-axis, which prevents the accelerometer from measuring rotation on the Z-axis. Instead, a different sensor called a magnetometer (i.e., digital compass) could be used to measure yaw by measuring an object's orientation relative to Earth's magnetic north pole.
The MMA8452Q triple-axis accelerometer in your Photon kit has 6 pins located along its front edge (which determines its orientation for measuring pitch and roll). There are labels for each pin printed on the accelerometer circuit board. However, only 4 of the pins will need to be connected to your Photon.
To connect the accelerometer to your Photon using the breadboard, you will need:
Accelerometer (MMA8452Q)
4 jumper wires (use different colors to help identify them)
3.3V MAXIMUM: The accelerometer operates at 3.3V of power. Connect it to the 3.3V pin on your Photon, or connect it to a positive power rail that's connected to the 3.3V pin.
Do NOT connect it to VIN or V-USB because the higher voltage could damage it.
Here are the steps to connect the accelerometer to your Photon using the breadboard:
Insert the six metal pins of the accelerometer into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as the accelerometer's 3.3V pin. Plug the other end of this jumper wire into the 3.3V pin on the Photon circuit board (or to a positive power rail on the breadboard connected to the 3.3V pin).
Plug one end of a second jumper wire into the same terminal strip row as the accelerometer's SDA pin. Plug the other end of this jumper wire into the D0 pin on the Photon circuit board.
Plug one end of a third jumper wire into the same terminal strip row as the accelerometer's SCL pin. Plug the other end of this jumper wire into the D1 pin on the Photon circuit board.
Plug one end of a fourth jumper wire into the same terminal strip row as the accelerometer's GND pin. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect the accelerometer (ignore the wiring for the push button):
Keep in mind that your connection can look different than this example diagram:
Your accelerometer pins could be inserted into different row numbers. (The example connects the accelerometer pins to rows 1-6 on the right side of the breadboard).
Your accelerometer pins could be inserted into a different column of the breadboard. (The example connects the accelerometer pins into column H of the terminal strip rows).
Your accelerometer could connect (through a jumper wire) directly to the 3.3V pin or to a positive power rail on the breadboard that's connected to the 3.3V pin.
Your accelerometer could connect (through a jumper wire) either directly to a GND pin or to a negative power rail that's connect to a GND pin. (There are three available GND pins.)
The basic steps to control the accelerometer in your app code are:
Include the SparkFun MMA8452Q library and Math library in your app.
Create a MMA8452Q
object assigned to a global variable called accel
.
Use the accel.begin()
method to start the accelerometer in the setup()
function. If app will detect taps, use the accel.setupTap()
method to initialize the tap settings.
Use custom functions to detect taps or measure tilt angles using the accelerometer.
Your Photon app must include a code library that will allow you to control the accelerometer (which is an MMA8452Q accelerometer). You'll also add a Math library that will be used to calculate tilt angles.
In Particle Build, click on the Libraries icon to open the Libraries menu panel.
Type mma8452q
into the search field. Select the result called: SparkFunMMA8452Q
Click the button to "Include in Project"
Select the title of your Photon app, and then click the "Confirm" button
Particle Build will automatically insert this #include
statement at the beginning of your app code:
In addition, you will include a Math library that has additional mathematical functions and constants, which will be needed to calculate tilt angles. (The Math library is available in Particle Build, but it won't show up in a search of the community libraries.)
You need to manually add this #include
statement (on new line after other #include
statement):
You need to create a new object using the MMA8452Q
class in the included SparkFun MMA8452Q library, and assign this object to a global variable named accel
.
Add this code statement before the setup()
function:
The accel.begin()
method is used to start the accelerometer, which will initialize its settings. (You do not need to set any pin modes for the accelerometer.)
Add this code statement within the setup()
function to start the accelerometer:
The accel.begin()
method can accept two parameters inside its parentheses (in this order):
The scale range, which determines the range and precision of the acceleration detection. The options for the scale are: SCALE_2G
, SCALE_4G
, or SCALE_8G
. A higher scale can detect larger changes in acceleration but is less precise. A lower scale is more precise. For your app, using SCALE_2G
is the probably the best choice because it will be the most precise.
The output data range (ODR), which determines how frequently it outputs new measurements. The ODR is set in Hz (number of times per second). The options for the ODR are: ODR_1
, ODR_6
, ODR_12
, ODR_50
, ODR_100
, ODR_200
, ODR_400
, or ODR_800
. A higher ODR is faster (more frequent), while a lower ODR is slower (less frequent). If your device is being powered by a battery, a lower ODR is more energy-efficient. For your app, using ODR_50
is probably a good choice.
Alternatively, you can exclude the parameters from the accel.begin()
statement. If you do this, the accelerometer will default to using SCALE_2G
and ODR_800
.
If your app will use the accelerometer to detect taps, then use the accel.setupTap()
method to initialize the settings for tap detection.
If detecting taps, add this code within the setup()
function (after the accel.begin()
statement):
If your app will NOT be detecting taps, then this code can be excluded.
If your app will use the accelerometer to detect an object's tilt, you'll add a custom function named checkTilt()
that measures tilt angles for pitch and roll using the accelerometer.
Add this checkTilt()
function after the loop()
function:
You'll need to add code within the function to do something with the values of pitch
and roll
, which indicate the direction(s) and angle(s) that the accelerometer is tilted.
Pitch is rotation on the Y-axis, which means the object is rotated up or down:
If the accelerometer is tilted up, the pitch will be a positive angle (between 1° to 180°).
If the accelerometer is tilted down, the pitch will be a negative angle (between -1° to -180°).
Roll is rotation on the X-axis, which means the object is rotated to the right or left:
If the accelerometer is tilted right, the roll will be a positive angle (between 1° to 180°).
If the accelerometer is tilted left, the roll will be a negative angle (between -1° to -180°).
When the accelerometer is perfectly level, the pitch and roll will both be equal to 0 (zero).
To check the tilt, call this function within the loop()
function (or within another custom function):
If your app will use the accelerometer to detect taps, you'll add a custom function named checkTap()
that detects taps using the accelerometer.
Add this checkTap()
function after the loop()
function:
The accel.readTap()
method is used to detect a tap. The method returns a value of 0
when no tap is detected. When a tap is detected, the method returns a non-zero value. The if
statement condition checks whether a non-zero value was returned (indicating a tap was detected).
You'll need to add code within the curly braces of the if
statement to do something when a tap is detected. Optionally, you can add code within the curly braces of the else
statement to do something when no tap is detected.
To check for a tap, call this function within the loop()
function (or within another custom function):
The motion sensor included in your Photon kit uses passive infrared (PIR) light to detect movement in the surrounding environment up to about 10 feet away.
To connect a motion sensor to your Photon using the breadboard, you will need:
Motion sensor (with 3-pin JST right angle connector)
3 jumper wires (use different colors to help identify them; it may help to match the sensor wires)
5V REQUIRED: The motion sensor requires 5V of power to operate.
If your Photon is being powered through the barrel jack, connect to the VIN pin.
If your Photon is being powered through the Micro-USB port, connect to the V-USB pin.
Here are the steps to connect the motion sensor to your Photon using the breadboard:
Insert the 3 pins of the motion sensor connector into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as the sensor's black wire. Plug the other end of this jumper wire into an I/O pin on the Photon circuit board.
Plug one end of a second jumper wire into the same terminal strip row as the sensor's white wire. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Plug one end of a third jumper wire into the same terminal strip row as the sensor's red wire. Plug the other end of this jumper wire into either the VIN pin or V-USB pin on the Photon circuit board (or to a positive power rail on the breadboard that is connected to VIN or V-USB). If your Photon is being powered through the barrel jack, connect to the VIN pin. Otherwise, if your Photon is being powered through the Micro-USB port, connect to the V-USB pin.
Here's a wiring diagram showing a possible way to connect a motion sensor:
Keep in mind that your connection can look different than this example diagram:
Your motion sensor pins could be inserted into different row numbers. (The example connects the sensor pins to rows 16-18 on the left side of the breadboard.)
Your motion sensor pins could be inserted into a different column of the breadboard. (The example connects the sensor pins into column A of the terminal strip rows.)
Your sensor's black wire could connect (through a jumper wire) to a different I/O pin. (The example connects to the D0 pin.)
Your sensor's white wire could connect (through a jumper wire) to either to a different GND pin or to a negative power rail connected to a GND pin. (There are three available GND pins.)
Your sensor's red wire could connect (through a jumper wire) to either the VIN pin or V-USB pin (or to a positive power rail that's connected to one of these pins). (The example connects directly to the V-USB pin.)
The basic steps to use a motion sensor in your app code are:
Declare a global variable to store the I/O pin number for the motion sensor.
Set the pin mode for the motion sensor pin in the setup()
function.
Use a digitalRead()
statement to check whether the sensor detects any motion, and add code statements that should be performed if motion is detected (or not detected).
You should declare a global variable to store the I/O pin number that the motion sensor's data wire is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the motion sensor to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
This line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called motion
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to D0
. If necessary, modify this value to match the actual I/O pin number that your button is connected to.
You need to set the pin mode for the motion sensor to be used as an input.
Add this code statement (modify if necessary) within the setup()
function:
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D0
, etc.) or a variable that stores a pin number. In this example, a variable named motion
is listed. If necessary, change this to match the variable name for your button.
The mode value, which will always be INPUT_PULLUP
for a motion sensor.
The digitalRead()
method is used to check whether the sensor currently detects any motion.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
In the first code statement, a local variable named motionState
is declared that will have a data type of int
(integer). This variable is made equal to whatever value is returned by the digitalRead()
method. You can change the name of this variable, but it will make sense if it's similar to the variable name used for the motion sensor pin number.
The digitalRead()
method requires one parameter insides its parentheses:
The I/O pin number, which can be the actual pin number (such as: D0
, etc.) or a variable that stores a pin number. In this example, the variable named motion
is listed. If necessary, change this to match the variable name for your motion sensor's pin number.
The digitalRead()
method will return a value of either HIGH
or LOW
(which are treated as if they were int
values):
HIGH
indicates that motion is NOT currently detected.
LOW
indicates that motion is currently detected.
If this condition is true, the code within the curly braces of the if
statement will be performed. You will need to add code statements within the curly braces that perform the actions you want.
IMPORTANT: You will notice that a delay()
of 2 seconds is included when motion is detected. This delay is needed to allow the motion sensor to capture a new "snapshot" of the environment before checking the sensor again.
The RHT03 sensor in your Photon kit can measure the relative humidity and temperature of the air.
To connect the RHT03 sensor to your Photon using the breadboard, you will need:
RHT03 Humidity and Temperature Sensor
3 jumper wires (use different colors to help identify them)
The RHT03 humidity and temperature sensor has 4 metal legs. The front side of the sensor has openings to allow air in.
If you were looking at the front of the sensor and the sensor legs were numbered left to right as 1-4, the wiring connections would be:
3.3V OR 5V: The RHT03 sensor can operate on either 3.3V or 5V of power.
If your Photon is being powered through the barrel jack, you can connect the RHT03 sensor to either the 3.3V pin or VIN pin.
If your Photon is being powered through the Micro-USB port, you can connect the RHT03 sensor to either the 3.3V pin or V-USB pin.
Here are the steps to connect the RHT03 sensor to your Photon using the breadboard:
Insert the four metal legs of the sensor into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as the power leg of the sensor. Plug the other end of this jumper wire into the 3.3V pin or a 5V pin (VIN or V-USB) on the Photon circuit board (or to a positive power rail on the breadboard connected to 3.3V, VIN, or V-USB). If your Photon is being powered through the barrel jack, connect to either the 3.3V pin or VIN pin. Otherwise, if your Photon is being powered through the Micro-USB port, connect to either the 3.3V pin or V-USB pin.
Plug one end of a second jumper wire into the same terminal strip row as the data leg of the sensor. Plug the other end of this jumper wire into any I/O pin on the Photon circuit board.
Plug one end of the third jumper wire into the same terminal strip row as the ground leg of the sensor. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect the RHT03 humidity and temperature sensor (ignore the wiring for the light sensor):
Keep in mind that your connection can look different than this example diagram:
Your RHT03 sensor legs could be inserted into different row numbers. (The example connects the RHT03 sensor legs to rows 1-4 on the right side of the breadboard).
Your RHT03 sensor legs could be inserted into a different column of the breadboard. (The example connects the RHT03 sensor legs into column H of the terminal strip rows).
Your RHT03 sensor could connect (through a jumper wire) to a different I/O pin. (The example connects the RHT03 sensor to the D3 pin.)
Your RHT03 sensor could connect (through a jumper wire) directly to the 3.3V pin or a 5V pin (VIN or V-USB) – or it could connect to a positive power rail on the breadboard that's connected to the 3.3V pin or a 5V pin.
Your RHT03 sensor could connect (through a jumper wire) either directly to a GND pin or to a negative power rail that's connect to a GND pin. (There are three available GND pins.)
The basic steps to control the RHT03 humidity and temperature sensor in your app code are:
Include the SparkFun RHT03 library in your app.
Declare a global variable to store the I/O pin number for the RHT03 sensor.
Create a RHT03
object assigned to a global variable called rht
.
Use the rht.begin()
method to start the RHT03 sensor in the setup()
function.
Use a sequence of rht.update()
, rht.humidity()
, and rht.tempF()
statements to get new humidity and temperature readings.
Your Photon app must include a code library that will allow you to control the RHT03 sensor.
In Particle Build, click on the Libraries icon to open the Libraries menu panel.
Type rht
into the search field. Select the result called: SparkFunRHT03
Click the button to "Include in Project"
Select the title of your Photon app, and then click the "Confirm" button
Particle Build will automatically insert this #include
statement at the beginning of your app code:
You should declare a global variable to store the I/O pin number that the RHT03 sensor's data leg is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the motion sensor to a different pin number).
You will also need to create an object using the RHT03
class in the included library, and assign this object to a global variable.
Add this code statement (modify if necessary) before the setup()
function:
The first line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called rhtData
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to D3
. If necessary, modify this value to match the actual I/O pin number that your sensor is connected to.
The second line of code creates a new object using the RHT03
class, and assigns the object to a global variable named rht
.
The rht.begin()
method is used to start the RHT03 sensor, which will automatically set its pin mode.
Add this code statement within the setup()
function to start the RHT03 sensor:
The rht.begin()
method requires the sensor's I/O pin number. In this case, the global variable named rhtData
stores this value. If you used a different name for the global variable storing your RHT03 sensor pin number, then insert that name instead.
The rht.update()
method is used to get new sensor readings for the relative humidity and temperature of the air.
If the update is successful, the rht.update()
method will return a value of 1
(which is equivalent totrue
). Then you can use these other rht
methods to get the updated values for the relative humidity (%) and temperature (in Fahrenheit or Celsius):
The rht.humidity()
method returns the relative humidity of the air as a value between 0-100, representing a percentage. A higher number means the air is more humid (has more water vapor).
The rht.tempF()
method returns the temperature of the air in degrees Fahrenheit – while the rht.tempC()
method will return the temperature of the air in degrees Celsius.
Each humidity and temperature measurement is returned as a float
value (decimal number). In most cases, it will be simpler to round these values to the nearest integer (whole number).
Add this code (modify as necessary) within the loop()
function or a custom function:
This code creates two variables named temperature
and humidity
to store the values returned by the sensor, which have been rounded to integer values.
If you want the temperature in degrees Celsius, then replace rht.tempF()
with rht.tempC()
.
Be sure to add code to do something with the temperature
and/or humidity
values.
You can also create a multi-screen web app that interacts with your Photon device through Particle Cloud. Your multi-screen web app will consist of an HTML file namedindex.html
, a CSS file named style.css
, and a JavaScript file named script.js
.
Your web app will be a that dynamically shows different "screens." Your web app will only have one HTML page, but different <div>
sections in the HTML will represent different screens. Your web app will only display one specific <div>
screen at a time, while hiding the other <div>
screens.
This section contains starter code that you can use for your HTML, CSS, and JS files. You'll need to add to the starter code (and modify certain parts).
This starter code has been designed to mimic the appearance and interaction of a native mobile app. A persistent navigation menu with icons will be displayed at the bottom of the viewport to allow the user to switch between screens to perform different tasks or view different information.
By default, this app code is designed to show 4 different screens (but you can modify the code to change the number of screens). This app code also has a <div>
section that can be use to display an incoming notification from your smart device.
You can use this starter code for your HTML file named index.html
:
COPY CODE: When using this IoT code guidebook, you can copy a code block simply by clicking the copy icon displayed in the upper right of the code block.
This HTML has been set up to display 4 different screens. However, you can modify the HTML to display more screens (or fewer screens).
This HTML does several things:
It loads two CSS stylesheet files.
It has <div>
sections for a notification message and 4 different screens.
It has a <nav>
section to show the navigation menu for the screens.
It loads three JavaScript files.
In the <head>
section, there is a <link>
tag to load a CSS stylesheet file named style.css
that you'll use to modify the appearance of certain HTML elements in your web app.
At the beginning of the <body>
section, there is a <div>
section with an id name of"notification"
that can be used to display a popup notification message. This <div> will normally be hidden, but you can use JavaScript to display the notification.
If your web app won't need to display notifications, you can delete this <div>
section (though you can just leave it and simply not use it – in case, you change your mind later).
For example, when an event notification is received from your smart device, your JavaScript can make the notification <div>
appear (and can customize the message within the notification, if needed). The notification will appear as a popup at the top of the current screen (though you can change the position if desired).
In the middle of the <body>
section, there are several <div>
sections to represent the different screens in your web app. Each <div>
section has the same class name of screen
to classify it as a screen but also has a unique id name to identify it as a specific screen: screen1
, screen2
, screen3
, or screen4
.
The starter code within each <div>
simply displays a heading for the name of the screen (so you can see that clicking the navigation menu actually does switch screens). You'll remove (or revise) this heading, and add your own HTML for each screen to display text, images, buttons, etc.
Towards the end of the <body>
section, there is a <nav>
section to display a navigation menu for switching between the different screens.
The <nav>
contains anchor tags (<a>
) for each screen. Normally, an anchor tag contains a link to a different HTML page, but in this case, the tags simply have an onclick
attribute that will call a custom function in your JavaScript that will display a specific <div>
screen.
At the end of the <body>
section, there are <script>
tags to load several JavaScript files into your web app:
Particle API JS library: particle.min.js
jQuery JS library: jquery.min.js
Your web app JS file: script.js
You can use this starter code for your CSS file named style.css
:
This CSS styles certain elements, classes, and IDs within your web app. However, you can modify some of this CSS if desired.
You'll typically want to add CSS to style other HTML elements in your web app, in order to produce the desired layout and appearance for your app's user interface.
You can use this starter code for your JS file named script.js
:
IMPORTANT: You must modify this JS code to insert your actual Photon device ID and access token. Otherwise, your web app will not work properly.
This JS creates a new Particle()
object and assigns it to a global variable named particle
. This object has built-in methods (functions) that can be used to interact with your Photon device through Particle Cloud.
This JS contains functions to show a specific screen in your web app (and also highlight the current screen in the navigation menu). There is also a function to show the notification (if your web app needs to display popup notifications).
Then you'll need to add the other necessary JS for your web app. Because your HTML file loaded the Particle API JS library and jQuery JS library, you can include Particle statements and jQuery statements within your JS code.
Your Photon kit includes a that can be used to detect whether a door, window, drawer, box, etc. is open or closed.
The switch consists of two pieces, and it can detect whether these two pieces are close to each other:
The piece with the wires contains a that moves in response to the presence or absence of a magnetic field.
The other piece without the wires contains a magnet, so it can activate the reed switch when the two pieces are close to each other.
If the two pieces of the magnetic switch are within 20 mm (0.75 inches) of each other, the switch detects that it's "closed" – otherwise, the switch will detect that it's "open."
These magnetic switches are commonly used in security systems for doors and windows, but they are also used in many other products. For example, a doorbell uses a magnetic switch to detect when it is being pressed. Magnetic switches are also used in many laptops and tablets to detect when the lid/cover is open or closed, in order to automatically wake up the device or put it to sleep.
The reed switch (the piece with the wires) will be connected to the Photon. Then the reed switch will be attached to a stationary edge near something that opens (such as: door, window, drawer, etc.). For example, the reed switch could be attached to the edge of a door frame – but not to the door itself.
The magnet (the piece without wires) would be attached to the object (door, window, etc.) that actually moves when opened. The two pieces of the magnetic switch should be positioned so they are very close together (no more than 0.75 inches apart) when the object (door, window, etc.) is closed.
To connect a magnetic switch to your Photon using the breadboard, you will need:
Magnetic Switch
2 jumper wires (use different colors to help identify them)
Here are the steps to connect the magnetic switch to your Photon using the breadboard:
Insert the two wires of the magnetic switch into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as one switch wire. Plug the other end of this jumper wire into an I/O pin on the Photon circuit board.
Plug one end of the other jumper wire into the same terminal strip row as the other switch wire. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail on the breadboard (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect a magnetic switch:
Keep in mind that your connection can look different than this example diagram:
Your magnetic switch wires could be inserted into different row numbers on either breadboard side. (The example connects the switch wires to rows 17-18 on the left side of the breadboard.)
Your magnetic switch wires could be inserted into a different column on the breadboard. (The example connects the switch wires into column A of the terminal strip rows.)
Your magnetic switch could connect (through a jumper wire) to a different I/O pin. (The example connects to the D0 pin on the Photon circuit board.)
Your magnetic switch could connect (through a jumper wire) either to a different GND pin or to a negative power rail connected to a GND pin. (There are three available GND pins on the Photon circuit board.)
The basic steps to use a magnetic switch in your app code are:
Declare a global variable to store the I/O pin number for the switch.
Set the pin mode for the switch pin in the setup()
function.
Use a digitalRead()
statement to check whether the switch is currently open or closed, and add code statements that should be performed depending on the result.
You should declare a global variable to store the I/O pin number that the switch is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the button to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
This line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called magSwitch
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to D0
. If necessary, modify this value to match the actual I/O pin number that your switch is connected to.
You need to set the pin mode for the magnetic switch to be used as an input.
Add this code statement (modify if necessary) within the setup()
function:
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D0
, etc.) or a variable that stores a pin number. In this example, a variable named magSwitch
is listed. If necessary, change this to match the variable name for your magnetic switch.
The mode value, which will always be INPUT_PULLUP
for a magnetic switch.
The digitalRead()
method is used to check whether a magnetic switch is currently open or closed.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
In the first code statement, a local variable named switchState
is declared that will have a data type of int
(integer). This variable is made equal to whatever value is returned by the digitalRead()
method. You can change the name of this variable, but it will make sense if it's similar to the variable name used for the switch pin number.
The digitalRead()
method requires one parameter insides its parentheses:
The I/O pin number, which can be the actual pin number (such as: D2
, etc.) or a variable that stores a pin number. In this example, the variable named magSwitch
is listed. If necessary, change this to match the variable name for your switch's pin number.
The digitalRead()
method will return a value of either HIGH
or LOW
(which are treated as if they were int
values):
HIGH
indicates that the magnetic switch is currently open.
LOW
indicates that the magnetic switch is currently closed.
If this condition is true, the code within the curly braces of the if
statement will be performed. You will need to add code statements within the curly braces that perform the actions you want when the magnetic switch is open.
Otherwise, if this condition is false (because switchState
is LOW
), the code within the curly braces of the else
statement will be performed. You will need to add code statements within the curly braces that perform the actions you want when the magnetic switch is closed.
Alternatively, you could check for just one condition (either HIGH
or LOW
) without including an else
statement to perform actions for the opposite condition.
The Photon kit includes a light sensor (also known as a photocell) which is a variable resistor that changes its resistance in response to the amount of ambient light in the environment.
For example, some outdoor lights on houses and buildings use photocells to automatically turn the light on or off depending on whether it is dark or light outside. Most smartphones have light sensors to automatically adjust the brightness of the screen depending on the amount of ambient light detected.
A static resistor will be used to connect one leg of the light sensor to a GND (-) pin.
Your Photon kit contains a set of resistors with a resistance rating of 330 Ohms. In order to insert a resistor into the pin holes of a breadboard, you will need to bend both resistor legs into ~90° angles:
The light sensor has 2 metal legs that will be inserted into pin holes on the breadboard. One of the legs will actually have two connections – this is the voltage divider created using a static resistor.
To connect a light sensor to your Photon using the breadboard, you will need:
Light sensor (aka photocell)
Resistor with bent legs
2 jumper wires (use different colors to help identify them)
3.3V MAXIMUM: Analog inputs, such as the light sensor, require 3.3V of power for accurate measurements. Connect the light sensor to the 3.3V pin on your Photon, or connect it to a positive power rail that's connected to the 3.3V pin.
RESISTOR REQUIRED: A static resistor will be used to create a voltage divider that allows the variable resistance of the light sensor to be measured.
TWIN PINS: Analog pins A2, A3, A4, and A5 are each represented by two pins on the Photon board. The duplicate pins are labeled as: SS/A2, SCK/A3, MISO/A4, MOSI/A5. If you use one of these pins, you cannot use its twin at the same time.
Here are the steps to connect the light sensor to your Photon using the breadboard:
Insert the two legs of the light sensor into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as one sensor leg. Plug the other end of this jumper wire into the 3.3V pin on the Photon circuit board (or plug it into a positive power rail that's connected to the 3.3V pin via a different jumper wire).
Plug one end of a second jumper wire into the same terminal strip row as the second sensor leg. Plug the other end of this jumper wire into any analog I/O pin on the Photon circuit board.
Insert one end of the resistor into the same terminal strip row as the second sensor leg. Insert the other end of the resistor into a pin hole of the negative column of the closest power rail on the breadboard.
If the negative power rail isn't already connected to a GND pin on the Photon circuit board, then plug one end of a third jumper wire into another pin hole in the negative power rail, and plug the other end of this jumper wire into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect a light sensor (ignore the wiring at the top for the temperature sensor):
Keep in mind that your connection can look different than this example diagram:
Your light sensor legs could be inserted into different row numbers on the breadboard. (The example connects the legs to row 27 and row 30.)
Your light sensor legs could be inserted into a different column on the breadboard. (The example connects the legs into column F of the terminal strip rows.)
Your light sensor could connect to a different analog I/O pin. (The example connects to the A0 pin.)
Your light sensor could connect (through a jumper wire) either directly to the 3.3V pin or to a positive power rail on the breadboard that's connected to the 3.3V pin.
The negative power rail on your breadboard could connect to a different GND pin. (There are three available GND pins.)
The basic steps to control a light sensor (photocell) in your app code are:
Declare a global variable to store the I/O pin number for the light sensor.
Use the analogRead()
method to measure the amount of light.
OPTIONAL: Use the map()
method to convert the sensor reading to a custom range.
You should declare a global variable to store the I/O pin number that the light sensor is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the trimpot to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
This line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called light
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to A0
. If necessary, modify this value to match the actual I/O pin that your speaker is connected to.
PIN MODE: Analog inputs do NOT need to have their pin mode set within the setup()
function. Their pin mode gets automatically set when the analogRead()
method is used.
The analogRead()
method is used to read the light sensor, which indicates the amount of ambient light reaching the sensor.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
A local variable named lightRead
is declared that will have a data type of int
(integer). This variable is made equal to whatever value is returned by the analogRead()
method. You can change the name of this variable, but it will make sense if it's similar to the variable name used for the trimpot pin number.
The analogRead()
method requires one parameter insides its parentheses:
The I/O pin number, which can be the actual pin number (such as: A0
, etc.) or a variable that stores a pin number. In this example, the variable named light
is listed. If necessary, change this to match the variable name for your trimpot's pin number.
The analogRead()
method will return an integer (whole number) value ranging from 0-4095:
When there is less light detected, the reading will have a lower value.
When there is more light detected, the reading will have a higher value.
You'll need to add code to do something with the reading stored as lightRead
. For example, this might be an if-else statement to perform certain actions based on whether lightRead
is greater than (or less than) one or more specific values.
Depending on the specific purpose of the light sensor in your device, you may need to gather some test values under different conditions to see how dark or how bright the environment will actually be where your device will be used. This will help you determine which values to use in your code to make decisions. For example, if the light sensor will be used to turn on an LED light when a room is too dark, what value will be used to decide that the room is too dark?
For example, the code below uses a value of 250
to decide whether a room is too dark. However, you would need to gather test data to determine whether this value should be higher or lower.
In many cases, it may not be convenient to work with a value that ranges from 0-4095. Instead, it might be easier to have a value within a smaller custom range (such as: 0-10, 0-100, etc.) that makes more sense for your particular task.
The map()
function can be used to convert a value from its original range (such as 0-4095) into a new range of your choice. You decide the minimum and maximum values for the new range.
For example, if the light sensor were being used to automatically turn on an LED light when the environment is too dark, you might want the sensor to return a value between 0-100 as an easier way to determine the relative brightness of the environment.
Add this code (modify as necessary) to your app within the loop()
function or a custom function:
As necessary, change the values assigned to minValue
and maxValue
to whatever numbers you want to use for your custom range. Also, the minValue
doesn't have to be zero.
Be sure to add code to do something with lightValue
. For example, this might be an if-else statement to perform certain actions based on whether lightValue
is greater than (or less than) one or more specific values.
NOTE: The code uses the round()
method to round the mapped value to the nearest integer because the map()
method returns a float
(decimal value). Also, inside the map()
method, the code intentionally adds 1 to the maxValue
because otherwise it is very difficult to get the maximum value even if the ambient light in the environment is very bright.
You could incorporate this code into a custom function called checkSensor()
that will read an analog sensor and return a value mapped to a custom range:
When calling the checkSensor()
function within the loop()
function, you will need to include values for these 3 parameters (in order) inside its parentheses:
the sensor's pin number, which will most likely be a variable that stores the pin number
the desired minimum value for the range, which should be an integer (whole number)
the desired maximum value for the range, which should be an integer (whole number)
The checkSensor()
function will return the mapped sensor value as an integer, which your code should store in a variable of data type int
.
For example, to call the checkSensor()
function within the loop()
function:
The checkSensor()
function could also be used to read other analog sensors, such as a trimpot dial:
ADD-ON COMPONENT: The SparkFun Photon Kit does NOT include an ultrasonic sensor as a standard component. However, SparkFun sells the , which can be easily connected to a Photon. Your teacher may have added this sensor to your kit.
An ultrasonic sensor uses sonar to measure the distance to an object, similar to how bats and dolphins use for navigation and hunting.
An ultrasonic sensor has a transmitter (i.e., speaker) that produces high-frequency sound (beyond the range of human hearing). The sensor also has a matching receiver (i.e., microphone) that detects the echo of the high-frequency sound when it reflects back from an object. By measuring how much time it takes for the echo to arrive, you can calculate the distance between the sensor and the object.
The HC-SR04 ultrasonic sensor measures distances in a narrow cone of about 15° directly in front of the sensor. This sensor can detect obstacles located up to 400 cm away (about 13 feet). The sensor measurements are very accurate, within about 3 mm (about 0.1 inch) of the actual distance.
The HC-SR04 ultrasonic sensor has 4 pins for plugging into a breadboard. Each pin is labeled on the sensor's circuit board.
To connect the ultrasonic sensor to your Photon using the breadboard, you will need:
Ultrasonic Sensor (HC-SR04)
4 jumper wires (use different colors to help identify them)
5V REQUIRED: The ultrasonic sensor requires 5V of power to operate.
If your Photon is being powered through the barrel jack, connect to the VIN pin.
If your Photon is being powered through the Micro-USB port, connect to the V-USB pin.
Here are the steps to connect the ultrasonic sensor to your Photon using the breadboard:
Insert the 4 pins of the ultrasonic sensor into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.) It is recommended to insert the sensor on the left half of the breadboard with the transmitter and receiver facing away from the Photon.
Plug one end of a jumper wire into the same terminal strip row as the sensor's VCC pin. Plug the other end of this jumper wire into either the VIN pin or V-USB pin on the Photon circuit board (or to a positive power rail on the breadboard that is connected to VIN or V-USB). If your Photon is being powered through the barrel jack, connect to the VIN pin. Otherwise, if your Photon is being powered through the Micro-USB port, connect to the V-USB pin.
Plug one end of a second jumper wire into the same terminal strip row as the sensor's Trig pin. Plug the other end of this jumper wire into an I/O pin on the Photon circuit board.
Plug one end of a third jumper wire into the same terminal strip row as the sensor's Echo pin. Plug the other end of this jumper wire into an I/O pin on the Photon circuit board.
Plug one end of a fourth jumper wire into the same terminal strip row as the sensor's GND pin. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect the ultrasonic sensor:
Keep in mind that your connection can look different than this example diagram:
Your ultrasonic sensor pins could be inserted into different row numbers. (The example connects the sensor pins to rows 23-26 on the left side of the breadboard.)
Your motion sensor pins could be inserted into a different column of the breadboard. (The example connects the sensor pins into column B of the terminal strip rows.)
Your sensor's VCC pin could connect (through a jumper wire) to either the VIN pin or V-USB pin (or to a positive power rail that's connected to one of these pins). (The example connects directly to the VIN pin.)
Your sensor's Trig pin could connect (through a jumper wire) to a different I/O pin. (The example connects to the D2 pin.)
Your sensor's Echo pin could connect (through a jumper wire) to a different I/O pin. (The example connects to the D3 pin.)
Your sensor's GND pin could connect (through a jumper wire) to either to a GND pin or to a negative power rail connected to a GND pin. (There are three available GND pins.)
The basic steps to use an ultrasonic sensor in your app code are:
Declare global variables to store the I/O pin numbers for the ultrasonic sensor.
Set the pin modes for the sensor in the setup()
function, and turn off the transmitter.
Use a custom function that will measure and return the distance to the nearest object.
You should declare global variables to store the I/O pin numbers that the ultrasonic sensor's transmitter (Trig) and receiver (Echo) are connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the trimpot to a different pin number).
Add this code (modify if necessary) before the setup()
function:
Each line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variables will be called TRIG_PIN
(transmitter) and ECHO_PIN
(receiver). You can change the variable names, but choose names that will make sense to anyone reading the code. You will need to make sure the same variable names are listed in the custom function which measures the distance to the nearest object.
It assigns a value to the variable. In this example, the variables will be equal to D2
and D3
. If necessary, modify these values to match the I/O pins that your sensor pins are connected to.
You need to set the pin modes for the sensor's transmitter (Trig) and receiver (Echo). Then you need turn off the sensor's transmitter until you're ready to actually take a distance measurement.
Add this code (modify if necessary) within the setup()
function:
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D2
, etc.) or a variable that stores a pin number. In this example, the variables named TRIG_PIN
and ECHO_PIN
are listed. If necessary, change these to match the variable names for your sensor's pins.
The mode value, which will be OUTPUT
for the sensor's transmitter pin and INPUT
for the sensor's receiver pin.
The digitalWrite()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D2
, etc.) or a variable that stores a pin number. In this example, the variable named TRIG_PIN
is listed. If necessary, change this to match the variable name for your sensor's transmitter pin.
The signal value, which can be HIGH
or LOW
. Your Photon uses this value to send an electrical signal through the pin: HIGH
is a signal of 3.3 volts which represents "on," while LOW
is a signal of 0 volts which represents "off." In this case, LOW
is being used to turn off the transmitter.
You'll add a custom function named measureDistance()
than can be called to measure the distance from the ultrasonic sensor to the nearest object. The function will return the distance as a float
value (decimal number).
Add this measureDistance()
function after the loop()
function:
Possible modifications to this custom function:
If you used different names for the global variables representing the transmitter (TRIG_PIN
) and receiver (ECHO_PIN
), then be sure to modify this function to use those variable names instead.
If you want the function to return the distance measurement in units of centimeters (instead of inches), then modify the return
statement towards the end of the function.
Each time you need a new distance measurement, you'll need to call the measureDistance()
function.
To call this custom function, add this code within the loop()
function (or within another custom function):
A local variable named sensorDist
is declared that will have a data type of float
(decimal number). This variable will be made equal to the value returned by the measureDistance()
function.
You'll need add code to do something with the distance measurement stored in sensorDist
. It's common to use an if
statement (or an if-else statement) to perform certain actions based on whether the distance is less than (or greater than) a specific value.
For example, this code example will turn on an LED light if the distance is less than 6 inches (otherwise it will turn the LED off):
A good way to test your ultrasonic sensor is to connect the Micro OLED display to your Photon, so you can show the value of sensorDist
on the OLED screen to verify the sensor is working accurately.
For example, once you've added the other necessary code for the Micro OLED, you could add this code within the loop()
function:
The motion sensor has a 3-wire JST connector with 3 pins for plugging into a breadboard. (If the end of your connector doesn't have 3 metal pins, attach the included in your kit.)
The condition listed inside the parentheses of the checks whether the value of motionState
is to LOW
:
If this condition is false (because the motionState
is HIGH
), the code within the curly braces will NOT be performed. Optionally, you can add an to perform a different set of code statements when motion is not detected.
There is also a <link>
tag to load a CSS stylesheet from . This will allow you to display different icons using HTML code that you'll copy from Font Awesome.
Each anchor tag displays an icon from (using special <i>
code), along with a text label. You can change the icon and the text label. In the starter code, each icon has the Font Awesome fa-2x
class added, in order to display the icon at double size.
The contains methods to allow your web app to interact with your Photon device through Particle Cloud. You'll use Particle methods in your web app JS file.
The contains methods that make it easy to modify the content and style of your web app by dynamically changing its HTML and CSS. You'll use jQuery methods in your web app JS file.
This JS also declares global variables to store your Photon device ID and access token. You must modify these lines to list , which you will need to get from your team's Particle Build account.
Review the reference section on to learn how to make your web app JS interact with your Photon device app.
If you want to learn more about web development or need a quick reference, consult these tutorials and references from :
SWITCH = KEYWORD: You cannot use "switch" as the name of a variable (or a custom function) because is a reserved keyword in the Wiring programming language.
The condition listed inside the parentheses of the checks whether the value of switchState
is to HIGH
:
The light sensor is a variable resistor: its resistance changes (depending on the amount of light it is exposed to). A static resistor (which has a fixed resistance) will be connected in series with the photocell to create a . This will allow the Photon to measure the resistance of the photocell, which indicates the amount of light reaching the sensor.
Trimpot
Photon Pin
Outer Leg (pick one)
3.3V
Middle Leg
any analog I/O pin (A0, A1, A2, A3, A4, A5)
Other Outer Leg
GND
Push Button
Photon Pin
One Leg (any leg)
any I/O pin
Adjacent Leg on same side
GND
Soil Moisture Sensor | Photon Pin |
SIG (Signal) – Yellow | any analog I/O pin (A0, A1, A2, A3, A4, A5) |
GND (Ground) – Black | GND |
VCC (Power) – Red | any I/O pin |
Accelerometer | Photon Pin |
3.3V | 3.3V |
SDA | D0 (SDA) |
SCL | D1 (SCL) |
I2 | (none) |
I1 | (none) |
GND | GND |
Motion Sensor | Photon Pin |
Black - Data | any I/O pin |
White - Ground | GND |
Red - Power (5-12V) | 5V through VIN or V-USB |
RHT03 Temperature Sensor | Photon Pin |
Leg 1 – Power (3.3-6V) | 3.3V or 5V (through VIN or V-USB) |
Leg 2 – Data | any I/O pin |
Leg 3 – Unused | (none) |
Leg 4 – Ground | GND |
Magnetic Switch | Photon Pin |
First Wire (either one) | any I/O pin |
Second Wire | GND |
Light Sensor (Photocell) | Photon Pin |
First Leg (either one) | 3.3V |
Second Leg | (1) any analog I/O pin (A0, A1, A2, A3, A4, A5) (2) GND using resistor |
Ultrasonic Sensor | Photon Pin |
VCC | 5V through VIN or V-USB |
Trig | any I/O pin |
Echo | any I/O pin |
GND | GND |
Here are references for how to connect and code each physical output in your SparkFun Photon kit:
LEDs (light-emitting diodes) are small, bright, long-lasting, energy-efficient lights. LEDs have been commonly used in electronic products for decades. More recently, incandescent light bulbs used in homes and other buildings are being replaced with LED light bulbs due to their energy efficiency.
Your Photon kit has a set of LED lights in different bulb colors: red, yellow, green, and blue.
An LED light is a polarized part, meaning there is one way to correctly connect its positive and negative terminals. If a polarized part is connected incorrectly (by switching the positive and negative), the part may not work or could become damaged.
Each LED in your Photon kit has a positive leg and a negative leg. These can be identified visually by length: the negative leg has been made slightly shorter.
You will use a breadboard to help connect the LED to your Photon circuit board. The negative leg will be connected to GND (-) through a resistor. The positive leg will be connected to an I/O pin, which will serve as the voltage source (+).
To make it easier to insert the LED into a breadboard, you can carefully bend the positive leg as shown below, so both legs have the same height. You can still identify them visually: the straight leg is the negative leg, and the bent leg is the positive leg.
An LED can be easily burned out if it receives too much power. Therefore, a resistor must be used to limit the amount of current flowing through the LED. The resistor is used to connect the negative leg of the LED to a GND (-) pin.
Your Photon kit contains a set of resistors with a resistance rating of 330 Ohms. In order to insert a resistor into the pin holes of a breadboard, you will need to bend both resistor legs into ~90° angles:
To connect an LED light to your Photon using the breadboard, you will need:
LED light with bent positive leg
Resistor with bent legs
2 jumper wires (use different colors to help identify them)
RESISTOR REQUIRED: Connect the LED's negative leg to GND using a resistor, which will limit the amount of current flowing through the LED. Otherwise, you will burn out the LED.
Here are the steps to connect the LED light to your Photon using the breadboard:
Insert the positive and negative legs of the LED into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as the bent positive leg of the LED. Plug the other end of this jumper wire into an I/O pin on the Photon circuit board.
Insert one end of the resistor into the same terminal strip row as the negative leg of the LED. Insert the other end of the resistor into a pin hole of the negative column of the closest power rail on the breadboard.
If the negative power rail isn't already connected to a GND pin on the Photon circuit board, then plug one end of the other jumper wire into another pin hole in the negative power rail, and plug the other end of this jumper wire into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect an LED light:
Keep in mind that your connection can look different than this example diagram:
Your LED legs could be inserted into different row numbers on the breadboard. (The example connects the positive leg to row 20 and the negative leg to row 21.)
Your LED legs could be inserted into a different column on the breadboard. (The example connects the LED legs into column I of the terminal strip rows.)
The positive LED leg could connect to a different I/O pin. (The example connects to the D0 pin.)
The negative power rail on your breadboard could connect to a different GND pin. (There are three available GND pins.)
The basic steps to control an LED light in your app code are:
Declare a global variable to store the I/O pin number for the LED.
Set the pin mode for the LED pin in the setup()
function.
Use digitalWrite()
statements to turn the LED on or off. (Another option is to use analogWrite()
statements to control the brightness of the LED.)
You should declare a global variable to store the I/O pin number that the LED is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the LED to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
This line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called LED
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to D0
. If necessary, modify this value to match the actual I/O pin that your LED is connected to.
If you have multiple LED lights connected to your Photon, then be sure to give each LED a unique variable name by adding an adjective or number to the variable names. For example:
You need to set the pin mode for the LED to be used as an output.
Add this code statement (modify if necessary) within the setup()
function:
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D0
, etc.) or a variable that stores a pin number. In this example, a variable named LED
is listed. If necessary, change this to match the variable name for your LED.
The mode value, which will always be OUTPUT
for an LED light because your app will send "on" and "off" signals (or brightness signals) to the LED light.
If you have multiple LED lights connected to your Photon, then be sure to set the pin mode for each LED pin variable. For example:
The digitalWrite()
method is used to turn an LED on or off.
Add this code statement (modify if necessary) to your app within the setup()
function, loop()
function, or a custom function:
The digitalWrite()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D0
, etc.) or a variable that stores a pin number. In this example, a variable named LED
is listed. If necessary, modify this to match the variable name for your LED.
The signal value, which can be HIGH
or LOW
. Your Photon uses this value to send an electrical signal through the pin: HIGH
is a signal of 3.3 volts which represents "on," while LOW
is a signal of 0 volts which represents "off." Modify this value to either turn the LED on or off.
DIM LED WHEN PHOTON STARTS: Depending on which I/O pin an LED is connected to, the LED light might be on (at a dim brightness) when your Photon app first starts.
If you need an LED light to be turned off when your app first starts running, then be sure to include code to turn off the LED within the setup()
function after setting its pin mode.
Alternatively, you can use the analogWrite()
method to adjust the brightness of an LED from minimum ("off") to maximum – or any value in-between.
However, the LED light must be connected to an I/O pin capable of PWM output. PWM stands for pulse-width modulation, which is a way to make a digital output signal (which has only two values: HIGH or LOW) act like an analog output signal (which has a range of values).
These Photon I/O pins are capable of PWM output: A4, A5, D0, D1, D2, D3, RX, TX, WKP.
Add this code statement (modify as necessary) to your app within the setup()
function, loop()
function, or a custom function:
The analogWrite()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D0
, etc.) or a variable that stores a pin number. In this example, a variable named LED
is listed. If necessary, modify this to match the variable name for your LED.
The signal value, which can be any integer value (whole number) between 0-255. Your Photon uses this value to send a PWM electrical signal through the pin: 0
is minimum brightness (LED will be off) while 255
is maximum brightness. In this example, a value of 128
represents 50% brightness. Modify this value based on the brightness needed.
The analogWrite()
and digitalWrite()
methods are both capable of setting an LED to either minimum or maximum brightness:
Setting an LED to minimum brightness ("off") using analogWrite(LED, 0)
produces the same result as using digitalWrite(LED, LOW)
Setting an LED to maximum brightness using analogWrite(LED, 255)
produces the same result as using digitalWrite(LED, HIGH)
However, the analogWrite()
method is the only way to set an LED to a brightness that's in-between these two extremes:
analogWrite(LED, 64)
would set the LED to 25% brightness
analogWrite(LED, 128)
would set the LED to 50% brightness
analogWrite(LED, 192)
would set the LED to 75% brightness
etc.
The servo motor included in your Photon kit can rotate back or forth to any position between 0° and ~180° and hold its position.
The servo motor comes with 4 different plastic mounts called "horns" that can be attached to the motor axis (the white part sticking out of the top of the motor – this is what actually rotates). There is a single-arm horn, a double-arm horn, a four-point horn, and a circular horn. Each horn slips onto the motor axis (the horn and axis have matching "teeth"). Each horn has holes, which can allow you to attach something to the horn using the included screws.
This servo motor can rotate to a specific angle (up to ~180°) and hold its position. It does NOT rotate continuously, like a motor used in a fan or an engine. If your IoT device requires a motor that can rotate continuously, then you need a gear motor or a continuous rotation servo motor.
The servo motor has a built-in 3-wire connector. You'll plug 3 jumper wires into the connector, and then plug the other end of each wire into the breadboard or directly into a pin on the Photon circuit board.
The white wire of the servo motor must be connected to an I/O pin capable of pulse-width modulation (PWM), which is a process used to make a digital output signal (which has only two values: HIGH or LOW) act like an analog output signal (which has a range of values).
These Photon I/O pins are capable of PWM output: A4, A5, D0, D1, D2, D3, RX, TX, WKP.
To connect a servo motor to your Photon using the breadboard, you will need:
Servo Motor (with 3-wire connector)
3 jumper wires (use different colors to help identify them; it may help to match the motor wires)
5V REQUIRED: The servo motor requires 5V of power to operate.
If your Photon is being powered through the barrel jack, connect to the VIN pin.
If your Photon is being powered through the Micro-USB port, connect to the V-USB pin.
Here are the steps to connect the servo motor to your Photon using the breadboard:
Plug one end of a jumper wire into the motor's white wire connector. Plug the other end of this jumper wire into a PWM-capable I/O pin on the Photon circuit board.
Plug one end of a second jumper wire into the motor's red wire connector. Plug the other end of this jumper wire into either the VIN pin or V-USB pin on the Photon circuit board (or to a positive power rail on the breadboard that is connected to VIN or V-USB). If your Photon is being powered through the barrel jack, connect to the VIN pin. Otherwise, if your Photon is being powered through the Micro-USB port, connect to the V-USB pin.
Plug one end of a third jumper wire into the motor's black wire connector. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail on the breadboard (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect a servo motor (ignore the wiring for the push button):
Keep in mind that your connection can look different than this example diagram:
Your servo motor's white wire could connect to a different I/O pin capable of PWM output. (The example connects to the D0 pin on the Photon circuit board).
Your servo motor's red wire could connect to either the VIN pin or V-USB pin – or to a positive power rail connected to one of these pins. (The example connects directly to the V-USB pin.)
Your servo motor's black wire could connect either to a different GND pin or to a negative power rail connected to a GND pin. (There are three available GND pins.)
Alternatively, you could connect the servo motor's wires into different terminal strip rows on a breadboard, and then use 3 additional jumper wires to connect to the Photon circuit board.
Be sure to attach one of the horns to your servo motor. Otherwise, rotating the motor won't provide much use to your device.
Later, once you test out your code to rotate the servo motor, you may need to remove and re-position the horn, so it's lined up where you want it to be as it rotates to specific angles. The best way to do this is to rotate the servo motor to 0° (or another specific angle, such as 90°) and then remove & re-position the horn to be pointed correctly for this particular angle.
The basic steps to control a servo motor in your app code are:
Declare a global variable to store the I/O pin number for the servo motor.
Create a Servo
object assigned to a global variable called servo
.
Use a sequence of servo.attach()
, servo.write()
, and servo.detach()
statements to rotate the motor to a specific angle.
The servo motor requires a code library that defines a class called Servo
which has built-in methods (functions) for controlling the motor. However, this library is already included in the Particle firmware on your Photon device, so you do not need an #include
statement to add the library to your app.
You should declare a global variable to store the I/O pin number that the servo motor is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the servo motor to a different pin number).
You will also need to create an object using the Servo
class included in the Particle firmware, and assign this object to a global variable.
Add this code (modify if necessary) before the setup()
function:
The first line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called motor
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to D0
. If necessary, modify this value to match the actual I/O pin that your servo motor is connected to.
The second line of code creates a new object using the Servo
class, and assigns the object to a global variable named servo
.
NOTE: The Servo
class name starts with an uppercase letter "S", while the servo
object variable name starts with a lowercase letter "s".
NO PIN MODE: Because you are controlling the servo motor using an object, you do not have to set a pin mode for the servo motor within the setup()
function.
The servo motor can rotate back or forth to any position between 0° and ~180° and hold its position.
Rotating the servo motor to a specific angle requires a sequence of four steps:
Turn on the motor using the servo.attach()
method.
Rotate the motor to a specific angle using the servo.write()
method.
Allow time for the motor to finish rotating by using the delay()
method.
Turn off the motor using the servo.detach()
method.
You'll add a custom function named rotateServo()
that will contain all these steps. The function will accept a parameter representing the desired angle of rotation.
Add this rotateServo()
custom function after the loop()
function:
The rotateServo()
function requires a parameter for the specific angle of rotation. The parameter value must be an integer (whole number) and will be stored in a local variable named angle
.
Here's what the code inside the rotateServo()
function does:
The servo.attach()
method turns on the motor. This method requires the servo motor I/O pin number. In this case, the global variable named motor
stores this value. If you used a different name for the global variable storing your servo motor pin number, then insert that name instead.
The servo.write()
method rotates the motor. This method requires an integer value from 0-180 representing the angle for the rotation. In this case, the parameter variable named angle
stores the value that will be used.
A delay()
of 500
ms (0.5 seconds) is included to give the motor enough time to physically rotate before turning the motor off again.
The servo.detach()
method turns off the motor. Otherwise, if the motor isn't turned off, the motor will be "jittery" as it tries to hold its position. After you turn off the motor, you may notice that it "debounces" (rotates backward slightly). This is normal.
The rotateServo()
function can be called within the setup()
function, loop()
function, or another custom function.
When calling the rotateServo()
function, you must include the desired angle of rotation (0-180) within the parentheses after the function name.
For example, to make the servo motor rotate to an angle of 90°, insert this code statement to call the rotateServo()
function:
APPROX. 180°: In reality, this servo motor can only physically rotate to about 160°, even if it is told to rotate to 180°. Just keep this in mind as you design and build your device.
CHECK HORN POSITION: Once you've got your servo motor working, you may need to remove and re-position its horn, so the horn is lined up where you want it to be as it rotates to specific angles. The best way to do this is to rotate the servo motor to 0° (or another specific angle, such as 90°) and then remove and re-position the horn to be pointed correctly for this particular angle.
ROTATE SERVO IN SETUP: In order to ensure that your device functions correctly, you should include a code statement to rotate your servo motor to a specific starting angle (such as 0°, 90°, 180°, etc.) in the setup()
function. Otherwise, the servo motor will start at whatever angle it was at when the device was last powered off.
If necessary, the servo.read()
method can be used to get the current angle of the servo motor. The method will return an integer value (whole number) between 0-180 representing the last angle used in the servo.write()
method.
Add this code statement wherever you need to read the current angle of the servo motor:
This code statement creates a local variable named angle
to store the integer value returned by servo.read()
.
The small speaker included in the Photon kit can produce tones or play simple music (note by note). The speaker can produce tones ranging in frequency from 20Hz (very low pitch) to 20KHz (very high pitch), covering the full range of sounds that humans can hear.
A speaker is a polarized part, meaning there is one way to correctly connect its positive and negative terminals. If a polarized part is connected incorrectly (by switching the positive and negative), the part may not work or could become damaged.
The speaker in your Photon kit has a positive leg and a negative leg. These can be identified by labels on the bottom of the speaker:
Also, there is a positive symbol ( ⊕ ) printed on the side of the speaker to identify which side has the positive leg. This allows you to verify the polarity while the speaker is plugged into a breadboard.
The positive leg of the speaker must be connected to an I/O pin capable of pulse-width modulation (PWM), which is a process used to make a digital output signal (which has only two values: HIGH or LOW) act like an analog output signal (which has a range of values).
These Photon I/O pins are capable of PWM output: A4, A5, D0, D1, D2, D3, RX, TX, WKP.
To connect a speaker to your Photon using the breadboard, you will need:
Speaker
2 jumper wires (use different colors to help identify them)
Here are the steps to connect the speaker to your Photon using the breadboard:
Insert the positive and negative legs of the speaker into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as the positive leg of the speaker. Plug the other end of this jumper wire into a PWM-capable I/O pin on the Photon circuit board.
Plug one end of the other jumper wire into the same terminal strip row as the negative leg of the speaker. Plug the other end of this jumper wire into a pin hole connected to GND: either plug it into a negative power rail on the breadboard (which is connected to GND via a different jumper wire), or plug it directly into a GND pin on the Photon circuit board.
Here's a wiring diagram showing a possible way to connect a speaker:
Keep in mind that your connection can look different than this example diagram:
Your speaker legs could be inserted into different row numbers on the breadboard. (The example connects the negative leg to row 3 and the positive leg to row 5.)
Your speaker legs could be inserted into a different column on the breadboard. (The example connects the LED legs into column F of the terminal strip rows.)
The positive leg of your speaker could connect to a different I/O pin capable of PWM output. (The example connects to the D2 pin.)
The negative leg of your speaker could connect (through a jumper wire) either to a different GND pin or to a negative power rail connected to a GND pin. (There are three available GND pins.)
The basic steps to control a speaker in your app code are:
Declare a global variable to store the I/O pin number for the speaker.
Set the pin mode for the speaker pin in the setup()
function.
Use tone()
statements to produce sounds.
You should declare a global variable to store the I/O pin number that the speaker is connected to. This will make it easier to understand your code (and easier to modify the code if you were to connect the speaker to a different pin number).
Add this code statement (modify if necessary) before the setup()
function:
This line of code does 3 things (in order):
It declares a data type for the variable's value. In this case, int
stands for integer (whole number). Photon pin numbers are always treated as int
values (even though they have letters).
It declares the variable's name. In this example, the variable will be called speaker
. You can change the variable name, but choose a name that will make sense to anyone reading the code.
It assigns a value to the variable. In this example, the variable's value will be equal to D2
. If necessary, modify this value to match the actual I/O pin that your speaker is connected to.
You need to set the pin mode for the speaker to be used as an output.
Add this code statement (modify if necessary) within the setup()
function:
The pinMode()
method requires two parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D0
, etc.) or a variable that stores a pin number. In this example, a variable named speaker
is listed. If necessary, change this to match the variable name for your speaker.
The mode value, which will always be OUTPUT
for a speaker.
The tone()
method is used to produce a sound of a specific frequency (pitch) for a specific duration of time. The speaker can produce tones ranging in frequency from 20Hz (very low pitch) to 20KHz (very high pitch), which covers the full range of sounds that humans can hear.
Add this code statement (modify as necessary) to your app within the setup()
function, loop()
function, or a custom function:
The tone()
method requires three parameters inside its parentheses (in this order):
The I/O pin number, which can be the actual pin number (such as: D2
, etc.) or a variable that stores a pin number. In this example, a variable named speaker
is listed. If necessary, modify this to match the variable name for your speaker.
The frequency for the tone, which can be an integer value (whole number) or a variable that stores an integer. The value can be between 20-20000 hertz. Lower numbers will have a lower pitch, while higher numbers will have a higher pitch. In this example, the frequency will be 2000
hertz. Modify this value to the frequency you want for your sound.
The duration for the tone, which can be an integer number (whole number) or a variable that stores an integer. The value represents the number of milliseconds that the tone will be played (1000 ms = 1 second). In this example, the duration will be 250
ms (0.25 seconds).
VOLUME: There isn't a way to change the volume of a tone produced by your Photon. However, you will notice that certain frequencies will naturally seem louder to your ears.
If you want to produce a continuous tone that keeps playing, you can either use a negative value for the duration – or you can leave out the duration parameter entirely:
To turn off a continuous tone, use the noTone()
method when you're ready to stop the sound:
The Micro OLED display included in your Photon kit is a monochrome (single-color) screen that is 64 pixels in width and 48 pixels in height. It can be used to display text, simple graphics, or a combination. You can even create simple animations by drawing an object, leaving it on the screen briefly, erasing it, and repeating these steps with the object drawn at a new position on the screen.
Although the Micro OLED display is small, it can be useful for displaying information. Since the display is so small, design your information to be "glanceable" – a person should be able to very quickly and easily read and understand the information.
To connect the Micro OLED display to your Photon using the breadboard, you will need:
Micro OLED display
7 jumper wires (use different colors to help identify them)
The Micro OLED has pins located along the top edge of the display. There are labels for each pin printed on the underside of the Micro OLED circuit board.
If the pins along the top edge were numbered left to right as 1-8, the wiring connections would be:
3.3V MAXIMUM: The Micro OLED display operates at 3.3V of power. Connect it to the 3.3V pin on your Photon, or connect it to a positive power rail that's connected to the 3.3V pin.
Do NOT connect it to VIN or V-USB because the higher voltage could damage the display.
TWIN PINS: Analog pins A2, A3, A4, and A5 are each represented by two pins on the Photon board. The duplicate pins are labeled as: SS/A2, SCK/A3, MISO/A4, MOSI/A5.
However, the Micro OLED has to connect to only one A2 pin – not both. The same goes for connecting the Micro OLED to the A3 and A5 pins.
The only limitation is that once you connect the Micro OLED, you will not be able to have a different part (such as an LED, etc.) connected to the other A2, A3, or A5 pins.
Here are the steps to connect the Micro OLED to your Photon using the breadboard:
Insert the 8 pins of the Micro OLED into different terminal strip rows on the breadboard. (Different terminal strip rows have different row numbers.)
Plug one end of a jumper wire into the same terminal strip row as the first OLED pin (CS). Plug the other end of this jumper wire into its corresponding pin on the Photon circuit board.
Repeat step 2 with the other jumper wires until each OLED pin is connected to its correct Photon pin. NOTE: The fourth OLED pin (SDO) will not be connected to anything.
Here's a wiring diagram showing a possible way to connect a servo motor (ignore the wiring for the three push buttons):
Keep in mind that your connection can look different than this example diagram:
Your Micro OLED pins could be inserted into different row numbers on the breadboard. (The example connects the OLED pins to rows 1-8 on the right side of the breadboard.)
Your Micro OLED pins could be inserted into a different column of the breadboard. (The example connects the OLED pins into column F of the terminal strip rows.)
Your Micro OLED could connect (through jumper wires) to the other A2, A3, and A5 pins located on the lower left side of the Photon circuit board.
Your Micro OLED 3V3 pin could connect (through a jumper wire) either directly to the 3.3V pin or to a positive power rail connected to the 3.3V pin.
Your Micro OLED GND pin could connect (through a jumper wire) either directly to a GND pin or to a negative power rail connected to a GND pin. (There are three available GND pins.)
The basic steps to control the Micro OLED display in your app code are:
Include the SparkFun Micro OLED library in your app.
Define the I/O pin numbers for certain Micro OLED pins.
Create a MicroOLED
object assigned to a global variable called oled
.
Use the oled.begin()
method to start the display in the setup()
function.
Use various oled
methods to display text or simple graphics on the screen.
Your Photon app must include a code library that will allow you to control the Micro OLED display.
In Particle Build, click on the Libraries icon to open the Libraries menu panel.
Type oled
into the search field. Select the result called: SparkFunMicroOLED
Click the button to "Include in Project"
Select the title of your Photon app, and then click the "Confirm" button
Particle Build will automatically insert this #include
statement at the beginning of your app code:
You need to define the I/O pin numbers for certain Micro OLED pins. This is similar to declaring global variables (except defined values are not allowed to change).
You will also need to create an object using the MicroOLED
class in the included library, and assign this object to a global variable.
Add this code before the setup()
function:
The first three lines of code define the I/O pin numbers for three specific OLED pins.
The fourth line of code creates a new object using the MicroOLED
class, and assigns the object to a global variable named oled
.
The oled.begin()
method is used to start the Micro OLED display.
Add this code statement within the setup()
function to start the OLED display:
The oled.begin()
method will initialize the settings (including pin modes) for the Micro OLED and turn it on.
Displaying text on the Micro OLED screen requires a sequence of five steps:
Clear the screen using the oled.clear()
method.
Set the font type using the oled.setFontType()
method.
Set the cursor position using the oled.setCursor()
method.
Print text to the screen using the oled.print()
and/or oled.println()
methods.
Display the printed text using the oled.display()
method.
For example:
CREATE CUSTOM FUNCTION: Rather than listing all your OLED code statements within the loop()
function, it may be better to create a custom function that contains all the code to display your text or graphics. Then call the custom function within the loop()
function.
To clear the screen before adding text or graphics:
The SparkFun Micro OLED library includes 4 available font types (numbered 0-3), which differ in font size and in which characters can be displayed:
By default, the Micro OLED will be set to font type 0 by the oled.begin()
method.
You can use the oled.setFontType()
method to set the font type by including the font type number within the parentheses:
You can use a mix of different font types by setting a new font type before printing a new line of text.
For example:
The cursor position represents the starting position for printing text to the screen. The cursor can be set to any (x,y)
position on the screen. The OLED screen is 64 pixels wide by 48 pixels tall:
The x
positions are numbered left to right as 0-63
The y
positions are numbered top to bottom as 0-47
For example, to have your text start at the top-left corner of the screen:
As you print text to the screen, the OLED display will automatically move the cursor position, so the next text printed to the screen will start at the next available screen position.
However, if desired, you can adjust the text layout by setting a new cursor position before printing a line of text, so the new text will start at a specific position on the screen.
For example:
The oled.print()
and oled.println()
methods can be used to print text (or variable values) to the screen. Text that is longer than the screen column width will automatically wrap to the next line.
To print text directly, include the text inside the method's parentheses by listing the text within double quotation marks:
To print the value stored in a variable, include the variable name inside the method's parentheses.:
In this case, myName
is a variable name (presumably a person's name). Change this to the name of your variable, which could store a text string or number.
If a variable stores a decimal number (data type is float
or double
), you have the option of indicating how many digits after the decimal point to show when printing the variable's value:
In this case, roomTemp
is a variable name that stores a decimal value (presumably a temperature sensor measurement). Its value will be displayed to 1
digit after the decimal point. So if the actual variable value were 70.1584275
, it would be printed on the screen as: 70.2
(the last digit is automatically rounded up if necessary).
There are two different print methods that can display text on the Micro OLED screen:
oled.print()
will print text to the screen, but the cursor will remain on the same line. The next text printed to the screen will start where the last text ended.
oled.println()
will print text to the screen, and then move the cursor to the start of a new line. The next text printed to the screen will start on the new line.
The oled.print()
command is useful for combining text and variable values on the same line.
For example, if you had a variable named hour
that stored the hour of the current time and another variable named minutes
that stored the minutes, you could combine these together on the screen:
Notice that the last code statement used the oled.println()
method to move the cursor to a new line for any text that might be printed after the time.
To add a blank line, just use the oled.println()
method without anything inside its parentheses:
Any text or graphics will NOT be shown until the OLED is instructed to display the screen:
GLANCEABLE: Because the Micro OLED display is small, be sure your text and graphics will be "glanceable" – a person should be able to quickly and easily understand the information.
Displaying simple graphics on the Micro OLED screen requires a sequence of three steps:
Clear the screen using the oled.clear()
method.
Draw graphics (dots, lines, rectangles, circles) on the screen using various methods.
Display the graphics using the oled.display()
method.
For example:
Rather than listing all these code statements within the loop()
function, you may want to create a custom function that contains all the code to display your graphics. Then you can call this custom function within the loop()
function.
The following drawing methods are available:
oled.pixel()
can be used to draw a dot
oled.line()
, oled.lineH()
, and oled.lineV()
can be used to draw a line
oled.rect()
and oled.rectFill()
can be used to draw a rectangle
oled.circle()
and oled.circleFill()
can be used to draw a circle
Each drawing method requires parameters for the (x, y) pixel position of a point (or two points if drawing a line). The OLED screen is 64 pixels wide by 48 pixels tall:
The x
pixel positions are numbered left to right as 0-63
The y
pixel positions are numbered top to bottom as 0-47
The oled.pixel()
method can be used to draw a dot (pixel) at a specific point:
For example, to draw a dot at the center of the screen:
The oled.line()
method can be used to draw a line from one point (x1, y1) to another point (x2, y2):
For example, to draw a line from the top-left corner (0,0) to the bottom-right corner (63, 47):
The oled.lineH()
method can be used to draw a horizontal line that starts from a specific point (representing the left end of the line) and has a specified width:
For example, to draw a horizontal line that starts at (12, 24) and has a width of 40 pixels:
The oled.lineV()
method can be used to draw a vertical line that starts from a specific point (representing the top end of the line) and has a specified height:
For example, to draw a vertical line that starts at (32, 9) and has a height of 30 pixels:
The oled.rect()
method can be used to draw an outline of a rectangle that starts from a specific point (representing the top-left corner of the rectangle) and has a specified width and height:
For example, to draw an outline of a rectangle with its top-left corner at (12, 14) with a width of 40 pixels and a height of 20 pixels:
The oled.rectFill()
method can be used to draw a solid (filled) rectangle that starts from a specific point (representing the top-left corner of the rectangle) and has a specified width and height:
For example, to draw a filled rectangle with its top-left corner at (12, 14) with a width of 40 pixels and a height of 20 pixels:
The oled.circle()
method can be used to draw an outline of a circle that has its center at specific point and has a specified radius:
For example, to draw an outline of a circle with its center at (32, 24) and a radius of 20 pixels:
The oled.circleFill()
method can be used to draw a solid (filled) circle that has its center at specific point and has a specified radius:
For example, to draw a filled circle with its center at (32, 24) and a radius of 20 pixels:
By default, all the drawing methods will draw using "white" pixels (which are actually light blue on your Micro OLED screen). However, you can modify each method to draw using black pixels instead, which represents erasing.
Any of the drawing methods can be modified to draw using black pixels by adding BLACK, NORM
as the last two parameters inside the method's parentheses.
For example, to draw a black dot:
For example, to draw a black line:
For example, to draw solid (filled) black circle:
The black pixels will only be visible if drawn on top of a white shape, so the black pixels are erasing white pixels.
For example, this code draws a white filled circle with its center at (32, 24) and a radius of 20 pixels, and then draws a black filled circle that also has its center at (32, 24) but with a radius of 10 pixels:
By drawing the black circle after the white circle, the black circle will erase part of the white circle.
You can also create more complex patterns by drawing a series of white and black shapes, such as:
This example code draws 4 filled circles that have the same center point but a different radius:
First, a white filled circle with a radius of 20 pixels is drawn.
Then, a black filled circle with a radius of 15 pixels erases part of the white circle.
Then, a new white filled circle with a radius of 10 pixels is drawn that fills part of the black circle.
Finally, a new black filled circle with a radius of 5 pixels erases part of the second white circle.
The overall pattern ends up looking like a "target" symbol:
You can also create simple animations by drawing something (with white pixels), leaving it on the screen briefly, erasing it (with black pixels), and then changing its position on the screen. A for
loop can be used to repeat the "animation" for a certain number of times.
For example, here is code for a simple animation that makes a circle "bounce" back and forth on the screen. The code inside each for
loop draws and displays a white filled circle, leaves the circle on the screen for a brief delay()
, and then erases the circle (by drawing and displaying a black filled circle of the same size at the same position).
The first for
loop increases the x-position of the circle's center from 10 to 53, which slowly moves the circle across the screen from left to right. The second for
loop decreases the x-position of the circle's center from 53 to 10, which moves the circle from the right back to the left.
You can also combine text and graphics on the OLED screen at the same time. For example:
The Micro OLED display is only 64 pixels in width by 48 pixels in height. Use this limited screen space effectively by designing your text and graphics to be "glanceable" – a person should be able to very quickly and easily read and understand the information.
LED Light
Photon Pin
Positive Leg (bent) = Power
any I/O pin
Negative Leg = Ground
GND using resistor
Servo Motor
Photon Pin
White – Data
any I/O pin capable of PWM output
Red – Power (4.8-6V)
5V through VIN or V-USB
Black – Ground
GND
Speaker
Photon Pin
Positive Leg
any I/O pin capable of PWM output
Negative Leg
GND
OLED Pin
Photon Pin
Pin 1 – CS
A2
Pin 2 – RST
D6
Pin 3 – D/C
D5
Pin 4 – SDO
(None)
Pin 5 – SCK
A3
Pin 6 – SDI
A5
Pin 7 – 3V3
3.3V
Pin 8 – GND
GND
Font Type
Font Size
Characters Allowed
Used For
0
5×7 pixels (10 columns by 6 rows)
any ASCII character
General
1
8×16 pixels (6 columns by 3 rows)
any character on keyboard
General
2
10×16 pixels (5 columns by 3 rows)
only numbers and period
Numbers
3
12×48 pixels (5 columns by 1 row)
only numbers and colon
Numbers or Time