# Data Logging IoT Weight Scale

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/074/001/medium800thumb/hacks_ezgif.com-video-to-gif_%2815%29.jpg?1554250215)

_How many grams of coffee did I add to my pour-over?_

_Is the bag of cat food empty?_

_Did I remember to water the plant?&nbsp;_

_What's the weight of these screws in my workshop?_

To answer these questions (and more), you're going to **build an internet-enabled scale to track weight data over a period of time**.

To do this, you'll be performing a bit of **hardware hacking** - **tearing down a DYMO Postage scale** and soldering wires to connect it to a PyPortal. Then, you'll **add some CircuitPython code** to the PyPortal which allows you to **read the the scale remotely using [Adafruit](http://io.adafruit.com)**[IO](http://io.adafruit.com)&nbsp;- our easy-to-use internet of things service.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/894/medium800/hacks_P1000419.jpg?1553891243)

This scale is _not just for keeping track of your coffee_ - **you can can monitor anything!** Here are some examples:

- Place a bag of cat food on the scale and enable Adafruit IO Feed Email Notifications for when you run out of cat food.
- Science experiments - no need to watch and chart a scale's weight - let Adafruit IO do that for you with automatic graph visualizations!
- Are you a beekeeper? Track the weight of a honeycomb and have Adafruit IO notify you when it exceeds a certain weight.

This is **an introduction to hacking and controlling consumer off-the-shelf electronics with CircuitPython**. To perform this guide, you'll need some soldering experience and willingness to tear down a consumer product your purchased.

## **Adafruit IO**

&nbsp;

**[Adafruit IO is the easiest way to stream, log, and interact with your data](https://io.adafruit.com).**&nbsp;It's built from the ground up to be easy to use - we do the hard stuff so you can focus on the fun stuff.

Data such as temperature and light levels can be hard to visualize and quantify - Adafruit IO makes it simple. Send IO your data and it can store and display it using charts, graphs, gauges, and more!

![hacks_DATA.png](https://cdn-learn.adafruit.com/assets/assets/000/073/883/medium640/hacks_DATA.png?1553883101)

## CircuitPython Code

&nbsp;

**CircuitPython is great for building Internet-of-Things projects.** Using the&nbsp;[Adafruit IO CircuitPython module](https://github.com/adafruit/Adafruit_CircuitPython_AdafruitIO), you can easily send data to Adafruit IO, receive data from Adafruit IO, and easily manipulate data with the powerful Adafruit IO API.

We've also built a [DymoScale module for CircuitPython](https://github.com/brentru/Adafruit_CircuitPython_DymoScale) to make interfacing with these scales incredibly easy.&nbsp;

You can rapidly update your code without having to compile and store WiFi and API secret keys on the device. This means that there's no editing code and re-uploading whenever you move the PyPortal to another network - just update a file and you're set.&nbsp;

![hacks_CODE.png](https://cdn-learn.adafruit.com/assets/assets/000/073/829/medium640/hacks_CODE.png?1553809502)

## Parts
Danger: 

To use this guide, you'll need a&nbsp;[DYMO scale](http://www.dymo.com/en-US). We've tested this guide with&nbsp;[DYMO M25](https://www.dymo.com/scales/dymo-m25-digital-postal-scale-25-pound-capacity/SAP_1772059.html) and a [DYMO M10](https://www.dymo.com/scales/dymo-m10-digital-postal-scale-10-pound-capacity/SAP_1772057.html).

**Note:** There are differences between the two scale models we tested (the **CircuitPython\_DymoScale** library handles this for you, you can use either). If you choose to use another DYMO mode with this guide, be warned that we have _not_ tested other DYMO scales with this library and your scale may not work with our library.&nbsp;

### Adafruit PyPortal - CircuitPython Powered Internet Display

[Adafruit PyPortal - CircuitPython Powered Internet Display](https://www.adafruit.com/product/4116)
 **PyPortal** , our easy-to-use IoT device that allows you to create all the things for the “Internet of Things” in minutes. Make custom touch screen interface GUIs, all open-source, and Python-powered using&nbsp;tinyJSON / APIs to get news, stock, weather, cat photos,...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4116)
[Related Guides to the Product](https://learn.adafruit.com/products/4116/guides)
![Front view of a Adafruit PyPortal - CircuitPython Powered Internet Display with a pyportal logo image on the display. ](https://cdn-shop.adafruit.com/640x480/4116-00.jpeg)

## Materials

You'll need the following materials to complete this guide. If you do not have them handy, consider picking them up from Adafruit:

### Part: Soldering Station
quantity: 1
Digital Genuine Hakko FX-888D
[Soldering Station](https://www.adafruit.com/product/1204)

### Part: Solder Spool
quantity: 1
Solder Wire - 60/40 Rosin Core
[Solder Spool](https://www.adafruit.com/product/1886)

### Part: Wire Strippers
quantity: 1
Hakko Professional Quality 20-30 AWG Wire Strippers - CSP-30-1
[Wire Strippers](https://www.adafruit.com/product/527)

### Part: Spudger
quantity: 1
Spudger - Double Sided Prying Tool
[Spudger](https://www.adafruit.com/product/3434)

### Part: Screwdriver
quantity: 1
Adafruit Pocket Screwdriver
[Screwdriver](https://www.adafruit.com/product/3284)

### Part: USB Cable
quantity: 1
USB cable - USB A to Micro-B - 3 foot long
[USB Cable](https://www.adafruit.com/product/592)

# Data Logging IoT Weight Scale

## Install CircuitPython

[CircuitPython](https://github.com/adafruit/circuitpython) is a derivative of [MicroPython](https://micropython.org) designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the **CIRCUITPY** &nbsp;"flash" drive to iterate.

The following instructions will show you how to install CircuitPython. If you've already installed CircuitPython but are looking to update it or reinstall it, the same steps work for that as well!

## Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

[Download the latest version of CircuitPython for the PyPortal via CircuitPython.org](https://circuitpython.org/board/pyportal/)
[Download the latest version of CircuitPython for the PyPortal Pynt via CircuitPython.org](https://circuitpython.org/board/pyportal_pynt/)
 **Click the link above to download the latest version of CircuitPython for the PyPortal.**

Download and save it to your desktop (or wherever is handy).

![circuitpython_pyportal-uf2.png](https://cdn-learn.adafruit.com/assets/assets/000/073/615/medium640/circuitpython_pyportal-uf2.png?1553610968)

Plug your PyPortal into your computer using a known-good USB cable.

**A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.**

Double-click the **Reset** button on the top in the middle (magenta arrow) on your board, and you will see the NeoPixel RGB LED (green arrow) turn green. If it turns red, check the USB cable, try another USB port, etc.&nbsp; **Note:** The little red LED next to the USB connector will pulse red. That's ok!

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

![circuitpython_PyPortalResetNeoPIxel.jpg](https://cdn-learn.adafruit.com/assets/assets/000/071/993/medium640/circuitpython_PyPortalResetNeoPIxel.jpg?1551213425)

You will see a new disk drive appear called **PORTALBOOT**.

Drag the **adafruit-circuitpython-pyportal-\<whatever\>.uf2** file to **PORTALBOOT.**

![circuitpython_PyPortal_PORTALBOOT.png](https://cdn-learn.adafruit.com/assets/assets/000/072/029/medium640/circuitpython_PyPortal_PORTALBOOT.png?1551287972)

![circuitpython_PyPortal_Drag_UF2.png](https://cdn-learn.adafruit.com/assets/assets/000/072/030/medium640/circuitpython_PyPortal_Drag_UF2.png?1551287983)

The LED will flash. Then, the **PORTALBOOT** drive will disappear and a new disk drive called **CIRCUITPY** will appear.

If you haven't added any code to your board, the only file that will be present is **boot\_out.txt**. This is absolutely normal! It's time for you to add your **code.py** and get started!

That's it, you're done! :)

![circuitpython_PyPortalCIRCUITPY.png](https://cdn-learn.adafruit.com/assets/assets/000/071/995/medium640/circuitpython_PyPortalCIRCUITPY.png?1551213875)

## PyPortal Default Files

Click below to download a zip of the files that shipped on the PyPortal or PyPortal Pynt.

[PyPortal Default Files](https://github.com/adafruit/circuitpython-default-files/tree/main/boards/pyportal/4.x)
[PyPortal Pynt Default Files](https://github.com/adafruit/circuitpython-default-files/tree/main/boards/pyportal_pynt/5.x)
# Data Logging IoT Weight Scale

## Assembly

Danger: 

Take your scale out of the box - it's **&nbsp;hardware hackin'&nbsp;time**!

![](https://cdn-learn.adafruit.com/assets/assets/000/073/763/medium800/hacks_scale.png?1553793297)

We're going to begin by popping the front faceplate off.

**Run a&nbsp;[spudger](https://www.adafruit.com/product/3434)&nbsp;along the top edge of the scale's faceplate**, from right to left. You should feel the faceplate _pop_ as you run it along.

Once the spudger reaches the end of the faceplate, it should pop off.

Then, **remove the front faceplate from the scale**.

![hacks_pry.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/764/medium640/hacks_pry.jpg?1553793393)

![hacks_post_pry.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/766/medium640/hacks_post_pry.jpg?1553793445)

![hacks_faceplate_off.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/768/medium640/hacks_faceplate_off.jpg?1553793637)

 **Flip the scale over -&nbsp;** at the end of the scale are removable rubber feet, **pop these out with a flathead screwdriver or a spudger**.

![hacks_hole.png](https://cdn-learn.adafruit.com/assets/assets/000/073/835/medium640/hacks_hole.png?1553810702)

We used the [Adafruit Pocket Screwdriver](https://www.adafruit.com/product/3284) - the [precision screwdriver set](https://www.adafruit.com/product/424) we usually use don't have a long enough shaft to reach the screw.

![hacks_base_screwdrivers.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/826/medium640/hacks_base_screwdrivers.jpg?1553809148)

![hacks_base.png](https://cdn-learn.adafruit.com/assets/assets/000/073/827/medium640/hacks_base.png?1553809669)

 **Unscrew**  **both**  **screws** from the bottom of the scale.&nbsp;

![hacks_screw_1.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/771/medium640/hacks_screw_1.jpg?1553794257)

![hacks_screw_pull.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/772/medium640/hacks_screw_pull.jpg?1553794946)

After the screws are removed, the top cover should remove cleanly _without any extra force_.

![hacks_cover_lift.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/783/medium640/hacks_cover_lift.jpg?1553800451)

![hacks_scale_sans_cover.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/784/medium640/hacks_scale_sans_cover.jpg?1553800402)

 **Using a spudger, gently pry at the seam between the scale's top cover and the base**.

As you go along the edges of the scale, the plastic will&nbsp;_ **pop** _. **Do&nbsp;not&nbsp;force the spudger** in any direction other than sideways - you'll risk breaking the scale's thin plastic cover.

![hacks_pry_tool.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/777/medium640/hacks_pry_tool.jpg?1553799107)

![hacks_pry_tool.jpeg](https://cdn-learn.adafruit.com/assets/assets/000/073/778/medium640/hacks_pry_tool.jpeg?1553799248)

![hacks_pry_under_plastic.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/780/medium640/hacks_pry_under_plastic.jpg?1553799374)

 **Continue running the spudger along the scale's seams** until you've gone completely around the scale. When you get to the front of the scale (near the LCD), you'll be running the spudger towards the bottom of the scale's base.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/073/782/medium800/hacks_pry_tool_2.png?1553799519)

Warning: 

 **Slowly remove the cover** , tilting it slowly towards the front of the scale.

**Do not completely remove the cover - there are wires connected to the front panel**

![hacks_lift_faceplate_off.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/787/medium640/hacks_lift_faceplate_off.jpg?1553803466)

![hacks_lift_faceplate_off_2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/788/medium640/hacks_lift_faceplate_off_2.jpg?1553803546)

![hacks_faceplate_3.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/789/medium640/hacks_faceplate_3.jpg?1553803762)

With the cover slightly open, you may notice some wires snagging. With your spudger or a dull screwdriver, **move these wires away from the plastic posts&nbsp;** so they do not snap when you open the case fully.

![hacks_annoyingwire.png](https://cdn-learn.adafruit.com/assets/assets/000/073/791/medium640/hacks_annoyingwire.png?1553803970)

Remove the foam adhesive on the right and left sides of the scale. This will let the PCB move around more, giving you more wiggle-room to solder later.

![hacks_remove_this.png](https://cdn-learn.adafruit.com/assets/assets/000/073/793/medium640/hacks_remove_this.png?1553805408)

![hacks_wire_cover_removed.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/794/medium640/hacks_wire_cover_removed.jpg?1553804517)

Flip over the PCB and preheat your soldering iron for the next few steps.

![hacks_overhang_1.jpeg](https://cdn-learn.adafruit.com/assets/assets/000/073/798/medium640/hacks_overhang_1.jpeg?1553804733)

## Wiring
We're going to be soldering to the trace highlighted.

**Locate this trace on the PCB** - it should be directly above the T28 silkscreen text.

![hacks_flip_pcb.png](https://cdn-learn.adafruit.com/assets/assets/000/073/802/medium640/hacks_flip_pcb.png?1553808695)

We can not solder to the board until we've removed the solder mask.

**Using a flathead screwdriver, scrape** off the green solder-mask until you've revealed the copper underneath.

Be careful to **scrape up-and-down** , instead of left-to-right, so you don't accidentally cut the trace.

![hacks_IMG_5432.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/815/medium640/hacks_IMG_5432.jpg?1553805319)

With a pair of wire cutters, **remove the header plug** from the end of the white wire.

Then, using a pair of wire strippers, **strip a short** (~2mm) **length of wire** from the end of the _white_ wire.&nbsp;

**Tin the copper pad** you exposed with the razor by applying a small amount of solder to it. Then, **tack the wire to the pad by heating the wire with the soldering iron**.

![hacks_tinning.png](https://cdn-learn.adafruit.com/assets/assets/000/073/817/medium640/hacks_tinning.png?1553805369)

The connection between the white wire and this pad is still fragile. Using kapton tape, or a dab of hot glue, **secure the white wire to the back of the board**.

![hacks_wire.png](https://cdn-learn.adafruit.com/assets/assets/000/073/819/medium640/hacks_wire.png?1553805705)

 **Solder the red header pin to the USB V+ pin** on the left side of the board.

Then, **solder the black header pin to the USB VSS pin**.&nbsp;

![hacks_vss.png](https://cdn-learn.adafruit.com/assets/assets/000/073/836/medium640/hacks_vss.png?1553812512)

Check out the right side of the board. There's two red wires below a white box on the PCB attached to the KG/LB button.

**Note:** On the DYMO M-25 model, this button is labeled **G/OZ&nbsp;** instead of KG/LB.

![hacks_P1000391.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/858/medium640/hacks_P1000391.jpg?1553868620)

![hacks_isolate.png](https://cdn-learn.adafruit.com/assets/assets/000/073/859/medium640/hacks_isolate.png?1553868784)

Using wire cutters, **remove the header pins** from a 3-Pin JST-PH cable.

Then, with a pair of wire strippers, **strip off a small amount of the rubber** sheathing covering each pin.

![hacks_ezgif.com-gif-maker_(2).gif](https://cdn-learn.adafruit.com/assets/assets/000/073/861/medium640thumb/hacks_ezgif.com-gif-maker_%282%29.jpg?1553869242)

 **Solder the white wire** &nbsp;from the JST cable&nbsp;**to the KG/LB (or G/OZ) pad**&nbsp;on the PCB.

**Solder the black wire** &nbsp;from the JST cable&nbsp; **to the GND pad** &nbsp;on the PCB.

![hacks_ezgif.com-video-to-gif_(13).gif](https://cdn-learn.adafruit.com/assets/assets/000/073/864/medium640thumb/hacks_ezgif.com-video-to-gif_%2813%29.jpg?1553871985)

![](https://cdn-learn.adafruit.com/assets/assets/000/073/865/medium800/hacks_P1000399_mp4.png?1553871964)

## Re-Assembly and PyPortal Wiring
Before you re-assemble the PyPortal, make sure the connections for the kg/oz button and data pins are still connected.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/856/medium800/hacks_Pasted_Image_3_29_19__9_22_AM.png?1553866043)

The rectangular holes in the scale's faceplate are _perfect_ for wires to be threaded through them.

**Thread the cables** through the rectangular holes in the faceplate.

Then, **place the top of the scale onto the metal top plate** and r **e-attach the screws underneath the scale** &nbsp;to secure the top of the scale.

![hacks_DSC_4172.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/822/medium640/hacks_DSC_4172.jpg?1553809148)

![hacks_DSC_4175.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/823/medium640/hacks_DSC_4175.jpg?1553808192)

On the right side of the PyPortal are two 3-Pin JST-PH connectors. These connectors can be used for analog or digital communication.

**Connect the 3-Pin JST-PH connector from the button** to **D3 on the PyPortal.**

**Connect the other 3-Pin JST-PH connector for the scale data** to **D4 on the PyPortal.**

![hacks_circuitpython_PyPortalPinouts_D3D4Connectors.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/825/medium640/hacks_circuitpython_PyPortalPinouts_D3D4Connectors.jpg?1553808505)

We're done! Lets move onto the software to control and communicate with the DYMO scale.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/857/medium800/hacks_Pasted_Image_3_29_19__9_33_AM.png?1553866812)

# Data Logging IoT Weight Scale

## Create Your settings.toml File

CircuitPython works with WiFi-capable boards to enable you to make projects that have network connectivity. This means working with various passwords and API keys. As of [CircuitPython 8](https://circuitpython.org/downloads), there is support for a **settings.toml** file. This is a file that is stored on your **CIRCUITPY** drive, that contains all of your secret network information, such as your SSID, SSID password and any API keys for IoT services. It is designed to separate your sensitive information from your **code.py** file so you are able to share your code without sharing your credentials.

CircuitPython previously used a **secrets.py** file for this purpose. The **settings.toml** file is quite similar.

Warning: Your **settings.toml** file should be stored in the main directory of your **CIRCUITPY** drive. It should not be in a folder.

## CircuitPython **settings.toml** File

This section will provide a couple of examples of what your **settings.toml** file should look like, specifically for CircuitPython WiFi projects in general.

The most minimal **settings.toml** file must contain your WiFi SSID and password, as that is the minimum required to connect to WiFi. Copy this example, paste it into your **settings.toml** , and update:

- `your_wifi_ssid`
- `your_wifi_password`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
```

Many CircuitPython network-connected projects on the Adafruit Learn System involve using Adafruit IO. For these projects, you must _also_ include your Adafruit IO username and key. Copy the following example, paste it into your settings.toml file, and update:

- `your_wifi_ssid`
- `your_wifi_password`
- `your_aio_username`
- `your_aio_key`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
ADAFRUIT_AIO_USERNAME = "your_aio_username"
ADAFRUIT_AIO_KEY = "your_aio_key"
```

Some projects use different variable names for the entries in the **settings.toml** file. For example, a project might use `ADAFRUIT_AIO_ID` in the place of `ADAFRUIT_AIO_USERNAME`. **If you run into connectivity issues, one of the first things to check is that the names in the settings.toml file match the names in the code.**

Warning: Not every project uses the same variable name for each entry in the **settings.toml** file! Always verify it matches the code.

## **settings.toml** File Tips
Here is an example **settings.toml** file.

```auto
# Comments are supported
CIRCUITPY_WIFI_SSID = "guest wifi"
CIRCUITPY_WIFI_PASSWORD = "guessable"
CIRCUITPY_WEB_API_PORT = 80
CIRCUITPY_WEB_API_PASSWORD = "passw0rd"
test_variable = "this is a test"
thumbs_up = "\U0001f44d"
```

In a **settings.toml** file, it's important to keep these factors in mind:

- Strings are wrapped in double quotes; ex: `"your-string-here"`
- Integers are _ **not** _ quoted and may be written in decimal with optional sign (`+1`, `-1`, `1000`) or hexadecimal (`0xabcd`).
  - Floats (decimal numbers), octal (`0o567`) and binary (`0b11011`) are not supported.

- Use `\u` escapes for weird characters, `\x` and `\ooo` escapes are not available in **.toml** files
  - Example: `\U0001f44d` for 👍 (thumbs up emoji) and `\u20ac` for € (EUR sign)

- Unicode emoji, and non-ASCII characters, stand for themselves as long as you're careful to save in "UTF-8 without BOM" format

&nbsp;

&nbsp;

When your&nbsp; **settings.toml&nbsp;** file is ready, you can save it in your text editor with the **.toml** &nbsp;extension.

![adafruit_products_dotToml.jpg](https://cdn-learn.adafruit.com/assets/assets/000/117/071/medium640/adafruit_products_dotToml.jpg?1671034293)

## Accessing Your **settings.toml** Information in **code.py**
In your **code.py** file, you'll need to `import` the `os` library to access the **settings.toml** file. Your settings are accessed with the `os.getenv()` function. You'll pass your settings entry to the function to import it into the **code.py** file.

```python
import os

print(os.getenv("test_variable"))
```

![](https://cdn-learn.adafruit.com/assets/assets/000/117/072/medium800/adafruit_products_tomlOutput.jpg?1671034496)

In the upcoming CircuitPython WiFi examples, you'll see how the **settings.toml&nbsp;** file is used for connecting to your SSID and accessing your API keys.

# Data Logging IoT Weight Scale

## Internet Connect!

# Connect to WiFi

OK, now that you have your&nbsp; **settings.toml** file set up - you can connect to the Internet.

To do this, you need to first install a few libraries, into the lib folder on your **CIRCUITPY** drive. Then you need to update **code.py** with the example script.

Thankfully, we can do this in one go. In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file. Extract the contents of the zip file, open the directory **examples/** and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your **CIRCUITPY** drive.

Your **CIRCUITPY** drive should now look similar to the following image:

![CIRCUITPY](https://adafruit.github.io/Adafruit_CircuitPython_Bundle/esp32spi_esp32spi_simpletest.py.png )

Info: Update to CircuitPython 9.2.x or later to use this example.

https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/main/examples/esp32spi_simpletest.py

And save it to your board, with the name **code.py**.

Don't forget you'll also need to create the **settings.toml** file as seen above, with your WiFi ssid and password.

In a serial console, you should see something like the following. For more information about connecting with a serial console, view the guide [Connecting to the Serial Console](https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console).

```terminal
>>> import wifitest
ESP32 SPI webclient test
ESP32 found and in idle mode
Firmware vers. 1.7.5
MAC addr: 24:C9:DC:BD:0F:3F
	HomeNetwork             RSSI: -46
	HomeNetwork             RSSI: -76
	Fios-12345              RSSI: -92
	FiOS-AB123              RSSI: -92
	NETGEAR53               RSSI: -93
Connecting to AP...
Connected to HomeNetwork 	RSSI: -45
My IP address is 192.168.1.245
IP lookup adafruit.com: 104.20.39.240
Ping google.com: 30 ms
Fetching text from http://wifitest.adafruit.com/testwifi/index.html
----------------------------------------
This is a test of Adafruit WiFi!
If you can read this, its working :)
----------------------------------------

Fetching json from http://wifitest.adafruit.com/testwifi/sample.json
----------------------------------------
{'fun': True, 'company': 'Adafruit', 'founded': 2005, 'primes': [2, 3, 5], 'pi': 3.14, 'mixed': [False, None, 3, True, 2.7, 'cheese']}
----------------------------------------
Done!
```

Going over the example above, here's a breakdown of what the program is doing:

- Initialize the ESP32 over SPI using the SPI port and 3 control pins:

```python
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

#...

else:
    spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
```

- Get the socket pool and the SSL context, and then tell the `adafruit_requests` library about them.

```python
pool = adafruit_connection_manager.get_radio_socketpool(esp)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp)
requests = adafruit_requests.Session(pool, ssl_context)
```

- Verify an ESP32 is found, checks the firmware and MAC address

```auto
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
print("MAC addr:", ":".join("%02X" % byte for byte in esp.MAC_address))
```

- Perform a scan of all access points it can see and print out the name and signal strength.

```python
for ap in esp.scan_networks():
    print("\t%-23s RSSI: %d" % (ap.ssid, ap.rssi))
```

- Connect to the AP we've defined here, then print out the local IP address. Then attempt to do a domain name lookup and ping google.com to check network connectivity. (Note sometimes the ping fails or takes a while; this isn't a big deal.)

```python
print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(ssid, password)
    except OSError as e:
        print("could not connect to AP, retrying: ", e)
        continue
print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi)
print("My IP address is", esp.ipv4_address)
print(
    "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com"))
)
```

Now we're getting to the really interesting part of the example program. We've written a library for web fetching web data, named [adafruit\_requests](https://github.com/adafruit/Adafruit_CircuitPython_Requests). It is a lot like the regular Python library named [requests](https://requests.readthedocs.io/en/latest/). This library allows you to send HTTP and HTTPS requests easily and provides helpful methods for parsing the response from the server.

- Here is the part of the example program is fetching text data from a URL.

```python
TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html"  # Further up in the program

# ...

print("Fetching text from", TEXT_URL)
r = requests.get(TEXT_URL)
print('-' * 40)
print(r.text)
print('-' * 40)
r.close()
```

- Finally, here the program is fetching some JSON data. The `adafruit_requests` library will parse the JSON into a Python dictionary whose structure is the same as the structure of the JSON.

```auto
JSON_URL = "http://wifitest.adafruit.com/testwifi/sample.json"   # Further up in the program

# ...

print("Fetching json from", JSON_URL)
r = requests.get(JSON_URL)
print('-' * 40)
print(r.json())
print('-' * 40)
r.close()
```

# Advanced Requests Usage

Want to send custom HTTP headers, parse the response as raw bytes, or handle a response's http status code in your CircuitPython code?

We've written an&nbsp;example to show advanced usage of the requests module below.

To use with CircuitPython, you need to first install a few libraries, into the lib folder on your **CIRCUITPY** drive. Then you need to update **code.py** with the example script.

Thankfully, we can do this in one go. In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file. Extract the contents of the zip file, open the directory **examples/** and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your **CIRCUITPY** drive.

https://github.com/adafruit/Adafruit_CircuitPython_Requests/blob/main/examples/esp32spi/requests_esp32spi_advanced.py

Your **CIRCUITPY** drive should now look similar to the following image:

![CIRCUITPY](https://adafruit.github.io/Adafruit_CircuitPython_Bundle/requests_esp32spi_requests_esp32spi_advanced.py.png )

# WiFi Manager

The way the examples above connect to WiFi works but it's a little finicky. Since WiFi is not necessarily so reliable, you may have disconnects and need to reconnect. For more advanced uses, we recommend using the `WiFiManager` class. It will wrap the connection/status/requests loop for you - reconnecting if WiFi drops, resetting the ESP32 if it gets into a bad state, etc.

Here's a more advanced example that shows using the `WiFiManager` and also how to fetch the current time from a web source.

https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/main/examples/esp32spi_localtime.py

# Further Information

For more information on the basics of doing networking in CircuitPython, see this guide:

### Networking in CircuitPython

[Networking in CircuitPython](https://learn.adafruit.com/networking-in-circuitpython)
# Data Logging IoT Weight Scale

## Adafruit IO Setup

## Feed Setup

If you do not already have an Adafruit IO account set up, head over to [io.adafruit.com](http://io.adafruit.com/) to link your Adafruit.com account to Adafruit IO.

The first step is to create a new Adafruit IO feed to hold the data from the PyPortal's temperature sensor. Navigate to the [feeds page](https://io.adafruit.com/feeds) on Adafruit IO. Then click **Actions&nbsp;-\> Create New Feed** , and name this feed **weight**.&nbsp;

- If you do not already know how to create a feed, head over to [Adafruit IO Basics: Feeds](https://learn.adafruit.com/adafruit-io-basics-feeds).

![](https://cdn-learn.adafruit.com/assets/assets/000/073/634/medium800/hacks_IO_-_Feeds.png?1553630488)

## Build an Adafruit IO Dashboard

Next, you'll create a dashboard to display the values from the feed you created.

- If you do not know how to create or use Dashboards in Adafruit IO, head over to the&nbsp;[Adafruit IO Basics: Dashboards](https://learn.adafruit.com/adafruit-io-basics-dashboards)&nbsp;guide.  
  

### Adding a Gauge Block

To display the values from your Scale, you'll add a gauge block to your dashboard. This blocks displays values within a fixed range and can serve as a visual indication for if the values are too low or high.

From the dashboard you created dashboard, **&nbsp;Select the Gauge block.**

![hacks_temperature___humidity_adafruit_io_weather_IO_-_Feather_Huzzah___ADT7410_Gauge.png](https://cdn-learn.adafruit.com/assets/assets/000/073/635/medium640/hacks_temperature___humidity_adafruit_io_weather_IO_-_Feather_Huzzah___ADT7410_Gauge.png?1553630538)

 **Select** the&nbsp;_weight_&nbsp;feed

![hacks_IO_-_IoT_Scale.png](https://cdn-learn.adafruit.com/assets/assets/000/073/637/medium640/hacks_IO_-_IoT_Scale.png?1553630606)

The code will be sending data from the scale in grams.

**Set the Block Title** to _Scale_

**Set the Gauge Min Value** to _0_

**Set the Gauge Max Value** to _500_

and **Set the Gauge Label** to _grams_

![hacks_IO_-_IoT_Scale.png](https://cdn-learn.adafruit.com/assets/assets/000/073/638/medium640/hacks_IO_-_IoT_Scale.png?1553630784)

### Adding a Line Chart

While displaying the current value of the weight is useful, Adafruit IO stores data so you can monitor how it changes a long period of time. Alternatively, you can visualize it in _real-time&nbsp;_To do this, we'll use the&nbsp; **Line Chart** &nbsp; **block**.

 **Select** the _weight_ feed.

![hacks_IO_-_IoT_Scale.png](https://cdn-learn.adafruit.com/assets/assets/000/073/639/medium640/hacks_IO_-_IoT_Scale.png?1553630891)

Give the line chart a name, and set it to display live history (you can change to display a longer time period this by editing this block)

![hacks_IO_-_IoT_Scale.png](https://cdn-learn.adafruit.com/assets/assets/000/073/640/medium640/hacks_IO_-_IoT_Scale.png?1553630974)

Your final dashboard should look like the following:

![](https://cdn-learn.adafruit.com/assets/assets/000/073/654/medium800/hacks_IO_-_IoT_Scale.png?1553635229)

If you want to customize your dashboard - add more blocks to the dashboard, or resize the existing blocks.

## Obtain Adafruit IO Key

You are also going to need your Adafruit IO username and secret API key.

**[Navigate to your profile](http://io.adafruit.com/profile) and click the View AIO Key button** to retrieve them. Write them down in a safe place, you'll need them for the next step.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/642/medium800thumb/hacks_temperature___humidity_weather_3d_printing_adafruit_io_username_and_password.jpg?1553631408)

# Data Logging IoT Weight Scale

## CircuitPython Code

## CircuitPython Library Installation

To interface your PyPortal with the DYMO scale and the internet - you'll need to install the&nbsp;[Adafruit CircuitPython Adafruit IO](https://github.com/adafruit/Adafruit_CircuitPython_AdafruitIO)&nbsp;and the [Adafruit CircuitPython DymoScale](https://github.com/adafruit/Adafruit_CircuitPython_DymoScale) libraries on your PyPortal.&nbsp;

First make sure you are running the&nbsp;[latest version of Adafruit CircuitPython](https://github.com/adafruit/circuitpython/releases)&nbsp;for your board.

Next you'll need to install the necessary libraries&nbsp;to use the hardware--carefully follow the steps to find and install these libraries from&nbsp;[Adafruit's CircuitPython library bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle)&nbsp;matching your version of CircuitPython. PyPortal requires at least CircuitPython version 4.0.0.

Before continuing make sure your board's **lib** folder has the following files and folders **&nbsp;** copied over.

- **adafruit\_io**
- **adafruit\_dymoscale**
- **adafruit\_esp32spi**
- **adafruit\_bus\_device**** &nbsp;**
- **adafruit\_bitmap\_font**
- **adafruit\_display\_text**
- **neopixel.mpy**

## settings.toml File Setup

You'll need your **Adafruit** &nbsp; **IO username** , and&nbsp; **Adafruit IO key**. Head to&nbsp;[io.adafruit.com](https://io.adafruit.com/)&nbsp;and simply click the&nbsp; **View AIO Key** &nbsp;link on the left hand side of the Adafruit IO page to get this information.

Then, add them to the&nbsp; **settings.toml** file [you set up previously](https://learn.adafruit.com/data-logging-iot-weight-scale/create-your-settings-toml-file).

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
ADAFRUIT_AIO_USERNAME="my_username"
ADAFRUIT_AIO_KEY="my_key"
```

## Add CircuitPython Code and Project Assets

In the embedded code element below, click on the&nbsp; **Download Project Bundle** button, and save the .zip archive file to your computer.

Then, **uncompress the .zip file** , it will unpack to a folder named&nbsp; **PyPortal\_IOT\_Scale**.

Copy the contents of the&nbsp; **PyPortal\_IOT\_Scale** directory to your PyPortal **CIRCUITPY** &nbsp;drive.

**Make sure** to **save the fonts (Helvetica-Bold-16.bdf and Helvetica-Bold-36.bdf) into the _fonts_ folder** on the **CIRCUITPY** volume.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/866/medium800/hacks_Photopea___Online_Image_Editor.png?1553872441)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/PyPortal/PyPortal_IOT_Scale/code.py

This is what the final contents of the&nbsp; **CIRCUITPY** &nbsp;drive will look like:

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/PyPortal_PyPortal_IOT_Scale.png )

## Code Usage
Ensure that the scale's data pin is plugged into D3 on the PyPortal and the units button is plugged into D4 on the PyPortal.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/873/medium800/hacks_P1000402.jpg?1553879398)

Then, the PyPortal will display&nbsp; **IOT Scale&nbsp;** and should display&nbsp;the current weight shown on the scale's LCD display.

If your scale is displaying&nbsp; **SCALE ERROR** , the scale is not turned on yet. Press the power button (the button all the way on the left) to turn on the scale's power.

Since you're not running the scale off of batteries, you'll need to perform this step each time you disconnect/reset the PyPortal.

![hacks_P1000410.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/880/medium640/hacks_P1000410.jpg?1553880234)

When you place something on the scale, the PyPortal's display will update with a new value and send it to Adafruit IO.

![hacks_P1000438.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/876/medium640/hacks_P1000438.jpg?1553879903)

![hacks_P1000440.jpg](https://cdn-learn.adafruit.com/assets/assets/000/073/877/medium640/hacks_P1000440.jpg?1553879996)

Every two minutes, the scale's LCD will switch between grams and ounces to avoid going into sleep mode (see the&nbsp; **Removing the Auto Shut Off** &nbsp;section below)&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/073/879/medium800/hacks_P1000419.jpg?1553880157)

# Data Logging IoT Weight Scale

## Sending Data to Adafruit.IO

## Adafruit IO Usage
While the PyPortal can display measurements on its LCD - _what if you're physically away from the scale or need to log weight data over a period of time?_

_How do we know that the weight data is being sent from the PyPortal to Adafruit IO?_

**Open the Adafruit IO Dashboard you created earlier.** &nbsp;Notice that the fill and values of the gauge changes as values are sent from your PyPortal to Adafruit IO.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/891/medium800/hacks_DATA.png?1553887216)

Then, leave the PyPortal running for a while and come back later to see new data appear on the line graph.

![](https://cdn-learn.adafruit.com/assets/assets/000/073/892/medium800thumb/hacks_Kapture_2019-03-29_at_15.21.58.jpg?1553887336)

# Data Logging IoT Weight Scale

## Code Walkthrough

## Code Overview

To interface with the DYMO scale's data protocol, we wrote a CircuitPython library called [Adafruit CircuitPython DymoScale](https://github.com/adafruit/Adafruit_CircuitPython_DymoScale).

To take a reading from the scale (the library [returns the weight in grams](https://circuitpython.readthedocs.io/en/latest/docs/design_guide.html#sensor-properties-and-units)), we call

```auto
reading = dymo.weight
```

Then, print out the weight of the reading to the REPL as well as the `weight_label` on the PyPortal's display:

```auto
text = "%0.1f g"%reading.weight
print(text)
weight_label.text = text
weight_label.color = 0xFFFFFF
```

Now that you have the data from the scale, it is time to send it to Adafruit IO. To do this, the code uses the `send_data`&nbsp;method from Adafruit IO CircuitPython.

For the weight on your dashboard to reflect what's displayed on the PyPortal the weight sent to IO is rounded to one decimal place.

```auto
print('Sending to Adafruit IO...')
text_label.color = 0xFFFFFF
text_label.text = 'Sending...'
# send data to Adafruit IO (rounded to one decimal place)
io.send_data(weight_feed['key'], round(reading.weight, 1))
```

That's it - sending data to Adafruit IO with CircuitPython is simple!

## Removing the Auto Shut Off

The M-series DYMO scales have an automatic shut off "feature". The scale turns off after three minutes of inactivity. While this is a useful feature to preserve the scale's batteries - it causes the scale to turn off if we're measuring anything over a length of three minutes.

If you're measuring the volume of a mug of pour-over coffee or a bag of cat food - the scale will turn off.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/073/647/medium800/hacks_M10_M25_UserGuide_en-US_pdf.png?1553633299 Dymo M-Series Manual (http://download.dymo.com/dymo/user-guides/scales/M10_M25_UserGuide_en-US.pdf))

In the Wiring page, you soldered a wire onto the Grams/Ounces button and connected it to your PyPortal. We've included a method in the **adafruit\_dymoscale**  **library** called&nbsp;`toggle_unit_button`&nbsp;to simulate pressing the button for you.

When the dymo object is initialized in the code, the `units_pin` is provided to it along with the scale's data pin.

```auto
units_pin = digitalio.DigitalInOut(board.D3)
units_pin.switch_to_output()
dymo = adafruit_dymoscale.DYMOScale(board.D4, units_pin)
```

Then, the code takes a reference time reading with&nbsp;`time.monotonic()`&nbsp;

```auto
# take a reading of the current time, used for toggling the units button
time_stamp = time.monotonic()
```

Each time the code runs through the `while True` loop, we'll check it against the current time. If it exceeds two minutes, the code toggles the unit button (`dymo.toggle_unit_button()`) and resets the timestamp by setting it to the current time.

```auto
# to avoid sleep mode, toggle the units pin every 2 mins.
if (time.monotonic() - time_stamp) > 120:
  print('toggling units button...')
  dymo.toggle_unit_button()
  # reset the time stamp
  time_stamp = time.monotonic()
```

By performing this toggle, our scale never falls asleep!&nbsp;

![hacks_ezgif.com-gif-maker_(3).gif](https://cdn-learn.adafruit.com/assets/assets/000/073/884/medium640thumb/hacks_ezgif.com-gif-maker_%283%29.jpg?1553884022)


## Featured Products

### Adafruit PyPortal - CircuitPython Powered Internet Display

[Adafruit PyPortal - CircuitPython Powered Internet Display](https://www.adafruit.com/product/4116)
 **PyPortal** , our easy-to-use IoT device that allows you to create all the things for the “Internet of Things” in minutes. Make custom touch screen interface GUIs, all open-source, and Python-powered using&nbsp;tinyJSON / APIs to get news, stock, weather, cat photos,...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4116)
[Related Guides to the Product](https://learn.adafruit.com/products/4116/guides)
### STEMMA JST PH 2mm 3-Pin to Male Header Cable - 200mm

[STEMMA JST PH 2mm 3-Pin to Male Header Cable - 200mm](https://www.adafruit.com/product/3893)
This cable will let you turn a JST PH 3-pin cable port into 3 individual wires with high-quality 0.1" male header plugs on the end. We're carrying these to match up with our Hallowing, for extending and connecting sensors or LEDs - and the wires are even color coded!

<a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/3893)
[Related Guides to the Product](https://learn.adafruit.com/products/3893/guides)
### Adafruit Pocket Screwdriver - Black

[Adafruit Pocket Screwdriver - Black](https://www.adafruit.com/product/3284)
Have you ever been in a situation where you desperately&nbsp;needed a screwdriver _right away_? Now you can have one at-the-ready all the time —&nbsp;enter the **Adafruit Pocket Screwdriver**!

OK, it's a little tough to write exciting copy for a pocket...

In Stock
[Buy Now](https://www.adafruit.com/product/3284)
[Related Guides to the Product](https://learn.adafruit.com/products/3284/guides)
### Spudger - Double Sided Prying Tool

[Spudger - Double Sided Prying Tool](https://www.adafruit.com/product/3434)
Is there something missing from your tool kit or workstation? Are you having trouble figuring out which elusive tool it is that you're lacking?&nbsp;Perhaps it's a spudger!&nbsp;"A what?"&nbsp;A&nbsp; **s-p-u-d-g-e-r**! It's&nbsp;a prying tool that has a wide...

In Stock
[Buy Now](https://www.adafruit.com/product/3434)
[Related Guides to the Product](https://learn.adafruit.com/products/3434/guides)
### Hakko Professional Quality 20-30 AWG Wire Strippers

[Hakko Professional Quality 20-30 AWG Wire Strippers](https://www.adafruit.com/product/527)
These are the finest wire strippers we have used, and if you have to do a lot of wiring, you will agree! They have soft rounded grips - very comfortable to use, and precision ground notches that do a perfect job every time. No more yanking or twisting to strip wires cleanly and quickly.<br...></br...>

In Stock
[Buy Now](https://www.adafruit.com/product/527)
[Related Guides to the Product](https://learn.adafruit.com/products/527/guides)
### Digital Genuine Hakko FX888DX-010SV (936 upgrade)

[Digital Genuine Hakko FX888DX-010SV (936 upgrade)](https://www.adafruit.com/product/1204)
Known by engineers for making excellent quality tools & soldering irons! This is a genuine Hakko FX-888D with **digital temperature control**! We worked hard to get the best and a great price, these are **not** &nbsp;knock-offs. This iron is an upgrade to the...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/1204)
[Related Guides to the Product](https://learn.adafruit.com/products/1204/guides)
### Solder Wire - 60/40 Rosin Core - 0.5mm/0.02" diameter - 50 grams

[Solder Wire - 60/40 Rosin Core - 0.5mm/0.02" diameter - 50 grams](https://www.adafruit.com/product/1886)
If you want to make a kit you'll need some solder. This 0.1 lb (about 50 grams) spool is a good amount, not too much (like 1 lb spools) and not too little (like those little 'pocket clip' vials).  
  
This spool of solder contains approximately 0.6mm / .02" diameter in...

Out of Stock
[Buy Now](https://www.adafruit.com/product/1886)
[Related Guides to the Product](https://learn.adafruit.com/products/1886/guides)
### USB cable - USB A to Micro-B

[USB cable - USB A to Micro-B](https://www.adafruit.com/product/592)
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or microcontroller

Approximately 3 feet / 1 meter long

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

## Related Guides

- [Adafruit PyPortal - IoT for CircuitPython](https://learn.adafruit.com/adafruit-pyportal.md)
- [Adafruit IO Basics: AirLift](https://learn.adafruit.com/adafruit-io-basics-airlift.md)
- [PyPortal 2FA TOTP Authentication Friend](https://learn.adafruit.com/pyportal-2fa-totp-authentication-friend.md)
- [Simple Vertical Wordclock](https://learn.adafruit.com/vertical-wordclock.md)
- [Making a PyPortal User Interface with DisplayIO](https://learn.adafruit.com/making-a-pyportal-user-interface-displayio.md)
- [PyPortal IoT Plant Monitor with Google Cloud IoT Core and CircuitPython](https://learn.adafruit.com/pyportal-iot-plant-monitor-with-google-cloud-iot-core-and-circuitpython.md)
- [PyPortal Astronauts in Space](https://learn.adafruit.com/pyportal-astronauts-in-space.md)
- [No-Solder LED Disco Tie with Bluetooth](https://learn.adafruit.com/no-solder-circuit-playground-bluetooth-disco-tie.md)
- [Arcada Animated GIF Display](https://learn.adafruit.com/pyportal-animated-gif-display.md)
- [PyPortal GitHub Stars Trophy](https://learn.adafruit.com/pyportal-github-stars-trophy.md)
- [Infinite Text Adventure](https://learn.adafruit.com/infinite-text-adventure.md)
- [PyPortal Wake-Up Light Alarm Clock](https://learn.adafruit.com/pyportal-wake-up-light.md)
- [PyPortal Smart Thermometer with Analog Devices ADT7410, Adafruit IO and CircuitPython](https://learn.adafruit.com/pyportal-smart-thermometer-with-analog-devices-adt7410-adafruit-io-and-circuitpython.md)
- [How to Make Animated Graphics for Hologram Displays](https://learn.adafruit.com/how-to-make-animated-graphics-for-hologram-displays.md)
- [Program CircuitPython USB Devices with iPhone & iPad](https://learn.adafruit.com/use-circuitpython-devices-with-iphone-ipad.md)
- [Quickstart: Adafruit IO WipperSnapper ](https://learn.adafruit.com/quickstart-adafruit-io-wippersnapper.md)
