Upload
jokin-alonso
View
316
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Bad quality to reduce the file size.
Citation preview
GETTING STARTED
What's in the box
GETTING STARTED
CONNECTING YOUR CORE
EXAMPLES
CORE CODE (FIRMWARE)
CLOUD CODE (API)
WEB IDE (BUILD)
HARDWARE DATASHEET
SHIELDS AND KITS
TINKER
COMMAND LINE
TROUBLESHOOTING
GETTING STARTED
What's in the box
Step 1: Power the Core
Step 2: Install the App
Step 3: Connect your Core to the Cloud!
NOW DO THINGS!
Blink an LED with Tinker
Put Code on Your Core
WAIT, WHAT IS THIS THING?
Buttons
LEDs
Pins
Congratulations on being the owner of a brand new Spark Core! Go ahead, open the box, and
let's talk about what you see. Your box should include:
Step 1: Power the Core
(1) Spark Core The reason you bought it!
(1) Breadboard A breadboard makes it easy to wire components to the Core without solder.
See Wikipedia for more information.
(1) USB cable The included USB cable is great for powering the Spark Core and more
technical things we'll cover later.
Plug the included USB cable into the Spark Core and your computer. The Core should start
blinking blue. Have one of these u.FL connectors? Make sure to connect an antenna to it now!
Step 2: Install the App
Not blinking blue?
Maybe it's already been configured. Hold down the MODE button until it starts blinking
blue, then continue.
It's called "Spark Core", or you can click one of these links:
iPhone Android
Now use the app to sign up for an account!
Step 3: Connect your Core to the Cloud!
Make sure your phone is connected to the WiFi you want to use (it'll show up in the SSID blank
on the app), then enter your password and click CONNECT!
This may take a little while- but don't worry. It should go through the following colors:
Did your phone not find any Cores?
NOW DO THINGS!
Blink an LED with Tinker
Blinking blue: Listening for Wi-Fi credentials
Solid blue: Getting Wi-Fi info from app
Blinking green: Connecting to the Wi-Fi network
Blinking cyan: Connecting to the Spark Cloud
Blinking magenta: Updating to the newest firmware
Breathing cyan: Connected!
See an animation
Is it blinking blue?
Give it another go.
Is it blinking green and not getting to cyan?
Try it again by holding the MODE button on the core until it begins flashing blue, then
double-check your network name and password.
Is it now breathing cyan, but the app didn't find any Cores?
Uh oh. Your Core's on the network, but it took too long. We're going to claim your core
manually.
Something else altogether?
Give the Connecting Your Core page a read-through and if you're still stuck, search the
community.
The Spark app should now be on the Tinker screen, as shown to the right.
Tap D7 then digitalWrite in the popup. Now when you tap the D7 circle the tiny blue LED
should turn off or on! This is because the LED shares a connection to the Core with the pin
labeled D7.
You could hook your own LED up to the Core on another pin and do the same thing, use
digitalRead to tell that a switch has been pressed, or analogRead to see the position of a
knob.
You can always get Tinker back on the Core by following these instructions
Put Code on Your Core
Now let's control the blue LED using code instead of Tinker. If you click here or on Build on
the main page, you'll be in the IDE- where we can write code and upload it to the Core. Log in
with the same email and password you used to sign up in the app, and we're off!
Click "BLINK AN LED" under the Example apps title. This code turns D7 (labeled led2) on and
off, once a second. Click the lightning bolt icon in the upper left and it will upload or "flash"
this code onto your Core. You'll see a series of status colors on the main LED, and then the
little blue LED blinking. Magic!
You can find more info in the Web IDE (Build) page
WAIT, WHAT IS THIS THING?
The Spark Core is a Wi-Fi development kit for internet-connected hardware. It is, in essence,
the "brains" of a connected hardware product or project.
The Core has on board a microcontroller, which is a small, low-cost, low-power computer that
can run a single application. The microcontroller runs the show; it runs your software and
tells the rest of the Core what to do. It doesn't have an Operating System the way that your
computer does; it just runs a single application (often called firmware or an embedded
application), which can be simple, just a few lines of code, or very complex, depending on
what you want to do.
Microcontrollers are particularly good at controlling things; hence the name. They have a set
of "pins" (little spider leg type things sticking off the chip) that are called GPIO (General
Purpose Input and Output) pins, or I/O pins. They can be hooked to sensors or buttons to
listen to the world, or they can be hooked to lights and motors to act upon the world. These
microcontroller's pins have been directly connected to the headers on the sides of the Core
so you can easily access them; specifically, the pins labeled D0 to D7 and A0 to A7 are hooked
directly to the microcontroller's GPIO pins.
The microcontroller can also communicate with other chips using common protocols like
Serial (also called UART), SPI, or I2C (also called Wire). You can then make the Core more
powerful by connecting it to special-purpose chips like motor drivers or shift registers.
Sometimes we'll wrap up these chips on a Shield, an accessory to the Core that makes it easy
to extend the Core.
The Core also has a Wi-Fi module, which connects it to your local Wi-Fi network in the same
way that your computer or smartphone might connect to a Wi-Fi network. The Core is
programmed to stay connected to the internet by default, so long as it can find and connect
to a network.
When the Core connects to the internet, it establishes a connection to the Spark Cloud. By
connecting to the Cloud, the Core becomes accessible from anywhere through a simple REST
API. This API is designed to make it very easy to interface with the Core through a web app or
mobile app in a secure, private way, so that only you and those you trust can access the Core.
Buttons
There are two buttons on the Core: the RESET button (when holding the Core with its USB-
port to the top, it's the button on the right) and the MODE button (on the left).
The RESET button will put the Core in a hard reset, effectively depowering and repowering
the microcontroller. This is a good way to restart the application that you've downloaded onto
the Core.
The MODE button serves three functions:
LEDs
There are two LEDs on the Core. The big fat one in the middle is a full-color RGB LED that
shows you the status of the Core's internet connection. The other small blue LED is the user
LED; it's hooked up to D7, so when you turn the D7 pin HIGH or LOW , it turns on and off,
respectively.
The RGB LED could show the following states:
The RGB LED can also let you know if there were errors in establishing an internet connection.
A red LED means an error has occurred. These errors might include:
Hold down the MODE button for three seconds to put the Core into Smart Config mode to
connect it to your local Wi-Fi network. The LED should start flashing blue.
Hold down the MODE button for ten seconds to clear the Core's memory of Wi-Fi networks.
Hold down the MODE button, tap on the RESET button and wait for three seconds to enter
Bootloader mode, where you can reprogram the Core over USB or JTAG. Release the MODE
button when you see the LED flashing yellow. If you do this by accident, simply hit RESET
button to leave Bootloader mode.
Hold down the MODE button, tap once on the RESET button and wait for ten seconds to do
a Factory Reset, where the Core is reprogrammed with the software that was installed on
the Core in the factory (the Tinker application). The LED should turn white for three
seconds and begin flashing quickly; when the LED switches to another color the Core has
been reset. This is useful if you encounter bugs with your firmware, or if you just want to
get back to Tinker.
Flashing blue: Listening mode, waiting for network information.
Solid blue: Smart Config complete, network information found.
Flashing green: Connecting to local Wi-Fi network.
Flashing cyan: Connecting to Spark Cloud.
High-speed flashing cyan: Spark Cloud handshake.
Slow breathing cyan: Successfully connected to Spark Cloud.
Flashing yellow: Bootloader mode, waiting for new code via USB or JTAG.
White pulse: Start-up, the Core was powered on or reset.
Flashing white: Factory Reset initiated.
Solid white: Factory Reset complete; rebooting.
Flashing magenta: Updating firmware.
Solid magenta: May have lost connection to the Spark Cloud. Pressing the Reset (RST)
button will attempt the update again.
Pins
The Core has 24 pins that you can connect a circuit to. These pins are:
PWM Pins
When you want to use the analogWrite() function on the Core, for instance to smoothly dim
the brightness of LEDs, you need to use pins that have a timer peripheral. People often call
these PWM pins, since what they do is called Pulse Width Modulation. The Core has 8 PWM
pins: A0, A1, A4, A5, A6, A7, D0 and D1.
Two red flashes: Connection failure due to bad internet connection. Check your network
connection.
Three red flashes: The Cloud is inaccessible, but the internet connection is fine. Check our
Twitter feed to see if there have been any reported outages; if not, visit our support page
for help.
Four red flashes: The Cloud was reached but the secure handshake failed. Visit our
support page for help.
Flashing yellow/red: Bad credentials for the Spark Cloud. Contact the Spark team
VIN: Connect an unregulated power source here with a voltage between 3.6V and 6V to
power the Core. If you're powering the Core over USB, this pin should not be used.
3V3: This pin will output a regulated 3.3V power rail that can be used to power any
components outside the Core. (Also, if you have your own 3.3V regulated power source, you
can plug it in here to power the Core).
3V3*: This is a separate low-noise regulated 3.3V power rail designed for analog circuitry
that may be susceptible to noise from the digital components. If you're using any sensitive
analog sensors, power them from 3V3* instead of from 3V3.
!RST: You can reset the Core (same as pressing the RESET button) by connecting this pin to
GND.
GND: These pins are your ground pins.
D0 to D7: These are the bread and butter of the Spark Core: 8 GPIO (General Purpose
Input/Output) pins. They're labeled "D" because they are "Digital" pins, meaning they can't
read the values of analog sensors. Some of these pins have additional peripherals (SPI,
JTAG, etc.) available, keep reading to find out more.
A0 to A7: These pins are 8 more GPIO pins, to bring the total count up to 16. These pins are
just like D0 to D7, but they are "Analog" pins, which means they can read the values of
analog sensors (technically speaking they have an ADC peripheral). As with the Digital pins,
some of these pins have additional peripherals available.
TX and RX: These pins are for communicating over Serial/UART. TX represents the
transmitting pin, and RX represents the receiving pin.
CONNECTING YOUR CORE
GETTING STARTED
CONNECTING YOUR CORE
EXAMPLES
CORE CODE (FIRMWARE)
CLOUD CODE (API)
WEB IDE (BUILD)
HARDWARE DATASHEET
SHIELDS AND KITS
TINKER
COMMAND LINE
TROUBLESHOOTING
CONNECTING YOUR CORE
Listening Mode
Smart Cong with the Spark app
Connect over USB
CLAIMING YOUR CORE
APPENDIX
DFU Mode (Device Firmware Upgrade)
Factory Reset
Smart Cong with the TI app
Coming soon: Hard-code credentials
The easiest way to connect the Spark Core to Wi-Fi is using the Spark mobile app for iPhone or
Android. But in case that's not working for you or you don't have an iOS/Android phone, there
are other methods as well.
For all of the following methods, the Spark Core must be in Listening Mode, which you'll know
by its flashing blue LED.
LISTENING MODE
The Core boots into listening mode by default, so if your Core is brand new, it should go
straight into listening mode. Otherwise, hold the MODE button for three seconds. The RGB
LED will be flashing blue in this mode. To completely clear all stored Wi-Fi credentials,
continue to hold the MODE button for 10 seconds until the RGB LED flashes blue quickly,
signaling that all profiles have been deleted. The RGB LED should now be flashing blue again.
SMART CONFIG WITH THE SPARK APP
Once you've downloaded the Spark Core app from the App Store or Google Play, you should
create an account. Afterwards, you'll be asked to connect your Core using a process called
Smart Config. If your Core has a u.FL connector, you must connect an external antenna before
initiating Smart Config. NOTE: Your phone must be connected to the Wi-Fi network that you
want to connect the Core to. Wi-Fi Hotspots generated from the phone you are running this
app on typically will yield an error claiming there is no Wi-Fi available. Please try to Connect
over USB and enter your Hotspot credentials manually. When connected to Wi-Fi, the app will
automatically fill the SSID field with the name of the network that your phone is connected to.
Enter your Wi-Fi password and hit connect.
NOTE: In places like a conference or workshop where multiple cores are connected, Smart
Config is not preferred. Claiming a Core over USB will prevent confusion with accidentally
claiming of another Core.
Smart Config can take up to a minute, so be patient. The closer your phone to your Spark
Core, the faster it will connect. Once the Core hears the signal, it will go through the following
sequence of lights:
Once the Spark Core has connected, your phone will "claim" the Core and attach it to your
account. Then you'll get to name your Core. If you're uncertain, you can confirm that the claim
process was successful by logging into the Spark Web IDE and clicking the "Cores" icon at the
bottom of the page. Is your Core listed? Great! The world is perfect.
NOTE: The Core MUST be online (breathing cyan) in order for the claiming process to work. If
the Spark Core has been claimed by someone else, the app won't recognize it. If you need to
transfer a Spark Core to another account, email us at [email protected].
Solid blue: Credentials captured
Flashing green: Connecting to Wi-Fi network
Flashing cyan: Connecting to Spark Cloud
Breathing cyan: Connected to Spark Cloud
If you are connecting multiple Cores, you'll go through this naming process for each Core.
You'll know which one is which by the rainbow signal.
Once you've finished naming your Cores, you can control them with Tinker! Try digitalWrite on
D7 to turn on the user LED.
For more information on how the seemingly magical Smart Config mode works, check out this
community thread by GHawkins
CONNECT OVER USB
You can also connect the Spark Core to your Wi-Fi network over USB by communicating
through Serial. NOTE: This only works when the Spark Core is in Listening Mode (i.e. RGB led
is blinking blue).
First, you'll need to download a serial terminal application.
For Windows users, we recommend PuTTY. You'll also need to install the Windows driver:
Windows driver for Spark Core
CoolTerm provides a nice GUI.
For Mac users, either CoolTerm or screen work.
For Linux command line usage, GNU Screen works great. (On OS X, the command line
invocation might look something like screen /dev/cu.usbmodem1411 9600 . On Ubuntu, it looks
something like screen /dev/ttyACM0 9600 . Device location may vary, poke around in the /dev
directory if you don't find it immediately)
How-to
Plug your Spark Core into your computer over USB. When the Spark Core is in Listening Mode,
open a serial port over USB using the standard settings, which should be:
Once you've opened a serial connection, you have two commands at your disposal by hitting
either w or i on the keyboard. Here's what they do:
Baudrate: 9600
Data Bits: 8
Parity: none
Stop Bits: 1
w: Set up your Wi-Fi SSID and password
i: ("i" as in identify) Read out the Spark Core ID
NOTE: If you connect your Core over USB the first time, you will also need to manually claim
your Core to connect it with your account. Please see the section below on claiming your Core
for more details.
CLAIMING YOUR CORE
Once your Core is connected, it needs to be claimed in order to be associated with your
account. This is what lets you control your Core and keeps anyone else from doing so.
If you use the mobile app to set up your Core, it should claim it automatically. However if you
connect your Core over USB, or if the claiming process is unsuccessful, you can claim it
manually.
The easiest way to manually claim a Core over USB is to use the Spark Command Line
Interface. Once you have this installed, you can simply type spark setup and follow the
instructions.
Alternatively, if you have troubles installing the command line tool, you can get the Core's ID
over serial and claim it via the build site. You can do this by opening a Serial connection to
the Core and pressing the i key (see the above instuctions for connecting over USB). It should
show you a number like this:
# Example Core ID
55ff68064989495329092587
Then open up Spark Build and click the 'Cores' icon. Click the button that says 'Add a Core',
and enter your ID in the text box.
APPENDIX
DFU MODE (DEVICE FIRMWARE UPGRADE)
If you are wish to program a Core with a custom firmware via USB, you'll need to use this
mode. This mode triggers the on-board bootloader that accepts firmware binary files via the
dfu-utility.
Procedure:
1. Hold down BOTH buttons
2. Release only the RST button, while holding down the MODE button.
3. Wait for the LED to start flashing yellow
4. Release the MODE button
The Core now is in the DFU mode.
FACTORY RESET
A factory reset restores the firmware on the Core to the default Tinker app and clears all your
Wi-Fi credentials.
Procedure:
The procedure is same as the one described above (DFU Mode), but in this case you should
continue holding down the MODE button until you see the Core change from flashing yellow
to flashing white. Then release the button. The Core should begin after the factory reset is
complete.
1. Hold down BOTH buttons
2. Release only the RST button, while holding down the MODE button.
3. Wait for the LED to start flashing yellow (continue to hold the MODE button)
4. The LED will turn solid white (continue to hold the MODE button)
5. Finally, the LED will turn blink white rapidly
6. Release the MODE button
Note: The video here is a continuation of the video from above (DFU Mode).
SMART CONFIG WITH THE TI APP
Smart Config with the Texas Instruments CC3000 app is similar to the process above,
although you don't need an account with Spark, and TI also has a Java applet that can work
from a Mac, Windows, or Linux computer.
Follow the instructions on Texas Instrument's website:
CC3000 Smart Config @ Texas Instruments
The only thing that's different is that you'll need to activate the optional AES key and type
sparkdevices2013 .
NOTE: TI's Android app is not available in Google Play; you'll have to download it off of their
website and side-load the apk yourself.
COMING SOON: HARD-CODE CREDENTIALS
Currently there is not a mechanism to hard-code your SSID and password into the firmware
for the Spark Core. We're working on it!
ANNOTATED EXAMPLES
Here you will find a bunch of examples to get you started with your new Spark Core!
BLINK AN LED
GETTING STARTED
CONNECTING YOUR CORE
EXAMPLES
CORE CODE (FIRMWARE)
CLOUD CODE (API)
WEB IDE (BUILD)
HARDWARE DATASHEET
SHIELDS AND KITS
TINKER
COMMAND LINE
TROUBLESHOOTING
ANNOTATED EXAMPLES
BLINK AN LED
CONTROL LEDS OVER THE 'NET
MEASURING THE TEMPERATURE
LOCAL COMMUNICATION
TEXTING THE CORE
AN INTERNET BUTTON
Blinking an LED is the "Hello World" example of the microcontroller world. It's a nice way to
warm up and start your journey into the land of embedded hardware.
For this example, you will need a Spark Core (duh!), a Breadboard, an LED, a Resistor (we will
soon find out a suitable value) and a USB cable.
Connect everything together as shown in the picture. The LED is connected to pin D0 of the
Core. The positive (longer pin) of the LED is connected to D0 and its negative pin (shorter) is
connected to ground via a resistor.
But wait, what's the value of the resistor again?
Here's how we find that out:
According to Ohm's Law : Voltage = Current x Resistance
Therefore, Resistance = Voltage/ Current
In our case, the output voltage of the Core is 3.3V but the LED (typically) has a forward voltage
drop of around 2.0V. So the actual voltage would be:
3.3V - 2.0V = 1.3V
The required current to light up an LED varies any where between 2mA to 20mA. More the
current, brighter the intensity. But generally its a good idea to drive the LED at a lower limit to
prolong its life span. We will choose a drive current of 5mA.
Hence, Resistance = 1.3V/ 5mA = 260 Ohms
NOTE: Since there is so much variation in the values of the forward voltage drop of the LEDs
depending upon type, size, color, manufacturer, etc., you could successfully use a resistor
value from anywhere between 220Ohms to 1K Ohms.
In the picture above, we used a 1K resistor (Brown Black Red)
Now on to the actual program:
// Program to blink an LED connected to pin D0
// of the Spark Core.
// We name pin D0 as led
int led = D0;
// This routine runs only once upon reset
void setup()
{
// Initialize D0 pin as output
pinMode(led, OUTPUT);
}
// This routine loops forever
void loop()
{
digitalWrite(led, HIGH); // Turn ON the LED
delay(1000); // Wait for 1000mS = 1 second
digitalWrite(led, LOW); // Turn OFF the LED
delay(1000); // Wait for 1 second
}
CONTROL LEDS OVER THE 'NET
Now that we know how to blink an LED, how about we control it over the Internet? This is
where the fun begins.
Lets hook up two LEDs this time.
Here is the algorithm:
// -----------------------------------
// Controlling LEDs over the Internet
// -----------------------------------
// name the pins
int led1 = D0;
int led2 = D1;
// This routine runs only once upon reset
void setup()
{
//Register our Spark function here
Spark.function("led", ledControl);
Set up the pins as outputs that have LEDs connected to them
Create and register a Spark function ( this gets called automagically when you make an API
request to it)
Parse the incoming command and take appropriate actions
// Configure the pins to be outputs
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
// Initialize both the LEDs to be OFF
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
}
// This routine loops forever
void loop()
{
// Nothing to do here
}
// This function gets called whenever there is a matching API request
// the command string format is l,
// for example: l1,HIGH or l1,LOW
// l2,HIGH or l2,LOW
int ledControl(String command)
{
int state = 0;
//find out the pin number and convert the ascii to integer
int pinNumber = (command.charAt(1) - '0') - 1;
//Sanity check to see if the pin numbers are within limits
if (pinNumber < 0 || pinNumber > 1) return -1;
// find out the state of the led
if(command.substring(3,7) == "HIGH") state = 1;
else if(command.substring(3,6) == "LOW") state = 0;
else return -1;
// write to the appropriate pin
digitalWrite(pinNumber, state);
return 1;
}
The API request will look something like this:
POST /v1/devices/{DEVICE_ID}/led
# EXAMPLE REQUEST IN TERMINAL
# Core ID is 0123456789abcdef
# Your access token is 123412341234
curl https://api.spark.io/v1/devices/0123456789abcdef/led \
-d access_token=123412341234 \
-d params=l1,HIGH
Note that the API endpoint is 'led', not 'ledControl'. This is because the endpoint is defined by
the first argument of Spark.function(), which is a string of characters, rather than the second
argument, which is a function.
To better understand the concept of making API calls to your Core over the cloud checkout the
Cloud API reference.
MEASURING THE TEMPERATURE
We have now learned how to send custom commands to the Core and control the hardware.
But how about reading data back from the Core?
In this example, we will hook up a temperature sensor to the Core and read the values over
the internet with a web browser.
We have used a widely available analog temperature sensor called TMP36 from Analog
Devices. You can download the datasheet here.
Notice how we are powering the sensor from 3.3V* pin instead of the regular 3.3V. This is
because the 3.3V* pin gives out a (LC) clean filtered voltage, ideal for analog applications like
these. If the readings you get are noisy or inconsistent, add a 0.01uF (10nF) ceramic capacitor
between the analog input pin (in this case, A7) and GND as shown in the set up. Ideally, the
sensor should be placed away from the Core so that the heat dissipated by the Core does not
affect the temperature readings.
// -----------------
// Read temperature
// -----------------
// Create a variable that will store the temperature value
int temperature = 0;
void setup()
{
// Register a Spark variable here
Spark.variable("temperature", &temperature, INT);
// Connect the temperature sensor to A7 and configure it
// to be an input
pinMode(A7, INPUT);
}void loop()
{
// Keep reading the temperature so when we make an API
// call to read its value, we have the latest one
temperature = analogRead(A7);
}
The returned value from the Core is going to be in the range from 0 to 4095. You can easily
convert this value to actual temperature reading by using the following formula:
voltage = (sensor reading x 3.3)/4095
Temperature (in Celsius) = (voltage - 0.5) X 100
The API request will look something like this:
GET /v1/devices/{DEVICE_ID}/temperature
# EXAMPLE REQUEST IN TERMINAL
# Core ID is 0123456789abcdef
# Your access token is 123412341234
curl -G https://api.spark.io/v1/devices/0123456789abcdef/temperature \
-d access_token=123412341234
LOCAL COMMUNICATION
Now let's imagine you want to control your Core locally, so you build a simple server app to
which the Core will directly connect. One puzzle to solve is that you don't know in advance the
IP address of your Core or of the laptop that will run the server. How can the Core and the
server discover each other?
In this example, we will register a Spark function to pass the server IP address to the Core.
Once we've established the local connection, we'll be able to control the Core without the data
going through the Spark Cloud.
TCPClient client;
First, we construct the client that will connect to our local server.
void ipArrayFromString(byte ipArray[], String ipString) {
int dot1 = ipString.indexOf('.');
ipArray[0] = ipString.substring(0, dot1).toInt();
int dot2 = ipString.indexOf('.', dot1 + 1);
ipArray[1] = ipString.substring(dot1 + 1, dot2).toInt();
dot1 = ipString.indexOf('.', dot2 + 1);
ipArray[2] = ipString.substring(dot2 + 1, dot1).toInt();
ipArray[3] = ipString.substring(dot1 + 1).toInt();
}
Then we need a function for translating the IP address String into the array of four bytes
needed by the TCP client.
We work our way progressively through the string, saving the positions of the dots and the
numeric substrings between them.
int connectToMyServer(String ip) {
byte serverAddress[4];
ipArrayFromString(serverAddress, ip);
if (client.connect(serverAddress, 9000)) {
return 1; // successfully connected
} else {
return -1; // failed to connect
}
}
Here's the Spark function we're going to register. Like all Spark functions it takes a String
parameter and returns an int. We allocate an array of 4 bytes for the IP address, then call
ipArrayFromString() to convert the String into an array.
After that, we simply call client.connect() with the newly received address! Super simple!
void setup() {
Spark.function("connect", connectToMyServer);
for (int pin = D0; pin
char pin = client.read() - '0' + D0;
char level = client.read();
if ('h' == level) {
digitalWrite(pin, HIGH);
} else {
digitalWrite(pin, LOW);
}
}
}
}
In loop() we first check whether the client is connected to the server. If not, we don't do
anything.
If the client is connected, then we ask whether any commands have been received over local
communication. If not, again, we don't do anything.
However, if we are connected and have received a command then we use the command to
perform a digitalWrite() .
Example server and firmware on github
TEXTING THE CORE
coming soon!
AN INTERNET BUTTON
coming soon!
GETTING STARTED
CONNECTING YOUR CORE
EXAMPLES
CORE CODE (FIRMWARE)
CLOUD CODE (API)
WEB IDE (BUILD)
HARDWARE DATASHEET
SHIELDS AND KITS
TINKER
COMMAND LINE
TROUBLESHOOTING
SPARK CORE FIRMWARE
CLOUD FUNCTIONS
Spark.variable()
Spark.function()
Spark.publish()
Spark.subscribe()
Spark.connect()
Spark.disconnect()
Spark.connected()
Spark.process()
Spark.deviceID()
Spark.sleep()
Spark.syncTime()
WIFI
WiFi.on()
WiFi.o()
WiFi.connect()
WiFi.disconnect()
WiFi.connecting()
WiFi.ready()
WiFi.listen()
WiFi.listening()
WiFi.setCredentials()
WiFi.clearCredentials()
WiFi.hasCredentials()
WiFi.macAddress()
WiFi.SSID()
WiFi.RSSI()
WiFi.ping()
WiFi.localIP()
WiFi.subnetMask()
WiFi.gatewayIP()
INPUT/OUTPUT
Setup
pinMode()
I/O
digitalWrite()
digitalRead()
analogWrite()
analogRead()
COMMUNICATION
Serial
begin()
end()
available()
peek()
write()
read()
print()
println()
ush()
SPI
begin()
end()
setBitOrder()
setClockDivider()
setDataMode()
transfer()
Wire
begin()
requestFrom()
beginTransmission()
endTransmission()
write()
available()
read()
onReceive()
onRequest()
IPAddress
IPAddress
TCPServer
TCPServer
begin()
available()
write()
print()
println()
TCPClient
TCPClient
connected()
connect()
write()
print()
println()
available()
read()
ush()
stop()
UDP
begin()
available()
beginPacket()
endPacket()
write()
parsePacket()
read()
stop()
remoteIP()
remotePort()
LIBRARIES
Servo
attach()
write()
writeMicroseconds()
read()
attached()
detach()
RGB
control(user_control)
controlled()
color(red, green, blue)
brightness(val)
Time
hour()
hourFormat12()
isAM()
isPM()
minute()
second()
day()
weekday()
month()
year()
now()
zone()
setTime()
timeStr()
OTHER FUNCTIONS
Time
millis()
micros()
delay()
delayMicroseconds()
Interrupts
attachInterrupt()
detatchInterrupt()
interrupts()
noInterrupts()
Math
min()
max()
abs()
constrain()
map()
pow()
sqrt()
EEPROM
read()
write()
ADVANCED: SYSTEM MODES
Automatic mode
Semi-automatic mode
Manual mode
LANGUAGE SYNTAX
Structure
setup()
loop()
Control structures
if
Comparison Operators
if...else
for
switch case
while
do... while
break
continue
return
goto
Further syntax
; (semicolon)
{} (curly braces)
// (single line comment)
/* */ (multi-line comment)
#dene
#include
Arithmetic operators
= (assignment operator)
+ - * / (additon subtraction multiplication division)
% (modulo)
Boolean operators
&& (and)
|| (or)
! (not)
Bitwise operators
& (bitwise and)
| (bitwise or)
^ (bitwise xor)
~ (bitwise not)
> (bitwise right shift)
Compound operators
++ (increment), -- (decrement)
compound arithmetic
&= (compound bitwise and)
|= (compound bitwise or)
String Class
String()
charAt()
compareTo()
concat()
endsWith()
equals()
equalsIgnoreCase()
getBytes()
indexOf()
lastIndexOf()
length()
replace()
reserve()
setCharAt()
startsWith()
substring()
toCharArray()
toInt()
toLowerCase()
SPARK CORE FIRMWARE
CLOUD FUNCTIONS
Spark.variable()
Expose a variable through the Spark Cloud so that it can be called with GET
/v1/devices/{DEVICE_ID}/{VARIABLE} .
// EXAMPLE USAGE
int analogvalue = 0;
double tempC = 0;
char *message = "my name is spark";
void setup()
{
// variable name max length is 12 characters long
toUpperCase()
trim()
VARIABLES
Constants
HIGH | LOW
INPUT, OUTPUT, INPUT_PULLUP, INPUT_PULLDOWN
true | false
Data Types
void
boolean
char
unsigned char
byte
int
unsigned int
word
long
unsigned long
short
oat
double
string - char array
String - object
array
Spark.variable("analogvalue", &analogvalue, INT);
Spark.variable("temp", &tempC, DOUBLE);
Spark.variable("mess", message, STRING);
pinMode(A0, INPUT);
}
void loop()
{
// Read the analog value of the sensor (TMP36)
analogvalue = analogRead(A0);
//Convert the reading into degree celcius
tempC = (((analogvalue * 3.3)/4095) - 0.5) * 100;
Delay(200);
}
Currently, up to 10 Spark variables may be defined and each variable name is limited to a
max of 12 characters.
There are three supported data types:
# EXAMPLE REQUEST IN TERMINAL
# Core ID is 0123456789abcdef
# Your access token is 123412341234
curl "https://api.spark.io/v1/devices/0123456789abcdef/analogvalue?access_token=123412341234"
curl "https://api.spark.io/v1/devices/0123456789abcdef/temp?access_token=123412341234"
curl "https://api.spark.io/v1/devices/0123456789abcdef/mess?access_token=123412341234"
# In return you'll get something like this:
960
27.44322344322344
my name is spark
Spark.function()
Expose a function through the Spark Cloud so that it can be called with POST
device/{FUNCTION} .
// SYNTAX TO REGISTER A SPARK FUNCTION
Spark.function("funcKey", funcName);
// ^
// |
INT
DOUBLE
STRING (maximum string size is 622 bytes)
// (max of 12 characters long)
Currently the application supports the creation of up to 4 different Spark functions.
In order to register a Spark function, the user provides the funcKey , which is the string name
used to make a POST request and a funcName , which is the actual name of the function that
gets called in the Spark app. The Spark function can return any integer; -1 is commonly used
for a failed function call.
The length of the funcKey is limited to a max of 12 characters.
A Spark function is set up to take one argument of the String datatype. This argument length
is limited to a max of 64 characters.
// EXAMPLE USAGE
int brewCoffee(String command);
void setup()
{
// register the Spark function
Spark.function("brew", brewCoffee);
}
void loop()
{
// this loops forever
}
// this function automagically gets called upon a matching POST request
int brewCoffee(String command)
{
// look for the matching argument "coffee"
-d access_token=123412341234 \
-d "args=coffee"
The API request will be routed to the Spark Core and will run your brew function. The
response will have a return_value key containing the integer returned by brew.
Spark.publish()
Publish an event through the Spark Cloud that will be forwarded to all registered callbacks,
subscribed streams of Server-Sent Events, and Cores listening via Spark.subscribe() .
This feature allows the Core to generate an event based on a condition. For example, you
could connect a motion sensor to the Core and have the Core generate an event whenever
motion is detected.
Spark events have the following properties:
Anyone may subscribe to public events; think of them like tweets. Only the owner of the Core
will be able to subscribe to private events.
A Core may not publish events beginning with a case-insensitive match for "spark". Such
events are reserved for officially curated data originating from the Spark Cloud.
For the time being there exists no way to access a previously published but TTL-unexpired
event.
Publish a public event with the given name, no data, and the default TTL of 60 seconds.
// SYNTAX
Spark.publish(const char *eventName);
Spark.publish(String eventName);
// EXAMPLE USAGE
Spark.publish("motion-detected");
Publish a public event with the given name and data, with the default TTL of 60 seconds.
// SYNTAX
Spark.publish(const char *eventName, const char *data);
Spark.publish(String eventName, String data);
name (163 ASCII characters)
public/private (default public)
ttl (time to live, 016777215 seconds, default 60) !! NOTE: The user-specified ttl value is not
yet implemented, so changing this property will not currently have any impact.
optional data (up to 63 bytes)
// EXAMPLE USAGE
Spark.publish("temperature", "19 F");
Publish a public event with the given name, data, and TTL.
// SYNTAX
Spark.publish(const char *eventName, const char *data, int ttl);
Spark.publish(String eventName, String data, int ttl);
// EXAMPLE USAGE
Spark.publish("lake-depth/1", "28m", 21600);
Publish a private event with the given name, data, and TTL. In order to publish a private
event, you must pass all four parameters.
// SYNTAX
Spark.publish(const char *eventName, const char *data, int ttl, PRIVATE);
Spark.publish(String eventName, String data, int ttl, PRIVATE);
// EXAMPLE USAGE
Spark.publish("front-door-unlocked", NULL, 60, PRIVATE);
COMPLEMENTARY API CALL
GET /v1/events/{EVENT_NAME}
# EXAMPLE REQUEST
curl -H "Authorization: Bearer {ACCESS_TOKEN_GOES_HERE}" \
https://api.spark.io/v1/events/motion-detected
# Will return a stream that echoes text when your event is published
event: motion-detected
data: {"data":"23:23:44","ttl":"60","published_at":"2014-05-28T19:20:34.638Z","coreid"
Spark.subscribe()
Subscribe to events published by Cores.
This allows Cores to talk to each other very easily. For example, one Core could publish events
when a motion sensor is triggered and another could subscribe to these events and respond
by sounding an alarm.
int i = 0;
void myHandler(const char *event, const char *data)
{
i++;
Serial.print(i);
Serial.print(event);
Serial.print(", data: ");
if (data)
Serial.println(data);
else
Serial.println("NULL");
}
void setup()
{
Spark.subscribe("temperature", myHandler);
Serial.begin(9600);
}
To use Spark.subscribe() , define a handler function and register it in setup() .
You can listen to events published only by your own Cores by adding a MY_DEVICES constant.
// only events from my Cores
Spark.subscribe("the_event_prefix", theHandler, MY_DEVICES);
In the near future, you'll also be able to subscribe to events from a single Core by specifying
the Core's ID.
// Subscribe to events published from one Core
// COMING SOON!
Spark.subscribe("motion/front-door", motionHandler, "55ff70064989495339432587");
A subscription works like a prefix filter. If you subscribe to "foo", you will receive any event
whose name begins with "foo", including "foo", "fool", "foobar", and "food/indian/sweet-curry-
beans".
Received events will be passed to a handler function similar to Spark.function() . A
subscription handler (like myHandler above) must return void and take two arguments, both
of which are C strings ( const char * ).
Spark.subscribe() returns a bool indicating success.
The first argument is the full name of the published event.
The second argument (which may be NULL) is any data that came along with the event.
NOTE: A Core can register up to 4 event handlers. This means you can call Spark.subscribe()
a maximum of 4 times; after that it will return false .
Spark.connect()
Spark.connect() connects the Spark Core to the Cloud. This will automatically activate the Wi-
Fi module and attempt to connect to a Wi-Fi network if the Core is not already connected to a
network.
void setup() {}
void loop() {
if (Spark.connected() == false) {
Spark.connect();
}
}
After you call Spark.connect() , your loop will not be called again until the Core finishes
connecting to the Cloud. Typically, you can expect a delay of approximately one second.
In most cases, you do not need to call Spark.connect() ; it is called automatically when the
Core turns on. Typically you only need to call Spark.connect() after disconnecting with
Spark.disconnect() or when you change the system mode.
Spark.disconnect()
Spark.disconnect() disconnects the Spark Core from the Spark Cloud.
int counter = 10000;
void doConnectedWork() {
digitalWrite(D7, HIGH);
Serial.println("Working online");
}
void doOfflineWork() {
digitalWrite(D7, LOW);
Serial.println("Working offline");
}
bool needConnection() {
--counter;
if (0 == counter)
counter = 10000;
return (2000 > counter);
}
void setup() {
pinMode(D7, OUTPUT);
Serial.begin(9600);
}
void loop() {
if (needConnection()) {
if (!Spark.connected())
Spark.connect();
doConnectedWork();
} else {
if (Spark.connected())
Spark.disconnect();
doOfflineWork();
}
}
While this function will disconnect from the Spark Cloud, it will keep the connection to the Wi-
Fi network. If you would like to completely deactivate the Wi-Fi module, use WiFi.off() .
NOTE: When the Core is disconnected, many features are not possible, including over-the-air
updates, reading Spark.variables, and calling Spark.functions.
If you disconnect from the Cloud, you will NOT BE ABLE to flash new firmware over the air. A
factory reset should resolve the issue.
Spark.connected()
Returns true when connected to the Spark Cloud, and false when disconnected from the
Spark Cloud.
// SYNTAX
Spark.connected();
RETURNS
boolean (true or false)
// EXAMPLE USAGE
void setup() {
Serial.begin(9600);
}
void loop() {
if (Spark.connected()) {
Serial.println("Connected!");
}
delay(1000);
}
Spark.process()
Spark.process() checks the Wi-Fi module for incoming messages from the Cloud, and
processes any messages that have come in. It also sends keep-alive pings to the Cloud, so if
it's not called frequently, the connection to the Cloud may be lost.
void setup() {
Serial.begin(9600);
}
void loop() {
while (1) {
Spark.process();
redundantLoop();
}
}
void redundantLoop() {
Serial.println("Well that was unnecessary.");
}
Spark.process() is a blocking call, and blocks for a few milliseconds. Spark.process() is
called automatically after every loop() and during delays. Typically you will not need to call
Spark.process() unless you block in some other way and need to maintain the connection to
the Cloud, or you change the system mode. If the user puts the Core into MANUAL mode, the
user is responsible for calling Spark.process() . The more frequently this function is called,
the more responsive the Core will be to incoming messages, the more likely the Cloud
connection will stay open, and the less likely that the CC3000's buffer will overrun.
Spark.deviceID()
Spark.deviceID() provides an easy way to extract the device ID of your Core. It returns a
String object of the device ID, which is used frequently in Sparkland to identify your Core.
// EXAMPLE USAGE
void setup()
{
// Make sure your Serial Terminal app is closed before powering your Core
Serial.begin(9600);
// Now open your Serial Terminal, and hit any key to continue!
while(!Serial.available()) Spark.process();
String myID = Spark.deviceID();
// Prints out the device ID over Serial
Serial.println(myID);
}
void loop() {}
Spark.sleep()
Spark.sleep() can be used to dramatically improve the battery life of a Spark-powered
project by temporarily deactivating the Wi-Fi module, which is by far the biggest power draw.
// SYNTAX
Spark.sleep(int seconds);
// EXAMPLE USAGE: Put the Wi-Fi module in standbly (low power) for 5 seconds
Spark.sleep(5);
// The Core LED will flash green during sleep
Spark.sleep(int seconds) does NOT stop the execution of user code (non-blocking call). User
code will continue running while the Wi-Fi module is in standby mode. During sleep,
WiFi.status() will return WIFI_OFF. Once sleep time has expired and the Wi-FI module attempts
reconnection, WiFi.status() will return value WIFI_CONNECTING and WIFI_ON.
Spark.sleep() can also be used to put the entire Core into a deep sleep mode. In this
particular mode, the Core shuts down the Wi-Fi chipset (CC3000) and puts the microcontroller
in a stand-by mode. When the Core awakens from deep sleep, it will reset the Core and run
all user code from the beginning with no values being maintained in memory from before the
deep sleep. As such, it is recommended that deep sleep be called only after all user code has
completed.
// SYNTAX
Spark.sleep(SLEEP_MODE_DEEP, int seconds);
// EXAMPLE USAGE: Put the Core into deep sleep for 60 seconds
Spark.sleep(SLEEP_MODE_DEEP,60);
// The Core LED will shut off during deep sleep
The Core will automatically wake up and reestablish the WiFi connection after the specified
number of seconds.
In standard sleep mode, the Core current consumption is in the range of: 30mA to 38mA
In deep sleep mode, the Core current consumption is around: 3.2 A
Spark.syncTime()
Synchronize the time with the Spark Cloud. This happens automatically when the Core
connects to the Cloud. However, if your Core runs continuously for a long time, you may want
to synchronize once per day or so.
#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
unsigned long lastSync = millis();
void loop() {
if (millis() - lastSync > ONE_DAY_MILLIS) {
// Request time synchronization from the Spark Cloud
Spark.syncTime();
lastSync = millis();
}
}
WIFI
WiFi.on()
WiFi.on() turns on the Wi-Fi module. Useful when you've turned it off, and you changed your
mind.
Note that WiFi.on() does not need to be called unless you have changed the system mode or
you have previously turned the Wi-Fi module off.
WiFi.off()
WiFi.off() turns off the Wi-Fi module. Useful for saving power, since most of the power draw
of the Spark Core is the Wi-Fi module.
WiFi.connect()
Attempts to connect to the Wi-Fi network. If there are no credentials stored, this will enter
listening mode. If there are credentials stored, this will try the available credentials until
connection is successful. When this function returns, the device may not have an IP address
on the LAN; use WiFi.ready() to determine the connection status.
WiFi.disconnect()
Disconnects from the Wi-Fi network, but leaves the Wi-Fi module on.
WiFi.connecting()
This function will return true once the Core is attempting to connect using stored Wi-Fi
credentials, and will return false once the Core has successfully connected to the Wi-Fi
network.
WiFi.ready()
This function will return true once the Core is connected to the network and has been
assigned an IP address, which means that it's ready to open TCP sockets and send UDP
datagrams. Otherwise it will return false .
WiFi.listen()
This will enter listening mode, which opens a Serial connection to get Wi-Fi credentials over
USB, and also listens for credentials over Smart Config.
WiFi.listening()
This will return true once WiFi.listen() has been called and will return false once the
Core has been given some Wi-Fi credentials to try, either over USB or Smart Config.
WiFi.setCredentials()
Allows the user to set credentials for the Wi-Fi network from within the code. These
credentials will be added to the CC3000's memory, and the Core will automatically attempt to
connect to this network in the future.
// Connects to an unsecured network.
WiFi.setCredentials(SSID);
WiFi.setCredentials("My_Router_Is_Big");
// Connects to a network secured with WPA2 credentials.
WiFi.setCredentials(SSID, PASSWORD);
WiFi.setCredentials("My_Router", "mypasswordishuge");
// Connects to a network with a specified authentication procedure.
// Options are WPA2, WPA, or WEP.
WiFi.setCredentials(SSID, PASSWORD, AUTH);
WiFi.setCredentials("My_Router", "wepistheworst", WEP);
WiFi.clearCredentials()
This will clear all saved credentials from the CC3000's memory. This will return true on
success and false if the CC3000 has an error.
WiFi.hasCredentials()
Will return true if there are Wi-Fi credentials stored in the CC3000's memory.
WiFi.macAddress()
WiFi.macAddress() returns the MAC address of the device.
byte mac[6];
void setup() {
Serial.begin(9600);
while (!Serial.available()) Spark.process();
Serial.print(mac[5],HEX);
Serial.print(":");
Serial.print(mac[4],HEX);
Serial.print(":");
Serial.print(mac[3],HEX);
Serial.print(":");
Serial.print(mac[2],HEX);
Serial.print(":");
Serial.print(mac[1],HEX);
Serial.print(":");
Serial.println(mac[0],HEX);
}
void loop() {}
WiFi.SSID()
WiFi.SSID() returns the SSID of the network the Core is currently connected to as a char* .
WiFi.RSSI()
WiFi.RSSI() returns the signal strength of a Wifi network from from -127 to -1dB as an int .
WiFi.ping()
WiFi.ping() allows you to ping an IP address and returns the number of packets received as
an int . It takes two forms:
WiFi.ping(IPAddress remoteIP) takes an IPAddress and pings that address.
WiFi.ping(IPAddress remoteIP, uint8_t nTries) and pings that address a specified number
of times.
WiFi.localIP()
WiFi.localIP() returns the local IP address assigned to the Core as an IPAddress .
void setup() {
Serial.begin(9600);
while(!Serial.available()) Spark.process();
// Prints out the local IP over Serial.
Serial.println(WiFi.localIP());
}
WiFi.subnetMask()
WiFi.subnetMask() returns the subnet mask of the network as an IPAddress .
void setup() {
Serial.begin(9600);
while(!Serial.available()) Spark.process();
// Prints out the subnet mask over Serial.
Serial.println(WiFi.subnetMask());
}
WiFi.gatewayIP()
WiFi.gatewayIP() returns the gateway IP address of the network as an IPAddress .
void setup() {
Serial.begin(9600);
while(!Serial.available()) Spark.process();
// Prints out the gateway IP over Serial.
Serial.println(WiFi.gatewayIP());
}
INPUT/OUTPUT
SETUP
pinMode()
pinMode() configures the specified pin to behave either as an input (with or without an
internal weak pull-up or pull-down resistor), or an output.
// SYNTAX
pinMode(pin,mode);
pinMode() takes two arguments, pin : the number of the pin whose mode you wish to set and
mode : INPUT, INPUT_PULLUP, INPUT_PULLDOWN or OUTPUT.
pinMode() does not return anything.
// EXAMPLE USAGE
int button = D0; // button is connected to D0
int LED = D1; // LED is connected to D1
void setup()
{
pinMode(LED, OUTPUT); // sets pin as output
pinMode(button, INPUT_PULLDOWN); // sets pin as input
}
void loop()
{
// blink the LED as long as the button is pressed
while(digitalRead(button) == HIGH) {
digitalWrite(LED, HIGH); // sets the LED on
delay(200); // waits for 200mS
digitalWrite(LED, LOW); // sets the LED off
delay(200); // waits for 200mS
}
}
I/O
digitalWrite()
Write a HIGH or a LOW value to a digital pin.
// SYNTAX
digitalWrite(pin, value);
If the pin has been configured as an OUTPUT with pinMode(), its voltage will be set to the
corresponding value: 3.3V for HIGH, 0V (ground) for LOW.
digitalWrite() takes two arguments, pin : the number of the pin whose value you wish to set
and value : HIGH or LOW .
digitalWrite() does not return anything.
// EXAMPLE USAGE
int LED = D1; // LED connected to D1
void setup()
{
pinMode(LED, OUTPUT); // sets pin as output
}
void loop()
{
digitalWrite(LED, HIGH); // sets the LED on
delay(200); // waits for 200mS
digitalWrite(LED, LOW); // sets the LED off
delay(200); // waits for 200mS
}
digitalRead()
Reads the value from a specified digital pin , either HIGH or LOW .
// SYNTAX
digitalRead(pin);
digitalRead() takes one argument, pin : the number of the digital pin you want to read.
digitalRead() returns HIGH or LOW .
// EXAMPLE USAGE
int button = D0; // button is connected to D0
int LED = D1; // LED is connected to D1
int val = 0; // variable to store the read value
void setup()
{
pinMode(LED, OUTPUT); // sets pin as output
pinMode(button, INPUT_PULLDOWN); // sets pin as input
}
void loop()
{
val = digitalRead(button); // read the input pin
digitalWrite(LED, val); // sets the LED to the button's value
}
analogWrite()
Writes an analog value (PWM wave) to a pin. Can be used to light a LED at varying
brightnesses or drive a motor at various speeds. After a call to analogWrite(), the pin will
generate a steady square wave of the specified duty cycle until the next call to analogWrite()
(or a call to digitalRead() or digitalWrite() on the same pin). The frequency of the PWM signal is
approximately 500 Hz.
On the Spark Core, this function works on pins A0, A1, A4, A5, A6, A7, D0 and D1.
The analogWrite function has nothing to do with the analog pins or the analogRead function.
// SYNTAX
analogWrite(pin, value);
analogWrite() takes two arguments, pin : the number of the pin whose value you wish to set
and value : the duty cycle: between 0 (always off) and 255 (always on).
analogWrite() does not return anything.
// EXAMPLE USAGE
int ledPin = D1; // LED connected to digital pin D1
int analogPin = A0; // potentiometer connected to analog pin A0
int val = 0; // variable to store the read value
void setup()
{
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop()
{
val = analogRead(analogPin); // read the input pin
analogWrite(ledPin, val/16); // analogRead values go from 0 to 4095,
// analogWrite values from 0 to 255.
delay(10);
}
analogRead()
Reads the value from the specified analog pin. The Spark Core has 8 channels (A0 to A7) with
a 12-bit resolution. This means that it will map input voltages between 0 and 3.3 volts into
integer values between 0 and 4095. This yields a resolution between readings of: 3.3 volts /
4096 units or, 0.0008 volts (0.8 mV) per unit.
// SYNTAX
analogRead(pin);
analogRead() takes one argument pin : the number of the analog input pin to read from ('A0
to A7'.)
analogRead() returns an integer value ranging from 0 to 4095.
// EXAMPLE USAGE
int ledPin = D1; // LED connected to digital pin D1
int analogPin = A0; // potentiometer connected to analog pin A0
int val = 0; // variable to store the read value
void setup()
{
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop()
{
val = analogRead(analogPin); // read the input pin
analogWrite(ledPin, val/16); // analogRead values go from 0 to 4095, analogWrite values from 0 to 255
delay(10);
}
COMMUNICATION
SERIAL
Used for communication between the Spark Core and a computer or other devices. The Core
has two serial channels:
Serial: This channel communicates through the USB port and when connected to a
computer, will show up as a virtual COM port.
Serial1: This channel is available via the Core's TX and RX pins.
Serial2: This channel is optionally available via the Core's D1(TX) and D0(RX) pins. To use
Serial2, add #include "Serial2.h" near the top of your Spark App's main code file.
To use the TX/RX (Serial1) or D1/D0 (Serial2) pins to communicate with your personal
computer, you will need an additional USB-to-serial adapter. To use them to communicate
with an external TTL serial device, connect the TX pin to your device's RX pin, the RX to your
device's TX pin, and the ground of your Core to your device's ground.
NOTE: Please take into account that the voltage levels on these pins runs at 0V to 3.3V and
should not be connected directly to a computer's RS232 serial port which operates at +/- 12V
and can damage the Core.
begin()
Sets the data rate in bits per second (baud) for serial data transmission. For communicating
with the computer, use one of these rates: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200,
28800, 38400, 57600, or 115200. You can, however, specify other rates - for example, to
communicate over pins TX and RX with a component that requires a particular baud rate.
// SYNTAX
Serial.begin(speed); // serial via USB port
Serial1.begin(speed); // serial via TX and RX pins
Serial2.begin(speed); // serial via D1(TX) and D0(RX) pins
speed : parameter that specifies the baud rate (long)
begin() does not return anything
// EXAMPLE USAGE
void setup()
{
Serial.begin(9600); // open serial over USB
// On Windows it will be necessary to implement the following line:
// Make sure your Serial Terminal app is closed before powering your Core
// Now open your Serial Terminal, and hit any key to continue!
while(!Serial.available()) SPARK_WLAN_Loop();
Serial1.begin(9600); // open serial over TX and RX pins
Serial.println("Hello Computer");
Serial1.println("Hello Serial 1");
}
void loop() {}
end()
Disables serial communication, allowing the RX and TX pins to be used for general input and
output. To re-enable serial communication, call Serial1.begin() .
// SYNTAX
Serial1.end();
available()
Get the number of bytes (characters) available for reading from the serial port. This is data
that's already arrived and stored in the serial receive buffer (which holds 64 bytes).
// EXAMPLE USAGE
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
}
void loop()
{
// read from port 0, send to port 1:
if (Serial.available())
{
int inByte = Serial.read();
Serial1.write(inByte);
}
// read from port 1, send to port 0:
if (Serial1.available())
{
int inByte = Serial1.read();
Serial.write(inByte);
}
}
peek()
Returns the next byte (character) of incoming serial data without removing it from the
internal serial buffer. That is, successive calls to peek() will return the same character, as will
the next call to read() .
// SYNTAX
Serial.peek();
Serial1.peek();
peek() returns the first byte of incoming serial data available (or -1 if no data is available) -
int
write()
Writes binary data to the serial port. This data is sent as a byte or series of bytes; to send the
characters representing the digits of a number use the print() function instead.
// SYNTAX
Serial.write(val);
Serial.write(str);
Serial.write(buf, len);
Parameters:
write() will return the number of bytes written, though reading that number is optional.
// EXAMPLE USAGE
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.write(45); // send a byte with the value 45
int bytesSent = Serial.write(OhelloP); //send the string OhelloP and return the length of the string.
}
val : a value to send as a single byte
str : a string to send as a series of bytes
buf : an array to send as a series of bytes
len : the length of the buffer
read()
Reads incoming serial data.
// SYNTAX
Serial.read();
Serial1.read();
read() returns the first byte of incoming serial data available (or -1 if no data is available) -
int
// EXAMPLE USAGE
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
print()
Prints data to the serial port as human-readable ASCII text. This command can take many
forms. Numbers are printed using an ASCII character for each digit. Floats are similarly
printed as ASCII digits, defaulting to two decimal places. Bytes are sent as a single character.
Characters and strings are sent as is. For example:
An optional second parameter specifies the base (format) to use; permitted values are BIN
(binary, or base 2), OCT (octal, or base 8), DEC (decimal, or base 10), HEX (hexadecimal, or base
16). For floating point numbers, this parameter specifies the number of decimal places to use.
Serial.print(78) gives "78"
Serial.print(1.23456) gives "1.23"
Serial.print('N') gives "N"
Serial.print("Hello world.") gives "Hello world."
For example:
println()
Prints data to the serial port as human-readable ASCII text followed by a carriage return
character (ASCII 13, or '\r') and a newline character (ASCII 10, or '\n'). This command takes the
same forms as Serial.print() .
// SYNTAX
Serial.println(val);
Serial.println(val, format);
Parameters:
println() returns the number of bytes written, though reading that number is optional -
size_t (long)
EXAMPLE
//reads an analog input on analog in A0, prints the value out.
int analogValue = 0; // variable to hold the analog value
void setup()
{
// Make sure your Serial Terminal app is closed before powering your Core
Serial.begin(9600);
// Now open your Serial Terminal, and hit any key to continue!
while(!Serial.available()) SPARK_WLAN_Loop();
}
void loop() {
// read the analog input on pin A0:
analogValue = analogRead(A0);
Serial.print(78, BIN) gives "1001110"
Serial.print(78, OCT) gives "116"
Serial.print(78, DEC) gives "78"
Serial.print(78, HEX) gives "4E"
Serial.println(1.23456, 0) gives "1"
Serial.println(1.23456, 2) gives "1.23"
Serial.println(1.23456, 4) gives "1.2346"
val : the value to print - any data type
format : specifies the number base (for integral data types) or number of decimal places
(for floating point types)
// print it out in many formats:
Serial.println(analogValue); // print as an ASCII-encoded decimal
Serial.println(analogValue, DEC); // print as an ASCII-encoded decimal
Serial.println(analogValue, HEX); // print as an ASCII-encoded hexadecimal
Serial.println(analogValue, OCT); // print as an ASCII-encoded octal
Serial.println(analogValue, BIN); // print as an ASCII-encoded binary
// delay 10 milliseconds before the next reading:
delay(10);
}
flush()
Waits for the transmission of outgoing serial data to complete.
// SYNTAX
Serial.flush();
Serial1.flush();
flush() neither takes a parameter nor returns anything
SPI
This library allows you to communicate with SPI devices, with the Spark Core as the master
device.
begin()
Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low, and
SS high.
Note that once the pin is configured, you can't use it anymore as a general I/O, unless you call
the SPI.end() method on the same pin.
// SYNTAX
SPI.begin();
end()
Disables the SPI bus (leaving pin modes unchanged).
// SYNTAX
SPI.end();
setBitOrder()
Sets the order of the bits shifted out of and into the SPI bus, either LSBFIRST (least-significant
bit first) or MSBFIRST (most-significant bit first).
// SYNTAX
SPI.setBitOrder(order);
Where, the parameter order can either be LSBFIRST or MSBFIRST .
setClockDivider()
Sets the SPI clock divider relative to the system clock. The available dividers are 2, 4, 8, 16, 32,
64, 128 or 256. The default setting is SPI_CLOCK_DIV4, which sets the SPI clock to one-quarter
the frequency of the system clock.
// SYNTAX
SPI.setClockDivider(divider) ;
Where the parameter, divider can be:
setDataMode()
Sets the SPI data mode: that is, clock polarity and phase. See the Wikipedia article on SPI for
details.
// SYNTAX
SPI.setDataMode(mode) ;
Where the parameter, mode can be:
SPI_CLOCK_DIV2
SPI_CLOCK_DIV4
SPI_CLOCK_DIV8
SPI_CLOCK_DIV16
SPI_CLOCK_DIV32
SPI_CLOCK_DIV64
SPI_CLOCK_DIV128
SPI_CLOCK_DIV256
SPI_MODE0
SPI_MODE1
SPI_MODE2
SPI_MODE3
transfer()
Transfers one byte over the SPI bus, both sending and receiving.
// SYNTAX
SPI.transfer(val);
Where the parameter val , can is the byte to send out over the SPI bus.
WIRE
This library allows you to communicate with I2C / TWI devices. On the Spark Core, D0 is the
Serial Data Line (SDA) and D1 is the Serial Clock (SCL). Both of these pins runs at 3.3V logic but
are tolerant to 5V.
begin()
Initiate the Wire library and join the I2C bus as a master or slave. This should normally be
called only once.
// SYNTAX
Wire.begin();
Wire.begin(address);
Parameters: address : the 7-bit slave address (optional); if not specified, join the bus as a
master.
requestFrom()
Used by the master to request bytes from a slave device. The bytes may then be retrieved
with the available() and read() functions.
If true, requestFrom() sends a stop message after the request, releasing the I2C bus.
If false, requestFrom() sends a restart message after the request. The bus will not be
released, which prevents another master device from requesting between messages. This
allows one master device to send multiple requests while in control.
The default value is true.
// SYNTAX
Wire.requestFrom(address, quantity);
Wire.requestFrom(address, quantity, stop) ;
Parameters:
Returns: byte : the number of bytes returned from the slave device.
beginTransmission()
Begin a transmission to the I2C slave device with the given address. Subsequently, queue
bytes for transmission with the write() function and transmit them by calling
endTransmission() .
// SYNTAX
Wire.beginTransmission(address);
Parameters: address : the 7-bit address of the device to transmit to.
address : the 7-bit address of the device to request bytes from
quantity : the number of bytes to request
stop : boolean. true will send a stop message after the request, releasing the bus. false
will continually send a restart after the request, keeping the connection active.
endTransmission()
Ends a transmission to a slave device that was begun by beginTransmission() and transmits
the bytes that were queued by write() .
If true, endTransmission() sends a stop message after transmission, releasing the I2C bus.
If false, endTransmission() sends a restart message after transmission. The bus will not be
released, which prevents another master device from transmitting between messages. This
allows one master device to send multiple transmissions while in control.
The default value is true.
Wire.endTransmission();
Wire.endTransmission(stop);
Parameters: stop : boolean. true will send a stop message, releasing the bus after
transmission. false will send a restart, keeping the connection active.
Returns: byte , which indicates the status of the transmission:
write()
Writes data from a slave device in response to a request from a master, or queues bytes for
transmission from a master to slave device (in-between calls to beginTransmission() and
endTransmission() ).
// Syntax
Wire.write(value);
Wire.write(string);
Wire.write(data, length);
Parameters:
Returns: byte
0: success
1: data too long to fit in transmit buffer
2: received NACK on transmit of address
3: received NACK on transmit of data
4: other error
value : a value to send as a single byte
string : a string to send as a series of bytes
data : an array of data to send as bytes
length : the number of bytes to transmit
write() will return the number of bytes written, though reading that number is optional.
// EXAMPLE USAGE
byte val = 0;
void setup()
{
Wire.begin(); // join i2c bus
}
void loop()
{
Wire.beginTransmission(44); // transmit to device #44 (0x2c)
// device address is specified in datasheet
Wire.write(val); // sends value byte
Wire.endTransmission(); // stop transmitting
val++; // increment value
if(val == 64) // if reached 64th position (max)
{
val = 0; // start over from lowest value
}
delay(500);
}
available()
Returns the number of bytes available for retrieval with read() . This should be called on a
master device after a call to requestFrom() or on a slave inside the onReceive() handler.
Wire.available();
Returns: The number of bytes available for reading.
read()
Reads a byte that was transmitted from a slave device to a master after a call to
requestFrom() or was transmitted from a master to a slave. read() inherits from the Stream
utility class.
Wire.read() ;
Returns: The next byte received
// EXAMPLE USAGE
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop()
{
Wire.requestFrom(2, 6); // request 6 bytes from slave device #2
while(Wire.available()) // slave may send less than requested
{
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
onReceive()
Registers a function to be called when a slave device receives a transmission from a master.
Parameters: handler : the function to be called when the slave receives data; this should take
a single int parameter (the number of bytes read from the master) and return nothing, e.g.:
void myHandler(int numBytes)
onRequest()
Register a function to be called when a master requests data from this slave device.
Parameters: handler : the function to be called, takes no parameters and returns nothing, e.g.:
void myHandler()
IPADDRESS
IPAddress
Creates an IP address that can be used with TCPServer, TCPClient, UPD, and Network objects.
// EXAMPLE USAGE
IPAddress localIP;
IPAddress server(8,8,8,8);
IPAddress IPfromInt( 167772162UL ); // 10.0.0.2 as 10*256^3+0*256^2+0*256+2
uint8_t server[] = { 10, 0, 0, 2};
IPAddress IPfromBytes( server );
The IPAddress also allows for comparisons.
if (IPfromInt == IPfromBytes)
{
Serial.println("Same IP addresses");
}
You can also use indexing the get or change individual bytes in the IP address.
// PING ALL HOSTS ON YOUR SUBNET EXCEPT YOURSELF
IPAddress localIP = Network.localIP();
uint8_t myLastAddrByte = localIP[3];
for(uint8_t ipRange=1; ipRange
TCPServer
Create a server that listens for incoming connections on the specified port.
// SYNTAX
TCPServer server = TCPServer(port);
Parameters: port : the port to listen on ( int )
// EXAMPLE USAGE
// telnet defaults to port 23
TCPServer server = TCPServer(23);
TCPClient client;
void setup()
{
// start listening for clients
server.begin();
// Make sure your Serial Terminal app is closed before powering your Core
Serial.begin(9600);
// Now open your Serial Terminal, and hit any key to continue!
while(!Serial.available()) SPARK_WLAN_Loop();
Serial.println(Network.localIP());
Serial.println(Network.subnetMask());
Serial.println(Network.gatewayIP());
Serial.println(Network.SSID());
}
void loop()
{
if (client.connected()) {
// echo all available bytes back to the client
while (client.available()) {
server.write(client.read());
}
} else {
// if no client is yet connected, check for a new connection
client = server.available();
}
}
begin()
Tells the server to begin listening for incoming connections.
// SYNTAX
server.begin();
available()
Gets a client that is connected to the server and has data available for reading. The
connection persists when the returned client object goes out of scope; you can close it by
calling client.stop() .
available() inherits from the Stream utility class.
write()
Write data to all the clients connected to a server. This data is sent as a byte or series of
bytes.
// Syntax
server.write(val);
server.write(buf, len);
Parameters:
Returns: byte : write() returns the number of bytes written. It is not necessary to read this.
print()
Print data to all the clients connected to a server. Prints numbers as a sequence of digits,
each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3').
// Syntax
server.print(data);
server.print(data, BASE) ;
Parameters:
val : a value to send as a single byte (byte or char)
buf : an array to send as a series of bytes (byte or char)
len : the length of the buffer
data : the data to print (char, byte, int, long, or string)
BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for
Returns: byte : print() will return the number of bytes written, though reading that number
is optional
println()
Print data, followed by a newline, to all the clients connected to a server. Prints numbers as a
sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three
characters '1', '2', '3').
// Syntax
server.println();
server.println(data);
server.println(data, BASE) ;
Parameters:
TCPCLIENT
TCPClient
Creates a client which can connect to a specified internet IP address and port (defined in the
client.connect() function).
// SYNTAX
TCPClient client;
// EXAMPLE USAGE
TCPClient client;
byte server[] = { 74, 125, 224, 72 }; // Google
void setup()
{
// Make sure your Serial Terminal app is closed before powering your Core
Serial.begin(9600);
// Now open your Serial Terminal, and hit any key to continue!
while(!Serial.available()) SPARK_WLAN_Loop();
decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16).
data (optional): the data to print (char, byte, int, long, or string)
BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for
decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16).
Serial.println("connecting...");
if (client.connect(server, 80))
{
Serial.println("connected");
client.println("GET /search?q=unicorn HTTP/1.0");
client.println("Host: www.google.com");
client.println("Content-Length: 0");
client.println();
}
else
{
Serial.println("connection failed");
}
}
void loop()
{
if (client.available())
{
char c = client.read();
Serial.print(c);
}
if (!client.connected())
{
Serial.println();
Serial.println("disconnecting.");
client.stop();
for(;;);
}
}
connected()
Whether or not the client is connected. Note that a client is considered connected if the
connection has been closed but there is still unread data.
// SYNTAX
client.connected();
Returns true if the client is connected, false if not.
connect()
Connects to a specified IP address and port. The return value indicates success or failure.
Also supports DNS lookups when using a domain name.
// SYNTAX
client.connect();
client.connect(ip, port);
client.connect(URL, port);
Parameters:
Returns true if the connection succeeds, false if not.
write()
Write data to the server the client is connected to. This data is sent as a byte or series of
bytes.
// SYNTAX
client.write(val);
client.write(buf, len);
Parameters:
Returns: byte : write() returns the number of bytes written. It is not necessary to read this
value.
print()
Print data to the server that a client is connected to. Prints numbers as a sequence of digits,
each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3').
// Syntax
client.print(data);
client.print(data, BASE) ;
ip : the IP address that the client will connect to (array of 4 bytes)
URL : the domain name the client will connect to (string, ex.:"spark.io")
port : the port that the client will connect to ( int )
val : a value to send as a single byte (byte or char)
buf : an array to send as a series of bytes (byte or char)
len : the length of the buffer
Parameters:
Returns: byte : print() will return the number of bytes written, though reading that number
is optional
println()
Print data, followed by a carriage return and newline, to the server a client is connected to.
Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent
as the three characters '1', '2', '3').
// Syntax
client.println();
client.println(data);
client.println(data, BASE) ;
Parameters:
available()
Returns the number of bytes available for reading (that is, the amount of data that has been
written to the client by the server it is connected to).
// SYNTAX
client.available();
Returns the number of bytes available.
read()
Read the next byte received from the server the client is connected to (after the last call to
read() ).
// SYNTAX
client.read();
data : the data to print (char, byte, int, long, or string)
BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for
decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16).
data (optional): the data to print (char, byte, int, long, or string)
BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for
decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16).
Returns the next byte (or character), or -1 if none is available.
flush()
Discard any bytes that have been written to the client but not yet read.
// SYNTAX
client.flush();
stop()
Disconnect from the server.
// SYNTAX
client.stop();
UDP
This class enables UDP messages to be sent and received.
The UDP protocol implementation has known issues that will require extra consideration
when programming with it. Please refer to the Known Issues category of the Community for
details. The are also numerous working examples and workarounds in the searchable
Community topics.
begin()
Initializes the UDP library and network settings.
// EXAMPLE USAGE
// UDP Port used for two way communication
unsigned int localPort = 8888;
// An UDP instance to let us send and receive packets over UDP
UDP Udp;
void setup() {
// start the UDP
Udp.begin(localPort);
// Print your device IP Address via serial
Serial.begin(9600);
Serial.println(Network.localIP());
}
void loop() {
// Check if data has been received
if (Udp.parsePacket() > 0) {
// Read first char of data received
char c = Udp.read();
// Ignore other chars
Udp.flush();
// Store sender ip and port
IPAddress ipAddress = Udp.remoteIP();
int port = Udp.remotePort();
// Echo back data to sender
Udp.beginPacket(ipAddress, port);
Udp.write(c);
Udp.endPacket();
}
}
available()
Get the number of bytes (characters) available for reading from the buffer. This is data that's
already arrived.
This function can only be successfully called after UDP.parsePacket() .
available() inherits from the Stream utility class.
// SYNTAX
UDP.available()
Returns the number of bytes available to read.
beginPacket()
Starts a connection to write UDP data to the remote connection.
// SYNTAX
UDP.beginPacket(remoteIP, remotePort);
Parameters:
It returns nothing.
endPacket()
Called after writing UDP data to the remote connection.
// SYNTAX
UDP.endPacket();
Parameters: NONE
write()
Writes UDP data to the remote connection. Must be wrapped between beginPacket() and
endPacket() . beginPacket() initializes the packet of data, it is not sent until endPacket() is
called.