# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/109/585/medium800thumb/sensors_Kapture_2022-03-09_at_12.56.24.jpg?1646848661)

You've set up an internet-enabled development board with [Adafruit IO Wippersnapper](https://learn.adafruit.com/quickstart-adafruit-io-wippersnapper). _But,_ after glancing at the component picker, you don't see the component you need for your IoT project. Let's get your favorite input, output, or sensor added to Adafruit IO WipperSnapper so it can be used by projects designed by you and others!

The process for adding components _varies with difficulty depending on what type of component you're adding:_

- If you're adding a "pin component", such as a digital output (i.e.: an LED), analog input (i.e.: potentiometer or light sensor), or digital input (i.e.: push-button or PIR sensor) - **adding a new component is easy**. It involves writing a small amount of descriptive JSON and adding an image!
- If you're adding an "I2C sensor component" - **adding a new I2C sensor component is a little bit trickier.** The process involves writing a small amount of JSON, adding an image, setting up a build environment for WipperSnapper, and writing/modifying C++ code.&nbsp;

## How Components Work in Adafruit IO

Adding a new component to WipperSnapper means your component will show up in this list on Adafruit IO, for everyone using the platform:

![](https://cdn-learn.adafruit.com/assets/assets/000/109/582/medium800/sensors_144505905-1d1a34e0-df2b-4ee2-9dd2-309e389d14d5.png?1646848280)

It will also automatically generate a web-form like this:

![](https://cdn-learn.adafruit.com/assets/assets/000/109/583/medium800/sensors_144505968-e5a1385a-f73e-4948-8380-fee40945a38f.png?1646848291)

The sensor or component will have its current state either monitored or controlled by the device.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/584/medium800/sensors_144506091-971ef397-63d2-4477-9ea8-b645896af07f.png?1646848304)

Once created, a WipperSnapper component can work seamlessly with the rest of Adafruit IO's features including Historical Feeds, Dashboards, and Actions!

# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## Get Set Up

This guide assumes you already have a&nbsp;[GitHub account](https://github.com/) and have installed Git.

- If you are unfamiliar with GitHub and Git or would like to refresh before starting,&nbsp;[we have a great guide on using the features of GitHub here \>\>\>.](https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github/overview)

## Fork the WipperSnapper\_Components Repository

We'll start by creating a fork of the WipperSnapper Components repository on your account. Sign in to your GitHub account and navigate to the [WipperSnapper\_Components](https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github/grab-your-fork) repository.

Click the "Fork" button on the upper-right-hand corner of the website.

![](https://cdn-learn.adafruit.com/assets/assets/000/108/643/medium800/sensors_adafruit_Wippersnapper_Components__Component_Description_Models_for_Adafruit_IO_Wippersnapper_Beta_.png?1644009173)

Your fork should take a few seconds to complete, once done, let's move on to adding the component type you want.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/078/medium800/sensors_forking.png?1645212541)

# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## Adding a Pin Component

In WipperSnapper terminology, pin components are digital outputs (i.e.: an LED, a motor), analog inputs (i.e.: a potentiometer or a light sensor), or digital inputs (i.e.: a push-button or a PIR sensor).&nbsp;

Adding a "pin component" to WipperSnapper involves writing a small amount of descriptive JSON and adding an image.&nbsp;

## Identifying the Type of Pin Component to Use
This guide page uses the [Flat Vibration Switch sold in the Adafruit store](https://www.adafruit.com/product/4081) as an example of a pin component that can be added to WipperSnapper. You will need to modify the instructions to fit the needs/specifications of your component.

### Flat Vibration Switch - Breadboard friendly

[Flat Vibration Switch - Breadboard friendly](https://www.adafruit.com/product/4081)
This is a **low sensitivity** , **directional** vibration-induced trigger switch. Inside is a very soft spring coiled around a long metal pin. When the switch is bumped _from the side only_, the spring attached to the first pin touches the center pole to make...

In Stock
[Buy Now](https://www.adafruit.com/product/4081)
[Related Guides to the Product](https://learn.adafruit.com/products/4081/guides)
![Flat Vibration Switch with Breadboard friendly pins](https://cdn-shop.adafruit.com/640x480/4081-00.jpg)

The first step is to identify _what type of pin component_ this switch is.

When the vibration switch gets bumped, it acts as a closed switch. In order to get the state of the switch, a microcontroller needs to configure the switch as a digital input as it only reports two states: when the switch is either open ('0') or closed ('1').

So, we'll be creating _a digital&nbsp;input pin component_ as we'll want the vibration switch to send data to WipperSnapper when it reports a boolean state (open or closed).

## Add Component JSON

This page assumes you've followed [the instructions on the Get Setup page and have the WipperSnapper\_Components repository forked and locally cloned](https://learn.adafruit.com/how-to-add-a-new-component-to-adafruit-io-wippersnapper/get-setup).

First, create a Git branch to work within. In this case, name it `add-flat-vibration-switch`.

![](https://cdn-learn.adafruit.com/assets/assets/000/108/778/medium800/sensors_flatvibbranch.png?1644270089)

Next, navigate to the **Wippersnapper\_Components/components/pin** directory and make a copy of a component with similar functionality. The toggle switch component and the vibration switch both operate the same way and send the same values if they're toggled.

Create a copy of the **toggle\_switch** folder.

![](https://cdn-learn.adafruit.com/assets/assets/000/108/781/medium800/sensors_dup-toggle-switch.png?1644270370)

Component folder names should use underscores and the name should be lower case (i.e: `my_component`).

Rename the **toggle\_switch copy** folder to **flat\_vibration\_switch**.

![](https://cdn-learn.adafruit.com/assets/assets/000/108/782/medium800/sensors_flat_vibration_switch_folder.png?1644270574)

## Modify Component Definition JSON File

The **definition.json** file within this folder is known as the definition file, it defines the pin-based WipperSnapper component for use in Adafruit IO.&nbsp;

Using a text editor, open the toggle switch's **definition.json** file.

https://github.com/adafruit/Wippersnapper_Components/blob/main/components/pin/toggle_switch/definition.json

JSON files are written as pairs of keys and values, separated by a semicolon.

The first key/value pair in the JSON definition is the `displayName`, which is the human-friendly name of a component. This field is&nbsp; **required**.

We'll start by changing the `displayName` from "Toggle Switch" to "Flat Vibration Switch". You should change the `displayName` to reflect the component you're adding.

At this point, the **definition.json** file looks like the following.

```auto
{
  "displayName": "Flat Vibration Switch",
  "autoSelectString": "toggle",
  "mode": "DIGITAL",
  "direction": "INPUT",
  "defaultPeriod": 30
}
```

Next, set the required pin `mode` field. This field may either be `ANALOG` _or_ `DIGITAL`. Since the microcontroller reading a vibration switch will either read a digital 1 or a digital 0 value, its mode is digital.

At this point, the **definition.json** file looks like the following.

```auto
{
  "displayName": "Flat Vibration Switch",
  "autoSelectString": "toggle",
  "mode": "DIGITAL",
  "direction": "INPUT",
  "defaultPeriod": 30
}
```

Finally, the last of the required fields is the pin's `direction` which may be either `INPUT` or `OUTPUT`. Data from the vibration switch will be read into the board, so&nbsp; define an `INPUT` direction.

```auto
{
  "displayName": "Flat Vibration Switch",
  "autoSelectString": "toggle",
  "mode": "DIGITAL",
  "direction": "INPUT",
  "defaultPeriod": 30
}
```

The optional `autoSelectString` field is a hint for automatically looking up pin names. For example, an LED component will automatically select a pin labeled "LED" if the pin exists.&nbsp;

In the vibration switch case, this field is not required so it can be removed.

```auto
{
  "displayName": "Flat Vibration Switch",
  "mode": "DIGITAL",
  "direction": "INPUT",
  "defaultPeriod": 30
}
```

The `defaultPeriod` field describes the default value of the _Period_ field on the "Component Settings" form on WipperSnapper (in seconds). You may leave this as-is.

However, some sensors may take a longer amount of time than the 30-second default to gather readings and this time period may need to be adjusted.

```auto
{
  "displayName": "Flat Vibration Switch",
  "mode": "DIGITAL",
  "direction": "INPUT",
  "defaultPeriod": 30
}
```

## (Optional) Add Component Visualization&nbsp;

You may (optionally) add some text to the definition file to describe its "look" on the Adafruit IO device interface.&nbsp;

While optional, a component with visualization not only makes it visually prettier - it adds _function!_ Adafruit IO component visualization includes icons and labels to explain what the component does.

For example, this is a LED switch component without a defined visualization:

![](https://cdn-learn.adafruit.com/assets/assets/000/114/048/medium800/sensors_led_no_viz.png?1660151514)

And this is a vibration switch component on Adafruit IO with a visualization defined in its definition file.

![](https://cdn-learn.adafruit.com/assets/assets/000/114/049/medium800/sensors_vswitch.png?1660152546)

Adding the following `visualization` object to your component's definition.json will define its look and feel:

```auto
"visualization": {
    "type": "switch",
    "offLabel": "Still",
    "offIcon": "fa6:regular:bell-slash",
    "onLabel": "Bzzz",
    "onIcon": "fa6:solid:bell-on"
  }
```

The components visualization `type` may be either a `switch` or a `button` (we're working on adding more component types). Each type is omnidirectional, meaning it may be used as either an output or an input.

The `off/onLabel` and `off/onIcons` are specific to the `switch` component type.

- For an example of how the button component type works, [check out the definition.json file for the push button component](https://github.com/adafruit/Wippersnapper_Components/blob/main/components/pin/push_button/definition.json).

The component's labels (`onLabel` and `offLabel`) correspond to its physical state. For example, a vibration sensor when "off" is still (reflected by the `offLabel` above). When the vibration sensor is activated (by movement or touch), we'll change the `onLabel` to "Touched".

The component's icons, `onIcon` and `offIcon`, correspond to the component's on and off state.

For example, the `onIcon` is defined as:

`"onIcon": "fa6:solid:bell-on"`

bell-on is the name of the icon, with a bunch of namespaces in front of it. Let's break it down:

- `fa6` means we are using a set of icons called [Font Awesome 6](https://fontawesome.com/icons)
- `solid` is the style of the icon. There are 4 icon styles to pick from - `light`, `thin`, `regular` and `solid`.
- `bell-on` is the name of the icon.&nbsp;

To find an icon, visit [https://fontawesome.com/icons](https://fontawesome.com/icons) to search for an icon you like.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/114/050/medium800/sensors_fa.png?1660155110)

Clicking on an icon will show you the various icon styles.

![](https://cdn-learn.adafruit.com/assets/assets/000/114/051/medium800/sensors_bell-on.png?1660155129)

Once you've completed adding the `visualization` object to the component's definition, you're finished editing its definition. A complete `definition.json` file should look something like the following.

https://github.com/adafruit/Wippersnapper_Components/blob/main/components/pin/toggle_switch/definition.json

## Add Component Image

Next, you'll need to add an image of your component. It's best to get a photo of the component from the manufacturer's website.

First, make sure your image adheres to the following specifications:&nbsp;

- Image file's extension can be any one of: jpg, jpeg, gif, png, svg  
- Image file's dimensions must be 300px x 300px  
- Image file's size must be at least 3kb and must not exceed 100kb

For the flat vibration switch, it is the first image from [the Adafruit Store product page](https://www.adafruit.com/product/4081). Next, this image must be resized. Using a web-based tool such as [https://picresize.com](https://picresize.com) is suggested and ensuring the final image is 300px by 300px.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/109/033/medium800/sensors_PicResize-Vib-Switch.png?1645034112)

Add the resized image to the **`flat_vibration_switch`** folder and rename it **image.png**. You may need to delete the existing file, there should only be one file named **image.EXTENSION** in this folder.

You may also delete the optional **animation.gif** file within this folder if you are not planning to add one.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/034/medium800/sensors_flat_vibration_switch_folder.png?1645034343)

## (Optional) Add Component Animation

This step is optional due to the amount of work required to produce an animation. The Ruiz brothers have a video on how to create a spinning board animation below:

https://www.youtube.com/watch?v=5Nh3Tudt-Fk&feature=youtu.be

The optional **animation.gif** file also must adhere to the following specifications:

- File must ALWAYS be .gif  
- File dimensions must be 300px x 300px  
- File is between 5kb and 700kb

## Commit Your Changes and Push

Next, let's add all these changes to your fork. Add your components using the `git add` command.

Typing `git status` shows the files you're about to add.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/035/medium800/sensors_1__fish__Users_brentrubell_Desktop_github_brentru_WipperSnapper_Components__fish_.png?1645035809)

Then, commit the files by typing `git commit -m "adding new component"`

And push to your forked repository, `git push yourRepo add-component-name`

![](https://cdn-learn.adafruit.com/assets/assets/000/109/037/medium800/sensors_1__fish__Users_brentrubell_Desktop_github_brentru_WipperSnapper_Components__fish_.png?1645035877)

Next, [follow this page to submit a pull request to add your component to WipperSnapper.](https://learn.adafruit.com/how-to-add-a-new-component-to-adafruit-io-wippersnapper/submit-a-pull-request)

## Submit a Pull Request

Finally, it's time to submit a pull request to add the component to WipperSnapper!

After you've pushed the updated files to your branch, navigate to [https://github.com/adafruit/Wippersnapper\_Components/pulls](https://github.com/adafruit/Wippersnapper_Components/pulls) and click "Compare & pull request".

![](https://cdn-learn.adafruit.com/assets/assets/000/109/469/medium800/sensors_pr_1.png?1646426212)

Give your pull request a name and a description. Make it as descriptive as possible!

Click "Create pull request".

![](https://cdn-learn.adafruit.com/assets/assets/000/109/470/medium800/sensors_pr-2.png?1646426233)

The repository will run checks on these files. If the checks pass, Adafruit will review the files.&nbsp;

For reference, [an example of this pull request is here \>\>\>](https://github.com/adafruit/Wippersnapper_Components/pull/25)

![](https://cdn-learn.adafruit.com/assets/assets/000/109/471/medium800/sensors_pr-3.png?1646426267)

## Testing your Pin Component

As part of our review process, we'll make your component appear under the component picker as "in development". This allows you to test the component before giving us (Adafruit) the final OK.

On your Adafruit IO Device page, open the component picker. Click the "Show Dev" checkbox.

![](https://cdn-learn.adafruit.com/assets/assets/000/116/787/medium800/sensors_show_dev.png?1669146961)

You should see the pin component you just added.

![](https://cdn-learn.adafruit.com/assets/assets/000/116/791/medium800/sensors_show_dev_2.png?1669149336)

Make sure everything on the form looks okay. Then, create your component and test it out with a device.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/473/medium800/sensors_IO_-_WipperSnapper.png?1646426297)

Once you've fully tested your component and are satisfied with how it works, let us know in the Pull Request and we'll make it live on Adafruit IO!

# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## Adding an I2C Component

![](https://cdn-learn.adafruit.com/assets/assets/000/109/118/medium800/sensors_5027-00.jpeg?1645547176)

[I2C](https://learn.adafruit.com/working-with-i2c-devices) is a popular protocol that uses two wires to communicate with sensors (often called I2C _devices_). If you need a quick overview (or refresher!) of how I2C works, [read through this guide page](https://learn.adafruit.com/i2c-addresses/overview).

The following page(s) will go over the process of adding your favorite I2C sensor.

**You will need to follow this page first, then the "Adding an I2C Component Driver" page after.**

The process of adding I2C components is more involved than adding a pin component and you'll be asked to write some C++ code. If you haven't written C++ before - don't worry - this guide will walk you through the process and provide examples.

As an example, the following uses the [MCP9808 High Accuracy I2C Temperature Sensor Breakout](https://www.adafruit.com/product/5027) for this guide since it's a simple breakout that only reports temperature data.

Keep in mind that some I2C breakouts have _multiple&nbsp;_sensors which report&nbsp;_multiple&nbsp;_types of data (such as temperature, humidity, altitude, etc.). The more types of data reported by a sensor, the more _involved_ its I2C component driver code will be.

## Add Component JSON Definition

This page assumes you've followed [the instructions on the Get Setup page and have the WipperSnapper\_Components repository forked and locally cloned](https://learn.adafruit.com/how-to-add-a-new-component-to-adafruit-io-wippersnapper/get-setup).

First, create a branch to work within. In our case, we'll name it `add-mcp9808`.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/079/medium800/sensors_1__fish__Users_brentrubell_Desktop_github_brentru_Wippersnapper_Components__fish_.png?1645213011)

Next, navigate to the **Wippersnapper\_Components/components/i2c** directory. Create a new folder named **mcp9808**.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/080/medium800/sensors_mcp9808-folder.png?1645213190)

Within the mcp9808 folder, add a new file named **definition.json**. This will hold the definition of the physical sensor for the WipperSnapper website.

JSON files are written as pairs of keys and values, separated by a semicolon.

The first key/value pair in the JSON definition is the `displayName`, which is the human-friendly name of a component. This field is&nbsp; **required**.&nbsp;

```auto
{
    "displayName": "MCP9808",
}
```

Each I2C device has a unique _address_ to identify it by. We have [a list of I2C addresses on this page](https://learn.adafruit.com/i2c-addresses/the-list). If it's not on that page, check the sensor's datasheet.&nbsp;

[According to its documentation, the Adafruit MCP9808's I2C addresses can range from 0x18 to 0x1C](https://learn.adafruit.com/adafruit-mcp9808-precision-i2c-temperature-sensor-guide/pinouts#optional-pins-2958189-4).

These addresses are listed within the `i2cAddresses` field in the JSON definition:

```auto
{
    "displayName": "MCP9808",
    "i2cAddresses": [ "0x18", "0x19", "0x1A", "0x1C" ],
}
```

Next, add the list of `subcomponents`. These are all the sensors on the I2C device.

The MCP9808 breakout only has an ambient temperature sensor. There are two types of ambient temperature sensors on [the list of sensor types](https://github.com/adafruit/Wippersnapper_Components#i2c-sensor-types) - `"ambient-temp``"` and `"ambient-temp-fahrenheit"`. The `ambient-temp` sensor type tells Adafruit IO that a sensor on this breakout will send ambient temperature data back in degree Celsius. Adding `ambient-temp-fahrenheit` to the list of `subcomponents` will allow a user on Adafruit IO to select between having the sensor return the temperature in either degree Celsius or degree Fahrenheit.&nbsp;

The final .JSON file for this sensor is below ([and here it is on GitHub](https://github.com/adafruit/Wippersnapper_Components/blob/main/components/i2c/mcp9808/definition.json))

```auto
{
  "displayName": "MCP9808",
  "i2cAddresses": [ "0x18", "0x19", "0x1A", "0x1C" ],
  "subcomponents": [ "ambient-temp", "ambient-temp-fahrenheit" ]
}
```

## Add Component Image

Next, you'll need to add an image of your component. It is recommended you get a photo of the component from the manufacturer's website.

First, make sure your image adheres to the following specifications:&nbsp;

- Image file's extension can be any one of: jpg, jpeg, gif, png, svg  
- Image file's dimensions must be 300px by 300px  
- Image file's size must be at least 3kb and must not exceed 100kb

Below is the first image from [the Adafruit Store product page](https://www.adafruit.com/product/5027).

Next, this image must be resized. It is suggested using a web-based tool such as [https://picresize.com](https://picresize.com) and ensuring the final image is 300px by 300px.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/109/110/medium800/sensors_PicResize_-_Crop__Resize__Edit_images_online_for_free_.png?1645546341)

Add the resized image to the **mcp9808** &nbsp;folder and rename it **image.EXTENSION**. You may need to delete the existing file, there should only be one file named **image.EXTENSION** in this folder.

You may also delete the optional **animation.gif** file within this folder if you are not planning to add one.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/111/medium800/sensors_mcp9808.png?1645546466)

## (Optional) Add Component Animation

This step is optional due to the amount of work required to produce an animation. The Ruiz brothers have a video on how to create a spinning board animation below:

https://www.youtube.com/watch?v=5Nh3Tudt-Fk&feature=youtu.be

The optional animation.gif file also must adhere to the following specifications:

- File must ALWAYS be .gif  
- File dimensions must be 300px by 300px  
- File is between 5kb and 700kb

## Commit Your Changes and Push

Next, add all these changes to your fork. Add your components using the `git add` command.

Typing `git status` shows the files you're about to add.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/112/medium800/sensors_fish_mcp_add_1.png?1645546558)

Then, commit the files by typing `git commit -m "adding new component"`

And push to your forked repository, `git push yourRepo add-component-name`

![](https://cdn-learn.adafruit.com/assets/assets/000/109/113/medium800/sensors_1__fish__Users_brentrubell_Desktop_github_brentru_Wippersnapper_Components__fish_.png?1645546608)

## Submit a Pull Request

Finally, to submit a pull request to add the component to WipperSnapper!

After you've pushed the updated files to your branch, navigate to [https://github.com/adafruit/Wippersnapper\_Components/pulls](https://github.com/adafruit/Wippersnapper_Components/pulls) and click "Compare & pull request".

Give your pull request a name and a description. Make it as descriptive as possible and click "Create pull request".

![](https://cdn-learn.adafruit.com/assets/assets/000/109/581/medium800/sensors.png?1646848044)

The repository will run checks on these files. If the checks pass, Adafruit) will review the files.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/109/474/medium800/sensors_pr-3.png?1646426739)

When approved, they'll be automatically added to WipperSnapper and available under the component picker along with the form options you added to the **definition.json** file.

For reference, [the pull request above is located here](https://github.com/adafruit/Wippersnapper_Components/pull/26).&nbsp;

# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## Add the Definition JSON

## Add Component JSON Definition

This page assumes you've followed [the instructions on the Get Setup page and have the WipperSnapper\_Components repository forked and locally cloned](https://learn.adafruit.com/how-to-add-a-new-component-to-adafruit-io-wippersnapper/get-setup).

First, create a branch to work within. In our case, we'll name it `add-mcp9808`.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/842/medium800/sensors_1__fish__Users_brentrubell_Desktop_github_brentru_Wippersnapper_Components__fish_.png?1689807535)

Next, navigate to the **Wippersnapper\_Components/components/i2c** directory. Create a new folder named **mcp9808**.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/843/medium800/sensors_mcp9808-folder.png?1689807558)

Within the mcp9808 folder, add a new file named **definition.json**. This will hold the definition of the physical sensor for the WipperSnapper website.

JSON files are written as pairs of keys and values, separated by a semicolon.

The first key/value pair in the JSON definition is `displayName`, which is the human-friendly name of a component. This field is&nbsp; **required**.&nbsp;

The next key/value pair is `published`. This pair should be set to **false** until the component driver is distributed with a release of WipperSnapper.

```auto
{
    "displayName": "MCP9808",
    "published": false,
}
```

Each I2C device has a unique _address_ to identify it by. We have [a list of I2C addresses on this page](https://learn.adafruit.com/i2c-addresses/the-list). If it's not on that page, check the sensor's datasheet.&nbsp;

[According to its documentation, the Adafruit MCP9808's I2C addresses can range from 0x18 to 0x1C](https://learn.adafruit.com/adafruit-mcp9808-precision-i2c-temperature-sensor-guide/pinouts#optional-pins-2958189-4).

These addresses are listed within the `i2cAddresses` field in the JSON definition:

```auto
{
    "displayName": "MCP9808",
    "i2cAddresses": [ "0x18", "0x19", "0x1A", "0x1C" ],
}
```

## Add an Image of the Sensor

Next, you'll need to add an image of the sensor. It is recommended to obtain a photo of the component from the manufacturer's website.

First, make sure your image adheres to the following specifications:&nbsp;

- The Image file's extension can be any one of: jpg, jpeg, gif, png, svg  
- The image file's dimensions must not exceed 400px by 300px 
- The image file's proportions / aspect ratio (Width : Height) must be 4:3  
- The image file's size must be at least 3kb and must not exceed 100kb

For this example, we are using the first image from [the Adafruit Store product page](https://www.adafruit.com/product/5027).

Next, this image must be resized. It is suggested to use a web-based tool such as [https://picresize.com](https://picresize.com) and ensure the final image is 400px x 300px.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/130/073/medium800/sensors_thLFut4Gi9.png?1715945078)

Add the resized image to the **mcp9808** &nbsp;folder and rename it **image.EXTENSION**. You may need to delete the existing file, there should only be one file named **image.EXTENSION** in this folder.

You may also delete the optional **animation.gif** file within this folder if you are not planning to add one.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/845/medium800/sensors_mcp9808.png?1689807684)

## (Optional) Add an Animation GIF

This step is optional due to the amount of work required to produce an animation. The optional animation.gif file also must adhere to the following specifications:

- File must ALWAYS be .gif  
- File dimensions must be a maximum of 400px by 300px and at 4:3 ratio  
- File is between 5kb and 700kb

The Ruiz brothers have a video on how to create a spinning board animation below:

https://www.youtube.com/watch?v=5Nh3Tudt-Fk&feature=youtu.be

## Commit Your Changes and Push

Next, add all these changes to your fork. Add your components using the `git add` command.

Typing `git status` shows the files you're about to add.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/847/medium800/sensors_fish_mcp_add_1.png?1689807769)

Then, commit the files by typing `git commit -m "adding new component"`

And push to your forked repository, `git push yourRepo add-component-name`

![](https://cdn-learn.adafruit.com/assets/assets/000/122/848/medium800/sensors_1__fish__Users_brentrubell_Desktop_github_brentru_Wippersnapper_Components__fish__%281%29.png?1689807755)

## Submit a Pull Request

Finally, submit a pull request to add the component to WipperSnapper!

After you've pushed the updated files to your branch, navigate to [https://github.com/adafruit/Wippersnapper\_Components/pulls](https://github.com/adafruit/Wippersnapper_Components/pulls) and click "Compare & pull request".

Give your pull request a name and a description. Make it as descriptive as possible and click "Create pull request".

![](https://cdn-learn.adafruit.com/assets/assets/000/122/849/medium800/sensors.png?1689807742)

The repository will run checks on these files. If the checks pass, Adafruit will review the files.&nbsp;When approved, they'll be automatically added to WipperSnapper and available under the component picker along with the form options you added to the **definition.json** file.

For reference, [the pull request above is located here](https://github.com/adafruit/Wippersnapper_Components/pull/26).&nbsp;

# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## Build WipperSnapper with PlatformIO

The easiest way to build WipperSnapper firmware on your computer is by using a combination of [Microsoft Visual Studio Code](https://code.visualstudio.com/) (VSCode) and [PlatformIO](https://platformio.org/).&nbsp;

Navigate to [https://code.visualstudio.com](https://code.visualstudio.com) and install the latest version of the VSCode editor.&nbsp;

Once downloaded and installed, open VSCode and navigate to the Extensions tab (If you do not have this tab, you can find it using the toolbar by navigating to _Settings-\>Extensions_).

![](https://cdn-learn.adafruit.com/assets/assets/000/122/482/medium800/sensors_extensions.png?1689108006)

Search for the [_PlatformIO_](https://marketplace.visualstudio.com/items?itemName=platformio.platformio-ide) extension.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/483/medium800/sensors_platformio_search.png?1689108152)

Select the PlatformIO extension and click Install.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/484/medium800/sensors_platformio_install.png?1689108159)

## Fork WipperSnapper Firmware

To contribute to WipperSnapper, you will need to create a copy of the [WipperSnapper project's repository](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino). This copy is called a **fork&nbsp;** and you will use it to make changes to WipperSnapper before submitting them to the official project repository.

Sign in to your [Github.com](https://github.com/) account and navigate to [the WipperSnapper firmware repository](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino).

![](https://cdn-learn.adafruit.com/assets/assets/000/122/486/medium800/sensors_f1.png?1689108952)

Click the "Fork" button to fork your own copy of the _adafruit/Adafruit\_Wippersnapper\_Arduino&nbsp;_repository.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/487/medium800/sensors_f2.png?1689109037)

Click "Create Fork" and wait a few seconds for GitHub to create a copy of the WipperSnapper repository on your account.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/488/medium800/sensors_f3.png?1689109229)

## Clone WipperSnapper Firmware

Next, let's clone your fork of the Wippersnapper firmware so we can download it, make changes locally, compile it, and eventually send your changes up to the official repository.

On the page for your forked repository, click the green Code button. The dropdown should present a link like the one below:

[https://github.com/brentru/Adafruit\_Wippersnapper\_Arduino.git](https://github.com/brentru/Adafruit_Wippersnapper_Arduino.git)

Copy the link to your clipboard.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/522/medium800/sensors_brentru_Adafruit_Wippersnapper_Arduino__WipperSnapper_is_a_firmware_for_creating_no-code_IoT_electronics_projects__%F0%9F%94%8A.png?1689195280)

Using a terminal program, enter the following command to clone the forked repository to your computer. Be sure to replace `youruserid` with your GitHub user ID, and paste the URL from your clipboard.&nbsp;

`git clone -o youruserid https://your-fork-URL`

![](https://cdn-learn.adafruit.com/assets/assets/000/122/525/medium800/sensors_termclone.png?1689196079)

Now that the WipperSnapper firmware is local on your computer, check out a new branch and move on to the new step - building WipperSnapper.

If you are unfamiliar with how to check out a new branch, [Kattni wrote a great overview of the process here](https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github/always-work-on-a-branch)...

## Open WipperSnapper Firmware in PlatformIO

Open Visual Studio Code and click Open to bring up the file explorer.

Navigate to the _Folder_ containing your local copy of _Adafruit\_Wippersnapper\_Arduino_ and click Open.&nbsp;&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/122/526/medium800/sensors_open.png?1689196471)

VSCode should open to WipperSnapper's _platformio.ini&nbsp;_file. A notification on the bottom-right of your VSCode instance shows a message that PlatformIO is configuring the project and installing the required libraries to build WipperSnapper.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/529/medium800/sensors_pio_install.png?1689196871)

When the libraries finish installing, you should see a notification (or terminal output) that the "Project has been successfully updated!".

Click the PlatformIO logo (it looks like an alien's head) on the left-hand side of the VSCode editor to open PlatformIO.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/530/medium800/sensors_vscode_sidebar.png?1689197006)

Under PlatformIO's Project Tasks tab, every board WipperSnapper supports is listed as a folder.

Select the board you'd like to build for. For example, I have an Adafruit Feather ESP32 v2 and I will select the `featheresp32v2` board from the dropdown.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/531/medium800/sensors_platformio_ini_%E2%80%94_Adafruit_Wippersnapper_Arduino.png?1689197138)

When PlatformIO is loading tasks for a new environment, a blue clock appears on top of the logo. Wait until the blue clock disappears before continuing the build process.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/532/medium800/sensors_platformio_ini_%E2%80%94_Adafruit_Wippersnapper_Arduino.png?1689197147)

When PlatformIO loads the featheresp32v2 environment, you should see a Build step underneath featheresp32v2-\>General-\>Build.&nbsp;

Click Build and PlatformIO should begin to build WipperSnapper firmware for the Feather ESP32 V2.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/533/medium800/sensors_build_out.png?1689197368)

Once WipperSnapper builds successfully, the terminal will show SUCCESS along with the time it took to build.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/534/medium800/sensors_ok_build.png?1689197621)

Congrats- you've successfully built WipperSnapper locally!&nbsp;

## Upload Locally-Built WipperSnapper Firmware

To upload and test WipperSnapper on your device, you will need to specify the [`upload_port`](https://docs.platformio.org/en/latest/projectconf/sections/env/options/upload/upload_port.html) belonging to your device.

Within VSCode, open the platformio.ini file and navigate to the board you are using. Using this guide as an example, we previously compiled for the Adafruit Feather ESP32 V2. The build environment looks like the following.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/586/medium800/sensors_env.png?1689355040)

Next, add the [upload\_port](https://docs.platformio.org/en/latest/projectconf/sections/env/options/upload/upload_port.html) for your board. This port name varies but will take the form of:

- `/dev/ttyUSB0`&nbsp;- Serial port (Unix-based OS)

- `COM3`&nbsp;- Serial port (Windows OS)

![](https://cdn-learn.adafruit.com/assets/assets/000/122/588/medium800/sensors_upload_port.png?1689355215)

On the VSCode sidebar, click the PlatformIO logo.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/589/medium800/sensors_pio_alien.png?1689355241)

Under Project Tasks-\> Your Board (for this example, the board is featheresp32v2), click Upload to upload WipperSnapper firmware to your development board.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/590/medium800/sensors_upload_good.png?1689355418)

After the PlatformIO upload succeeds, press the RESET button on your board and navigate to [https://io.adafruit.com/devices](https://io.adafruit.com/devices)

![](https://cdn-learn.adafruit.com/assets/assets/000/122/591/medium800/sensors_device_online.png?1689355423)

If the upload was successful, you should see your board connected to Adafruit IO!

# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## Adding the I2C Component Driver

Now that you have built WipperSnapper, it's time to add the driver for the I2C sensor.

## Get Setup

As an example, we'll be creating a new WipperSnapper I2C component for the MCP9808 High Accuracy I2C Temperature Sensor Breakout. This breakout is perfect to use as an example as it only reports the temperature reading.

You will need to alter/edit the code below to reflect the sensor you're adding, keeping in mind that sensors that report more readings (temperature, humidity, air quality, etc) require more code.

### Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout

[Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout](https://www.adafruit.com/product/5027)
The MCP9808 digital temperature sensor is one of the more accurate/precise we've ever seen, with a typical accuracy of ±0.25°C over the sensor's -40°C to +125°C range and precision of +0.0625°C. They work great with any microcontroller using standard I2C. With...

In Stock
[Buy Now](https://www.adafruit.com/product/5027)
[Related Guides to the Product](https://learn.adafruit.com/products/5027/guides)
![Top view of temperature sensor breakout above an OLED display FeatherWing. The OLED display reads "MCP9808 Temp: 24.19ºC"](https://cdn-shop.adafruit.com/640x480/5027-04.jpg)

WipperSnapper firmware is based on Arduino. You will need an Arduino library that already contains the driver code for your sensor.&nbsp;

This page is using the Adafruit MCP9808 sensor breakout as an example. The corresponding Arduino library for this sensor is [listed on the Arduino Library Manager](https://www.arduino.cc/reference/en/libraries/adafruit-mcp9808-library/) and [publicly available on GitHub](https://github.com/adafruit/Adafruit_MCP9808_Library).

In your IDE/text editor of choice, open [the src folder](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/tree/main/src) within Adafruit\_WipperSnapper\_Arduino.

## Create a new Header File
WipperSnapper's I2C drivers are stored as header (`.h`) files [within the src/components/i2c/drivers folder](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/tree/main/src/components/i2c/drivers) and each driver follows the naming convention `WipperSnapper_I2C_Driver_SensorName.h`.

For our example, we'll create a new header file called `WipperSnapper_I2C_Driver_MCP9808.h` within _src/components/i2c/drivers&nbsp;_and add the following skeleton code to the file:

```cpp
/*!
 * @file WipperSnapper_I2C_Driver_MCP9808.h
 *
 * Device driver for the MCP9808 Temperature sensor.
 *
 * Adafruit invests time and resources providing this open source code,
 * please support Adafruit and open-source hardware by purchasing
 * products from Adafruit!
 *
 * Copyright (c) Brent Rubell 2023 for Adafruit Industries.
 *
 * MIT license, all text here must be included in any redistribution.
 *
 */
#ifndef WipperSnapper_I2C_Driver_MCP9808_H
#define WipperSnapper_I2C_Driver_MCP9808_H

#include "WipperSnapper_I2C_Driver.h"
#include &lt;Adafruit_MCP9808.h&gt;

/**************************************************************************/
/*!
    @brief  Class that provides a driver interface for a MCP9808 sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_MCP9808 : public WipperSnapper_I2C_Driver {
public:
  /*******************************************************************************/
  /*!
      @brief    Constructor for a MCP9808 sensor.
      @param    i2c
                The I2C interface.
      @param    sensorAddress
                7-bit device address.
  */
  /*******************************************************************************/
  WipperSnapper_I2C_Driver_MCP9808(TwoWire *i2c, uint16_t sensorAddress)
      : WipperSnapper_I2C_Driver(i2c, sensorAddress) {
    _i2c = i2c;
    _sensorAddress = sensorAddress;
  }

  /*******************************************************************************/
  /*!
      @brief    Destructor for an MCP9808 sensor.
  */
  /*******************************************************************************/
  ~WipperSnapper_I2C_Driver_MCP9808() {
    // Called when a MCP9808 component is deleted.
    delete _mcp9808;
  }

  /*******************************************************************************/
  /*!
      @brief    Initializes the MCP9808 sensor and begins I2C.
      @returns  True if initialized successfully, False otherwise.
  */
  /*******************************************************************************/
  bool begin() {
    // TO-DO: Initialization code goes here!
  }

protected:
  Adafruit_MCP9808 *_mcp9808; ///&lt; Pointer to MCP9808 temperature sensor object
};

#endif // WipperSnapper_I2C_Driver_MCP9808
```

At the top of the code are [include guards](https://www.cplusplus.com/forum/articles/10627/) which prevent the compiler from including multiple instances of this class.&nbsp;

Next, we'll include the base I2C class (`#include"WipperSnapper_I2C_Driver.h"`) and the Arduino driver library for the I2C sensor (in this example, `#include ``<Adafruit_MCP9808.h>`).&nbsp;

The constructor (`WipperSnapper_I2C_Driver_MCP9808()`) and destructor (`~WipperSnapper_I2C_Driver_MCP9808()`) are called when the component is either initialized or deleted via the WipperSnapper website. The constructor is passed the I2C object and the sensor address from the new component form.

At the bottom, underneath `protected`, you'll need to create a pointer to access the sensor driver&nbsp;(in this example, `*_mcp9808`).

## Add `begin()`

The `begin()` function contains the code required to initialize the sensor's driver and returns True upon successful initialization.&nbsp;

The MCP9808 has a very simple initialization routine:&nbsp;

```cpp
/*******************************************************************************/
  /*!
      @brief    Initializes the MCP9808 sensor and begins I2C.
      @returns  True if initialized successfully, False otherwise.
  */
  /*******************************************************************************/
  bool begin() {
    _mcp9808 = new Adafruit_MCP9808();
    return _mcp9808-&gt;begin((uint8_t)_sensorAddress, _i2c);
  }
```

## About I2C Sensors in WipperSnapper

Before explaining how to add a function to read the sensor, let's first talk a little bit about how this works within WipperSnapper.

WipperSnapper utilizes the [Adafruit Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor) library which provides a single type for all sensor readings, `sensors_event_t`, and enforces standardized SI units for each type of sensor.

By reducing all data to a single&nbsp;`sensors_event_t`&nbsp;'type' and settling on specific,&nbsp; **standardized SI units** &nbsp;for each sensor family, the same sensor types return values which are compatible with any similar sensor. This enables us to support all types of sensor breakouts without worrying about the units matching and prevents code re-use.

[This section of the Adafruit Unified Sensor Driver's GitHub README](https://github.com/adafruit/Adafruit_Sensor#how-does-it-work) provides an in-depth explanation of how the driver works.

## Add a function to read a sensor

Next, a function needs to be added to read the value of the sensor. The [WipperSnapper\_I2C\_Driver.h](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/blob/main/src/components/i2c/drivers/WipperSnapper_I2C_Driver.h) file contains base class implementations for reading each type of sensor prefixed by `getEvent_`.

The MCP9808 contains an ambient temperature sensor. Looking within the [WipperSnapper\_I2C\_Driver.h](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/blob/main/src/components/i2c/drivers/WipperSnapper_I2C_Driver.h), the `getEventAmbientTemp()` function "reads an ambient temperature sensor".&nbsp;

Let's add an empty getEventAmbientTemp() function to our header file:

```cpp
/*******************************************************************************/
  /*!
      @brief    Gets the MCP9808's current temperature.
      @param    tempEvent
                Pointer to an Adafruit_Sensor event.
      @returns  True if the temperature was obtained successfully, False
                otherwise.
  */
  /*******************************************************************************/
  bool getEventAmbientTemp(sensors_event_t *tempEvent) {
    // TODO: Add code here!
  }
```

Add code to read the sensor's temperature. The temperature is stored&nbsp;within the `sensor_event_t` type's `temperature` field.

```cpp
/*******************************************************************************/
  /*!
      @brief    Gets the MCP9808's current temperature.
      @param    tempEvent
                Pointer to an Adafruit_Sensor event.
      @returns  True if the temperature was obtained successfully, False
                otherwise.
  */
  /*******************************************************************************/
  bool getEventAmbientTemp(sensors_event_t *tempEvent) {
    tempEvent-&gt;temperature = _mcp9808-&gt;readTempC();
    return true;
  }
```

### 

WipperSnapper uses the&nbsp;[Adafruit Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor)&nbsp;to handle reading sensors and enforces&nbsp;standardized SI units for every type of sensor. In&nbsp;**[WipperSnapper\_I2C\_Driver.h](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/blob/main/src/components/i2c/drivers/WipperSnapper_I2C_Driver.h)**, there are functions for&nbsp;[each predefined sensor type within the Adafruit Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor#sensor-types-sensors_type_t).

The sensor driver header file should implement a&nbsp;`getEventTYPE()`&nbsp;function call for each value to be read.

- For examples of implementations (some might match your sensor!), check out&nbsp;[Adafruit\_Wippersnapper\_Arduino/tree/main/src/components/i2c/drivers](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/tree/main/src/components/i2c/drivers)&nbsp;folder.

## Include the new driver in the I2C Base Driver

With the sensor driver complete, the next step is to add it to the base I2C class file, `src/components/i2c/WipperSnapper_I2C.h`

Open the file `src/components/i2c/WipperSnapper_I2C.h`. At the top, add a line to `#include` the MCP9808 driver:

```auto
...
#include "drivers/WipperSnapper_I2C_Driver_DPS310.h"
#include "drivers/WipperSnapper_I2C_Driver_SCD30.h"
#include "drivers/WipperSnapper_I2C_Driver_MCP9808.h"
```

At the bottom of this file, add a new pointer to the MCP9808 driver:

```auto
private:
  WipperSnapper_I2C_Driver_MCP9808 *_mcp9808 = nullptr;
  ...
```

## Add Handling Code to the I2C Base Driver

Finally, we'll need to add code to detect and initialize the MCP9808. Within `src/components/i2c/WipperSnapper_I2C.cpp`, locate the `initI2CDevice()` function:

```cpp
/*******************************************************************************/
/*!
    @brief    Initializes I2C device driver.
    @param    msgDeviceInitReq
              A decoded I2CDevice initialization request message.
    @returns True if I2C device is initialized and attached, False otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_Component_I2C::initI2CDevice(
    wippersnapper_i2c_v1_I2CDeviceInitRequest *msgDeviceInitReq) {
  WS_DEBUG_PRINT("Attempting to initialize I2C device: ");
  WS_DEBUG_PRINTLN(msgDeviceInitReq-&gt;i2c_device_name);
  uint16_t i2cAddress = (uint16_t)msgDeviceInitReq-&gt;i2c_device_address;
  ...
```

Within initI2CDevice(), add code to detect the I2C sensor and, if detected, initialize it.

```auto
bool WipperSnapper_Component_I2C::initI2CDevice(
    wippersnapper_i2c_v1_I2CDeviceInitRequest *msgDeviceInitReq) {
  ...
  } else if (strcmp("mcp9808", msgDeviceInitReq-&gt;i2c_device_name) == 0) {
    _mcp9808 = new WipperSnapper_I2C_Driver_MCP9808(this-&gt;_i2c, i2cAddress);
    if (!_mcp9808-&gt;begin()) {
      WS_DEBUG_PRINTLN("ERROR: Failed to initialize MCP9808!");
      _busStatusResponse =
          wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
      return false;
    }
    _mcp9808-&gt;configureDriver(msgDeviceInitReq);
    drivers.push_back(_mcp9808);
    WS_DEBUG_PRINTLN("MCP9808 Initialized Successfully!");
  ...
}
```

## Test the new I2C Sensor Driver

Assuming you have successfully built WipperSnapper using PlatformIO, navigate to the PlatformIO tab and select the board you are using to test.

Click Build.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/122/834/medium800/sensors_pio_build.png?1689811609)

Once PlatformIO has built WipperSnapper successfully, it'll display **SUCCESS** at the bottom of VSCode (or terminal):

![](https://cdn-learn.adafruit.com/assets/assets/000/122/835/medium800/sensors_success.png?1689811695)

Next, upload the modified WipperSnapper firmware to your board by navigating to PlatformIO and clicking Upload.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/839/medium800/sensors_pio_upload.png?1689807285)

From the PlatformIO tab, click Monitor. A new serial monitor should open. You should see the following debug output stating WipperSnapper is running.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/840/medium800/sensors_monitor.png?1689807332)

Additionally, you should see your device appear as **Online** on io.adafruit.com. From the device page on Adafruit IO, click **+ New Component**.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/508/medium800/sensors_IO_-_WipperSnapper_-_device_-_page.png?1646773256)

As part of the development process, your component appears under the component picker as "in development". This allows you to test the component before giving us (Adafruit) final approval to make it live.

At the top of the component picker, click the "Show Dev" checkbox. Your sensor should appear in the I2C Components list with a badge showing "In Development"

![](https://cdn-learn.adafruit.com/assets/assets/000/116/792/medium800/sensors_in_dev_i2c.png?1669149759)

Click your component. On the monitor, you should see an I2C Scan command being executed on the development board.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/512/medium800/sensors__dev_cu_SLAB_USBtoUART.png?1646773397)

On Adafruit IO, configure your component and click **Create Component**.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/181/medium800/sensors_IO_-_WipperSnapper.png?1645653076)

After clicking Create Component, the sensor should initialize. After the period you specified, it should read the sensor's value and publish it to Adafruit IO.

You should see the new value appear on your WipperSnapper device page.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/514/medium800/sensors_IO_-_WipperSnapper_-_mcp_-_page.png?1646773602)

It's good practice to keep the monitor open during this process as its useful for detecting errors and tracing them back.

![](https://cdn-learn.adafruit.com/assets/assets/000/109/513/medium800/sensors_sensor_init_i2c.png?1646773518)

Almost done - let's add a pull request to the Adafruit WipperSnapper library so others can use this sensor.

## Create a Pull Request to WipperSnapper Arduino

First, read over [the Doxygen page on this guide](https://learn.adafruit.com/the-well-automated-arduino-library/doxygen) and run Doxygen on your code. Then, [format your code using clang-format](https://learn.adafruit.com/the-well-automated-arduino-library/formatting-with-clang-format).

Once you've run Doxygen and linted using clang-format, you're ready to submit a pull request adding the sensor to the WipperSnapper Arduino library.

Commit and push your files to a branch on local your fork of _Adafruit\_WipperSnapper\_Arduino_ and open a new pull request on the [Adafruit\_WipperSnapper\_Arduino](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino) repository.

[Adafruit has an example of a "perfect" pull request here](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/pull/228).

![](https://cdn-learn.adafruit.com/assets/assets/000/109/516/medium800/sensors_mcp-pr-2.png?1646773827)

Once reviewed and accepted, Adafruit will include support for your sensor in the latest version of the Adafruit IO Wippersnapper library. We will also remove the "in-development" flag from the component to make it live on Adafruit IO.

# How to Add a New Sensor or Component to Adafruit IO WipperSnapper

## F.A.Q.

### 

WipperSnapper does not currently support components that communicate over SPI or UART. It may in the future, though!

### 

You may request a component to be added to WipperSnapper by navigating to the [**WipperSnapper\_Components GitHub page and filing a request for a component type**](https://github.com/adafruit/Wippersnapper_Components/issues/new). Please be descriptive as possible, and include any libraries/documentation/URLs you may have. **Requests have no ETA** regarding when they will be implemented into WipperSnapper.


## Featured Products

### Adafruit IO+ Subscription Pass – One Year

[Adafruit IO+ Subscription Pass – One Year](https://www.adafruit.com/product/3792)
The all-in-one Internet of Things service from Adafruit you know and love is now _even better_ with IO+. The 'plus' stands for MORE STUFF! More feeds, dashboards, storage, speed. Power up your [Adafruit IO](https://io.adafruit.com/) with the $99 pass for 1 year of the...

In Stock
[Buy Now](https://www.adafruit.com/product/3792)
[Related Guides to the Product](https://learn.adafruit.com/products/3792/guides)
### Adafruit IO+ 1 Year Subscription Card

[Adafruit IO+ 1 Year Subscription Card](https://www.adafruit.com/product/3980)
It's the Internet of the Things!&nbsp;[Adafruit IO+](https://io.adafruit.com/plus) is the easiest way to stream, log, and interact with your data. Whether you're interesting in&nbsp;datalogging or communicating with your microcontroller over the web, Adafruit IO is our cloud...

In Stock
[Buy Now](https://www.adafruit.com/product/3980)
[Related Guides to the Product](https://learn.adafruit.com/products/3980/guides)
### Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout

[Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout](https://www.adafruit.com/product/5027)
The MCP9808 digital temperature sensor is one of the more accurate/precise we've ever seen, with a typical accuracy of ±0.25°C over the sensor's -40°C to +125°C range and precision of +0.0625°C. They work great with any microcontroller using standard I2C. With...

In Stock
[Buy Now](https://www.adafruit.com/product/5027)
[Related Guides to the Product](https://learn.adafruit.com/products/5027/guides)

## Related Guides

- [CircuitPython OctoPrint Controller and Monitor](https://learn.adafruit.com/circuitpython-octoprint-controller-and-monitor.md)
- [Using ItsaSNAP for HomeKit PIR Motion Detection](https://learn.adafruit.com/itsasnap-homekit-pir-motion-detection.md)
- [Welcome to Adafruit IO](https://learn.adafruit.com/welcome-to-adafruit-io.md)
- [Memento Photo Capture with itsaSNAP](https://learn.adafruit.com/memento-photo-capture-with-itsasnap.md)
- [Adafruit QT Py ESP32-C3 WiFi Dev Board](https://learn.adafruit.com/adafruit-qt-py-esp32-c3-wifi-dev-board.md)
- [CircuitPython Webcam with OV2640](https://learn.adafruit.com/circuitpython-webcam-with-ov2640.md)
- [itsaSNAP Daily Weather Forecast Board](https://learn.adafruit.com/itsasnap-daily-weather-forecast-board.md)
- [Adafruit Trinkey QT2040](https://learn.adafruit.com/adafruit-trinkey-qt2040.md)
- [Monitor Your Greenhouse with a No-Code Environmental Sensor](https://learn.adafruit.com/monitor-your-greenhouse-with-a-no-code-environmental-sensor.md)
- [Adafruit IO Basics: Color](https://learn.adafruit.com/adafruit-io-basics-color.md)
- [All the Internet of Things - Episode Four: Adafruit IO](https://learn.adafruit.com/all-the-internet-of-things-episode-four-adafruit-io.md)
- [Adafruit PiCowbell Adalogger for Pico](https://learn.adafruit.com/adafruit-picowbell-adalogger-for-pico.md)
- [Adafruit MCP9808 Precision I2C Temperature Sensor Guide](https://learn.adafruit.com/adafruit-mcp9808-precision-i2c-temperature-sensor-guide.md)
- [Adafruit QT Py ESP32 Pico](https://learn.adafruit.com/adafruit-qt-py-esp32-pico.md)
- [No-Code Pool Party Notifier](https://learn.adafruit.com/pool-party-notification-device.md)
