Smart Prototyping with Arduino and Framer X

Steve Ruiz

In this article, I’ll show you how to share data and send messages between a Framer X prototype and an Arduino Uno.

Arduino is an open source electronics platform for prototyping electronics. A designer can connect an Arduino board (such as the Uno) to a breadboard, plug in some components — inputs, sensors, lights and displays — and then write code to control their interactions. You can use an Arduino to power anything from a self-watering garden to a fireworks display or even a self-driving car.

Arudino is especially popular for prototyping web-connected hardware, an emergent field of design sometimes called the “internet of things”. Take just about anything you can imagine, add an internet connection and the word “smart” as a prefix, and you’ve got yourself an IOT device. Smart toaster. Smart lamp. Smart socks.

While some devices can include their own displays and controls, these projects will often use a second device as a user interface. For example, you might control the color of a smart lightbulb an app on your phone.

Here’s where Framer X comes in. If you’re using Arduino to design and prototype a physical electronic system, you can also use Framer X to design and prototype a user interface for that system. And with some clever code, you can make that interface actually work, too.

Now that we know why we might use these two products together, let’s move on to the how. In short, we’ll be creating a small network that connects both our Framer X prototype and our Arduino project to a host. This will let the two projects trade messages.

If you’ve read a previous article, Multiplayer Prototypes with Framer X, then this should all sound very familiar. (You’ll even find some copy-and-pasted paragraphs from that article in the guide below). It’s not required reading, but it might help to work through that guide first.

Before we begin

You’ll need to set up a few things before starting this guide.

The first, of course, is Framer X itself. If you’re new to Framer X, you can download a free 14-day trial here.

You’ll also need to have Node.js installed on your computer. You might actually have this installed already — but if you’re not sure, or if you run into errors in the steps below, follow this guide to get set up.

As for hardware, you’ll need an Arduino board and a few components. For this tutorial, I’ll be using parts from the Arduino Uno Starter Kit. Here’s the full list of hardware:

  • Arduino Uno
  • USB 2.0 Type A/B Cable
  • Breadboard
  • Jumper wires
  • 10k Ohm resistor
  • Push button
  • One single-color LED

You’ll also need a Mac computer to run Framer X, and to which we’ll be connecting the Arduino. If you’re on a newer Macbook, you may need a USB C to USB converter.

Setting up the Arduino board

Set the Arduino board up according to this diagram and connect the board to your computer.

Setting up the Arduino software

You’ll also need the Arduino IDE, available for free from the Arduino website.

  1. Open the Arduino IDE.
  2. In the Arduino IDE, select File > Examples > Firmata > StandardFirmata in the menu. This loads the code that we’ll need to flash to the Arduino board.
  3. Upload the Sketch by pressing ⌘ + u or by selecting Sketch > Upload in the menu.

Ok, setup complete! We’re ready to begin.

Getting started

For this tutorial, I’ve prepared a starter file that has a lot of the harder parts worked out already. Let’s start with that.

  1. Download the starter file.
  2. Open the file in Framer X.
  3. Duplicate the file by selecting File > Duplicate in the Menu.
  4. Rename the file to something fun, like StarterArduinoA.
  5. Close the original starter file.

Our starter is ready, so we can start connecting the different parts of our project.

Connecting through a local host

In this tutorial, we’ll be setting up a little network consisting of a host and two several clients. The clients — our Framer X prototype and the Arduino board — will connect to the host, allowing the host to route messages between the clients. Click here for a visual.

In the starter file, I’ve included a host as well as a server that will make this host available to both the Arduino and our prototype. Before we can use the host, we’ll need to turn on the server. Note: If you’ve completed the multiplayer prototypes guide, this should feel very familiar.

  1. In Framer X, open your project’s Project Folder by selecting File > Show Project Folder. This should open a Finder window showing the project’s files.
  2. Now open the Terminal app. As a shortcut, press ⌘ + space, type “Terminal”, and select Terminal under Applications. Click here for a 5 second video.
  3. In Finder, click back into the Project Folder’s window.
  4. Open the Project Folder’s host folder in the Terminal app. Click on the folder named host, drag it to the dock, and release it on top of the Terminal app’s icon. If you’re stuck, click here for a 5 second video.
  5. In the Terminal window, type npm start and press Enter.
A Terminal window after starting the host’s server.

You should see the Server started message as shown above. If you instead see a message like command not found: npm, you’ll need to install Node.js. Complete that guide, then come back to the Terminal and try again.

If you do see the Server started message, then congratulations — your server is running and the host is listening for connections. (You’ve also completed the hardest part of this tutorial).

You can now connect to the host at the URL shown in the terminal.

Connecting our prototype to the host

Now that our server is running, let’s connect to it from our prototype.

  1. Click back into Framer X.
  2. On the canvas, select the Frame named Template.
  3. Open the Preview Window by pressing ⌘ + p or by clicking the play icon in the upper-right corner of the app.
  4. Open the Console by pressing ⌘ + i or by clicking on the Preview’s hamburger menu icon and clicking Show Console.
  5. Refresh the Preview by pressing ⌘ + r or by clicking the refresh icon next to the Preview window’s menu icon.

You should see a message in the console that reads Connected as shown above. This means that our prototype has successfully connected to the host and is ready to send and receive messages.

Now let’s connect our Arduino, too.

Connecting our Arduino to the host

For this demo, we’ll be using JavaScript to communicate with the Arduino. The process here is very similar to how we started our host server, however we’ll also be editing some code.

  1. In Framer X, open your project’s Project Folder by selecting File > Show Project Folder. This should open a Finder window showing the project’s files.
  2. Open Visual Studio Code.
  3. Open the Project Folder’s arduino folder in Visual Studio Code. Click on the folder named arduino, drag it to the dock, and release it on top of the Visual Studio Code app icon. Click here for a 5 second video.
  4. Open Visual Studio Code’s integrated terminal by selecting View > Terminal in the menu.
  5. In the integrated terminal, type npm start and press Enter.

You’ll see a few messages in the terminal as the project starts up and connects to the Arduino board, followed by a Connected message confirming that the Arduino has connected to the host server.

Testing the connection

Now that our little network is complete, it’s time to test it out!

  1. Click back into Framer X.
  2. Open or refresh the Preview.
  3. In the Preview, click on the switch to turn it on. If we have everything set up correctly, the board’s LED should turn on too. If your LED doesn’t turn on, check the Debugging section below.
  4. On the breadboard, press the button. In the Framer X Preview, the blue indicator should turn on.

If everything is working correctly, congratulations! You have a working connection between your Framer X prototype and your Arduino board — and you can skip the next section on debugging. If either step failed, read on for some tips.

Debugging

There are a few reasons why your setup may not be working.

Your Arduino circuit may not be set up correctly

Even if the software is connecting correctly, you may have made a mistake setting up the components on your breadboard. You’ll need to do some physical debugging: checking whether each wire is connected to the right place as shown in the diagram below.

Your host server is not running

Our two projects connect to one another through the host server. If the server isn’t running, they won’t be able to connect. Click back to the Terminal app and make sure that you still see a message like this:

In a pinch, you may need to stop the server and start it again.

  1. Press ^ + c to stop the server.
  2. Type npm start to start it back up.
  3. Click back into the Framer X preview.
  4. Refresh the Preview by pressing ⌘ + r or by clicking the refresh icon next to the Preview window’s menu icon.
  5. Test the connection again by flipping the LED switch and pressing the breadboard’s button.

Your Arduino project is not running

In order for the Arduino to connect to the host, you need to have started the project through Visual Studio Code’s integrated terminal. To check, click back into Visual Studio Code and make sure that you see still see a message like this:

If you’re still having problems, let me know if the Responses below!


Doing more with actions

In this last section, I’ll introduce the starter file’s action system and show how you can use the system to do more interesting things between your Arduino board and your Framer X prototype.

How it works

The network we’ve created is made up of three parts: a host and two clients, our Framer X project and our Arduino project. When a client connects to the host, the host adds the client to a list. When a client disconnects, the host removes it from the list.

Connecting to the host

Both our Framer X project and our Arduino project connect to the host by calling a function named connectToHost.

  • In our Framer X project, we call connectToHost from App.tsx.
  • In our Arduino project, we call connectToHost from index.js.

In both projects, we call this function with two arguments: the server’s URL and an object of responses (see Responses below).

The connectToHost function returns a second function, dispatch, that we can use to send actions to the host. (See Actions below).

Here’s the code in our Arduino project’s index.js showing our connection:

const serverUrl = "http://localhost:8080";const responses = {
CONNECT: () => console.log("Connected"),
DISCONNECT: () => console.log("Disconnected"),
FLIP_SWITCH: data => toggleLED(data.isOn)
};
const dispatch = connectToHost(serverUrl, responses);

Actions

The connection between a host and client allows either to dispatch actions that will be received by the other. When a client connects to the host, the host will listen for actions dispatched from that client; and likewise, the client will listen for actions dispatched from the host.

An action is a message with two parts: a name and (optionally) some data.

Here’s an example of an action:

"FLIP_SWITCH", { isOn: value }

And here is the same action being dispatched from the Switch override in our Framer X project’s App.tsx.

export function Switch(): Override {
return {
value: appState.switchIsOn,
onValueChange: value => {
dispatch("FLIP_SWITCH", { isOn: value })
},
}
}

Responses

Both clients have a set of responses for different actions. Responses are callback functions that take the action’s data as an argument and (usually) update the prototype’s state.

Here’s an example of a response:

FLIP_SWITCH: data => toggleLED(data.isOn)

And here it is again in our Arduino responses (from arduino/index.js).

const responses = {
CONNECT: () => console.log("Connected"),
DISCONNECT: () => console.log("Disconnected"),
FLIP_SWITCH: data => toggleLED(data.isOn),
}

The host forwards actions to clients

Whenever the host receives an action from a client, it will dispatch that action to each client on its list of connected clients. If the client has a response for this action, the client will call that response’s function with the action’s data as an argument.

That’s how it works.


Example: RGB Sliders

Now that we’ve learned the theory, let’s see it in practice. For this example, we’ll be controlling a common cathode RGB LED through a set of sliders.

Before we begin, let’s stop all the parts from our last project.

  1. Close the Terminal window. If asked if you want to terminate the process, select Terminate.
  2. Close the Visual Studio Code window.
  3. In Framer X, close the StarterArduinoA project.

That should give us a clean slate to work on for the new project. You can always go back to your previous project by:

  • setting up your Arduino circuit as shown in the first part of this article
  • opening StarterArduinoA
  • starting your host server
  • starting your Arduino project

These also happen to be the steps we’ll follow for this second project.

Setting up the board

Before we get into the code, set up your board as shown below. Note that in the diagram, the RGB LED’s longest leg should be second from the left (and connected to the black wire).

Setting up the Framer X project

Let’s also set up a new Framer X project.

  1. Click back into Framer X.
  2. Open up the original starter file by selecting File > Open Recent > ArduinoStarter.
  3. Duplicate the file by selecting File > Duplicate in the Menu.
  4. Rename the file to something neat, like StarterArduinoB.
  5. Close the original ArduinoStarter file — and StarterArduinoA, too.
  6. In the new StarterArduinoB file, delete the blue button-press indicator and Switch instance.

We’ll now have a clean start for our new project.

Laying out the prototype

For this example, we’ll be using three sliders to control the red, green and blue channels of our RGB LED. Let’s add them to our design now.

  1. Open the the Components Panel by clicking on the grid icon on the far-left, or by selecting View > Panels > Components in the menu.
  2. Click on the Learn Design System title to expand it.
  3. In the list of components, select the Slider component and drag it out onto the canvas.
  4. Place the Slider inside of the same Stack as the Switch component.
  5. Add two more Sliders to the Stack.

Let’s also make some changes to the Sliders’ properties through the component’s property controls.

  1. Select the top Slider.
  2. On the Properties Panel, change the Color property to Warn.
  3. Select the middle Slider and change its Color property to Secondary.
  4. We can leave the third Slider at Primary.

Writing the overrides

Now lets update our overrides file for these three sliders.

  1. In Framer X, open the Code Panel by clicking on the {} icon at the left hand side, or by selecting View > Panel > Code in the menu.
  2. In the files list, select the App.tsx file.
  3. Remove the FLIP_SWITCH and BUTTON_CHANGE responses.
  4. Remove the entire appState object.
  5. Remove the Switch and ButtonIndicator overrides.
  6. Add three new overrides for our Sliders.
export function RedSlider(): Override {
return {
onValueChange: value => {
dispatch("CHANGE_COLOR", {
color: "red",
value: value,
})
},
}
}
export function GreenSlider(): Override {
return {
onValueChange: value => {
dispatch("CHANGE_COLOR", {
color: "green",
value: value,
})
},
}
}
export function BlueSlider(): Override {
return {
onValueChange: value => {
dispatch("CHANGE_COLOR", {
color: "blue",
value: value,
})
},
}
}

In each of these overrides, we’re creating an event on the connected Slider. Each time the slider’s value changes, we’ll dispatch the new value under the name CHANGE_COLOR. The action’s data will contain two properties:

  • the name of the color channel ("red”, “green”, or “blue”)
  • the value from the slider (a number between 0 and 100).

Connecting the overrides

Before we’re done with our Framer X project, let’s connect the overrides we’ve just written to our Sliders.

  1. On the Canvas, select the red Slider.
  2. In the properties panel, select Overrides.
  3. In the File dropdown, select App.
  4. In the Override dropdown, select RedSlider.
  5. Repeat with GreenSlider and BlueSlider for the other two Sliders.

Click here for the full App.tsx code.

Ok, our Framer X project is all set up! We can leave it for a moment while we work on our Arduino project.

Starting our Host Server

But first! Let’s start our host server. These steps are the same as from earlier in the article — if you’re stuck on any steps check back above for more details.

  1. In Framer X, open your project’s Project Folder.
  2. Now open the Terminal app.
  3. In Finder, click back into the Project Folder’s window.
  4. Open the Project Folder’s host folder in the Terminal app.
  5. In the Terminal window, type npm start and press Enter.

Our host server should now be up and running again.

Writing our Arduino project

Now that we have our sliders set up to send actions when their values change, let’s edit the Arduino project to respond to those actions.

  1. In Finder, click back into your Framer X project’s Project Folder.
  2. Open the Project Folder’s arduino folder in Visual Studio Code.
  3. In the sidebar, select the file named index.js.

This file should look familiar: it’s using the same “client” as our App.tsx. If we read through the file, we can see the code that powered the starter file’s interactions.

The big difference betweeen this file and our Framer X code is that, rather than using Overrides to control code components, we’ll be using the johnny-five library to control the components on our Arduino board.

Let’s start by setting up those components:

  1. Under the // Components comment, remove the button and led components.
  2. In their place, create a new five.Led.RGB, passing it information about which of the Arduino board’s pins the LED is connected to. We’ll also need to “inject” it into the board’s event loop — and we’ll want to turn it on, too.
// Componentsconst led = new five.Led.RGB({
pins: [6, 5, 3],
});
board.repl.inject({
led: led
});

led.on();

Next, let’s add a little object to keep track of our LED’s color.

// Statelet rgb = {
red: 255,
green: 255,
blue: 255
};

Here’s a tricky part: we’ll need to turn these three colors into a hex code, like “#CCDD0F”. In order to do that, let’s bring in a tiny library named rgb-hex from NPM.

  1. Open Visual Studio Code’s integrated terminal by selecting View > Terminal in the menu.
  2. In the integrated terminal, type npm install rgb-hex and press Enter.

After a moment, you should see a confirmation message like this:

Before we can use the library, we’ll need to bring it into our file. At the very top of our project, you’ll see a few require statements. Let’s add a new one for rgb-hex.

var { connectToHost } = require("./client");
var five = require("johnny-five");
var board = new five.Board();
var rgbHex = require("rgb-hex");

Now let’s create a function that we can call whenever we receive a new action from our Framer X prototype. Remember that those actions will include two properties: the color (red, green or blue) and a value between 0 and 100.

// State changesconst updateColor = (color, value) => {
let intColor = Math.round((value / 100) * 255);
let hexColor = rgbHex(rgb.red, rgb.green, rgb.blue);

rgb[color] = intColor;
led.color(hexColor);
};

We’re doing four things in our updateColor function:

  • We’re turning our value from a number between 0 and 100 to an integer between 0 and 255.
  • Next, we’re then using the rgbHex turning all three of our colors (red, green and blue) into a hex color, like “#FFFFFF”.
  • Before we update the color, we add the integer color to our rgb state.
  • And then we update our LED’s color using the hex color.

Finally, let’s go back to our responses and tell our project when (and how) to run the updateColor function.

  1. Scroll back up in index.js to the file’s responses object.
  2. Add a new response named CHANGE_COLOR.
const responses = {
CONNECT: () => console.log("Connected"),
DISCONNECT: () => console.log("Disconnected"),
CHANGE_COLOR: data => updateColor(data.color, data.value)
};

When the Framer sliders send over a new action, we’ll respond to that action by calling updateColor with the color and value properties from the action’s data.

Click here for the full index.js code.

We’re done! All that’s left is to start our Arduino project.

  1. Click into Visual Studio Code’s integrated terminal.
  2. In the integrated terminal, type npm start and press Enter.

Putting it together

Now click back into Framer X, refresh the Preview and adjust the three sliders. If everything has gone correctly, your LED should change to reflect the values you set.


Wrapping Up

Ok, that was a lot! If you’d like to learn more about the action / response system, read my guide to connecting multiple Framer X prototypes. If you’d like to go further with the Arduino, I highly recommend exploring the examples on the johnny-five website.

I hope you’re able to flex creative on the starter file that I’ve provided and come up with something excellent. Whatever you make, please let me know! You can find me on Twitter at @steveruizok or on the Framer Slack or Spectrum channels.

As always, if you liked this article and want to see more like it, smash that clap button till you see fifties, share this article so that more people learn about flashing lights, and follow this account for lots more about design and prototyping and Framer X.

Good luck! 👋

Steve Ruiz

Written by

Design Educator at Framer.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade