SparkFun Inventor's Kit for Photon Experiment Guide
Introduction
Note: This tutorial was originally written for KIT-13320 but applies to the KIT-14684. The only differences
are the included buttons and thickness of the resistor leads that are included in the kit. Overall, they are
functionally the same.
The SparkFun Inventor's Kit for Photon, also known as the SIK for Photon, is the latest and greatest in Internet of
Things kits. Whether you're a software developer just getting in to hardware, an electronics engineer learning
software, or somewhere in between, this kit will help you get your projects hooked up to the Internet in no time.
For an overview of the Photon RedBoard and a preview of the kinds of experiments you'll get to build with this kit,
check out the video below.
SparkFun Redboard and Inventor's Kit for Photon
Set Aside Some Time - Each experiment in this kit has two parts, with the second half usually containing
an Internet-connected component. Please allow yourself ample time to complete each experiment. You may
not get through all the experiments in one sitting. Please understand that the second half of each experiment
is bonus material and relies on outside services, websites and technologies, to which some of you may not
have access.
Included Materials
Here is a complete list of all the parts included in the SIK for Photon.
SparkFun Inventor's Kit for Photon
KIT-14684
The SparkFun Inventor's Kit for Photon Includes the following:
SparkFun Photon RedBoard
Photon RedBoard and Breadboard Holder
White Solderless Breadboard
Pocket Screwdriver Set
Small Servo
9V Alkaline Battery
9V to Barrel Jack Adapter
USB microB Cable - 6 Foot
Jumper Wires
JST Right Angle Connector - Through-Hole 3-Pin
Soil Moisture Sensor
SparkFun Micro OLED Breakout (with Headers)
SparkFun Triple Axis Accelerometer Breakout - MMA8452Q (with Headers)
PIR Motion Sensor (JST)
RHT03 Humidity and Temperature Sensor
Magnetic Door Switch Set
Photocell
Red, Blue, Yellow, and Green LEDs
Red, Blue, Yellow, and Green Buttons
10K Trimpot
Piezo Speaker
330 Ohm Resistors
If, at any time, you are unsure which part a particular experiment is asking for, reference this section.
Suggested Reading
The following links are here to help guide you in your journey through the SIK for the Photon. Referencing these
documents throughout this guide will help you get the most out of this kit.
The Photon RedBoard Hookup Guide - This guide goes over the features of the Photon RedBoard in great
detail, from the functions of each pin to a compare and contrast between the Photon RedBoard, the Photon,
and the classic Arduino Uno.
Photon Development Guide - Learn how to develop with your Photon or Photon RedBoard using the three
different methods described in this tutorial.
Getting Started with Particle - The Particle website has tons of great documentation to get you started in the
world of IoT development.
Each experiment will also have a Suggested Reading section to aid you in understanding the components and
concepts used in that particular experiment.
Using the Kit
Before embarking upon the experiments, there are a few items to cover first. If you have completed one of our
other Inventor's Kits before, you should already be familiar with most of the concepts in this section. If this is your
first Inventor's Kit, please read carefully to ensure the best possible SIK experience.
Photon RedBoard
The SparkFun Photon RedBoard is quite literally the brains of the SIK for Photon. Sporting an ARM Cortex M3
processor and a Broadcom WiFi controller, it is a powerful system rolled into one of the most common form-factors
now found in embedded electronics. To learn more about the Photon RedBoard and all its functionality, visit the
Photon Redboard Hookup Guide.
Photon RedBoard Hookup Guide
AUGUST 27, 2015
Your guide to commissioning, tinkering, and programming the SparkFun Photon
RedBoard.
Base Plate
Building circuits can be a monumental task when you've never done so before. To make circuit development
easier, we have included a baseplate onto which you can attach your breadboard and your Photon RedBoard.
To attach the breadboard, peel off the adhesive backing, and place the breadboard on the baseplate, making sure
that the SparkFun logo and text on your breadboard all face the same direction.
To attach the Photon RedBoard, use the included screws and screwdriver to attach the board to the baseplate.
Again, be sure that the text on the pins matches the directions of the breadboard text and the SparkFun logo. The
USB connector should be pointing up when looking directly at the baseplate.
Breadboard
Solderless breadboards are the go-to prototyping tool for those getting started with electronics. If you have never
used a breadboard before, we recommend reading through our How to Use a Breadboard tutorial before starting
with the experiments.
How to Use a Breadboard
MAY 14, 2013
Welcome to the wonderful world of breadboards. Here we will learn what a
breadboard is and how to use one to build your very first circuit.
Jumper Wires
This kit includes twenty 6" long jumper wires terminated as male to male. Multiple jumpers can be connected next
to one another on a 0.1" header or breadboard.
Each group of jumpers are connected to each other and can either be pulled apart in any quantity or kept whole
based on you needs.
Screwdriver
Last, we've included a pocket screwdriver set to aid you in any mechanical portions of this guide. Unscrew the cap
on the tail end of the screwdriver to reveal the various tips that can be inserted into the head of the screwdriver.
You will need to swap out tips for various tasks throughout this guide.
Using the Particle IDE
If you've worked with Arduino or with our SparkFun Inventor's Kit for Arduino, then you are familiar with the
Arduino IDE, short for Integrated Development Environment. Particle has created their own cloud-based IDE, and
they have adopted the Arduino language and syntax allowing you to move from an Arduino to the Photon and
Photon RedBoard with ease.
Particle has written a great getting started guide for using their Web IDE, called Particle Build. You can read
through their documentation by following the link below.
GETTING STARTED WITH PARTICLE BUILD
We have also written a Photon Development guide to help aid you in your experience. There are numerous ways
to develop with the Photon and Photon RedBoard, and this guide covers the three most common methods:
Particle Build, Particle Dev, and ARM GCC.
Photon Development Guide
AUGUST 20, 2015
A guide to the online and offline Particle IDE's to help aid you in your Photon
development.
For the purposes of this guide, we recommend sticking to the online Particle Build IDE. However, once you feel
comfortable using the Photon RedBoard, you are free to explore the other methods for development.
All of the experiments and circuits in this guide are available in our Inventor's Kit for Photon GitHub Repository, or
you can download the entire repository by clicking the link below.
INVENTOR'S KIT FOR PHOTON GITHUB REPOSITORY
If you prefer to use Particle Dev, you may find having all the experiment folders in one location is much easier for
development.
First-Time Firmware Update: The first time you upload a sketch to your Photon or Photon RedBoard, you
will likely encounter an over-the-air firmware update. Particle has built in this feature so that the first time you
upload code to the device, it will go out and grab the latest firmware from the Particle Cloud. Please BE
PATIENT. This may take several minutes. Do not press any buttons or remove power from the device during
this time. You will know the device is updating via the RGB LED blinking random bursts of pink (magenta). It
should look distinctly different from the flashing magenta that accompanies a user uploading their sketch,
which is more of a steady, fast blink. You may need to go through this procedure twice for the entirety of the
firmware to be downloaded over the web. Most of the firmware files for the Photon devices come in two parts.
If your device is still blinking pink once it connects to the Internet after the first over-the-air update, give it a
few moments to download the second half.
Getting Started with the Photon RedBoard
The Photon RedBoard can be powered over either USB (using the included Micro-B Cable) or with a 4.5-15V
barrel jack power supply (like either our 5V and 9V wall warts). To begin using your Photon RedBoard, plug it in!
The red "POWER" LED should illuminate to indicate the Photon RedBoard is on. Also lighting up will be the RGB
LED, which indicates which mode the Photon RedBoard is in.
RGB LED and Device Modes
The RGB LED on the Photon RedBoard identifies the connectivity status -- or other state information -- of the
Photon P1 module. The color-to-mode mapping of the Photon RedBoard is described in detail in Particle's Device
Mode documentation. As a quick summary:
LED Color
Cyan
Cyan
Green
Blue
Pink
Pink
White
Orange-Yellow
●
●
●
●
●
●
●
●
LED activity
Device Mode
Breathing
Connected to WiFi and Particle Cloud
Blinking
Connected to WiFi, Connecting to Particle Cloud
Blinking
Connecting to WiFi
Blinking
Listening mode (waiting for WiFi info)
Blinking
Receiving new application over-the-air
Breathing
Connected in safe mode
Breathing
Application running, WiFi off
Blinking
DFU mode
The first time a Photon RedBoard is powered up, it should jump into listening mode -- indicated by the blinking
blue LED. That means it's time to set up WiFi!
Configuring WiFi, Connecting to Your Particle Account
To use the Particle cloud -- and their online IDE -- you'll need a Particle account. Head over to build.particle.io to
sign up, if you haven't already.
CREATE A PARTICLE ACCOUNT!
When you power on a Photon RedBoard for the first time, it should boot up into listening mode -- indicated by a
blinking, blue LED. It'll remain in listening mode until configured with your WiFi network and password.
There are a handful of ways to configure a Photon's WiFi credentials, including with the Particle smartphone app
(iOS8+ or Android), or through a serial terminal. Unless you're very comfortable with serial terminals -- or just
don't have a smartphone nearby -- we recommend using the app.
Windows users: To use the Photon in serial port mode, Windows users will need to install a driver. Follow
Particle's "Installing the Particle Driver" guide for help installing the driver.
Both setup methods are described below, click one of the buttons to expand your section of interest:
CONFIGURING WIFI WITH THE PARTICLE APP
CONFIGURING WIFI WITH A SERIAL TERMINAL
Reset After Credentials are Entered: Once you have entered the WiFi credentials for your Photon
RedBoard, you will likely need to hit the Reset button before your device will connect to the web. There is
currently an error in the P1 module's firmware that does not automatically reboot the device once the
credentials have been received. This should be fixed in a future release of the P1 firmware.
Experiment 1: Hello World, Blink an LED
Some of the experiments will have two parts. The first part, will focus on teaching you about electronic
concepts and technologies and how to build a circuit around those. The second part is bonus material
showing you how to connect your circuit to the Internet or creating a more complex circuit. You will be able to
complete part one of each experiment with the included parts. However, the second half of each experiment
relies on outside services, websites and technologies, some of which you may not have access to or may not
want to engage in. Should part two of a particular experiment not interest you, you may move on to the next
experiment.
Introduction
LEDs (light-emitting diodes) are small, powerful lights that are used in many different applications. To start off the
SIK for Photon, we will work on blinking an LED using a digital output. Chances are you have blinked an LED
before, or perhaps this is your first time -- but have you turned on an LED with the Internet? Blinking an LED is the
most basic "Hello World" test for hardware, but now we're going to be saying "Hello Internet." This experiment will
also walk you through uploading your first sketch with the Particle IDE.
Parts Needed
You will need the following parts:
1x LED (Choose any color in the bag full of LEDs)
1x 330Ω Resistor
2x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
LED - Assorted (20 pack)
Jumper Wires - Connected 6" (M/M, 20 pack)
COM-12062
PRT-12795
Resistor 330 Ohm 1/4 Watt PTH - 20 pack
(Thick Leads)
PRT-14490
Suggested Reading
Before continuing on with this experiment, we recommend you be familiar with the concepts in the following
tutorial:
What is a Circuit? -- This tutorial will explain what a circuit is, as well as discuss voltage in further detail.
Voltage, Current, Resistance, and Ohm's Law -- Learn the basics of electronics with these fundamental
concepts.
LEDs (Light-emitting Diodes) -- LEDs are found everywhere. Learn more about LEDs and why they are
used in some many products all over the world.
Resistors -- Why use resistors? Learn more about resistors and why they are important in circuits like this
one.
Polarity -- Polarity is a very important characteristic to pay attention to when building circuits.
Hardware Hookup
Ready to party? Components like resistors need to have their legs bent into 90° angles in order to correctly fit the
breadboard sockets. You can also cut the legs shorter to make them easier to work with on the breadboard.
Pay close attention to the LED. The negative side of the LED is the short leg, marked with a flat edge.
Each experiment will have a Fritzing hook-up diagram. Connect the components to the breadboard and Photon
RedBoard by following the Fritzing diagram below:
Pay special attention to the component’s markings indicating how to place it on the breadboard.
Polarized components can only be connected to a circuit in one direction. Orientation matters for the following
component: LED
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
All jumper wires work the same. They are used to connect two points together. All the experiments will show the
wires with different colored insulations for clarity, but using different combinations of colors is completely
acceptable.
Be sure to the polarity on the LED is correct. The longer lead should be connected to D0. You will need to slightly
bend the longer leg so that both are the same length when placed int he breadboard.
Photon Code
Now to the exciting part! You'll need to go to the Particle Build IDE (preferably on another tab or window) to get
started. If you are not familiar with the Particle Build IDE, please refer to the Particle Build IDE documentation or
the Particle Build IDE overview in the beginning of this guide.
Using an online IDE might be little different at first for some users, but it ends up being fantastic. You can program
your Photon from anywhere in the world as long as you have an Internet connection.
Double check your Photon RedBoard's RGB LED is breathing cyan. If it is, then your Photon RedBoard is
connected to the Internet and ready to go. If your Photon RedBoard is not breathing cyan, please refer to the
Connecting your Photon to WiFi documentation. If you go to the navigation bar, click on Devices to see if your
Photon RedBoard is connected.
There will be a breathing cyan dot next to your Photon RedBoard in the Devices section.
For each experiment, we recommend creating a new app. Go to the Code section in the navigation bar on the left.
The hit the CREATE NEW APP button. After typing in the name, you can hit enter.
When you create a new app, particle build creates an .ino file and renames the tab in the Particle Build editor.
Let's add the code! Copy and paste the code below into the in Particle Build editor. You can simply hit the COPY
CODE button below and paste (Right-click then click Paste or Command + V) into the Particle Build Editor.
/*
SparkFun Inventor's Kit for Photon
Experiment 1 - Part 1: Hello World Blink an LED
This sketch was written by SparkFun Electronics
August 31, 2015
https://github.com/sparkfun
This is a simple example sketch that turns on an LED
for one second, off for one second, and repeats forever.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
int led = D0; // LED is connected to D0
// This routine runs only once upon reset
void setup()
{
pinMode(led, OUTPUT); // Initialize D0 pin as output
}
// This routine loops forever
void loop()
{
digitalWrite(led, HIGH); //
delay(1000);
//
digitalWrite(led, LOW);
//
delay(1000);
//
}
Turn
Wait
Turn
Wait
ON the LED
for 1000mS = 1 second
OFF the LED
for 1 second
Once you've pasted the code into the window, let's get in the habit of checking our code. Hit Verify (circle icon with
a check mark in the top left of the Particle Build's IDE navigation bar) to check if there is any errors in the code.
Next, hit Save (folder icon) to save our code, so we can come back to the code later if we want to.
Drum roll please! Hit Flash (lightning bolt icon) to load the code onto the Photon RedBoard.
First-Time Firmware Update: The first time you upload a sketch to your Photon or Photon RedBoard, you
will likely encounter an over-the-air firmware update. Particle has built in this feature so that the first time you
upload code to the device, it will go out and grab the latest firmware from the Particle Cloud. Please BE
PATIENT. This may take several minutes. Do not press any buttons or remove power from the device during
this time. You will know the device is updating via the RGB LED blinking random bursts of pink (magenta). It
should look distinctly different from the flashing magenta that accompanies a user uploading their sketch,
which is more of a steady, fast blink. You may need to go through this procedure twice for the entirety of the
firmware to be downloaded over the web. Most of the firmware files for the Photon devices come in two parts.
If your device is still blinking pink once it connects to the Internet after the first over-the-air update, give it a
few moments to download the second half.
If there are any invalid characters (such as ':') in your code or something is syntactically incorrect, you will get the
following error when attempting to flash your device:
Error: Could not compile. Please review your code.
What You Should See
Once you click Flash, you should see your Photon RedBoard flash magenta, followed by green, and then back to
breathing Cyan. Now, your LED should be blinking. You've just wirelessly programmed your Photon RedBoard to
blink an LED, from the cloud!
Great job on successfully uploading your first sketch. If you want to learn how blink an LED with the Tinker mobile
app, you can head to part 2 of this experiment!
Code to Note
Variables
A variable can be a number, a character, and even a string of characters. We'll often use variables to store
numbers that change, such as measurements from the outside world, or to make a sketch easier to understand
(sometimes a descriptive name makes more sense than looking at a number).
Variables can be different "data types", which is the kind of number we're using (can it be negative? Have a
decimal point?) We'll introduce more data types later, but for the moment we'll stick with good old "integers" (called
"int" in your sketch). Integers are whole numbers (0, 3, 5643).
You must "declare" variables before you use them, so that the computer knows about them. Here we'll declare a
integer variable, and at the same time, initialize it to specific values. We're doing this so that further down, we can
refer to the pin by name rather than number.
Note that variable names are case-sensitive! If you get an "(variable) was not declared in this scope" error, doublecheck that you typed the name correctly.
Here we're creating a variable called "led" of type "int" and initializing it to have the value "0":
int led = D0;
The Photon RedBoard has digital input/output pins. These pins can be configured as either inputs or outputs. This
is declared with a built-in function called pinMode() . The pinMode() function takes two values, which you type in
the parenthesis after the function name. The first value is a pin number (or variable representing a pin number),
and the second value declares how the pin behaves, usually as some sort of INPUT or OUTPUT.
Here we'll set up pin 0 (the one connected to a LED) to be an output. We're doing this because we need to send
voltage "out" of the Photon RedBoard to light up the LED.
pinMode(led, OUTPUT);
When you're using a pin as an OUTPUT, you can command it to be HIGH (output 3.3 volts in this case), or LOW
(output 0 volts).
digitalWrite(led, HIGH);
For more info on the types of PinModes available, visit the Particle Documentation.
Comments
There are different ways to make comments in your code. Comments are a great way to quickly describe what is
happening in your code.
// This is a comment - anything on a line after "//" is ignored // by the computer.
/* This is also a comment - this one can be multi-line, but it must start and end with these
characters */
Troubleshooting
Code refuses to flash -- Try putting your Photon RedBoard into Safe Mode. Then, hit Flash. Sometimes to
get your Photon RedBoard breathing cyan again, unplugging from USB and replugging back can get your
board connecting to WiFi again. Please keep in mind if you just starting working with the Photon RedBoard
it might take a couple minutes for the firmware to upload when first connected to the Internet.
LED isn't blinking -- Try checking your connections again. Make sure the positive side of the LED is
connected to D0. It is really easy to put the jumper wire in the wrong hole on a breadboard.
Photon RedBoard RGB isn't doing anything -- Don't worry! We have an awesome tech support staff to
help you out if there is something wrong. Please contact our tech support team.
Part 2: Blink an LED with Tinker
Tinker is a mobile app for iPhone or Android smartphones that makes it easy to control your digital and analog pins
on your Photon or Photon RedBoard.
First you will need to download the app on your smartphone.
iPhone users (requires iOS 8 or later)
Android users
Windows users -- Unfortunately, this extra feature is only for iOS and Android devices. Don’t worry, this is
the only bonus material that uses with the Tinker app.
Non-smartphone users -- Most of us would love to go back the happy memories of not owning a
smartphone and not getting 50+ alerts each day. We applaud you! We also might secretly envy you.
Unfortunately, this bonus material isn't going to be your cup of tea. Don’t worry, this is the only bonus
material that uses with the Tinker app.
When the app is done installing on your phone, you will need to sign in with your login information (the same as
the Particle website). After logging in, you will see a list with all your devices.
Clicking on the more icon (three dots) next to the online dot, gives you more options from which to choose. For
example, you can rename your board here. We suggest naming your Photon RedBoard with unique names. When
you start having a lot of Photons and demos going at once, it is hard to remember which is which.
Reflash Tinker Since Tinker was overwritten when we uploaded the blink code from part 1, we'll need to
reflash it. Navigate to the 'more' tab mentioned above. If there is a little yellow circle next to the device you
want to use, it is online but does not have Tinker firmware running on it.
When you tap on one of these devices, it will give you the option to reflash the Tinker firmware.
Click flash, and wait for your device to come back to a breathing cyan state.
When you click over the name of the Photon RedBoard you want to work with, you will see a new screen with a list
of the different pins you can control.
First, click the circle that is label with D0. Anytime you want to work with a pin, you will need to select it first. You
can select multiple pins at a time.
You'll notice that you have a couple different options. For this example, we are going to control the LED ON and
OFF, by clicking on digitalWrite.
New Photon Code (There is none!)
What is great about this mobile app, you do not have to do any coding! Once you are signed into Tinker, you can
start playing with the pins.
What You Should See
To turn the LED ON/HIGH, click the circle labeled D0 again. It should show the LED turn on.
To turn the LED OFF/LOW, click the circle labeled D0 again. It should show the LED turn off.
This is a super fun and easy way to control an LED or any other hardware. To reset all the pins and start fresh,
click on the more icon (three dots) on the top right. You will see Reset all pin functions option.
Dig into the app a little bit more! What happens when you click D0 and choose analogWrite? What happens when
you select D7 instead? HINT: Take at look at your board!
Troubleshooting
The app froze -- If your app ever stops on you, close out the app and reopen. Report bugs to the wonderful
Particle team on their forums.
I have a Windows phone -- Unfortunately, this extra feature is only for iOS and Android devices. Don't
worry, this is the only bonus material that uses with the Tinker app.
There is a yellow circle and it says it is non-tinker -- All Photon RedBoards were shipped out with the
latest firmware that works with Tinker. If you get the yellow circle, it means the firmware on your RedBoard
was re-flashed with old firmware. You will need to flash with the latest firmware. Please follow the directions
here for now. We are working with Particle to make sure the Tinker app is pushing the latest firmware when
re-flashing.
Experiment 2: With the Touch of a Button
Introduction
Now that you have conquered blinking an LED and know what an output is, it is time to learn inputs!
In this circuit, we’ll be introducing one of the most common and simple inputs – a push button – by using a digital
input. Just like the LED, the push button is a basic component that is used in almost everything. The way a push
button works with your Photon is that when the button is pushed, the voltage goes LOW. You Photon reads this
and reacts accordingly. RedBoard Photon has internal pull-up resistor, which keeps the voltage HIGH when you're
not pressing the button.
Parts Needed
You will need the following parts:
1x LED
1x Push Button
1x 330Ω Resistor
4x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
LED - Assorted (20 pack)
Jumper Wires - Connected 6" (M/M, 20 pack)
COM-12062
PRT-12795
Multicolor Buttons - 4-pack
Resistor 330 Ohm 1/4 Watt PTH - 20 pack
(Thick Leads)
PRT-14460
PRT-14490
Suggested Reading
Switch Basics -- The push button is a momentary switch. Momentary switches are switches which only
remain in their on state as long as they’re being actuated (pressed, held, magnetized, etc.). Learn more
about the different types of switches.
Pull-up Resistors - Pull-up resistors are very common when using microcontrollers (MCUs) or any digital
logic device. This tutorial will explain when and where to use pull-up resistors, then we will do a simple
calculation to show why pull-ups are important.
How to use Logic like a Vulcan:
One of the things that makes the Photon RedBoard so useful is that it can make complex decisions based on the
input it's getting. For example, you could make a thermostat that turns on a heater if it gets too cold, or a fan if it
gets too hot, and it could even water your plants if they get too dry. In order to make such decisions, the particle
environment provides a set of logic operations that let you build complex "if" statements. They include:
==
EQUIVALENCE
A == B is true if A and B are the SAME.
!=
DIFFERENCE
A != B is true if A and B are NOT THE SAME.
&&
AND
A && B is true if BOTH A and B are TRUE.
||
OR
A || B is true if A or B or BOTH are TRUE.
!
NOT
!A is TRUE if A is FALSE. !A is FALSE if A is TRUE.
You can combine these functions to build complex if() statements. For example:
if ((mode == heat) && ((temperature < threshold) || (override == true)))
{
digitalWrite(HEATER, HIGH);
}
...will turn on a heater if you're in heating mode AND the temperature is low, OR if you turn on a manual override.
Using these logic operators, you can program your Photon RedBoard to make intelligent decisions and take
control of the world around it!
Hardware Hookup
Your kit comes with a bunch of different color push button. All push buttons behave the same, so go ahead and
use your favorite color! Add the push button to the same LED circuit from the first experiment. Follow the Fritzing
diagram below.
Pay special attention to the component’s markings indicating how to place it on the breadboard.
Polarized components can only be connected to a circuit in one direction. Orientation matters for the following
component: LED
While buttons aren't necessarily polarized (they can be flipped 180° and still work the same), they do have an
orientation that is correct. The legs of the button protrude out of two sides of the button, while the other two
side are bare. The sides with the legs should be on either side of the ravine on the breadboard.
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
Photon Code
Copy and paste this code into the IDE. Then upload.
/*
SparkFun Inventor's Kit for Photon
Experiment 2 - Part 1: With a Touch of a Button
This sketch was written by SparkFun Electronics
August 31, 2015
https://github.com/sparkfun
This is a simple example sketch that turns on an LED
when pushing down on the push button
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
int led = D0; // LED is connected to D0
int pushButton = D2; // Push button is connected to D2
// This routine runs only once upon reset
void setup()
{
pinMode(led, OUTPUT); // Initialize D0 pin as output
pinMode(pushButton, INPUT_PULLUP);
// Initialize D2 pin as input with an internal pull-up resistor
}
// This routine loops forever
void loop()
{
int pushButtonState;
pushButtonState = digitalRead(pushButton);
if(pushButtonState == LOW)
{ // If we push down on the push button
digitalWrite(led, HIGH); // Turn ON the LED
}
else
{
digitalWrite(led, LOW);
// Turn OFF the LED
}
}
What You Should See
When you hold down the push button, those warm fuzzy feelings from the first experiment should happen again,
and the LED should shine brightly. The LED will be off when the button is released.
Press down on the push button to see the LED light up
Code to Note
pinMode(pushButton, INPUT_PULLUP);
The digital pins can be used as inputs as well as outputs. Before you do either, you need to tell the Photon which
direction you're going. Normally, with push buttons we would use a pull-up resistor. However, you can program the
Photon RedBoard to use its internal pull-up and pull-down resistors.
pushButtonState = digitalRead(pushButton);
To read a digital input, you use the digitalRead() function. It will return HIGH if there's 5V present at the pin, or
LOW if there's 0V present at the pin.
if(pushButtonState == LOW)
Because we've connected the button to GND, it will read LOW when it's being pressed. Here we're using the
"equivalence" operator ("==") to see if the button is being pressed.
Troubleshooting
If nothing is happening when holding down the push button, don’t panic! Double check your jumper wire and
LED connections. It is easy to miss a jumper wire or two.
Code refuses to flash -- Try putting your Photon RedBoard into safe mode. Then, hit Flash. Sometimes to
get your Photon RedBoard breathing cyan again, unplugging from USB and replugging back can get your
board connecting to WiFi again. Please keep in mind if you just starting working with the Photon RedBoard
it might take a couple minutes for the firmware to upload when first connected to the Internet.
Part 2: Control the Internet with IFTTT and Push Button
Have you ever wanted to control something on the Internet with a touch of a button? How about having a button
that orders new laundry detergent when pressed? Okay, that has already been done with Amazon Dash Button.
However, you can make one too! For the second part of this experiment, we are going to use IFTTT to send an
email when the push button is pressed.
A fun feature of the Photon RedBoard is that it works with Particle's IFTTT channel. IFTTT is short for "if this then
that." It is a free site that makes connecting different popular apps or products really easy and fast!
Let's get started!
New Photon Code
/*
SparkFun Inventor's Kit for Photon
Experiment 2 - Part 2: Control the Internet with IFTTT and Push Button
This sketch was written by SparkFun Electronics
August 31, 2015
https://github.com/sparkfun
This is a simple example sketch that sends an email
with IFTTT when the push button is pressed
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
int led = D0; // LED is connected to D0
int pushButton = D2; // Push button is connected to D2
// This routine runs only once upon reset
void setup()
{
pinMode(led, OUTPUT); // Initialize D0 pin as output
pinMode(pushButton, INPUT_PULLUP);
// Initialize D2 pin as input with an internal pull-up resistor
}
// This routine loops forever
void loop()
{
int pushButtonState;
pushButtonState = digitalRead(pushButton);
if(pushButtonState == LOW){ //If we push down on the push button
digitalWrite(led, HIGH); // Turn ON the LED
Spark.publish("pushButtonState","Pressed",60,PRIVATE);
// Add a delay to prevent getting tons of emails from IFTTT
delay(5000);
}
else
{
digitalWrite(led, LOW);
// Turn OFF the LED
}
}
Code to Note
Spark.publish("pushButtonState", "Pressed",60,PRIVATE);
What is great about IFTTT is that you do not need a lot of extra code. This is the only piece of code we added.
Visit the Spark.publish() page to learn more.
Setup IFTTT
Now that the code is loaded on your Photon RedBoard, we can jump into setting up IFTTT.
Sign up, or log into IFTTT, and activate your account from your email address. For this experiment we are going to
create an IF recipe. The IF recipe is connecting two different apps and products in an if this then that statement.
Click on My Recipe on the top navigation bar on the IFTTT site.
Follow the 7 steps below to create an IF recipe.
1: This
Click on this
Find and select the Particle Channel. You will need to connect to the Particle channel.
2: Choose a Trigger
Selected New event published
3: Complete Trigger Fields
This is where you will enter the published event name. Type in pushButtonState in the If (Event Name) field. Go
ahead and select your personal Photon RedBoard from the drop down menu.
4: That
Click on the that button and find the Email Channel.
Remember, your Photon RedBoard has the unique name you gave it and will show up differently then the above
image.
5: Choose an Action
Depending on what Channel you are using, there might be one or more different actions you can choose from. For
this experiment, we will send an email.
6: Complete Action Fields
You can customize what you want to see in the subject and body of your email.
7: Create and connect
Name your recipe and hit Create Recipe.
You've just created your first IFTTT recipe!
What You Should See
When you push down on the button, an email will send! You might have allow the gearworks of the internet to
churn for a minute or two, but you should be able to see a new email. If you don't feel like waiting, go ahead and
click on the refresh-looking icon, named "Check Recipe now".
You might have noticed there's a vast amount of options for creating recipes. The possibilities are endless! Using
the same code, here are a few more examples on what you can do:
Post on social media and websites like Facebook, Twitter, Reddit, GitHub, Pinterest, Tumblr, and more!
There are tons of products you might already use that have their own Channels. Including appliances and
other home products
Send a text message
Shop at different sites
Troubleshooting
Not seeing the email? A lot of people have multiple email addresses. Double check the same email you
used to sign up for IFTTT. There is a Check Recipe now button for testing your recipes. This can be found
under the My Recipes page.
Still not working? Try redoing the IFTTT recipe again or check for typos.
Sometimes the IFTTT mail server might take longer than expected to send the email. Check the recipe log
to see if the event was triggered. If you see the log has been updated then wait for the email, it will come!
You can also try setting up the GMAIL channel instead, it works like a charm!
Experiment 3: Houseplant Monitor
Introduction
This experiment uses a soil moisture sensor to allow you to monitor your houseplants. The first half of the
experiment will introduce the concept of Analog Inputs, which allow us to read values that vary between two known
thresholds rather than just being a HIGH or LOW digital value. You will use a built in Analog-to-Digital Converter on
the Photon RedBoard to read the analog value coming from the soil moisture sensor. In the second half, we will
expose that analog variable to the Particle Cloud so that other online applications can request the current moisture
content and send you notifications when your plant needs watering.
Parts Needed
You will need the following parts:
1x Soil Moisture Sensor
3x Jumper Wire
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
SparkFun Soil Moisture Sensor (with Screw
Terminals)
Jumper Wires - Connected 6" (M/M, 20 pack)
PRT-12795
SEN-13637
Tools Needed
You will need the screwdriver included in the Photon SIK. Find the second smallest flathead head tip, labeled CRV 2.0, and insert it into the tip of the screwdriver.
Suggested Reading
Before continuing on with this experiment, we recommend you be familiar with the concepts in the following
tutorials:
Analog vs Digital - Before you can use analog inputs, you should have a good understanding of the
difference between analog and digital.
Analog to Digital Conversion (ADC) - This is a general explanation of how analog inputs work.
Particle Cloud Variables - We will use this feature to expose our variable to the Internet in the second half of
the experiment.
Soil Moisture Sensor Hookup Guide - For more information on the soil moisture sensor, visit this tutorial.
Serial Terminal Basics - This experiment will introduce you to Serial Print, which is a great way to print out
variables and other info for testing and troubleshooting.
Hardware Hookup
Hook up your circuit as pictured below:
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
The easiest way to connect the soil moisture sensor to the RedBoard is to insert one end of each jumper wire into
the 3-pin screw terminal attached to the soil sensor, and then screw each pin down until the jumper wire is secured
and won't pull out of the screw terminal.
Photon Code
Copy and paste this code into the IDE. Then upload.
/*
SparkFun Inventor's Kit for Photon
Experiment 3 - Part 1: LED Houseplant Monitor
This sketch was written by SparkFun Electronics
Joel Bartlett
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application monitors the moisture level of your houseplant
and turns the RGB LED red when the plant needs watered.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
int val = 0;//variable to store soil value
int soil = A2;//Declare a variable for the soil moisture sensor
int soilPower = D6;//Variable for Soil moisture Power
//Rather than powering the sensor through the V-USB or 3.3V pins,
//we'll use a digital pin to power the sensor. This will
//prevent oxidation of the sensor as it sits in the corrosive soil.
void setup()
{
Serial.begin(9600);
// open serial over USB
pinMode(soilPower, OUTPUT);//Set D6 as an OUTPUT
digitalWrite(soilPower, LOW);//Set to LOW so no power is flowing through the sensor
}
void loop()
{
Serial.print("Soil Moisture = ");
//get soil moisture value from the function below and print it
Serial.println(readSoil());
delay(1000);//take a reading every second
//This time is used so you can test the sensor and see it change in real-time.
//For in-plant applications, you will want to take readings much less frequently.
//If your soil is too dry, turn on Red LED to notify you
//This value will vary depending on your soil and plant
if(readSoil() < 200)
{
// take control of the RGB LED
RGB.control(true);
RGB.color(255, 0, 0);//set RGB LED to Red
}
else
{
// resume normal operation
RGB.control(false);
}
}
//Thi
i
f
ti
d t
t th
il
i t
t
t
//This is a function used to get the soil moisture content
int readSoil()
{
digitalWrite(soilPower, HIGH);//turn D6 "On"
delay(10);//wait 10 milliseconds
val = analogRead(soil);
digitalWrite(soilPower, LOW);//turn D6 "Off"
return val;
}
What You Should See
Once the code is uploaded to your Photon RedBoard, open your favorite Serial Terminal program. Connect to the
Photon RedBoard. You should see soil moisture data begin to stream in the window.
Pressing your finger across the two prongs at varying pressures results in different moisture readings.
Note: The PhotonRed Board has a 12-bit ADC in contrast with the more common 10-bit ADC you would have
used in other Arduino based development boards. This changes the resolution of the ADC. Now the maximum
ADC value is 2^12 i.e. 4096, instead of 2^10 i.e 1024. So do not worry if you see values above 1024 in the serial
terminal.
When the sensor detects very little moisture, the RGB LED on the Photon RedBoard will turn Red, notifying you
that your plant needs watered. When the moisture level is satisfactory, the LED will breathe cyan, as usual.
An exposed sensor should read close to zero, producing Red on the RGB LED.
Code to Note
Serial
Among other things, this example introduces serial communication with functions like Serial.begin() and
Serial.print() . To initialize a serial interface, call Serial.begin([baud]) where [baud] sets the baud rate of
the interface. In this example, we set the baud rate to 9600bps -- a reliable (if slow) standard rate -- in the
setup() function:
void setup()
{
...
Serial.begin(9600); // Start the serial interface at 9600 bps
...
}
To send data out of a serial interface, use either Serial.print() , Serial.println() , or Serial.write() . This
example only uses the first two.
Serial.print("Soil Moisture = ");
//get soil moisture value from the function below and print it
Serial.println(readSoil());
For more information on Serial functions, check out Particle's reference documentation.
Functions
int readSoil() is a user-made function. As with any other object-oriented language, you can declare your own
functions that can be passed and can return different types of variables.
This function has no parameters passed to it, but it does return the soil moisture value as an integer (INT). You can
create your own functions to accomplish tasks that you do not want to type out over and over again. Instead, you
can call that function anywhere you would have written all that other code.
Troubleshooting
Configuring the soil sensor can take a little trial and error. Different soils and moisture levels will result in
different data. To get good values on which to base your plant's condition, it best to take a reading when it is
is as dry as possible without jeopardizing the plant's well being. Take another reading after you've recently
watered the plant to get your upper threshold. You can then adjust the code accordingly.
Part 2: Particle Variables
Being notified visually that your plant needs watered is useful, but what about when you leave for a week? How
will you know if your plant is happy and thriving while you're gone? One way to give you a view into your plants
status is to use the Particle.variable function, which is a built-in feature of the Particle firmware. This second
example will use this feature to allow you to check the status of your plant anywhere that you have an Internet
connection.
New Photon Code
Copy, paste and upload this new sketch. You'll notice not much has changed. The Particle.variable("soil",
&val, INT); line is the only new addition.
/*
SparkFun Inventor's Kit for Photon
Experiment 3 - Part 2: Internet Houseplant Monitor
This sketch was written by SparkFun Electronics
Joel Bartlett
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application monitors the moisture level of your houseplant
and exposes that data to be monitored via the Internet.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
int val = 0;//variable to store soil value
int soil = A2;//Declare a variable for the soil moisture sensor
int soilPower = D6;//Variable for Soil moisture Power
//Rather than powering the sensor through the V-USB or 3.3V pins,
//we'll use a digital pin to power the sensor. This will
//prevent oxidation of the sensor as it sits in the corrosive soil.
void setup()
{
Serial.begin(9600);
// open serial over USB
pinMode(soilPower, OUTPUT);//Set D6 as an OUTPUT
digitalWrite(soilPower, LOW);//Set to LOW so no power is flowing through the sensor
//This line creates a variable that is exposed through the cloud.
//You can request its value using a variety of methods
Particle.variable("soil", &val, INT);
}
void loop()
{
Serial.print("Soil Moisture = ");
//get soil moisture value from the function below and print it
Serial.println(readSoil());
delay(1000);//take a reading every second
//This time is used so you can test the sensor and see it change in real-time.
//For in-plant applications, you will want to take readings much less frequently.
//If your soil is too dry, turn on Red LED to notify you
//This value will vary depending on your soil and plant
if(readSoil() < 200)
{
// take control of the RGB LED
RGB.control(true);
RGB.color(255, 0, 0);//set RGB LED to Red
}
else
{
//
l
ti
// resume normal operation
RGB.control(false);
}
}
//This is a function used to get the soil moisture content
int readSoil()
{
digitalWrite(soilPower, HIGH);//turn D6 "On"
delay(10);//wait 10 milliseconds
val = analogRead(soil);
digitalWrite(soilPower, LOW);//turn D6 "Off"
return val;
}
What You Should See
If you haven't already, place your sensor in the plant you would like to monitor.
You can open the serial terminal to see the soil moisture value, as in the previous example. However, you can now
also request that same value through the web. In order to do so, you'll need your Photon's device ID as well as
your account's access token. The device ID can be found in Particle Build by clicking the '>' next to your device
name.
Find your Device ID under the "Devices" tab, by clicking the carrot next to your Photon.
Your access token can be found under the "Settings" tab.
Find your access token under the "Settings" tab.
Armed with those long strings of hex characters, open a new browser tab and navigate to:
https://api.particle.io/v1/devices/DEVICE_ID/soil?access_token=ACCESS_TOKEN
Make sure to sub in the proper values for DEVICE_ID and ACCESS_TOKEN .
TIP: You can also use the Name of your device instead of the device ID.
If everything was entered correctly, you should see something like this where 'result' is the current value:
The Particle variable responds with a JSON string including a "result" key and value.
Now, you can create a bookmark using that URL. Every time you refresh that page, you'll get the current status of
your plant! You can expand upon this in many ways. You can use examples from other experiments to get email
notifications when your plant needs water, or you could even build an webpage that pulls that value in and displays
it in a more visually appealing manner.
Code to Note
The Particle.variable("soil", &val, INT); line is the only new addition to this code, however, it is a very
important addition, allowing for other applications to request the soil moisture value. The first parameter is the
name of the exposed variable. This will be the name your request in the URL. You can declare up to 10 cloud
variables, and each variable name is limited to a max of 12 characters. The second parameter requires a basic
understanding of pointers. The ampersand (&) symbol means the address of the variable it precedes, so in this
case it's requesting the value that resides at the memory address allocated to the val variable, which contains
the current soil moisture value. The last parameter is the type of variable that will be exposed, in this case an
integer. For more info on cloud variables, visit the particle website.
Troubleshooting
Having issues seeing the online data? Make sure you have grabbed the correct Device ID for the board you
are working with. If you have numerous Particle devices associated with your account, it's easy to get the
device ID from device mixed up with that of another. If you see a 'Permission Denied' error like the one
below, you either have the wrong device ID, or there is a typo in the ID you're attempting to use.
Similarly, you may get an access token error. If so, visit the Settings section of Particle Build, and reset your
access token or make sure there is no typos.
If you get a time out error, make sure your device is properly powered and connected to the web.
Experiment 4: Color Selector
Introduction
In this experiment you'll learn about analog input and output, the difference between analog and digital, and how to
incorporate analog inputs and outputs into your project. We will also touch on some more advanced concepts, like
using internal pull-up resistors and integrating with Twitter via IFTTT (If This Than That).
Parts Needed
You will need the following parts:
1x Breadboard
1x Photon RedBoard
1x Potentiometer
3x Pushbuttons (Red, Green, and Blue)
11x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
Trimpot 10K with Knob
Jumper Wires - Connected 6" (M/M, 20 pack)
COM-09806
PRT-12795
Multicolor Buttons - 4-pack
PRT-14460
Suggested Reading
There are a variety of core concepts in electronics that we will be touching on in this circuit, but not discussing in
depth. However, we do have some great tutorials that go into more detail about what's going on behind the
scenes.
Analog vs. Digital - understanding the difference between analog and digital devices is going to be very
helpful for this section.
Pulse-Width Modulation - pulse-width modulation (or PWM) is the way digital microcontrollers simulate
analog output.
Analog to Digital Conversion - knowing how your microcontroller translates between digital and analog
signals will help you understand many of the basics covered here.
Hardware Hookup
Connect the components on the breadboard and wire them to the Photon RedBoard as shown below. The red
button should go to pin D2, the green button to D3, and the blue button to pin D4. The potentiometer should go to
pin A0. Don't forget to run power (3.3V) and ground (GND) from your Photon to your breadboard.
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
Photon Code
Copy and paste this code into the IDE. Then upload.
/*
SparkFun Inventor's Kit for Photon
Experiment 4 - Part 1
This sketch was written by SparkFun Electronics
Ben Leduc-Mills
August 31, 2015
https://github.com/sparkfun
This is an example sketch using buttons and a potentiometer to change the color and brightne
ss of the Photon RedBoard onboard LED.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
int redButton = D2; // declare variable for red button
int greenButton = D3; // declare variable for green button
int blueButton = D4; // declare variable for blue button
int potentiometer = A0; // declare variable for potentiometer
int colorMode; // declare variable to keep track of color
int potValue = 0; // // declare variable for the value of the potentiometer
void setup() {
RGB.control(true); // command to control the RGB led on the Photon
// buttons need an internal pullup resistor - see below for notes
pinMode(redButton, INPUT_PULLUP);
pinMode(greenButton, INPUT_PULLUP);
pinMode(blueButton, INPUT_PULLUP);
pinMode(potentiometer, INPUT); // potentiometers are an analog input
colorMode = 0;
}
void loop() {
// change colorMode variable depending on which button was pressed
if(digitalRead(redButton) == LOW) { // double equals checks for equality
colorMode = 1; // single equals is for assigning a new value to the variable
}
if(digitalRead(greenButton) == LOW) {
colorMode = 2;
}
if(digitalRead(blueButton) == LOW) {
colorMode = 3;
}
// read from the potentiometer, divide by 16 to get a number we can use for a color value
potValue = analogRead(potentiometer)/16;
changeColor(colorMode, potValue); // call changeColor function
}
// changeColor takes a color mode and a potentiometer value and changes the color and brightness
of the Photon RGB LED
void changeColor(int _colorMode, int _potValue) {
if(_colorMode == 1) {
RGB.color(_potValue, 0, 0);
}
if(_colorMode == 2) {
RGB.color(0, _potValue, 0);
}
if(_colorMode == 3) {
RGB.color(0, 0, _potValue);
}
else if(_colorMode == 0) {
RGB.color(0,0,0);
}
}
What You Should See
After the you click 'flash' and the upload process is complete, you should be able to control the color and
brightness of the Photon RedBoard's onboard LED. The buttons will turn the LED red, green, or blue, and turning
the potentiometer will affect the brightness of the LED.
Switching colors:
Fading:
Pretty neat, huh? Now, let's take this circuit and make it a part of the Internet of Things!
Troubleshooting
If your buttons aren't working, make sure they are pushed down firmly into the breadboard and that you
declared them as INPUT_PULLUP in your code.
If the LED is still breathing Cyan, double check that you put in the RGB.control(true); line in your
setup() function.
Part 2: Turn on an LED with IFTTT (If This Then That)
IFTTT is a website that uses conditional statements and does very useful things with well known applications, such
as Gmail, Craigslist, Twitter, or Facebook. For this experiment, we're going to tweet the color of your LED.
Photon Code Part 2
Since we'll be needing IFTTT to communicate with our Photon RedBoard, we'll need to modify our code. Particle.io
has created many useful IoT functions for the Photon RedBoard, and we'll be using one of them -- more
specifically Particle.function(). In our case, we're going to find a way to 'tweet' an RGB color value, and have the
onboard LED of the Photon RedBoard turn that color.
Go ahead and paste this code into the Particle Build IDE. Then upload.
/*
SparkFun Inventor's Kit for Photon
Experiment 4 - Part 2
This sketch was written by SparkFun Electronics
Ben Leduc-Mills
August 31, 2015
https://github.com/sparkfun
This is an example sketch showing how to change the color of the Photon Redboard onboard LED
using Twitter and IFTTT (If this then that).
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
//declare the name of our function (and its parameters) at the top of our program
int rgbColor(String val);
//variables for our colors (red, green, blue)
int r,g,b;
void setup() {
//take control of the Photon RGB LED
RGB.control(true);
//register our function in the Particle cloud
Particle.function("rgbColor", rgbColor);
}
void loop() {
//don't need to do anything in the loop
}
//our actual function call
//looking for a string of three numbers that represents an RGB color
//e.g. 200,12,42
int rgbColor(String val) {
//check if incoming string is empty
if(val.length() > 0) {
//if not, use indexOf to find the first comma delimiter
//this string class has no split command
//more about indexOf: https://docs.particle.io/reference/firmware/photon/#indexofint i = val.indexOf(",");
//use substring to get the value from the beginning of the string until the first comma
//then use toInt to convert from a string to an integer
//which gets us our first number, the r value
r = val.substring(0,i).toInt();
//more string manipulation to get our g and b values
int j = val.indexOf(",", i+1);
g = val.substring(i+1, j).toInt();
b = val.substring(j+1, val.length()).toInt();
//put it all together and make the LED light up
RGB.color(r, g, b);
//if we're successful return 1
return 1;
}
//something went wrong
else return -1;
}
Setup IFTTT
Now that we've prepped our code to talk with the IFTTT service, we have to actually sign up for it and create our
Internet of Things 'recipe'. If you're completing the exercises in order, you will have signed up for IFTTT in the last
exercise, if not, go ahead and sign up now.
Sign up, or log into IFTTT, and activate your account from your email address.
Create your first recipe:
Click on the blue lettered: "This"
Type Twitter into the search bar and click on it
Connect your Twitter account to IFTTT, hit continue
On the "Choose a Trigger" page, select "New tweet by @yourtwitter with hashtag"
For the hashtag, type in #rgb
You should see something like:
Click on "Create trigger"
Click on "That"
Search for "Particle", click on it
Choose "Call a function", and select the function we put in our photon code: "rgbColor on (your Photon
RedBoard's name)".
In the "with input(Function Input)" field, choose TextNoHashtag
You should see:
Finally, click on "Create Action" and finally "Create Recipe"
Great! You've just created an IFTTT recipe that calls our rgbColor() function whenever we send a tweet with a
specific hashtag.
What You Should See
Send a tweet with the hashtag #rgb followed by numbers for red, green, and blue values. You might have to allow
the gears of the Internet to churn for a minute or two, but you should eventually see your LED turn on. If you don't
feel like waiting, go ahead and click on the refresh-looking icon in the IFTTT dashboard for your recipe, named
"Check Recipe now".
Your tweet should look something like:
Code to Note
Particle.function("rgbColor", rgbColor);
Particle.function is a function specifically made for communication with IFTTT. It works as
Particle.function("cloudNickname", firmwareFunctionName). The cloud name can be maximum 12 characters long.
There's a great write up for this provided by Particle.io, click HERE.
Manipulating groups of words and symbols, or 'strings' is a key component in many programs - so much so that
Particle has a String 'class' - which allows us to use several different pre-built methods for dealing with strings. In
fact, use four of them just in this exercise: length() , indexOf() , substring() , and toInt() . More info on
these and other useful methods for strings can be found in the Particle docs here.
Code to Note
RGB.control(true);
You may have noticed by now that there is no LED on your breadboard. Instead, we're going to take control of the
RGB LED on the Photon RedBoard that's usually reserved for showing the status of the board. We do this by
using the built-in RGB library and setting control to us, the user.
pinMode(redButton, INPUT_PULLUP);
Push buttons like the ones we're using operate by closing or opening a circuit when you push down the button.
The Photon can detect this change and report it to us so we know when someone pushes our buttons. Often,
buttons are hooked up to the breadboard with a 'pull-up' resistor (usually 10KΩ) which in essence pulls the voltage
reading from the button to HIGH. This means that when we push the button the value goes LOW, which seems to
make sense to us logically. Luckily for us, the Photon has internal pull-up resistors that we can turn on through the
code - by changing the pinMode type from the usual INPUT to INPUT_PULLUP .
Troubleshooting
If the LED is still breathing Cyan, double check that you put in the RGB.control(true); line in your
setup() function.
If the function name doesn't show up when trying to complete the 'call a function' step (6 of 7), make sure
your board is plugged in, and that you've saved your code in the cloud with the
Particle.function("turnOnLED", LEDstate); line in your code.
If the function still doesn't show up, you may have to go into IFTTT, delete your Particle channel (and all
your recipes), then reconnect the channel and rebuild your recipe from scratch.
Experiment 5: Music Time
Introduction
In this circuit, we'll again bridge the gap between the digital world and the analog world. We'll be using a piezo
speaker that makes a small "click" when you apply voltage to it (try it!). By itself that isn't terribly exciting, but if you
turn the voltage on and off hundreds of times a second, the piezo speaker will produce a tone. And if you string a
bunch of tones together, you've got music! This circuit and sketch will play a classic tune. We'll never let you down!
Parts Needed
You will need the following parts:
Photon RedBoard, Breadboard, and Base Plate
1x Piezo Speaker
2x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
Jumper Wires - Connected 6" (M/M, 20 pack)
Mini Speaker - PC Mount 12mm 2.048kHz
PRT-12795
COM-07950
Suggested Reading
tone() -- Read up about tone() to get started on making your own songs!
Let's Talk More about Polarity
We talked about polarity shortly in the past experiments. In the realm of electronics, polarity indicates whether a
circuit component is symmetric or not. A non-polarized component – a part without polarity – can be connected in
any direction and still function the way it’s supposed to function. A symmetric component rarely has more than two
terminals, and every terminal on the component is equivalent. You can connect a non-polarized component in any
direction, and it’ll function just the same.
A polarized component – a part with polarity – can only be connected to a circuit in one direction. A polarized
component might have two, twenty, or even two-hundred pins, and each one has a unique function and/or position.
If a polarized component was connected to a circuit incorrectly, at best it won’t work as intended. At worst, an
incorrectly connected polarized component will smoke, spark, and be one very dead part.
To learn more about polarity, check out our What is Polarity? tutorial!
Hardware Hookup
If the piezo speaker doesn't easily fit into the holes on the breadboard, try rotating it slightly.
Pay special attention to the component’s markings indicating how to place it on the breadboard.
Polarized components can only be connected to a circuit in one direction. Orientation matters for the following
component: Piezo Speaker. It's hard to tell which pin is '+' and which is '-' from the image below. The buzzer
should have a tiny '+' simbol on one of the pins. This pin should be connected to pin 2, and the other pin
should go to GND.
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
Photon Code
/*
SparkFun Inventor's Kit for Photon
Experiment 5 - Part 1: Music Time
This sketch was written by SparkFun Electronics
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application plays Rick Astley - Never Gonna Give You Up song
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License (http://opensource.org/licenses/MIT)
*/
const int speakerPin = D2;
// We'll set up an array with the notes we want to play
// change these values to make different songs!
// Length must equal the total number of notes and spaces
const int songLength = 18;
// Notes is an array of text characters corresponding to the notes
// in your song. A space represents a rest (no tone)
char notes[] = "cdfda ag cdfdg gf "; // a space represents a rest
// Beats is an array of values for each note and rest.
// A "1" represents a quarter-note, 2 a half-note, etc.
// Don't forget that the rests (spaces) need a length as well.
int beats[] = {1,1,1,1,1,1,4,4,2,1,1,1,1,1,1,4,4,2};
// The tempo is how fast to play the song.
// To make the song play faster, decrease this value.
int tempo = 150;
void setup()
{
pinMode(speakerPin, OUTPUT);
// We only want to play the song once, so we'll put it in the setup loop
int i, duration;
for (i = 0; i < songLength; i++) // step through the song arrays
{
duration = beats[i] * tempo; // length of note/rest in ms
if (notes[i] == ' ')
{
delay(duration);
}
// is this a rest?
// then pause for a moment
}
else
// otherwise, play the note
{
tone(speakerPin, frequency(notes[i]), duration);
delay(duration);
// wait for tone to finish
}
delay(tempo/10);
// brief pause between notes
}
//If you want your song to loop forever, place that code in the loop() below.
}
void loop()
{
//do nothing
}
int frequency(char note)
{
// This function takes a note character (a-g), and returns the
// corresponding frequency in Hz for the tone() function.
int i;
const int numNotes = 8;
//
//
//
//
// number of notes we're storing
The following arrays hold the note characters and their
corresponding frequencies. The last "C" note is uppercase
to separate it from the first lowercase "c". If you want to
add more notes, you'll need to use unique characters.
// For the "char" (character) type, we put single characters
// in single quotes.
char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523};
// Now we'll search through the letters in the array, and if
// we find it, we'll return the frequency for that note.
for (i = 0; i < numNotes; i++) // Step through the notes
{
if (names[i] == note)
// Is this the one?
{
return(frequencies[i]);
// Yes! Return the frequency
}
}
return(0); // We looked through everything and didn't find it,
// but we still need to return a value, so return 0.
}
What You Should See
You should see - well, nothing! But you should be able to hear a song. If it isn't working, make sure you have
assembled the circuit correctly and verified and uploaded the code to your board or see the troubleshooting
section.
See if you can recreate your favorite songs!
Code to Note
Up until now we've been working solely with numerical data, but the Photon RedBoard can also work with text.
Characters (single, printable, letters, numbers and other symbols) have their own type, called "char". When you
have an array of characters, it can be defined between double-quotes (also called a "string"), OR as a list of
single-quoted characters.
tone(pin, frequency, duration);
One of Photon RedBoard's many useful built-in commands is the tone() function. This function drives an output
pin at a certain frequency, making it perfect for driving piezo speakers. If you give it a duration (in milliseconds), it
will play the tone then stop. If you don't give it a duration, it will keep playing the tone forever (but you can stop it
with another function, noTone() ).
Troubleshooting
No Sound - Given the size and shape of the piezo buzzer it is easy to miss the right holes on the
breadboard. Try double checking its placement.
Can't Think While the Melody is Playing - Just pull up the piezo buzzer whilst you think, upload your
program then plug it back in.
Feeling Let Down and Deserted - The code is written so you can easily add your own songs.
Experiment 6: Environment Monitor
Introduction
This experiment will hook the Photon up to a temperature/humidity sensor and a photocell to observe lighting
conditions. We'll initially use serial communication to check their readings. Once you've gotten a handle on
interacting with those sensors, we can gather their data and regularly post it to a data stream.
In addition to covering the basics of serial communication, this experiment will also introduce libraries. Libraries
are a powerful tool in the Particle IDE. They're pre-written files of code designed to accomplish certain tasks -- like
reading a sensor -- in a very concise manner. They'll make your life a lot easier.
Once the experiment is completed, you'll have a fully functional environmental data logging station, which can be
observed from anywhere in the world!
Parts Needed
1x RHT03 Humidity and Temperature Sensor
1x Mini Photocell
1x 330Ω Resistor
7x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
Humidity and Temperature Sensor - RHT03
Mini Photocell
SEN-10167
SEN-09088
Jumper Wires - Connected 6" (M/M, 20 pack)
Resistor 330 Ohm 1/6 Watt PTH - 20 pack
PRT-12795
COM-11507
Suggested Reading
Serial Communication -- Serial interfaces allow devices to exchange complex strings of data using just two
wires. In this experiment, we'll use a serial interface between the Photon RedBoard and our computer to
check the latest readings from the light and temperature/humidity sensors.
Serial Terminal Basics -- To interact with a serial interface on your computer, you'll need a serial terminal
program. You may already have a serial terminal installed on your computer. If not, check out this tutorial
for our recommendations, and a guide to getting started.
Including Particle Libraries -- Libraries are one of the most powerful tools availabe in the Particle Build IDE.
Read through this tutorial to find out how to add a library to your application code.
Hardware Hookup
Hook up your circuit as shown below:
The yellow wire running from the photocell to the Photon's A0 pin carries an analog value relative to the light being
sensed. The blue wire, running between the RHT03 sensor and Photon pin D3, is a very precisely-timed digital
data interface. The SparkFunRHT03 library simplifies this interface to just a few lines of code.
Both the photocell and the RTH03 need a power supply to be operational. In this circuit, we're powering both off
the Photon's 3.3V/GND supply.
Photon Code
Copy and paste the code below into a new application -- ours is called EnvironmentLoggerSerial:
/////////////////////
// Pin Definitions //
/////////////////////
const int RHT03_DATA_PIN = D3; // RHT03 data pin
const int LIGHT_PIN = A0; // Photocell analog output
const int LED_PIN = D7; // LED to show when the sensor's are being read
///////////////////////////
// RHT03 Object Creation //
///////////////////////////
RHT03 rht; // This creates a RTH03 object, which we'll use to interact with the sensor
unsigned int minimumLight = 65536;
unsigned int maximumLight = 0;
float minimumTempC = 5505;
float maximumTempC = 0;
float minimumTempF = 9941;
float maximumTempF = 0;
float minimumHumidity = 100;
float maximumHumidity = 0;
#define PRINT_RATE 1500 // Time in ms to delay between prints.
void setup()
{
But wait! Don't try to upload it yet. In fact, if you try to compile, you should get an error, because we need to add
the SparkFunRHT03 library.
Click the Libraries icon
on the left. Then click into the search bar and find SparkFunRHT03. Click it to get a
description of the library, and options for using it.
Next, click the INCLUDE IN APP button, and select your new application, and verify by selecting ADD TO THIS
APP.
Two lines of code should be appended to your application:
// This #include statement was automatically added by the Particle IDE.
#include "SparkFunRHT03/SparkFunRHT03.h"
That's the library! Now you can verify and flash.
Including libraries: Unfortunately, there aren't any shortcuts to including libraries in your applications. Simply
copying and pasting the #include statement won't actually include the library files in your application. Every
time you want to include a library, you'll have to go through the process described above.
What You Should See
After uploading the code, open up a serial terminal to your Photon RedBoard's port. If you're on a Windows
machine, it should look something like "COMN". On Mac or Linux, the port should be something like
"/dev/tty.usbmodenNNNN".
Make sure the baud rate is set to 9600. Once the Photon connects (starts pulsing cyan), you should begin to see
the light, temperature, and humidity values stream by.
Cover up the light sensor, or shine a flashlight on it. Covering the sensor should make the readings go down -- can
you get it to 0?
Breathe on the temperature/humidity sensor. Does the temperature value go up? Can you influence the humidity
value as well (don't try too hard -- no pouring water on the sensor!)?
Code to Note
Including the SparkFunRHT03 library gives us access to the RHT03 class. To begin using that class, we need to
begin by creating an RHT03 object in the global section:
RHT03 rht; // This creates a RTH03 object, which we'll use to interact with the sensor
rht is the object we'll use from here on to interact with the sensor. Once that's set up, we can call
rht.begin() in the setup() function to initialize the sensor. should be the Photon digital pin
connected to the sensor.
const int RHT03_DATA_PIN = D3; // RHT03 data pin
...
void setup()
{
...
rht.begin(RHT03_DATA_PIN); // Initialize the RHT03 sensor
...
}
Finally, we can read the the temperature and humidity values from the sensor. This is a two-step process: (1) read
the sensor to update all values, then (2) using get functions to use the value.
Begin by calling rht.update() . If update() succeeds (indicated by returning a 1 ), you can call rht.tempF() ,
rht.tempC() , and rht.humidity() to get the values of interest:
int update = rht.update(); // Read from the RHT
if (update == 1) // If the update was successful:
{
float humidity = rht.humidity(); // Read humidity into a variable
float tempC = rht.tempC(); // Read celsius temperature into a variable
float tempF = rht.tempF(); // Read farenheit temperature into a variable
...
}
Troubleshooting
If your terminal program won't let you open the serial port -- citing an error like: "COM port in use". Or, if the COM
port has disappeared from a selectable list, try following these steps:
1.
2.
3.
4.
Close the serial terminal program.
Reset your Photon RedBoard
Wait for the RedBoard to connect to WiFi
Open the terminal program back up and try connecting.
If all you see is a stream of "Error reading from the RHT03", make sure everything is correctly wired up. If you're
still not having any luck with the sensor, consider getting in touch with our tech support team. (It's normal for the
"Error..." output to show up occasionally -- the RHT03's one-wire interface isn't very robust.)
Experiment 7: Automatic Fish Feeder
Introduction
In this experiment, you’ll learn how to control the physical world with digital world using a servo motor. Having the
ability to control devices such as motors, relays, actuators, and other moving objects opens up a world of
opportunities. For this particular example, you will learn how to control a servo motor with the Photon RedBoard.
Once you learn the basics of controlling a servo motor, you'll automate the task of feeding fish or other small pets
by creating an internet-connected auto-feeder.
Parts Needed
You will need the following parts:
1x Servo Motor with Bag of Motor Mounts and Screws
1x Button
5x Jumper Wire
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
Servo - Generic (Sub-Micro Size)
Jumper Wires - Connected 6" (M/M, 20 pack)
ROB-09065
PRT-12795
Multicolor Buttons - 4-pack
PRT-14460
Along with the parts mentioned above, you will also need a bottle cap or something similar (not included with the
Inventor's Kit) to build your fish feeder. The cap from a water or soda bottle will work best.
The various motor mounts included with your servo motor.
Tools Needed
You will need the screwdriver included in the Photon SIK. If screwing the bottle cap to a servo motor mount proves
to be too difficult, you can substitute hot glue or other adhesives to attach the cap the a motor mount.
Suggested Reading
Before continuing on with this experiment, we recommend you be familiar with the concepts in the following
tutorials:
Pulse-width Modulation (PWM) - Pulse-width modulation is the driving force behind how servo motors work
and maintain their precision.
Servo Motor Background - This portion of our Servo Trigger Hookup Guide has a lot of good background
information on the theory behind servo motor operation.
Particle Servo Library - Particle built the servo library into their default functions, so you don't have to
download any extra libraries to use servo motors! Learn about all the functions you can use with Servo.
Particle Time Library - We will also be using the built-in Particle Time Library to tell our automatic feeder to
dispense food at a specific time.
Particle Cloud Functions - Some of these will be used in the second half of this experiment to expose
variables and functions for us to manipulate them over the web.
Hardware Hookup
Hook up your circuit as pictured below:
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
You can plug the jumper wire ends directly into the servo motor header.
The button will only be used for a brief portion of this experiment. After it has served its use, you can leave out the
breadboard entirely. Should you wish to leave your fish feeder intact after you've completed all the other
experiments, you can hook up the servo to just the Photon RedBoard to make the project more compact.
Photon Code Part 1a
For this experiment, we will need a few different pieces of code. The very first sketch you'll need to upload will put
the servo motor in a known state. When first unpacked, it's difficult to know what position the servo motor is in, so
this sketch moves the motor all the way to the end of its 180° range of motion. Copy and paste the following code
into the Particle IDE, and upload it to the Photon RedBoard.
/*
SparkFun Inventor's Kit for Photon
Experiment 7 - Part 1a: Servo Motor
This sketch was written by SparkFun Electronics
Joel Bartlett
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application controls a servo with the press of a button.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
Servo myservo;// create servo object using the built-in Particle Servo Library
int button = D1;
int servoPin = D0;
int pos = 0;
bool flag = 1;
//declare variable
//declare variable
//variable to keep
//variable to keep
for button
for servo
track of the servo's position
track of the button presses
// This routine runs only once upon reset
void setup()
{
Serial.begin(9600);//Start the Serial port @ 9600 baud
pinMode(button, INPUT_PULLUP);
myservo.attach(servoPin);
myservo.write(180);
delay(500);
myservo.detach();
// sets button pin as input with internal pullup resistor
//Initialize the servo attached to pin D0
//set servo to furthest position
//delay to give the servo time to move to its position
//detach the servo to prevent it from jittering
}
// This routine loops forever
void loop()
{
if(digitalRead(button) == LOW) //if a button press has been detected...
{
//This is known a s state machine.
//It will move the servo to the opposite end from where it's set currently
if(flag == 1)
pos = 0;
if(flag == 0)
pos = 180;
myservo.attach(servoPin);
myservo.write(pos);
delay(500);
//debounce and give servo time to move
myservo.detach();
flag = !flag;
//set flag to the opposite of what it's currently set to
Serial.println(pos);
//prints to the serial port to keep track of the position
}
}
What You Should See Part 1a
When you first power your Photon RedBoard, give it a few seconds to connect to the web, then you should see the
motor move to the 180° position. Once there, it will stay until the button is pressed. Press the button to move it to
0°. Press the button again and it will move back to the first position. The purpose of this code it to give you an idea
for the full range of motion for the servo motor and to help you plan out your fish feeder.
Assemble the Fish Feeder
With the above sketch still loaded on your RedBoard, it's time to build the actual feeding mechanism. Take your
bottle cap, and screw (or glue) it onto a motor mount of your choosing. We opted for the single arm in this setup.
Next, power your RedBoard with the Micro USB cable, if it isn't already, and open up your favorite Serial Terminal
program at 9600 baud. You should now see the position of the servo printed to the screen when the button is
pressed.
0
180
0
180
0
180
Hold you servo so that the moving portion is facing you and is on the right-hand side of the motor. Now it's time to
attach the mount to the servo so that the cap dumps your food into the tank. This may take a few tries to get it
exactly right.
Move the servo in the 180° position, using the button. Attach the mount by pressing it onto the servo gear until it
is snug. We found that positioning the cap at a 45° angle works well as it holds the food and provides a good angle
for dumping the food. If you would like to secure your mount with the provided screw, now would be the best time.
You may need to screw then unscrew the cap (making holes in it), attach the mount to the servo, screw the mount,
then screw the cap back on to the mount.
With the feeding mechanism attached, press the button again to move into the dumping position (0°). This is your
chance to make any adjustments necessary to ensure all of the food gets dumped out.
If you attached your cap to the motor mount opposite of the image above, you may have to reverse these steps,
starting at position 0° and then dumping at 180°.
Photon Code Part 1b
Now, the code will trigger the servo motor at a specific time instead of on a button press. You will need to change
the Timezone to your local timezone. You will also need to select an hour and minute at which you'd like your
feeder to activate. Copy, paste, and upload the code below.
/*
SparkFun Inventor's Kit for Photon
Experiment 7 - Part 1b: Servo Motor with Time
This sketch was written by SparkFun Electronics
Joel Bartlett
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application controls a servo at a specific time.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
Servo myservo;// create servo object using the built-in Particle Servo Library
int servoPin = D0;
//declare variable for servo
void setup()
{
myservo.attach(servoPin);
myservo.write(180);
delay(500);
myservo.detach();
//Initialize the servo attached to pin D0
//set servo to 180. This position will hold the food
//delay to give the servo time to move to its position
//detach the servo to prevent it from jittering
Time.zone(-6);//Set timezone to Mountain Daylight Time (MDT) Spring/Summer
//Time.zone(-7);//Set timezone to Mountain Standard Time (MST) Fall/Winter
//Find out your time zone here: http://www.timeanddate.com/time/map/
Spark.syncTime();//sync with the Particle Cloud's time
}
void loop()
{
//This if statement checks to see if it is the correct hour and minute of the day to dispense
food.
//The Photon uses 24 hour time so there's no confusion between 1am and 1pm, etc.
if(Time.hour() == 15 && Time.minute() == 0) //feed at 3:00pm
{
myservo.attach(servoPin);
myservo.write(0);//set to a zero position. Dumps food
delay(2000);
myservo.write(180);//set to a zero position
delay(500);
myservo.detach();//detach to keep the servo from jittering
delay(60000);//wait the rest of the minute out
}
}
What You Should See Part 1b
Depending on what time you chose in your code, you should see your servo motor turn to the food dumping
position at that time and then return to its original position. Before implementing, you should test your code out by
entering a time in the not-so-distant future, so you can see the servo move and verify it is working. Once, verified,
program the actual feeding time in and integrate it into your fish tank or other habitat.
This code will only get you through one day of feeding. If you will be gone for say three days and want to feed on
the second day, you can use the Time.month() and Time.day() functions to check for a specific time on a
specific day of the month to feed. Learn more about all of the time functions at Particle.io.
Code to Note
To prepare the Photon RedBoard to control a servo, you must first create a Servo "object" for each servo (here
we've named it "myservo"), and then "attach" it to a digital pin (here we're using digital pin D0). This is creating an
instance of the Servo class, which is part of the built-in Servo Library.
Servo myservo;
To use the servo after it's been declared, you must attach it. This tells the Photon to which pin this servo is
connected. The detach function relinquishes that pin and stops all signals from being sent to the servo.
myservo.attach(D0);
myservo.detach();
The servo in this kit doesn't spin all the way around, but they can be commanded to move to a specific position.
We use the servo library's write() command to move a servo to a specified number of degrees(0 to 180).
Remember that the servo requires time to move, so give it a short delay() if necessary.
servo.write(180);
delay(500);
The Time library is also built in to the Photon firmware. However, you may have noticed that it does not need to be
initialized before it can be used. You can call any of the Time functions at any point in your code. For example, we
call Time.zone(-6) without any reference to Time before that.
Troubleshooting
Servo not moving at all - Make sure you have the correct pins in the correct place. Most all servo are colorcoded with Red being Power, Black being GND, and White or Yellow being the Signal.
Servo twitching and jittering a lot - If you do not detach your servo after every call, it may twitch and jitter a
lot. If this is a problem, add myservo.detach() after every myservo.write() function. Don't forget to reattach it before writing it again.
These servos can only withstand a small amount of abuse. If held in a position it doesn't like for very long,
the servo can be permanently damaged. If all the connections are correct, you're detaching after every
servo write, and the servo is still misbehaving, you may have damaged your servo. If your servo arrived in
this state, contact our customer service team, and they'll help you get a replacement.
Part 2: Feed Your Pets from the Internet
Thus far, we've only used the web to sync the time on our Photon Redboard. Accurate time is great, but let's see if
we can't use the Internet more to our advantage. In part 2 of this experiment, you'll learn how to trigger your auto
fish feeder from anywhere in the world as long as it and you have an Internet connection.
New Photon Code
Your circuit will be the same as it was in Part 1, but the code will be slightly different. We've added a new line,
Spark.function("feed",triggerFeed); and the corresponding function triggerFeed() , explained in the
comments below. Copy, paste, and upload the code.
/*
SparkFun Inventor's Kit for Photon
Experiment 7 - Part 2: Automatic Fish Feeder
This sketch was written by SparkFun Electronics
Joel Bartlett
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application controls a servo at a specific time and over the web.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
Servo myservo;// create servo object using the built-in Particle Servo Library
int servoPin = D0;
int
int
int
int
//declare variable for servo
myMinute = 0; //00
myHour = 9; //9 am
myDay = 14;
myMonth = 8;//August
void setup()
{
myservo.attach(servoPin);
myservo.write(180);
delay(500);
myservo.detach();
//Initialize the servo attached to pin D0
//set servo to 180. This position will hold the food
//delay to give the servo time to move to its position
//detach the servo to prevent it from jittering
Time.zone(-6);//Set timezone to Mountain Daylight Time (MDT) Spring/Summer
//Time.zone(-7);//Set timezone to Mountain Standard Time (MST) Fall/Winter
//Find out your time zone here: http://www.timeanddate.com/time/map/
Particle.syncTime();//sync with the Particle Cloud's time
// We are also going to declare a Spark.function so that we can trigger our feeder from the cl
oud.
Particle.function("feed",triggerFeed);
// When we ask the cloud for the function "feed", it will employ the function triggerFeed() fr
om this app.
}
void loop()
{
//The Photon uses 24 hour time so there's no confusion between 1am and 1pm, etc.
//This time we are checking for a specific date and time.
if(Time.month() == myMonth && Time.day() == myDay) //check the date, if it's not the right da
y, don't bother with the time.
{
if(Time.hour() == myHour && Time.minute() == myMinute) //check the time
{
myservo.attach(servoPin);
myservo.write(0);//set to a zero position. Dumps food
delay(2000);
myservo.write(180);//set to a zero position
delay(500);
myservo.detach();//detach to keep the servo from jittering
delay(60000);//wait the rest of the minute out
}
}
}
int triggerFeed(String command)
{
/* Particle.functions always take a string as an argument and return an integer.
Since we can pass a string, it means that we can give the program commands on how the function s
hould be used.
In this case, telling the function "feed" will trigger the servo.
Then, the function returns a value to us to let us know what happened.
In this case, it will return 1 if the function was called and -1 if we
received a totally bogus command that didn't do anything.
This does not check for any mechanical failures however. Only code.
*/
if (command=="feed")
{
myservo.attach(servoPin);
myservo.write(0);//set to a zero position. Dumps food
delay(2000);
myservo.write(180);//holding position
delay(500);
myservo.detach();
return 1;
}
else
return -1;
}
What You Should See
When you register a function or variable in the cloud, you're making a space for it on the internet. There's a
specific address that identifies you and your device. You can send requests, like GET and POST requests, to this
URL just like you would with any webpage in a browser.
The code below will give you a webpage from which you can trigger the auto-feeder. Copy and paste the code
below into your favorite text editor that can save files as .html.
Feed your pets anywhere you have an Internet connection!
Edit the code in your text file so that "your-device-ID-goes-here" is your actual device ID, and "your-access-tokengoes-here" is your actual access token. These things are accessible through your IDE at build.particle.io. Your
device ID can be found in your Devices drawer (the crosshairs) when you click on the device you want to use, and
your access token can be found in Settings (the cogwheel).
Open that .html file in a browser. You'll see a very simple HTML form that allows you to call the triggerFeed
functions we exposed earlier.
You'll get some info back after you submit the page that gives the status of your device and lets you know that it
was indeed able to post to the URL. If you want to go back, just click "back" on your browser.
Similarly, you can also call this function by opening a Command Line Terminal and typing
particle call device_name feed feed
Remember to replace device_name with either your device ID or the casual nickname you made for your device
when you set it up.
Now, if you need to trigger your autofeeder ahead of schedule for any reason, you can do so with the click of a
button on your smartphone or computer.
Code to Note
The Particle.function line is allowing us to "expose" that function to the rest of the Internet. This allows us to
trigger the feeder from other mediums such as a webpage or the command line. You can learn more about the
Particle Cloud Functions here.
Troubleshooting
If you cannot get your servo to move via the web or command line interface, you may be calling the wrong
device ID. If you have more than one Photon, Photon RedBoard or Core, then it is possible that the device
IDs may have been mixed up at some point.
Another problem could be your access token. If you get an error saying the access token is expired, visit the
Particle IDE at build.particle.io and refresh your access token.
Going Further
Need to feed your fish for multiple days? Add a second servo, or grab a continuous rotation servo to create a
feeding mechanism that only dispenses a small portion of its food reserves at a time.
You could then try to create a webpage app that allows you to change the feeding time on the fly without having to
reprogram your Photon RedBoard.
Experiment 8: Activity Tracker
Introduction
This experiment will get you (or at least your Photon) moving, because we'll be wiring up a motion-sensing,
orientation-finding, 3-axis accelerometer. This experiment serves as an introduction to accelerometers and I2C
communication. You'll also learn about system modes, which allow you to turn WiFi on or off and save loads of
battery juice.
Parts Needed
1x MMA8452Q Accelerometer
1x Green Button
6x Jumper wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
Jumper Wires - Connected 6" (M/M, 20 pack)
PRT-12795
SparkFun Triple Axis Accelerometer Breakout MMA8452Q (with Headers)
BOB-13926
Multicolor Buttons - 4-pack
PRT-14460
Suggested Reading
Two big new electronics concepts are introduced in this experiment: Accelerometers and I2C Communication. If
you're interested in learning a lot more about them, check out our tutorials. For now, here's a quick introduction:
Accelerometers
Accelerometers are movement sensors. They feel acceleration -- the rate of change of velocity (how fast
something is speeding up or slowing down). They've become incredibly common throughout consumer electronics,
with a huge range of applications: smartphone's use them to sense orientation, activity trackers often track steps
using an accelerometer, and hard drives use them to sense free-fall (giving them enough time to move and protect
delicate parts).
Even if a device isn't visibly moving, an accelerometer can still give you a lot of information about its orientation.
Accelerometers sense the acceleration of gravity, which is a constant, pulling force toward earth. In fact, one of the
most common units of acceleration is the g -- "gravity" -- which is equal to about 9.8 m/s2. An accelerometer
sitting flat and motionless, will sense 1g of acceleration towards the ground (usually on the z-axis), and 0g of
acceleration in the other two dimensions (x and y).
There are a huge variety of accelerometers out there. They can monitor anywhere from 1-to-3 axes of
acceleration, support various communication interfaces, and host a range of other unique features. In this
experiment, we're using the MMA8452Q -- a 3-axis accelerometer with a digital interface. It can be set to sense a
maximum of either ±2, 4, or 6 g. It also supports a neat feature called tap, or "pulse" detection.
I2C
The accelerometer we're using in this experiment communicates over an interface called I2C, short for Inter IC
Communication. I2C is an extremely popular embedded computing communication interface. It's relatively slow
(the Photon and accelerometer communicate at about 400kHz), but only requires two wires for communication.
These wires are usually called serial data (SDA) and serial clock (SCL). As you'll see in the next section, hooking
up I2C circuits is as easy as connecting SDA-to-SDA and SCL-to-SCL (don't forget to power the device too!).
Devices on an I2C bus are called "slaves", while the lone, controlling component (our Photon RedBoard in this
case), is called the "master". What makes I2C even more powerful is it allows multiple slave devices on a single,
two-wire bus. Want to add a pressure sensor to your circuit? Just connect the SDA's and SCL's. Each slave device
on an I2C bus has a unique address, so they can ignore messages for other devices, and only take action on bytes
meant for them.
Hardware Hookup
Here's the hookup for both parts of this experiment:
As we mentioned in the I2C section above, an I2C bus is made up of two signals: SDA and SCL. An I2C interface
also requires pullup-resistors on those signals, but the breakout board already takes care of that for you.
The button signal is routed to the RedBoard's D3 pin. We'll internally pull that pin up, so when the button is inactive
it'll read HIGH. When the button is pressed, D3 will go LOW. We won't use the button in the first part, but it'll come
in handy later on.
Photon Code
In this experiment, we'll once again be using the Libraries feature of the Build IDE. To communicate with the
accelerometer, we'll be using the SparkFunMMA8452Q library.
This time, however, we'll be using another feature of the Libraries tab: examples. Most libraries include at least
one example, to help demonstrate their features and usage. To use the SparkFunMMA8452Q library's example,
click USE THIS EXAMPLE (make sure the MMA8452Q-Serial_Example tab is active up top).
The Build IDE will create a new app in your code tab called MMA8452Q-Serial_Example, and it will already have
the library included for you.
All you have to do is flash the code!
What You Should See
This part of the experiment is designed to get you familiar with what, exactly, an accelerometer senses. We'll be
reading the acceleration from each of the three axes, then printing those values out to the serial monitor.
Once the Photon begins running the application, open up a serial terminal to view the data. Acceleration sensed
on all three axes is displayed at a rate of about 1Hz. There are also some fancy ASCII bar graphs, to visually
represent the acceleration values.
Sitting flat, you should see about 1 g of acceleration on the z-axis, and nearly 0 g on the x- and y-axes. Carefully -without disturbing any of the wires -- tilt your RedBoard and Breadboard around, and monitor the three
accelerometer readings. If you flip the board 90°, the z-axis should become 0 g and either x or y will go to 1. Can
you tilt the board and get each axis nearly equal?
Code to Note
This example introduces the SparkFunMMA8452Q library. To begin using the library, create an MMA8452Q class
object. This'll often go in the global section of the code:
// Create an MMA8452Q object, used throughout the rest of the sketch.
MMA8452Q accel; // Default constructor, SA0 pin is HIGH
We'll use accel from here on to access the accelerometer functions and variables. To initialize the sensor, stick
accel.begin() in your setup() . You can give the begin() function two parameters, if you want to configure the
sensing range of the accelerometer or the output data rate (ODR).
// Initialize the accelerometer with begin():
// begin can take two parameters: full-scale range, and output data rate (ODR).
// Full-scale range can be: SCALE_2G, SCALE_4G, or SCALE_8G (2, 4, or 8g)
// ODR can be: ODR_800, ODR_400, ODR_200, ODR_100, ODR_50, ODR_12, ODR_6 or ODR_1
accel.begin(SCALE_2G, ODR_1); // Set up accel with +/-2g range, and slowest (1Hz) ODR
The scale can be set to either ±2, 4, or 8 g, while the output data rate can be set to either 1, 6, 12, 50, 100, 200,
400, or 800 Hz. In our example, the scale is set to its minimum -- meaning it'll have the highest resolution, but be
limited to sensing a maximum of ±2 g.
To check if new data is available from the sensor, use the accel.available() function, which will return 1 if
there's data to be read or 0 otherwise.
Once new data is available, call accel.read() to read all acceleration data from the sensor. Then you'll be able to
access any of six class variables: x , y , z -- the "raw" 12-bit values from the accelerometer -- or cx , cy , and
cz , the calculated accelerations in g.
The whole process goes something like this:
if (accel.available())
{
accel.read();
Serial.println("X: " + String(accel.x) + " | " + String(accel.cx, 2) + " g");
Serial.println("Y: " + String(accel.y) + " | " + String(accel.cy, 2) + " g");
Serial.println("Z: " + String(accel.z) + " | " + String(accel.cz, 2) + " g");
}
Troubleshooting
Motion and breadboard/jumper circuits aren't usually a great combination. If your circuit works initially, but
mysteriously stops working, a jumper may have been (even briefly) disconnected. Double-check all of your wiring,
and restart if anything stops working. Move things around carefully! The base plate is extremely useful for this
experiment.
Part 2: Tracking Steps, Publishing Your Acitvity
Accelerometers are commonly used as the motion-sensing foundation of pedometers -- step counters. And while
the baseplate probably isn't the most comfortable thing to strap to your belt and walk around with, creating an
activity monitor of our own can be a fun exercise. Plus it provides an algorithm you can endlessly try to tweak and
perfect.
New Photon Code
Create a new application, and post this code in:
// Pin definitions:
const int BUTTON_PIN = 3; // The Publish button is connected to D3
const int LED_PIN = 7; // The on-board LED is used to indicate status
MMA8452Q accel; // Create an accelerometer object to be used throught the sketch
// stepCount keeps track of the number of steps since the last publish:
unsigned int stepCount = 0;
// To save battery power, we'll put the Photon in SEMI_AUTOMATIC mode.
// So our Photon will not attempt to connect to the Cloud automatically.
// It'll be up to us to issue Particle.connect() commands, when we want
// to connect.
// More on modes here: https://docs.particle.io/reference/firmware/photon/#system-modes
SYSTEM_MODE(SEMI_AUTOMATIC); // Set system mode to SEMI_AUTOMATIC
// We'll use a few booleans to keep track of _if_ we need to publish,
// and if our publish was successful.
bool publishFlag = false;
bool publishSuccess = false;
void setup()
{
// Begin by turning WiFi off - we're running off batteries, so
// need to save as much power as possible.
WiFi.off(); // Turn WiFi off
As with the previous part's code, you'll need to include the SparkFunMMA8452Q library in this application.
What You Should See
After flashing code to your Photon, remove the USB cable, and plug in a 9V battery via the included 9V-to-Barrel
Jack adapter.
Before walking away, open up the Particle Dashboard, and click over to the "Logs" tab. It should be empty for now.
When your Photon boots up, it'll immediately begin running the application code. You'll also notice the RGB LED is
blinking white-ish, which indicates the device is not connected to the Particle cloud.
Strap your circuit to your belt, or just hold it in your hand, and take about 50 steps. When you want to publish your
step count, hit the green button. Your Photon will stop tracking steps while it connects to WiFi and the Particle
Cloud, then posts the step count. When the activity publishes, you should see a new row-entry on the dashboard.
After successfully publishing, the Photon RedBoard shuts of WiFi and goes back into step counting mode.
There are a variety of ways to check for published events from your Photon. In raw URL form, you can subscribe
to events by directing your browser to a URL like:
https://api.particle.io/v1/devices/DEVICE_ID/events?access_token=ACCESS_TOKEN
Replacing DEVICE_ID with your Photon RedBoard's device ID (found under the "Devices" tab), and swapping in
your access token (in the "Settings" tab) for ACCESS_TOKEN . You'll initially get a mostly blank page, but as your
Photon connects and publishes, new events will pop up:
Those events include your Photon RedBoard connecting, disconnecting, and publishing an event called "Steps". If
you listen for those events, and do some JSON-parsing, you can build a simple HTML/Javascript page to list your
step counts.
As a simple example, copy and paste this code into a text editor. Grab your device ID and access token and plug
them into the deviceID and accessToken variables (between the quotes).
Status: Nothing yet
Step Counts:
function connect()
{
var deviceID = ""; // Photon RedBoard device ID
var accessToken = ""; // Particle account access token
// Subscribe to any events published by our Photon Device ID:
var eventSource = new EventSource(
"https://api.particle.io/v1/devices/" + deviceID + "/events/?access_token=" + accessToke
n);
// When the connection opens, it'll publish an "open" event:
eventSource.addEventListener('open', function(event)
{
var subSpan = document.getElementById("subscription");
subSpan.innerHTML = "Connected. Listening for steps!";
}, false);
// If our eventSource fails to connect, it'll give an error:
eventSource.addEventListener('error', function(event)
{
var subSpan = document.getElementById("subscription");
subSpan.innerHTML = "Not connected :(";
}, false);
// Online/offline messages are published as "spark/status" events:
eventSource.addEventListener('spark/status', function(event)
{
var jData = JSON.parse(event.data); // Parse the JSON data
// Find the "data" key. It'll either be "offline" or "online":
var statusData = jData.data;
// Find the "publihsed_at" key, it'll be a timestamp:
var statusTime = jData.published_at;
// Put the data we've parsed into the "connectStatus" span:
var statusSpan = document.getElementById("connectStatus");
statusSpan.innerHTML = statusData + " (" + statusTime + ")";
}, false);
eventSource.addEventListener('Steps', function(event)
{
var jData = JSON.parse(event.data); // Parse the JSON data
var stepCount = jData.data; // Find the "data" key, it'll be the step count
var stepTime = jData.published_at; // Also get the timestamp from "published_at" key
// Put the data we've parsed into the "stepList" span:
var stepsSpan = document.getElementById("stepList");
stepsSpan.innerHTML = stepsSpan.innerHTML + stepCount + " (" + stepTime + ")" + "";
}, false);
}
window.onload = connect; // Run the connect() function when the page loads
Then open your HTML file with your favorite web browser. And publish some step counts. Eventually your HTML
page will begin to fill out:
System Modes, and Controlling WiFi
Photon System Modes are used to control the Photon RedBoard's connection to WiFi and the Particle cloud. In
this experiment we turn off WiFi whenever it's not necessary -- you don't need an Internet connection to track
steps!
The Photon's WiFi component is a relatively huge power-consumer (pulling, on average, about 50-60mA).
That may not be a big deal when it's powered over USB, but when we're operating on battery power, every
miliwatt (mW) saved means less money going toward replacing batteries. Turning off WiFi can more than
double the amount of time our project can run off a battery.
Control of the Photon's WiFi connection begins before setup() , by calling the SYSTEM_MODE macro:
// SEMI_AUTOMATIC mode starts the application up without WiFi, not connected to the
// Particle cloud. Call Particle.connect() manually to connect to WiFi, after that
// Particle.process()'s will be handled for us.
SYSTEM_MODE(SEMI_AUTOMATIC); // Semi-automatic WiFi/cloud mode
SYSTEM_MODE can either be AUTOMATIC , SEMI_AUTOMATIC or MANUAL . AUTOMATIC is the default state, which you
should be extremely familiar with by now. The Photon boots up and immediately tries to connect to WiFi and the
Cloud before running the sketch.
In SEMI_AUTOMATIC mode, our Photon jumps straight into our application code. It won't try to connect to the cloud
until we call Particle.connect() . While the device is connected, its connection with the cloud is automatically
administered, and Particle.disconnect() can be called to disconnect from the Particle cloud.
In addition to the SYSTEM_MODE control, the application also manages our WiFi connection with WiFi.on() ,
WiFi.connect() , and WiFi.off() . For example, after the button has been pressed, we tell the Photon RedBoard
to connect to WiFi and the Particle cloud like this:
WiFi.on(); // Turn the WiFi module on
WiFi.connect(); // Connect to the pre-set WiFi SSID
Particle.connect(); // Connect to the Particle Cloud
And once we've successfully published, WiFi.off() is called to shut the WiFi system down.
It takes some extra planning to use anything but AUTOMATIC mode, but it can result in a big payoff.
Sensing Steps
Before we can publish any step count, we have to sense them. To be honest, pedometer algorithm's are tough.
The MMA8452Q has a neat feature called pulse detection, that we can pigeonhole into our step-counting
application. We can set the accelerometer to continuously monitor all three axes for short pulses of motion on any
of the three axes, which will be assumed as a step.
To setup pulse or "tap" detection on the MMA8452Q, use the setupTap() function -- giving it threshold and timing
parameters. We'll set the threshold to be very low -- so just about any movement will create a tap -- and set the
time window between pulses to about 500ms.
// Threshold can range from 1-127, with steps of 0.063g/bit.
byte threshold = 1; // 2 * 0.063g = 0.063g (minimum threshold
// Pulse time limit: Maximum time interval that can elapse between the start of
// the acceleration exceeding the threshold, and the end, when acceleration goes
// below the threshold to be considered a valid pulse.
byte pulseTimeLimit = 255; // 0.625 * 255 = 159ms (max)
// Pulse latency: the time interval that starts after first pulse detection, during
// which all other pulses are ignored. (Debounces the pulses).
// @50Hz: Each bit adds 10ms (max: 2.56s)
byte pulseLatency = 64; // 1.25 * 64 = 640ms
accel.setupTap(threshold, threshold, threshold, pulseTimeLimit, pulseLatency);
How fast do you walk? Everyone has a different gait, so you may have to tweak these values to get a more
accurate step count.
Code to Note
Particle Publish will be our tool for sharing our step activity with the world. Publish can be used to post named
event data to the Particle Cloud, where it can be grabbed by another application and displayed or used otherwise.
In this example, we're publishing our step data under the "Steps" event name, and including the step count under
that data. Just a few lines of code are required to publish, and verify a successful publish:
// Call Particle.publish to push our step count to the web:
publishSuccess = Particle.publish("Steps", String(stepCount / 2));
// If the publish was successful
if (publishSuccess)
{
publishFlag = false; // clear the publishFlag
stepCount = 0; // and reset the step count
}
The Particle Dashboard is an easy tool for viewing your device's published data. In leiu of anything more complex,
we can use that interface to easily monitor the number of steps our RedBoard has taken.
Beyond the Dashboard, once you've published your data to the Cloud, there should be no shortage of actions you
can take with it. You can set up a webhook, to monitor the event and post its data. Or even configure a second
Photon to Subscribe to the event, to track multiple Photon activity monitors.
Troubleshooting
Saving power is great, but it can lead to some headaches if you need to upload new code to the Photon. If your
Photon's WiFi is off, or if it's not connected to the cloud, you won't be able to flash new code to it. Thankfully,
there's Safe Mode. By booting your Photon into safe mode, it skips running your application and instead connects
to the Particle Cloud and waits for a new program.
To boot into safe mode, hold down both the RESET and MODE buttons. Then release RESET to turn the Photon
on. When the RGB LED begins blinking pink-ish, release MODE. Your Photon will run through its WiFi/Cloud
connection process, then breathe pink. Once it's breathing pink, you'll be able to successfully flash new code to it.
Going Further
There are plenty of projects that can combine motion sensing and the Internet. How about putting this same circuit
on top of your dryer -- have it alert you when the shaking stops, so you can go grab your clothes before they
wrinkle (escaping any potential scolding from your significant other)!
Experiment 9: Home Security
Introduction
Home security and automation are hot topics for IoT (Internet of Things). In this experiment, you will learn how to
detect if someone is entering a room. There are a lot of different ways you can detect motion in your home. For
this kit, we included both the PIR motion sensor and the Magnetic Door Switch Set. PIR motion sensor is great for
when you need to detect motion farther away within a room. The Magnetic Door Switch Set is a small reed switch
assembly specifically designed to alert you when doors, drawers, or any other aperture opens.
We are going to show you two different circuits. One for the PIR motion sensor and the other for the Magnetic
Door Switch. The code and hook-up for both circuits are fairly similar, so we decided to put both of them in one big
experiment about home security.
If you want to have an alarm, add piezo speaker to the experiments below. For the sake of your ears, we are using
the onboard LED (D7) to show when motion is detected instead of the piezo speaker. You will thank us later.
Alright, time to learn how to catch anyone who steals cookies out of your cookie jar!
PIR Motion Sensor
PIR (passive infrared) sensor is a simple to use motion sensor. We are going to power it up and wait 1-2 seconds
for the sensor to get a snapshot of the still room. If anything moves after that period, the ‘alarm’ pin will go low.
Parts Needed
You will need the following parts:
Photon RedBoard, Breadboard, and Base Plate
1x PIR Sensor
1x JST Right Angle Connector - Through-Hole 3-Pin
3x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
PIR Motion Sensor (JST)
Jumper Wires - Connected 6" (M/M, 20 pack)
SEN-13285
PRT-12795
JST Right Angle Connector - Through-Hole 3Pin
PRT-09750
Suggested Reading
Pull-up Resistors - Pull-up resistors are very common when using microcontrollers (MCUs) or any digital
logic device. This tutorial will explain when and where to use pull-up resistors, then we will do a simple
calculation to show why pull-ups are important.
PIR Motion Sensor Hardware Hookup
To make it easier to breadboard the PIR motion sensor, you will want to add the JST Right Angle Connector Through-Hole 3-Pin.
Make sure to push the PIR motion sensor's JST female connector into the JST right angle connector as much as
you can. After you do that, now you are ready to breadboard.
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
Photon Code
/*
SparkFun Inventor's Kit for Photon
Experiment 9 - Part 1: Home Security with PIR
This sketch was written by SparkFun Electronics
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application uses a PIR motion sensor to detect motion
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License (http://opensource.org/licenses/MIT)
*/
int pirPin = D0; // PIR is connected to D3
int led = D7;
// Onboard LED is D7
void setup()
{
pinMode(pirPin, INPUT_PULLUP); // Initialize D3 pin as input with an internal pull-up resistor
pinMode(led, OUTPUT);
// Initialize D7 pin as output
}
void loop()
{
int pirValState;
pirValState = digitalRead(pirPin);
if(pirValState == LOW){
// Was motion detected
digitalWrite(led, HIGH);
// Turn ON the LED
delay(2000); // Wait 1-2 seconds for the sensor to get a snapshot of the still room
}
else
{
digitalWrite(led, LOW); // Turn the LED off
}
}
What You Should See
When you wave your hand over the PIR motion sensor, the onboard LED (D7) will light up!
Get creative and add a piezo speaker! You can be far away and hear an alarm go off if someone sneaks in! Maybe
useful in a zombie apocalypse to give you enough time to escape. Might attract attention of more zombies too. We
haven't decided yet.
Code to Note
if(pirValState == LOW){ // Was motion detected
When motion is detected, the ‘alarm’ pin will go low.
Troubleshooting
If nothing happens, double check your connections. It is easy to swap the jumper wires for the PIR motion
sensor. The white wire on the PIR motion sensor is connected to the GND. Lots of time when we see a
black wire, we think it automatically is GND. It is always important to check the datasheets and hook-up
guides. Wire colors varies from different manufacturers and don't always follow the same standards.
Magnetic Door Switch Set
These types of switches are primarily used in home security systems. One half of the assembly set on a window or
door frame and the other attached to the window or door itself. When the switch set is separated from each other
the contact is broken and triggers an alarm. You can use this set in non-security applications too. For example to
trigger a music box to play a song when you open the box.
When each piece comes within 20mm of each other they complete the circuit with the internal reed switches.
Parts Needed
You will need the following parts:
Photon RedBoard, Breadboard, and Base Plate
1x Magnetic Door Switch Set
2x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
Jumper Wires - Connected 6" (M/M, 20 pack)
Magnetic Door Switch Set
PRT-12795
COM-13247
Suggested Reading
Pull-up Resistors - Pull-up resistors are very common when using microcontrollers (MCUs) or any digital
logic device. This tutorial will explain when and where to use pull-up resistors, then we will do a simple
calculation to show why pull-ups are important.
Switch Basics - Reed switches open or close when exposed to the presence of a magnetic field. Learn more
about different types of switches with this tutorial.
Magnetic Door Switch Set Hookup
You have two parts of the Magnetic Door Switch Set. Set off to the side, the part that does not have the wires.
Connect the part that has the wires coming out to the breadboard. It doesn't matter which wire goes to GND pin or
a digital pin. They are interchangeable.
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
Photon Code
/*
SparkFun Inventor's Kit for Photon
Experiment 9 - Part 1: Home Security with Magnetic Door Switch Set
This sketch was written by SparkFun Electronics
August 31, 2015
https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments
This application uses a Magnetic Door Switch Set to detect motion
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License (http://opensource.org/licenses/MIT)
*/
int magnetPin = D3; // magnet part is connected to D3
int led = D7;
// Onboard LED is D7
void setup()
{
pinMode(magnetPin, INPUT_PULLUP); // Initialize D3 pin as input with an internal pull-up resis
tor
pinMode(led, OUTPUT);
// Initialize D7 pin as output
}
void loop()
{
int magnetValState;
magnetValState = digitalRead(magnetPin);
if(magnetValState == HIGH){
digitalWrite(led, HIGH);
}
else
// Was motion detected
// Turn ON the LED
{
digitalWrite(led, LOW);
// Turn the LED off
}
}
What You Should See
Move the two parts next to each other. The onboard LED (D7) will be off. If you move the parts away from each
other the onboard LED will come on.
You can add a piezo speaker as an alarm or play fun songs when something opens.
Code to Note
if(magnetValState == HIGH){ // Was motion detected
This code is almost identical to the PIR motion sensor. Instead of LOW, we switched it HIGH, so the onboard LED
(D7) will only come on when both parts are away from each other.
Troubleshooting
If your code refuses to flash, try putting your Photon RedBoard into safe mode. Then, hit Flash.
Experiment 10: Pong!
Introduction
In this experiment, we'll use the OLED Breakout, potentiometer, and a photo resistor to make a game of Pong,
where the paddles are controlled by the analog values of the two sensors.
Parts Needed
You will need the following parts (besides your Photon RedBoard and Breadboard, of course):
1x OLED Breakout Board
1x Potentiometer
1x Photoresistor
1x 330 Ohm Resistor
15x Jumper Wires
Using a Photon by Particle instead or you don't have the kit? No worries! You can still have fun and
follow along with this experiment. We suggest using the parts below:
Trimpot 10K with Knob
Mini Photocell
COM-09806
SEN-09088
SparkFun Micro OLED Breakout
Resistor 330 Ohm 1/4 Watt PTH - 20 pack
(Thick Leads)
LCD-13003
PRT-14490
Heads up! If you are getting the parts separately from the kit, make sure to solder header pins to the OLED
breakout board.
Break Away Headers - Straight
PRT-00116
Suggested Reading
OLED Breakout Hookup Guide - if you're stuck hooking up the OLED breakout, check this lovely guide for
more info
What is an Arduino? -- We'll use an Arduino to send commands and display data to the OLED.
Serial Peripheral Interface (SPI) -- SPI is the preferred method of communication with the display.
I2C -- Alternatively, I2C can be used to control the display. It uses less wires, but is quite a bit slower.
How to Use a Breadboard -- The breadboard ties the Arduino to the OLED breakout.
Hardware Hookup
We'll be connecting three devices to our Photon RedBoard - the OLED breakout, a trim potentiometer, and a
photocell. These last two are analog sensors that are going to act as the paddle controllers for each player, while
the OLED screen displays the ball, the paddles, and the score.
Having a hard time seeing the circuit? Click on the Fritzing diagram to see a bigger image.
The photocell is hooked up to pin A0 and GND though a 330 (NOT 10K) Ohm resistor from one pin, while the
other pin is connected to +3.3V. The potentiometer's middle pin goes to pin A1, while the side pins are connected
to GND and 3.3V.
Here's a handy table for the OLED Breakout connections:
Photon RedBoard Pin
OLED Breakout Pin
A2
CS
A3
SCK
A5
SDI
D5
D/C
D6
RST
3V3
3.3V
GND
GND
The table and Fritzing image are much more helpful, but if you wanted to see inside the box, here's a shot of the
breadboarded circuit:
Photon Code
Pong is a great programming exercise for getting used to a new language or environment. There are tons of great
pong tutorials out there, so we're not going to focus too much on the general code beyond the parts that interact
with the hardware.
The first thing we need to do after creating a new app is to add the SparkFun OLED library to our sketch. This let's
us draw and write all manner of things to the OLED screen quite easily. First, click on the bookmark icon in the
sidebar (it's the fourth one up from the bottom). Under 'Community Libraries', there should be a search box - type
in OLED, and you should see the 'SparkFunMicroOLED' Library pop up, like so:
Click on the library name, and then on the big blue button that says "Include in App". That should cause a line like
#include "SparkFunMicroOLED/SparkFunMicroOLED.h" to appear near the top of your sketch. Voila!
Now that you've imported the library, you can copy and paste the rest of the code beneath:
/*
SparkFun Inventor's Kit for Photon
Experiment 10 - Part 1
This sketch was written by SparkFun Electronics
Ben Leduc-Mills
August 31, 2015
https://github.com/sparkfun
This is an example sketch for an analog sensor Pong game.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
//////////////////////////
// MicroOLED Definition //
//////////////////////////
#define PIN_RESET D6 // Connect RST to pin 6
#define PIN_DC
D5 // Connect DC to pin 5 (required for SPI)
#define PIN_CS
A2 // Connect CS to pin A2 (required for SPI)
//MicroOLED oled(MODE_SPI, PIN_RESET, PIN_DC, PIN_CS);
MicroOLED oled(MODE_SPI, PIN_RESET, PIN_DC, PIN_CS);
//#define SINGLE_PLAYER
const int player1Pin = A1;
#ifndef SINGLE_PLAYER
const int player2Pin = A0;
#endif
/*** Sensor Calibration ****/
int sensor1Calibration = LCDHEIGHT; //photocell w/330
int sensor2Calibration = LCDHEIGHT; //potentiometer
//potentiometer
int sensor1Min =
int sensor1Max =
//photocell
int sensor2Min =
int sensor2Max =
/*** Game
const int
const int
const int
const int
0;
4096;
100;
1000;
Settings ***/
renderDelay = 16;
startDelay = 2000;
gameOverDelay = 3000;
scoreToWin = 10;
int player1Score = 0;
int player2Score = 0;
const
const
const
const
float
float
float
float
paddleWidth = LCDWIDTH / 16.0;
paddleHeight = LCDHEIGHT / 3.0;
halfPaddleWidth = paddleWidth / 2.0;
halfPaddleHeight = paddleHeight / 2.0;
float
float
float
float
player1PosX
player1PosY
player2PosX
player2PosY
=
=
=
=
1.0 + halfPaddleWidth;
0.0;
LCDWIDTH - 1.0 - halfPaddleWidth;
0.0;
// This is only used in SINGLE_PLAYER mode:
#ifdef SINGLE_PLAYER
float enemyVelY = 0.5;
#endif
/*** Ball Physics ***/
const float ballRadius = 2.0;
const float ballSpeedX = 1.0;
float ballPosX = LCDWIDTH / 2.0;
float ballPosY = LCDHEIGHT / 2.0;
float ballVelX = -1.0 * ballSpeedX;
float ballVelY = 0;
void setup()
{
// in our setup, we call a few custom functions to get everything ready
initializeGraphics();
initializeInput();
displayGameStart();
Serial.begin(9600);
}
void loop()
{
updateGame(); //custom function to advance the game logic
renderGame(); //custom function to dislay the current game state on the OLED screen
// print out sensor values via serial so we can calibrate
Serial.print(analogRead(A0));
Serial.print(" ");
Serial.println(analogRead(A1));
//winning conditions
if (player1Score >= scoreToWin)
{
gameOver(true);
}
else if (player2Score >= scoreToWin)
{
gameOver(false);
}
}
//start the OLED and set the font type we want
void initializeGraphics()
{
oled.begin();
oled.setFontType(1);
}
//get either 1 or 2 pins ready for analog input
void initializeInput()
{
pinMode(player1Pin, INPUT);
#ifndef SINGLE_PLAYER
pinMode(player2Pin, INPUT);
#endif
}
//display the start screen
void displayGameStart()
{
oled.clear(PAGE);
renderString(20, 10, "Get");
renderString(10, 30, "Ready!");
oled.display();
delay(startDelay);
}
//update the positions of the player paddles and the ball
void updateGame()
{
updatePlayer1();
updatePlayer2();
updateBall();
}
//reset the score, ball position, and paddle positions for a new game
void resetGame()
{
player2Score = 0;
player1Score = 0;
player2PosY = 0.0;
ballPosX = LCDWIDTH / 2.0;
ballPosY = LCDHEIGHT / 2.0;
ballVelX = -1.0 * ballSpeedX;
ballVelY = 0.0;
}
float clampPaddlePosY(float paddlePosY)
{
float newPaddlePosY = paddlePosY;
if (paddlePosY - halfPaddleHeight < 0)
{
newPaddlePosY = halfPaddleHeight;
}
else if (paddlePosY + halfPaddleHeight > LCDHEIGHT)
{
newPaddlePosY = LCDHEIGHT - halfPaddleHeight;
}
return newPaddlePosY;
}
void updatePlayer1()
{
int potVal = analogRead(player1Pin);
player1PosY = map(potVal, sensor1Min, sensor1Max, 0, sensor1Calibration);
}
void updatePlayer2()
{
// If it's a single player game, update the AI's position
#ifdef SINGLE_PLAYER
// Follow the ball at a set speed
if (player2PosY < ballPosY)
{
player2PosY += enemyVelY;
}
else if (player2PosY > ballPosY)
{
player2PosY -= enemyVelY;
}
player2PosY = clampPaddlePosY(player2PosY);
#else // Else if this is multiplayer, get player 2's position
int lightVal = analogRead(player2Pin);
player2PosY = map(lightVal, sensor2Min, sensor2Max, 0, sensor2Calibration);
//Serial.println(player2PosY);
#endif
}
void updateBall()
{
ballPosY += ballVelY;
ballPosX += ballVelX;
// Top and bottom wall collisions
if (ballPosY < ballRadius)
{
ballPosY = ballRadius;
ballVelY *= -1.0;
}
else if (ballPosY > LCDHEIGHT - ballRadius)
{
ballPosY = LCDHEIGHT - ballRadius;
ballVelY *= -1.0;
}
// Left and right wall collisions
if (ballPosX < ballRadius)
{
ballPosX = ballRadius;
ballVelX = ballSpeedX;
player2Score++;
}
else if (ballPosX > LCDWIDTH - ballRadius)
{
ballPosX = LCDWIDTH - ballRadius;
ballVelX *= -1.0 * ballSpeedX;
player1Score++;
}
// Paddle collisions
if (ballPosX < player1PosX + ballRadius + halfPaddleWidth)
{
if (ballPosY > player1PosY - halfPaddleHeight - ballRadius &&
ballPosY < player1PosY + halfPaddleHeight + ballRadius)
{
ballVelX = ballSpeedX;
ballVelY = 2.0 * (ballPosY - player1PosY) / halfPaddleHeight;
}
}
else if (ballPosX > player2PosX - ballRadius - halfPaddleWidth)
{
if (ballPosY > player2PosY - halfPaddleHeight - ballRadius &&
ballPosY < player2PosY + halfPaddleHeight + ballRadius)
{
ballVelX = -1.0 * ballSpeedX;
ballVelY = 2.0 * (ballPosY - player2PosY) / halfPaddleHeight;
}
}
}
void renderGame()
{
oled.clear(PAGE);
renderScores(player1Score, player2Score);
renderPaddle(player1PosX, player1PosY);
renderPaddle(player2PosX, player2PosY);
renderBall(ballPosX, ballPosY);
oled.display();
delay(renderDelay);
}
void renderString(int x, int y, String string)
{
oled.setCursor(x, y);
oled.print(string);
}
void renderPaddle(int x, int y)
{
oled.rect(
x - halfPaddleWidth,
y - halfPaddleHeight,
paddleWidth,
paddleHeight);
}
void renderBall(int x, int y)
{
oled.circle(x, y, 2);
}
void renderScores(int firstScore, int secondScore)
{
renderString(10, 0, String(firstScore));
renderString(LCDWIDTH - 14, 0, String(secondScore));
}
void gameOver(bool didWin)
{
if (didWin)
{
#ifdef SINGLE_PLAYER
renderString(20, 10, "You");
renderString(20, 30, "Win!");
#else
renderString(0, 10, "Playr 1");
renderString(15, 30, "Wins");
#endif
}
else
{
#ifdef SINGLE_PLAYER
renderString(20, 10, "You");
renderString(15, 30, "Lose!");
#else
renderString(0, 10, "Playr 2");
renderString(15, 30, "Wins");
#endif
}
oled.display();
delay(gameOverDelay);
// Get ready to start the game again.
resetGame();
displayGameStart();
}
What You Should See
After successfully flashing the code onto your Photon RedBoard, you should see the words 'Get Ready!' on the
OLED screen, followed soon after by the familiar Pong game screen. If you've calibrated your sensors well, you
should be able to move each paddle up and down to defend your side. After a player wins, the game should start
all over again.
If you turn the potentiometer or place your hand over the photocell, the paddles should move up and down,
allowing you to play a game of Pong:
Code to Note
Whew! That's a lot of code to digest all at once. Let's look at a few of the key sections that make this work.
Defining our pin assignments and declaring our OLED object happens right at the top:
#define PIN_RESET D6 // Connect RST to pin 6
#define PIN_DC
D5 // Connect DC to pin 5 (required for SPI)
#define PIN_CS
A2 // Connect CS to pin A2 (required for SPI)
MicroOLED oled(MODE_SPI, PIN_RESET, PIN_DC, PIN_CS);
//#define SINGLE_PLAYER
const int player1Pin = A1; //connected to potentiometer
#ifndef SINGLE_PLAYER
const int player2Pin = A0; //connected to photocell
#endif
This is also where we decide a few important things: which communication mode we're using - SPI in our case
means we put MODE_SPI as that first variable in the MicroOLED object. Below that, we're also deciding if we want
a 1 player or 2 player game. To make the game one player, simply uncomment the //#define SINGLE_PLAYER
line.
The next section is crucial - it's where we 'calibrate' our sensors, by telling the program what we expect the
minimum and maximum values for each sensor to be. Changes are you'll have to run the program first and look at
the serial monitor while testing your sensors to get a good 'sense' of the value ranges.
/*** Sensor Calibration ****/
int sensor1Calibration = LCDHEIGHT; //photocell w/330
int sensor2Calibration = LCDHEIGHT; //potentiometer
//potentiometer
int sensor1Min =
int sensor1Max =
//photocell
int sensor2Min =
int sensor2Max =
0;
4096;
100;
1000;
For example, if you're in a very brightly lit room, your photocell will get a wider range of values than if you're in a
dimly lit place -- but we still want the paddle to move the entire range of the screen, which is why we save the
LCDHEIGHT value to a separate variable to use later on.
After we set a number of global variables that control things like how fast the ball moves and what number each
game goes until (the winning number), we're on to our setup() and loop() functions.
void setup()
{
// in our setup, we call a few custom functions to get everything ready
initializeGraphics();
initializeInput();
displayGameStart();
Serial.begin(9600);
}
void loop()
{
updateGame(); //custom function to advance the game logic
renderGame(); //custom function to dislay the current game state on the OLED screen
// print out sensor values via serial so we can calibrate
Serial.print(analogRead(A0));
Serial.print(" ");
Serial.println(analogRead(A1));
//winning conditions
if (player1Score >= scoreToWin)
{
gameOver(true);
}
else if (player2Score >= scoreToWin)
{
gameOver(false);
}
}
You'll notice that we make use of a lot of custom functions in order to keep our main setup and loop short and
readable. In the setup() , we call a few functions that help start up the OLED screen, initialize our input pins,
display the start screen, and open up serial communication. The loop() is simply updating the game state,
displaying that state, checking to see if anyone won, and ending the game if so. Dig into all of these functions to
get a better sense of how the game works!
Troubleshooting
The main challenge (besides being good at Pong) is making sure your sensor inputs are calibrated to the point
where each paddle covers the entire height of the OLED screen. Checking the serial monitor while testing your
sensors is the best way to get an idea of what the range for each sensor is.
Part 2: Scoreboard!
What does every serious Pong competition need? A scoreboard, that's what! In this half of the exercise, we're
going to use Particle.variable() with the Particle Cloud API to create a web page that stores our Pong scores
locally (i.e., without a database) in HTML 5 localData, displays them in a table, and updates when a new score in
ready.
Photon Code
Here's the new code that goes on the Photon RedBoard - in reality, there are just a few changes. We'll go over
them in the next section, but this is the complete sketch on the Photon side.
/*
SparkFun Inventor's Kit for Photon
Experiment 10 - Part 2
This sketch was written by SparkFun Electronics
Ben Leduc-Mills
August 31, 2015
https://github.com/sparkfun
This is an example sketch for an analog sensor Pong game, with
an html/javascript scoreboard.
Development environment specifics:
Particle Build environment (https://www.particle.io/build)
Particle Photon RedBoard
Released under the MIT License(http://opensource.org/licenses/MIT)
*/
//////////////////////////
// MicroOLED Definition //
//////////////////////////
#define PIN_RESET D6 // Connect RST to pin 6
#define PIN_DC
D5 // Connect DC to pin 5 (required for SPI)
#define PIN_CS
A2 // Connect CS to pin A2 (required for SPI)
//MicroOLED oled(MODE_SPI, PIN_RESET, PIN_DC, PIN_CS);
MicroOLED oled(MODE_SPI, PIN_RESET, PIN_DC, PIN_CS);
//#define SINGLE_PLAYER
const int player1Pin = A1;
#ifndef SINGLE_PLAYER
const int player2Pin = A0;
#endif
/*** Sensor Calibration ****/
int sensor1Calibration = LCDHEIGHT; //photocell w/330
int sensor2Calibration = LCDHEIGHT; //potentiometer
//potentiometer
int sensor1Min =
int sensor1Max =
//photocell
int sensor2Min =
int sensor2Max =
/*** Game
const int
const int
const int
const int
0;
4096;
100;
1000;
Settings ***/
renderDelay = 16;
startDelay = 2000;
gameOverDelay = 3000;
scoreToWin = 10;
int player1Score = 0;
int player2Score = 0;
const
const
const
const
float
float
float
float
paddleWidth = LCDWIDTH / 16.0;
paddleHeight = LCDHEIGHT / 3.0;
halfPaddleWidth = paddleWidth / 2.0;
halfPaddleHeight = paddleHeight / 2.0;
float
float
float
float
player1PosX
player1PosY
player2PosX
player2PosY
=
=
=
=
1.0 + halfPaddleWidth;
0.0;
LCDWIDTH - 1.0 - halfPaddleWidth;
0.0;
// This is only used in SINGLE_PLAYER mode:
#ifdef SINGLE_PLAYER
float enemyVelY = 0.5;
#endif
/*** Ball Physics ***/
const float ballRadius = 2.0;
const float ballSpeedX = 1.0;
float ballPosX = LCDWIDTH / 2.0;
float ballPosY = LCDHEIGHT / 2.0;
float ballVelX = -1.0 * ballSpeedX;
float ballVelY = 0;
//score keeper
char postScore[64];
//game ID
int gameID = 0;
void setup()
{
// in our setup, we call a few custom functions to get everything ready
//here's our call to Particle.variable - we're just sending a string called 'data' out to the
cloud
Particle.variable("data", &postScore, STRING);
initializeGraphics();
initializeInput();
displayGameStart();
Serial.begin(9600);
}
void loop()
{
updateGame(); //custom function to advance the game logic
renderGame(); //custom function to dislay the current game state on the OLED screen
//winning conditions
if (player1Score >= scoreToWin)
{
gameOver(true);
}
else if (player2Score >= scoreToWin)
{
gameOver(false);
}
}
//start the OLED and set the font type we want
void initializeGraphics()
{
oled.begin();
oled.setFontType(1);
}
//get either 1 or 2 pins ready for analog input
void initializeInput()
{
pinMode(player1Pin, INPUT);
#ifndef SINGLE_PLAYER
pinMode(player2Pin, INPUT);
#endif
}
//display the start screen
void displayGameStart()
{
oled.clear(PAGE);
renderString(20, 10, "Get");
renderString(10, 30, "Ready!");
oled.display();
delay(startDelay);
}
//update the positions of the player paddles and the ball
void updateGame()
{
updatePlayer1();
updatePlayer2();
updateBall();
}
//reset the score, ball position, and paddle positions for a new game
void resetGame()
{
player2Score = 0;
player1Score = 0;
player2PosY = 0.0;
ballPosX = LCDWIDTH / 2.0;
ballPosY = LCDHEIGHT / 2.0;
ballVelX = -1.0 * ballSpeedX;
ballVelY = 0.0;
}
float clampPaddlePosY(float paddlePosY)
{
float newPaddlePosY = paddlePosY;
if (paddlePosY - halfPaddleHeight < 0)
{
newPaddlePosY = halfPaddleHeight;
}
else if (paddlePosY + halfPaddleHeight > LCDHEIGHT)
{
newPaddlePosY = LCDHEIGHT - halfPaddleHeight;
}
return newPaddlePosY;
}
void updatePlayer1()
{
int potVal = analogRead(player1Pin);
player1PosY = map(potVal, sensor1Min, sensor1Max, 0, sensor1Calibration);
}
void updatePlayer2()
{
// If it's a single player game, update the AI's position
#ifdef SINGLE_PLAYER
// Follow the ball at a set speed
if (player2PosY < ballPosY)
{
player2PosY += enemyVelY;
}
else if (player2PosY > ballPosY)
{
player2PosY -= enemyVelY;
}
player2PosY = clampPaddlePosY(player2PosY);
#else // Else if this is multiplayer, get player 2's position
int lightVal = analogRead(player2Pin);
player2PosY = map(lightVal, sensor2Min, sensor2Max, 0, sensor2Calibration);
//Serial.println(player2PosY);
#endif
}
void updateBall()
{
ballPosY += ballVelY;
ballPosX += ballVelX;
// Top and bottom wall collisions
if (ballPosY < ballRadius)
{
ballPosY = ballRadius;
ballVelY *= -1.0;
}
else if (ballPosY > LCDHEIGHT - ballRadius)
{
ballPosY = LCDHEIGHT - ballRadius;
ballVelY *= -1.0;
}
// Left and right wall collisions
if (ballPosX < ballRadius)
{
ballPosX = ballRadius;
ballVelX = ballSpeedX;
player2Score++;
}
else if (ballPosX > LCDWIDTH - ballRadius)
{
ballPosX = LCDWIDTH - ballRadius;
ballVelX *= -1.0 * ballSpeedX;
player1Score++;
}
// Paddle collisions
if (ballPosX < player1PosX + ballRadius + halfPaddleWidth)
{
if (ballPosY > player1PosY - halfPaddleHeight - ballRadius &&
ballPosY < player1PosY + halfPaddleHeight + ballRadius)
{
ballVelX = ballSpeedX;
ballVelY = 2.0 * (ballPosY - player1PosY) / halfPaddleHeight;
}
}
else if (ballPosX > player2PosX - ballRadius - halfPaddleWidth)
{
if (ballPosY > player2PosY - halfPaddleHeight - ballRadius &&
ballPosY < player2PosY + halfPaddleHeight + ballRadius)
{
ballVelX = -1.0 * ballSpeedX;
ballVelY = 2.0 * (ballPosY - player2PosY) / halfPaddleHeight;
}
}
}
void renderGame()
{
oled.clear(PAGE);
renderScores(player1Score, player2Score);
renderPaddle(player1PosX, player1PosY);
renderPaddle(player2PosX, player2PosY);
renderBall(ballPosX, ballPosY);
oled.display();
delay(renderDelay);
}
void renderString(int x, int y, String string)
{
oled.setCursor(x, y);
oled.print(string);
}
void renderPaddle(int x, int y)
{
oled.rect(
x - halfPaddleWidth,
y - halfPaddleHeight,
paddleWidth,
paddleHeight);
}
void renderBall(int x, int y)
{
oled.circle(x, y, 2);
}
void renderScores(int firstScore, int secondScore)
{
renderString(10, 0, String(firstScore));
renderString(LCDWIDTH - 14, 0, String(secondScore));
}
// OK - here's the new bit
void gameOver(bool didWin)
{
//at the end of a game, increment the gameID by 1
gameID += 1;
//now, send out the player 1 score, player 2 score, and the game ID
//we do this by using 'sprintf', which takes a bunch of random data types (in our case, intege
rs),
//and puts them all into a nicely formatted string - which is exactly what our Particle.variab
le is supposed to be
sprintf(postScore, "{\"player1Score\":%d, \"player2Score\":%d, \"gameID\":%d}", player1Score,
player2Score, gameID);
//give us a sec, and start a new game
delay(1000);
if (didWin)
{
#ifdef SINGLE_PLAYER
renderString(20, 10, "You");
renderString(20, 30, "Win!");
#else
renderString(0, 10, "Playr 1");
renderString(15, 30, "Wins");
#endif
}
else
{
#ifdef SINGLE_PLAYER
renderString(20, 10, "You");
renderString(15, 30, "Lose!");
#else
renderString(0, 10, "Playr 2");
renderString(15, 30, "Wins");
#endif
}
oled.display();
delay(gameOverDelay);
// Get ready to start the game again.
resetGame();
displayGameStart();
}
HTML Code
This is where the real action is happening for this exercise - on the web. We'll be using a combination of good ol'
HTML, the HTML 5 localStorage ability, and some basic javaScript to create a page that reads the values of our
Particle.variable, stores them (without using a database), displays them in a table, and checks every 15 seconds
for a new score to come in.
Create a new html file in your favorite text editor, save it as 'experiment10.html' and paste in the code below
(doesn't matter where you save it, just remember where it is):