Quantcast
Channel: SparkFun Tutorials
Viewing all 1123 articles
Browse latest View live

Secure DIY garage door opener

$
0
0

Secure DIY garage door opener a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1113

Introduction

Project showcase video.

If you'd like to increase the security of your garage door, or you are just interested in learning more about cryptography, then read on! At its core, this project is simply about a secure wireless button. This could be used to trigger any number of things, so we hope it can inspire message security on many other future projects.

I was surprized to learn that even if your garage door is fairly new, then you may still be vulnerable to man-in-the-middle or roll-jam attacks. With this tutorial, you can achieve an extremely high level of security utilizing ECC signatures and the SparkFun Cryptographic Co-processor.

If you'd like to read more about garage doors, here are two great articles about hacking and history.

Garage Door Hacking: What's the Deal?

A (Very) Short History of the Garage Door Opener

During my research for this project, I also came across an interesting story about garage doors in San Francisco. In 2004, military radio signals were jamming garage door openers. It seems that most garage door openers at the time were operating on the same frequency as a new military communications system (390 MHz). For more details, check out this CBS News article. After learning this, I was glad to know that my new setup is operating on 915MHz, and so shouldn't be effected.

Most communication channels are exposed to the world. Whether it's a hard wired connection or a wireless signal flying through the air, anyone can listen in and try to intercept, record and/or impersonate your signal. So how do we protect ourselves against these malicious attacks? Surprisingly, you can make a very robust solution with a couple of Pro RFs and our Cryptogrpahic Co-processors.

Suggested Reading

If you aren’t familiar with the following concepts, we recommend you read over these tutorials before continuing.

Serial Communication

Asynchronous serial communication concepts: packets, signal levels, baud rates, UARTs and more!

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

SparkFun SAMD21 Pro RF Hookup Guide

Using the super blazing, nay blinding, fast SAMD21 whipping clock cycles at 48MHz and the RFM96 module to connect to the Things Network (and other Radio woodles).

Qwiic Single Relay Hookup Guide

Get started switching those higher power loads around with the Qwiic Single Relay.

Three Quick Tips About Using U.FL

Quick tips regarding how to connect, protect, and disconnect U.FL connectors.

Cryptographic Co-Processor ATECC508A (Qwiic) Hookup Guide

Learn how to use some of the standard features of the SparkFun Cryptographic Co-processor.

The Secure Solution

We are going to use digital signatures to add security to our system. If you want to learn more about how to use the Cryptographic Co-processor, check out this tutorial and video. These will show you the fundamental ideas behind digital signatures, walk you through how to setup each co-processor.

For the secure garage door opener example shown here, we are going to do something very similar to Example 6 in the Arduino Library. A complete cycle will follow these steps:

  1. User presses button on remote to engage cycle.
  2. Remote sends a "request for token".
  3. Base generates a new random token (32-bytes).
  4. Base sends token to remote.
  5. Remote creates ECC signature on token (using its unique private key).
  6. Remote sends ECC signature to base.
  7. Base verifies signature using remote's public key.
  8. If verified, base opens garage.

What makes this so secure is the fact that the only place in the world that can create a valid signature is inside the remote's co-processor. This is because the private key was generated randomly during configuration and will never leave the IC. If you don't have that actual piece of hardware (the remote co-processor), you will never be able to create a signature.

Also, the fact that the base creates a new random token for each cycle, allows us to prevent against man-in-the-middle and roll-jam attacks.

Wahoo! That's one heck of a secure wireless button!

Hardware Overview

For this project, we need to build up two separate circuits. One will be the remote control (that lives in my car or bike), and the second will be the base transceiver that lives inside my garage (listening for the ECC signature, and then engaging the garage door button).

Remote Control:

  • Pro RF
  • Duck Antennae
  • Cryptographic Co-processor (for creating the ECC signature)
  • Enclosure
  • Button
  • 400mAh Lipo Battery
  • Qwiic Cable (QTY:1)

Base Transceiver:

  • Pro RF
  • Wire antennae
  • Cryptographic Co-processor (for creating the TTL token, and verifying the ECC signature)
  • SparkFun Qwiic Single Relay
  • Wire antennae
  • USB wall wort
  • Qwiic Cable (QTY:2)

For easy one click ordering, here is a wish list. Be sure to read the entire tutorial, and then adjust as necessary.

Hardware Hookup

All of these boards use qwiic, so that made things much easier and faster to hookup.

The Remote

For the remote control, there are only 4 connections that need to be made:

From/Device 1Connection TypeTo/Device 2
1. Pro RFQwiic CableCryptographic Co-processor
2. Lipo BatteryJSTPro RF
3. Duck AntennaeU.FL to SMA adapter cablePro RF
4. ButtonWireSwitch Headers on Pro RF

alt text

The remote control all wired up.

The Base Transceiver

The Base Transceiver also requires hooking up just 4 connections:

From/Device 1Connection TypeTo/Device 2
1. Power adapterUSBPro RF
2. Pro RFQwiic CableCryptographic Co-processor
3. Cryptographic Co-processorQwiic CableRelay
4. Relay COM & NOWireGarage door button

Note, the order of boards in the qwiic system didn't matter, but I put the relay last so I could position it for easier access. I also soldered to the PTH pins on the bottom of the screw pin terminal, but you could choose to do a solderless connection if you like.

alt text

The Base Transceiver all wired up.

Integration

To engage the garage door, I opted to emulate what a human does (press the button on the wall inside). I opened up the wall-mounted controller and saw this:

alt text

The wall-mounted garage door button opened up.

Aha! I recognize those mini push button switches.Upon further inspection, I saw that there are various passive components involved:

alt text

Backlight exposes the copper. Hmm... What is going on here?

Pretty neat how they are able to get three button control from simply two wires. I wonder if there is an ADC involved? Or maybe some sort of pulsing and time sensitive digital reads? Maybe an AC signal? What do you think?

For this project, I was only concerned with the lower momentary switch (aka the "big button"). From looking at the circuit board with backlight as shown above, I was able to see that the lower button simply connects the two leads together directly without any extra passives involved. With this in mind, I decided to use a relay and run it in parallel with the switch. I used a SparkFun Qwiic Single Relay to engage this button from my Arduino. I know this is probably overkill for the amount of current this will ever see, but I liked that this solution would be very easy to connect/control using qwiic and was a sure bet in emulating the button.

For the connection to the garage door wall-mounted button, I chose to open it up and solder to the connection points on either side of the button. After doing so, I actually realized that you could "tap" into the two wires out to the button anywhere in the line and potentially use the screw pin terminals on the relay for a solder-less connection point. Nevertheless, I used a couple XT-60 connectors on the lines, and this makes it pretty easy to take apart if necessary for re-programming.

alt text

Some slight hacking necssary to gain access to the garage door button

Power Considerations

In order to save power on the remote control, I opted to put a momentary push button in series on the power input. This way, power would only be connected when I wanted to open the garage door. Otherwise, it would remain completely off. Also, with a more traditional DPST switch, we'd me more likely to accidentally leave it switched on and drain the battery. Luckily, the ProRF has a couple headers already in the design for an external switch.

alt text

These switch headers made it easy to integrate the momentary power switch.

Now I wanted to consider how much power is actually being used during each attempt to open the garage door. I hooked up an SparkFun RedBoard Artemis and a Zio Current and Voltage Sensor - INA219 (Qwiic), and I had some data streaming in no time!

alt text

The Zio qwiic current setup to measure current draw on the system.

Here is what a complete cycle looked like on the serial plotter and monitor:

alt text

Serial plotter showing the current used during a complete cycle.

Each reading is precisely 100ms apart, so adding them all up I can see that it will use 0.065mAh per cycle.

21 readings (2100ms) at 36mA = 0.021mAh

1 reading (100ms) at 56mA = 0.002mAh

20 readings (2000ms) at 76mA = 0.042mAh

Total: 0.065mAh

Battery capacity is 400mAh

400mAh / 0.065mAh = 6,153

So according to my rough math, I think I can press this button 6153 times with this single battery. At 2 times a day, 300 days a year (600/year), that's 10 years. Even with capacity loss during storage in my car (let's say 10% each year), it'll still should last... let's see...

Year: capacity : -10% - yearly use for cycles (600 * 0.065 = ~40mAh)

Year 1 : 400 - 40 - 40 = 320

Year 2 : 320 - 32 - 40 = 248

Year 3 : 248 - 25 - 40 = 183

Year 4 : 183 - 18 - 40 = 125

Year 5 : 125 - 13 - 40 = 72

Year 6 : 72 - 7 - 40 = 25

Wahoo! Six years is pretty good. Now I just need to make sure it doesn't get squashed somewhere in my car.

Arduino Code

There are two separate sketches: one for the remote control and a second for the base transceiver. You can see both sketches in the project github repository located here:

The code used in this project was kept fairly clean by using three Arduino Libraries:

For help with installing each necessary Arduino library, see the individual hookup guides for the Qwiic Relay and Cryptographic Co-processor. But you can also check out a more general tutorial on Arduino library installation here:

Installing an Arduino Library

January 11, 2013

How do I install a custom Arduino library? It's easy! This tutorial will go over how to install an Arduino library using the Arduino Library Manager. For libraries not linked with the Arduino IDE, we will also go over manually installing an Arduino library.

Also, to use the SparkFun Pro RF, you will need to install the SamD boards packages. You can follow along how to do that at this section of the Pro RF Hookup Guide.

Now let's take a closer look at each individual sketch.

Remote Control Sketch

This sketch basically does everything inside its setup(). This is because, it will actually remain un-powered for most of its life. When I want to power it up and begin an entire attempt cycle, I will press the momentary button on the enclosure and this will supply power.

After setting up the RF module, the cryptographic co-processor and button, the most important thing to note is that it calls "attempt_cycle" at the very end of setup(). All the good stuff happens in there!

attempt_cycle() does essentially four things:

  • Engages a cycle by sending "$$$".
  • Receives 64-byte token.
  • Creates the ECC signature.
  • Sends Signature back to the base.

    /*
  Remote Control
  This sketch is used to create a cryptographically secure wireless controller to open you garage.
  The complete system uses SparkFun Pro RF modules, Cryptographic Co-processors, and the qwiic relay.
  Note, it also requires a base transceiver setup with separate sketch.

  See the complete tutorial here:
  https://learn.sparkfun.com/tutorials/secure-diy-garage-door-opener

  By: Pete Lewis
  SparkFun Electronics
  Date: January 13th, 2020
  License: This code is public domain but you can buy me a beer if you use this and we meet someday (Beerware license).

  Feel like supporting our work? Please buy a board from SparkFun!
  https://www.sparkfun.com/products/15573

  Some of this code is a modified version of the example provided by the Radio Head
  Library which can be found here:
  www.github.com/PaulStoffregen/RadioHeadd

  Some of this code is a modified version of the example provided by the SparkFun ATECCX08a
  Arduino Library which can be found here:
  https://github.com/sparkfun/SparkFun_ATECCX08a_Arduino_Library
*/

#include <SPI.h>

//Radio Head Library:
#include <RH_RF95.h>

// We need to provide the RFM95 module's chip select and interrupt pins to the
// rf95 instance below.On the SparkFun ProRF those pins are 12 and 6 respectively.
RH_RF95 rf95(12, 6);

int LED = 13; //Status LED is on pin 13

int packetCounter = 0; //Counts the number of packets sent
long timeSinceLastPacket = 0; //Tracks the time stamp of last packet received

// The broadcast frequency is set to 921.2, but the SADM21 ProRf operates
// anywhere in the range of 902-928MHz in the Americas.
// Europe operates in the frequencies 863-870, center frequency at 868MHz.
// This works but it is unknown how well the radio configures to this frequency:
//float frequency = 864.1;
float frequency = 921.2; //Broadcast frequency


//////////////crypto stuff

#include <SparkFun_ATECCX08a_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_ATECCX08a
#include <Wire.h>

ATECCX08A atecc;

uint8_t token[32]; // time to live token, created randomly each authentication event


/////////////

byte buf[RH_RF95_MAX_MESSAGE_LEN];

void setup()
{
  pinMode(LED, OUTPUT);

  SerialUSB.begin(115200);
  // It may be difficult to read serial messages on startup. The following line
  // will wait for serial to be ready before continuing. Comment out if not needed.
  //while (!SerialUSB);
  SerialUSB.println("RFM Client!");

  //Initialize the Radio.
  if (rf95.init() == false) {
    SerialUSB.println("Radio Init Failed - Freezing");
    while (1);
  }
  else {
    //An LED inidicator to let us know radio initialization has completed.
    //SerialUSB.println("Transmitter up!");
    //digitalWrite(LED, HIGH);
    //delay(500);
    //digitalWrite(LED, LOW);
    //delay(500);
  }

  // Set frequency
  rf95.setFrequency(frequency);

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
  // you can set transmitter powers from 5 to 23 dBm:
  // Transmitter power can range from 14-20dbm.
  rf95.setTxPower(14, false);

  pinMode(5, INPUT_PULLUP);

  Wire.begin();

  if (atecc.begin() == true)
  {
    SerialUSB.println("Successful wakeUp(). I2C connections are good.");
  }
  else
  {
    SerialUSB.println("Device not found. Check wiring.");
    while (1); // stall out forever
  }

  attempt_cycle();

}


void loop()
{

  if (digitalRead(5) == LOW)
  {
//    attempt_cycle();
  }
  delay(10); // button debounce
}


void printBuf64()
{
  SerialUSB.println();
  SerialUSB.println("uint8_t buf[64] = {");
  for (int i = 0; i < 32 ; i++)
  {
    SerialUSB.print("0x");
    if ((buf[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(buf[i], HEX);
    if (i != 31) SerialUSB.print(", ");
    if ((31 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void printToken()
{
  SerialUSB.println();
  SerialUSB.println("uint8_t token[32] = {");
  for (int i = 0; i < sizeof(token) ; i++)
  {
    SerialUSB.print("0x");
    if ((token[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(token[i], HEX);
    if (i != 31) SerialUSB.print(", ");
    if ((31 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}


// Note, in Example4_Alice we are printing the signature we JUST created,
// and it lives inside the library as a public array called "atecc.signature"
void printSignature()
{
  SerialUSB.println("uint8_t signature[64] = {");
  for (int i = 0; i < sizeof(atecc.signature) ; i++)
  {
    SerialUSB.print("0x");
    if ((atecc.signature[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(atecc.signature[i], HEX);
    if (i != 63) SerialUSB.print(", ");
    if ((63 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void attempt_cycle()
{
  SerialUSB.println("Sending message");

  //Send a message to the other radio
  uint8_t toSend[] = "$$$";
  //sprintf(toSend, "Hi, my counter is: %d", packetCounter++);
  rf95.send(toSend, sizeof(toSend));
  rf95.waitPacketSent();

  // Now wait for a reply

  byte len = sizeof(buf);

  if (rf95.waitAvailableTimeout(2000)) {
    // Should be a reply message for us now
    if (rf95.recv(buf, &len)) {
      SerialUSB.print("Got reply: ");
      printBuf64();
      for (int i = 0 ; i < 32 ; i++) token[i] = buf[i]; // read in token from buffer.
      printToken(); // nice debug to see what token we just sent. see function below

      boolean sigStat = false;
      sigStat = atecc.createSignature(token); // by default, this uses the private key securely stored and locked in slot 0.

      SerialUSB.print("sigStat: ");
      SerialUSB.println(sigStat);

      //printSignature();


      // Copy our signature from library array to local toSend array
      //for (int i = 0 ; i < 64 ; i++) toSend[i] = atecc.signature[i]; // store locally

      //Send signature to the other radio
      rf95.send(atecc.signature, sizeof(atecc.signature));
      rf95.waitPacketSent();
      SerialUSB.println("Sent signature");
      //SerialUSB.println((char*)buf);
      //SerialUSB.print(" RSSI: ");
      //SerialUSB.print(rf95.lastRssi(), DEC);
    }
    else {
      SerialUSB.println("Receive failed");
    }
  }
  else {
    SerialUSB.println("No reply, is the receiver running?");
  }
  delay(500);
}

Base Transceiver Sketch

This sketch is very similar to the first Example Sketch in our hookup guide for the Pro RF: Point to Point Radio Arduino Examples In fact, that's were I started from. And then I added in the necessary libraries for the Cryptographic chip and the qwiic relay. And then I stole some code from each of their initial examples. A whole lot of copy/paste going on. Isn't that convenient, Gromit!

Inside the main loop, the Base does the following:

  • Listens to incoming messages.
  • If it receives a "$$$", then create a new random token and send it to remote.
  • Listens for a signature from remote.
  • Receives 64-byte signature.
  • Verifies signature.
  • If valid, trigger relay to "close" for 500ms, emulating a button press.
  • If success hasn't happened within 1 second, destroy token. This protects against repeater attacks.

Note, whenever the Base hears any message come in, it checks for the "$$$". This will tell it if the message is an request or a signature. If it doesn't see "$$$" then it pulls in the next 64 bytes and attempts to verify the signature.

/*
  Base Transceiver
  This sketch is used to create a cryptographically secure wireless controller to open you garage.
  The complete system uses SparkFun Pro RF modules, Cryptographic Co-processors, and the qwiic relay.
  Note, it also requires a remote control setup with separate sketch.

  See the complete tutorial here:
  https://learn.sparkfun.com/tutorials/secure-diy-garage-door-opener

  By: Pete Lewis
  SparkFun Electronics
  Date: January 13th, 2020
  License: This code is public domain but you can buy me a beer if you use this and we meet someday (Beerware license).

  Feel like supporting our work? Please buy a board from SparkFun!
  https://www.sparkfun.com/products/15573

  Some of this code is a modified version of the example provided by the Radio Head
  Library which can be found here:
  www.github.com/PaulStoffregen/RadioHeadd

  Some of this code is a modified version of the example provided by the SparkFun ATECCX08a
  Arduino Library which can be found here:
  https://github.com/sparkfun/SparkFun_ATECCX08a_Arduino_Library

  Some of the code is a modified version of the example provided by the SparkFun Qwiic
  Relay Arduino Library which can be found here:
  https://github.com/sparkfun/SparkFun_Qwiic_Relay_Arduino_Library
*/



#include <SPI.h>

//Radio Head Library:
#include <RH_RF95.h>

// We need to provide the RFM95 module's chip select and interrupt pins to the
// rf95 instance below.On the SparkFun ProRF those pins are 12 and 6 respectively.
RH_RF95 rf95(12, 6);

int LED = 13; //Status LED on pin 13

int successLED = 3; // green
int failLED = 4; // red
int statLED = 2; // blue

int packetCounter = 0; //Counts the number of packets sent
long timeSinceLastPacket = 0; //Tracks the time stamp of last packet received
// The broadcast frequency is set to 921.2, but the SADM21 ProRf operates
// anywhere in the range of 902-928MHz in the Americas.
// Europe operates in the frequencies 863-870, center frequency at
// 868MHz.This works but it is unknown how well the radio configures to this frequency:
//float frequency = 864.1;
float frequency = 921.2;

uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];


////////////////relay

#include "SparkFun_Qwiic_Relay.h"

#define RELAY_ADDR 0x18 // Alternate address 0x19


Qwiic_Relay relay(RELAY_ADDR);

////////////////

/////////////////crypto

#include <SparkFun_ATECCX08a_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_ATECCX08a
#include <Wire.h>

ATECCX08A atecc;

uint8_t token[32]; // time to live token, created randomly each authentication event

uint8_t signature[64]; // incoming signature from Alice

int headerCount = 0; // used to count incoming "$", when we reach 3 we know it's a good fresh new message.

// Alice's public key.
// Note, this will be unique to each co-processor, so your will be different.
// copy/paste Alice's true unique public key from her terminal printout in Example6_Challenge_Alice.

uint8_t AlicesPublicKey[64] = {
  0x38, 0xD6, 0xE5, 0x49, 0xAC, 0x57, 0x2D, 0x1F, 0xD0, 0x58, 0x0A, 0xE8, 0x59, 0xB8, 0xF8, 0x20,
  0x1E, 0x0A, 0x7E, 0x8D, 0x5B, 0x7D, 0xD9, 0x8A, 0x26, 0xAF, 0x88, 0x73, 0x6D, 0x8C, 0xB7, 0x2D,
  0x8D, 0x3A, 0xB9, 0x5F, 0x60, 0x9D, 0x3F, 0x49, 0x72, 0xF1, 0x44, 0x74, 0x82, 0x3F, 0x7B, 0xCF,
  0x1F, 0x18, 0xD3, 0xA4, 0xBF, 0x62, 0x15, 0xCC, 0xAF, 0xAD, 0x7E, 0x03, 0xD8, 0xE9, 0x93, 0x7E
};

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(successLED, OUTPUT);
  pinMode(failLED, OUTPUT);
  pinMode(statLED, OUTPUT);

  SerialUSB.begin(115200);
  // It may be difficult to read serial messages on startup. The following
  // line will wait for serial to be ready before continuing. Comment out if not needed.
  //while (!SerialUSB);
  SerialUSB.println("RFM Server!");

  //Initialize the Radio.
  if (rf95.init() == false) {
    SerialUSB.println("Radio Init Failed - Freezing");
    while (1);
  }
  else {
    // An LED indicator to let us know radio initialization has completed.
    SerialUSB.println("Receiver up!");
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
  }

  rf95.setFrequency(frequency);

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
  // you can set transmitter powers from 5 to 23 dBm:
  // rf95.setTxPower(14, false);


  Wire.begin();

  if (atecc.begin() == true)
  {
    SerialUSB.println("Successful wakeUp(). I2C connections are good.");
  }
  else
  {
    SerialUSB.println("Device not found. Check wiring.");
    while (1); // stall out forever
  }

  if (!relay.begin())
  {
    Serial.println("Check connections to Qwiic Relay.");
    while (1); // stall out forever
  }
  else
  {
    Serial.println("Qwiic Relay is ready to go.");
  }

}

void loop()
{
  if (rf95.available()) {
    // Should be a message for us now

    uint8_t len = sizeof(buf);

    if (rf95.recv(buf, &len)) {
      digitalWrite(LED, HIGH); //Turn on status LED
      timeSinceLastPacket = millis(); //Timestamp this packet

      SerialUSB.print("Got message: ");
      printBuf64();
      //SerialUSB.print(" RSSI: ");
      //SerialUSB.print(rf95.lastRssi(), DEC);
      SerialUSB.println();

      // if message from Alice is "$$$", Send a random token for her to sign.
      if (buf[0] == '$' && buf[1] == '$' && buf[2] == '$')
      {
        SerialUSB.println("Received $$$. Creating a new random TTL-token now...");

        // update library instance public variable.
        atecc.updateRandom32Bytes();

        uint8_t toSend[32];
        // copy from library public variable into our local variable
        for (int i = 0 ; i < 32 ; i++)
        {
          token[i] = atecc.random32Bytes[i]; // store locally
        }

        rf95.send(token, sizeof(token));
        rf95.waitPacketSent();
        SerialUSB.println("Sent token");
        digitalWrite(LED, LOW); //Turn off status LED
      }
      else // this means Alice just sent us a signature
      {
        SerialUSB.println("Received signature. Verifying now...");
        for (int i = 0 ; i < 64 ; i++) signature[i] = buf[i]; // read in signature from buffer.
        printSignature();
        // Let's verirfy!
        if (atecc.verifySignature(token, signature, AlicesPublicKey))
        {
          SerialUSB.println("Success! Signature Verified.");
          // Let's turn on the relay...
          relay.turnRelayOn();
          delay(1000);
          // Let's turn that relay off...
          relay.turnRelayOff();
          blinkStatus(successLED);
        }
        else
        {
          SerialUSB.println("Verification failure.");
          blinkStatus(failLED);
        }
      }

    }
    else
      SerialUSB.println("Recieve failed");
  }
  //Turn off status LED if we haven't received a packet after 1s
  if (millis() - timeSinceLastPacket > 1000) {
    digitalWrite(LED, LOW); //Turn off status LED
    timeSinceLastPacket = millis(); //Don't write LED but every 1s
    clearBuf();
    // destory token, to require a new cycle if this doesn't complete within 1 second
    for (int i = 0 ; i < 32 ; i++)
    {
      token[i] = 0x00;
    }
  }
}


void printSignature()
{
  SerialUSB.println("uint8_t signature[64] = {");
  for (int i = 0; i < sizeof(signature) ; i++)
  {
    SerialUSB.print("0x");
    if ((signature[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(signature[i], HEX);
    if (i != 63) SerialUSB.print(", ");
    if ((63 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void printBuf64()
{
  SerialUSB.println();
  SerialUSB.println("uint8_t buf[64] = {");
  for (int i = 0; i < 64 ; i++)
  {
    SerialUSB.print("0x");
    if ((buf[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(buf[i], HEX);
    if (i != 63) SerialUSB.print(", ");
    if ((63 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void clearBuf()
{
  for (int i = 0; i < 64 ; i++) buf[i] = 0x00;
}

void blinkStatus(int LED)
{
  digitalWrite(LED, HIGH);
  delay(2000);
  digitalWrite(LED, LOW);
  delay(500);
}

Resources & Going Further

Now that you've incorporated ECC authentication security into your garage door opener, you can add security to any future project they may need it. How about your internet-connected front door?

For more information, check out the resources below:

Project Source Code:

Hookup Guides:

Arduino Libraries:

Videos:

Need inspiration? Check out some of the Qwiic or IoT related tutorials!

CCS811/BME280 (Qwiic) Environmental Combo Breakout Hookup Guide

Sense various environmental conditions such as temperature, humidity, barometric pressure, eCO2 and tVOCs with the CCS811 and BME280 combo breakout board.

SparkFun Qwiic RFID-IDXXLA Hookup Guide

The Qwiic RFID ID-XXLA is an I2C solution that pairs with the ID-LA modules: ID-3LA, the ID-12LA, or the ID-20LA, and utilizes 125kHz RFID chips. Let's take a look at the hardware used for this tutorial.

Qwiic Pro Kit Project Guide

The Qwiic Pro Kit was designed to allow users to get started with Arduino without the need for soldering or a breadboard. We've included three inputs (a joystick, accelerometer, and proximity sensor) and one display that can be daisy chained to the RedBoard Turbo (SAMD21) Development Board.

GPS Geo-Mapping at the Push of a Button

Let's ramp up our GPS tracking skills with KML files and Google Earth. We'll make a tracker that logs location and allows us to visualize our steps with Google Earth.

Experiment Guide for the Johnny-Five Inventor's Kit

Use the Tessel 2 and the Johnny Five Inventors kit to explore the world of JavaScript enabled hardware through 14 awesome experiments!

Getting Started with the Tessel 2

Get your Tessel 2 up and running by blinking and LED, the Hello World of embedded electronics.

Three Quick Tips About Using U.FL

Quick tips regarding how to connect, protect, and disconnect U.FL connectors.

Hookup Guide for the SparkFun RedBoard Artemis

Get started with the RedBoard Artemis - all the functionality of the SparkFun Artemis module wrapped in the familiar Uno footprint

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado


Secure DIY Garage Door Opener

$
0
0

Secure DIY Garage Door Opener a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1113

Introduction

Project showcase video.

If you'd like to increase the security of your garage door, or you are just interested in learning more about cryptography, then read on! At its core, this project is simply about a secure wireless button. This could be used to trigger any number of things, so we hope it can inspire message security on many other future projects.

I was surprized to learn that even if your garage door is fairly new, then you may still be vulnerable to man-in-the-middle or roll-jam attacks. With this tutorial, you can achieve an extremely high level of security utilizing ECC signatures and the SparkFun Cryptographic Co-processor.

If you'd like to read more about garage doors, here are two great articles about hacking and history.

Garage Door Hacking: What's the Deal?

A (Very) Short History of the Garage Door Opener

During my research for this project, I also came across an interesting story about garage doors in San Francisco. In 2004, military radio signals were jamming garage door openers. It seems that most garage door openers at the time were operating on the same frequency as a new military communications system (390 MHz). For more details, check out this CBS News article. After learning this, I was glad to know that my new setup is operating on 915MHz, and so shouldn't be effected.

Most communication channels are exposed to the world. Whether it's a hard wired connection or a wireless signal flying through the air, anyone can listen in and try to intercept, record and/or impersonate your signal. So how do we protect ourselves against these malicious attacks? Surprisingly, you can make a very robust solution with a couple of Pro RFs and our Cryptogrpahic Co-processors.

Suggested Reading

If you aren’t familiar with the following concepts, we recommend you read over these tutorials before continuing.

Serial Communication

Asynchronous serial communication concepts: packets, signal levels, baud rates, UARTs and more!

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

SparkFun SAMD21 Pro RF Hookup Guide

Using the super blazing, nay blinding, fast SAMD21 whipping clock cycles at 48MHz and the RFM96 module to connect to the Things Network (and other Radio woodles).

Qwiic Single Relay Hookup Guide

Get started switching those higher power loads around with the Qwiic Single Relay.

Three Quick Tips About Using U.FL

Quick tips regarding how to connect, protect, and disconnect U.FL connectors.

Cryptographic Co-Processor ATECC508A (Qwiic) Hookup Guide

Learn how to use some of the standard features of the SparkFun Cryptographic Co-processor.

The Secure Solution

We are going to use digital signatures to add security to our system. If you want to learn more about how to use the Cryptographic Co-processor, check out this tutorial and video. These will show you the fundamental ideas behind digital signatures, walk you through how to setup each co-processor.

For the secure garage door opener example shown here, we are going to do something very similar to Example 6 in the Arduino Library. A complete cycle will follow these steps:

  1. User presses button on remote to engage cycle.
  2. Remote sends a "request for token".
  3. Base generates a new random token (32-bytes).
  4. Base sends token to remote.
  5. Remote creates ECC signature on token (using its unique private key).
  6. Remote sends ECC signature to base.
  7. Base verifies signature using remote's public key.
  8. If verified, base opens garage.

What makes this so secure is the fact that the only place in the world that can create a valid signature is inside the remote's co-processor. This is because the private key was generated randomly during configuration and will never leave the IC. If you don't have that actual piece of hardware (the remote co-processor), you will never be able to create a signature.

Also, the fact that the base creates a new random token for each cycle, allows us to prevent against man-in-the-middle and roll-jam attacks.

Wahoo! That's one heck of a secure wireless button!

Hardware Overview

For this project, we need to build up two separate circuits. One will be the remote control (that lives in my car or bike), and the second will be the base transceiver that lives inside my garage (listening for the ECC signature, and then engaging the garage door button).

Remote Control:

  • Pro RF
  • Duck Antennae
  • Cryptographic Co-processor (for creating the ECC signature)
  • Enclosure
  • Button
  • 400mAh Lipo Battery
  • Qwiic Cable (QTY:1)

Base Transceiver:

  • Pro RF
  • Wire antennae
  • Cryptographic Co-processor (for creating the TTL token, and verifying the ECC signature)
  • SparkFun Qwiic Single Relay
  • Wire antennae
  • USB wall wort
  • Qwiic Cable (QTY:2)

For easy one click ordering, here is a wish list. Be sure to read the entire tutorial, and then adjust as necessary.

Hardware Hookup

All of these boards use qwiic, so that made things much easier and faster to hookup.

The Remote

For the remote control, there are only 4 connections that need to be made:

From/Device 1Connection TypeTo/Device 2
1. Pro RFQwiic CableCryptographic Co-processor
2. Lipo BatteryJSTPro RF
3. Duck AntennaeU.FL to SMA adapter cablePro RF
4. ButtonWireSwitch Headers on Pro RF

alt text

The remote control all wired up.

The Base Transceiver

The Base Transceiver also requires hooking up just 4 connections:

From/Device 1Connection TypeTo/Device 2
1. Power adapterUSBPro RF
2. Pro RFQwiic CableCryptographic Co-processor
3. Cryptographic Co-processorQwiic CableRelay
4. Relay COM & NOWireGarage door button

Note, the order of boards in the qwiic system didn't matter, but I put the relay last so I could position it for easier access. I also soldered to the PTH pins on the bottom of the screw pin terminal, but you could choose to do a solderless connection if you like.

alt text

The Base Transceiver all wired up.

Integration

To engage the garage door, I opted to emulate what a human does (press the button on the wall inside). I opened up the wall-mounted controller and saw this:

alt text

The wall-mounted garage door button opened up.

Aha! I recognize those mini push button switches.Upon further inspection, I saw that there are various passive components involved:

alt text

Backlight exposes the copper. Hmm... What is going on here?

Pretty neat how they are able to get three button control from simply two wires. I wonder if there is an ADC involved? Or maybe some sort of pulsing and time sensitive digital reads? Maybe an AC signal? What do you think?

For this project, I was only concerned with the lower momentary switch (aka the "big button"). From looking at the circuit board with backlight as shown above, I was able to see that the lower button simply connects the two leads together directly without any extra passives involved. With this in mind, I decided to use a relay and run it in parallel with the switch. I used a SparkFun Qwiic Single Relay to engage this button from my Arduino. I know this is probably overkill for the amount of current this will ever see, but I liked that this solution would be very easy to connect/control using qwiic and was a sure bet in emulating the button.

For the connection to the garage door wall-mounted button, I chose to open it up and solder to the connection points on either side of the button. After doing so, I actually realized that you could "tap" into the two wires out to the button anywhere in the line and potentially use the screw pin terminals on the relay for a solder-less connection point. Nevertheless, I used a couple XT-60 connectors on the lines, and this makes it pretty easy to take apart if necessary for re-programming.

alt text

Some slight hacking necssary to gain access to the garage door button

Power Considerations

In order to save power on the remote control, I opted to put a momentary push button in series on the power input. This way, power would only be connected when I wanted to open the garage door. Otherwise, it would remain completely off. Also, with a more traditional DPST switch, we'd me more likely to accidentally leave it switched on and drain the battery. Luckily, the ProRF has a couple headers already in the design for an external switch.

alt text

These switch headers made it easy to integrate the momentary power switch.

Now I wanted to consider how much power is actually being used during each attempt to open the garage door. I hooked up an SparkFun RedBoard Artemis and a Zio Current and Voltage Sensor - INA219 (Qwiic), and I had some data streaming in no time!

alt text

The Zio qwiic current setup to measure current draw on the system.

Here is what a complete cycle looked like on the serial plotter and monitor:

alt text

Serial plotter showing the current used during a complete cycle.

Each reading is precisely 100ms apart, so adding them all up I can see that it will use 0.065mAh per cycle.

21 readings (2100ms) at 36mA = 0.021mAh

1 reading (100ms) at 56mA = 0.002mAh

20 readings (2000ms) at 76mA = 0.042mAh

Total: 0.065mAh

Battery capacity is 400mAh

400mAh / 0.065mAh = 6,153

So according to my rough math, I think I can press this button 6153 times with this single battery. At 2 times a day, 300 days a year (600/year), that's 10 years. Even with capacity loss during storage in my car (let's say 10% each year), it'll still should last... let's see...

Year: capacity : -10% - yearly use for cycles (600 * 0.065 = ~40mAh)

Year 1 : 400 - 40 - 40 = 320

Year 2 : 320 - 32 - 40 = 248

Year 3 : 248 - 25 - 40 = 183

Year 4 : 183 - 18 - 40 = 125

Year 5 : 125 - 13 - 40 = 72

Year 6 : 72 - 7 - 40 = 25

Wahoo! Six years is pretty good. Now I just need to make sure it doesn't get squashed somewhere in my car.

Arduino Code

There are two separate sketches: one for the remote control and a second for the base transceiver. You can see both sketches in the project github repository located here:

The code used in this project was kept fairly clean by using three Arduino Libraries:

For help with installing each necessary Arduino library, see the individual hookup guides for the Qwiic Relay and Cryptographic Co-processor. But you can also check out a more general tutorial on Arduino library installation here:

Installing an Arduino Library

January 11, 2013

How do I install a custom Arduino library? It's easy! This tutorial will go over how to install an Arduino library using the Arduino Library Manager. For libraries not linked with the Arduino IDE, we will also go over manually installing an Arduino library.

Also, to use the SparkFun Pro RF, you will need to install the SamD boards packages. You can follow along how to do that at this section of the Pro RF Hookup Guide.

Now let's take a closer look at each individual sketch.

Remote Control Sketch

This sketch basically does everything inside its setup(). This is because, it will actually remain un-powered for most of its life. When I want to power it up and begin an entire attempt cycle, I will press the momentary button on the enclosure and this will supply power.

After setting up the RF module, the cryptographic co-processor and button, the most important thing to note is that it calls "attempt_cycle" at the very end of setup(). All the good stuff happens in there!

attempt_cycle() does essentially four things:

  • Engages a cycle by sending "$$$".
  • Receives 64-byte token.
  • Creates the ECC signature.
  • Sends Signature back to the base.

    /*
  Remote Control
  This sketch is used to create a cryptographically secure wireless controller to open you garage.
  The complete system uses SparkFun Pro RF modules, Cryptographic Co-processors, and the qwiic relay.
  Note, it also requires a base transceiver setup with separate sketch.

  See the complete tutorial here:
  https://learn.sparkfun.com/tutorials/secure-diy-garage-door-opener

  By: Pete Lewis
  SparkFun Electronics
  Date: January 13th, 2020
  License: This code is public domain but you can buy me a beer if you use this and we meet someday (Beerware license).

  Feel like supporting our work? Please buy a board from SparkFun!
  https://www.sparkfun.com/products/15573

  Some of this code is a modified version of the example provided by the Radio Head
  Library which can be found here:
  www.github.com/PaulStoffregen/RadioHeadd

  Some of this code is a modified version of the example provided by the SparkFun ATECCX08a
  Arduino Library which can be found here:
  https://github.com/sparkfun/SparkFun_ATECCX08a_Arduino_Library
*/

#include <SPI.h>

//Radio Head Library:
#include <RH_RF95.h>

// We need to provide the RFM95 module's chip select and interrupt pins to the
// rf95 instance below.On the SparkFun ProRF those pins are 12 and 6 respectively.
RH_RF95 rf95(12, 6);

int LED = 13; //Status LED is on pin 13

int packetCounter = 0; //Counts the number of packets sent
long timeSinceLastPacket = 0; //Tracks the time stamp of last packet received

// The broadcast frequency is set to 921.2, but the SADM21 ProRf operates
// anywhere in the range of 902-928MHz in the Americas.
// Europe operates in the frequencies 863-870, center frequency at 868MHz.
// This works but it is unknown how well the radio configures to this frequency:
//float frequency = 864.1;
float frequency = 921.2; //Broadcast frequency


//////////////crypto stuff

#include <SparkFun_ATECCX08a_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_ATECCX08a
#include <Wire.h>

ATECCX08A atecc;

uint8_t token[32]; // time to live token, created randomly each authentication event


/////////////

byte buf[RH_RF95_MAX_MESSAGE_LEN];

void setup()
{
  pinMode(LED, OUTPUT);

  SerialUSB.begin(115200);
  // It may be difficult to read serial messages on startup. The following line
  // will wait for serial to be ready before continuing. Comment out if not needed.
  //while (!SerialUSB);
  SerialUSB.println("RFM Client!");

  //Initialize the Radio.
  if (rf95.init() == false) {
    SerialUSB.println("Radio Init Failed - Freezing");
    while (1);
  }
  else {
    //An LED inidicator to let us know radio initialization has completed.
    //SerialUSB.println("Transmitter up!");
    //digitalWrite(LED, HIGH);
    //delay(500);
    //digitalWrite(LED, LOW);
    //delay(500);
  }

  // Set frequency
  rf95.setFrequency(frequency);

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
  // you can set transmitter powers from 5 to 23 dBm:
  // Transmitter power can range from 14-20dbm.
  rf95.setTxPower(14, false);

  pinMode(5, INPUT_PULLUP);

  Wire.begin();

  if (atecc.begin() == true)
  {
    SerialUSB.println("Successful wakeUp(). I2C connections are good.");
  }
  else
  {
    SerialUSB.println("Device not found. Check wiring.");
    while (1); // stall out forever
  }

  attempt_cycle();

}


void loop()
{

  if (digitalRead(5) == LOW)
  {
//    attempt_cycle();
  }
  delay(10); // button debounce
}


void printBuf64()
{
  SerialUSB.println();
  SerialUSB.println("uint8_t buf[64] = {");
  for (int i = 0; i < 32 ; i++)
  {
    SerialUSB.print("0x");
    if ((buf[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(buf[i], HEX);
    if (i != 31) SerialUSB.print(", ");
    if ((31 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void printToken()
{
  SerialUSB.println();
  SerialUSB.println("uint8_t token[32] = {");
  for (int i = 0; i < sizeof(token) ; i++)
  {
    SerialUSB.print("0x");
    if ((token[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(token[i], HEX);
    if (i != 31) SerialUSB.print(", ");
    if ((31 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}


// Note, in Example4_Alice we are printing the signature we JUST created,
// and it lives inside the library as a public array called "atecc.signature"
void printSignature()
{
  SerialUSB.println("uint8_t signature[64] = {");
  for (int i = 0; i < sizeof(atecc.signature) ; i++)
  {
    SerialUSB.print("0x");
    if ((atecc.signature[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(atecc.signature[i], HEX);
    if (i != 63) SerialUSB.print(", ");
    if ((63 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void attempt_cycle()
{
  SerialUSB.println("Sending message");

  //Send a message to the other radio
  uint8_t toSend[] = "$$$";
  //sprintf(toSend, "Hi, my counter is: %d", packetCounter++);
  rf95.send(toSend, sizeof(toSend));
  rf95.waitPacketSent();

  // Now wait for a reply

  byte len = sizeof(buf);

  if (rf95.waitAvailableTimeout(2000)) {
    // Should be a reply message for us now
    if (rf95.recv(buf, &len)) {
      SerialUSB.print("Got reply: ");
      printBuf64();
      for (int i = 0 ; i < 32 ; i++) token[i] = buf[i]; // read in token from buffer.
      printToken(); // nice debug to see what token we just sent. see function below

      boolean sigStat = false;
      sigStat = atecc.createSignature(token); // by default, this uses the private key securely stored and locked in slot 0.

      SerialUSB.print("sigStat: ");
      SerialUSB.println(sigStat);

      //printSignature();


      // Copy our signature from library array to local toSend array
      //for (int i = 0 ; i < 64 ; i++) toSend[i] = atecc.signature[i]; // store locally

      //Send signature to the other radio
      rf95.send(atecc.signature, sizeof(atecc.signature));
      rf95.waitPacketSent();
      SerialUSB.println("Sent signature");
      //SerialUSB.println((char*)buf);
      //SerialUSB.print(" RSSI: ");
      //SerialUSB.print(rf95.lastRssi(), DEC);
    }
    else {
      SerialUSB.println("Receive failed");
    }
  }
  else {
    SerialUSB.println("No reply, is the receiver running?");
  }
  delay(500);
}

Base Transceiver Sketch

This sketch is very similar to the first Example Sketch in our hookup guide for the Pro RF: Point to Point Radio Arduino Examples In fact, that's were I started from. And then I added in the necessary libraries for the Cryptographic chip and the qwiic relay. And then I stole some code from each of their initial examples. A whole lot of copy/paste going on. Isn't that convenient, Gromit!

Inside the main loop, the Base does the following:

  • Listens to incoming messages.
  • If it receives a "$$$", then create a new random token and send it to remote.
  • Listens for a signature from remote.
  • Receives 64-byte signature.
  • Verifies signature.
  • If valid, trigger relay to "close" for 500ms, emulating a button press.
  • If success hasn't happened within 1 second, destroy token. This protects against repeater attacks.

Note, whenever the Base hears any message come in, it checks for the "$$$". This will tell it if the message is an request or a signature. If it doesn't see "$$$" then it pulls in the next 64 bytes and attempts to verify the signature.

/*
  Base Transceiver
  This sketch is used to create a cryptographically secure wireless controller to open you garage.
  The complete system uses SparkFun Pro RF modules, Cryptographic Co-processors, and the qwiic relay.
  Note, it also requires a remote control setup with separate sketch.

  See the complete tutorial here:
  https://learn.sparkfun.com/tutorials/secure-diy-garage-door-opener

  By: Pete Lewis
  SparkFun Electronics
  Date: January 13th, 2020
  License: This code is public domain but you can buy me a beer if you use this and we meet someday (Beerware license).

  Feel like supporting our work? Please buy a board from SparkFun!
  https://www.sparkfun.com/products/15573

  Some of this code is a modified version of the example provided by the Radio Head
  Library which can be found here:
  www.github.com/PaulStoffregen/RadioHeadd

  Some of this code is a modified version of the example provided by the SparkFun ATECCX08a
  Arduino Library which can be found here:
  https://github.com/sparkfun/SparkFun_ATECCX08a_Arduino_Library

  Some of the code is a modified version of the example provided by the SparkFun Qwiic
  Relay Arduino Library which can be found here:
  https://github.com/sparkfun/SparkFun_Qwiic_Relay_Arduino_Library
*/



#include <SPI.h>

//Radio Head Library:
#include <RH_RF95.h>

// We need to provide the RFM95 module's chip select and interrupt pins to the
// rf95 instance below.On the SparkFun ProRF those pins are 12 and 6 respectively.
RH_RF95 rf95(12, 6);

int LED = 13; //Status LED on pin 13

int successLED = 3; // green
int failLED = 4; // red
int statLED = 2; // blue

int packetCounter = 0; //Counts the number of packets sent
long timeSinceLastPacket = 0; //Tracks the time stamp of last packet received
// The broadcast frequency is set to 921.2, but the SADM21 ProRf operates
// anywhere in the range of 902-928MHz in the Americas.
// Europe operates in the frequencies 863-870, center frequency at
// 868MHz.This works but it is unknown how well the radio configures to this frequency:
//float frequency = 864.1;
float frequency = 921.2;

uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];


////////////////relay

#include "SparkFun_Qwiic_Relay.h"

#define RELAY_ADDR 0x18 // Alternate address 0x19


Qwiic_Relay relay(RELAY_ADDR);

////////////////

/////////////////crypto

#include <SparkFun_ATECCX08a_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_ATECCX08a
#include <Wire.h>

ATECCX08A atecc;

uint8_t token[32]; // time to live token, created randomly each authentication event

uint8_t signature[64]; // incoming signature from Alice

int headerCount = 0; // used to count incoming "$", when we reach 3 we know it's a good fresh new message.

// Alice's public key.
// Note, this will be unique to each co-processor, so your will be different.
// copy/paste Alice's true unique public key from her terminal printout in Example6_Challenge_Alice.

uint8_t AlicesPublicKey[64] = {
  0x38, 0xD6, 0xE5, 0x49, 0xAC, 0x57, 0x2D, 0x1F, 0xD0, 0x58, 0x0A, 0xE8, 0x59, 0xB8, 0xF8, 0x20,
  0x1E, 0x0A, 0x7E, 0x8D, 0x5B, 0x7D, 0xD9, 0x8A, 0x26, 0xAF, 0x88, 0x73, 0x6D, 0x8C, 0xB7, 0x2D,
  0x8D, 0x3A, 0xB9, 0x5F, 0x60, 0x9D, 0x3F, 0x49, 0x72, 0xF1, 0x44, 0x74, 0x82, 0x3F, 0x7B, 0xCF,
  0x1F, 0x18, 0xD3, 0xA4, 0xBF, 0x62, 0x15, 0xCC, 0xAF, 0xAD, 0x7E, 0x03, 0xD8, 0xE9, 0x93, 0x7E
};

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(successLED, OUTPUT);
  pinMode(failLED, OUTPUT);
  pinMode(statLED, OUTPUT);

  SerialUSB.begin(115200);
  // It may be difficult to read serial messages on startup. The following
  // line will wait for serial to be ready before continuing. Comment out if not needed.
  //while (!SerialUSB);
  SerialUSB.println("RFM Server!");

  //Initialize the Radio.
  if (rf95.init() == false) {
    SerialUSB.println("Radio Init Failed - Freezing");
    while (1);
  }
  else {
    // An LED indicator to let us know radio initialization has completed.
    SerialUSB.println("Receiver up!");
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
  }

  rf95.setFrequency(frequency);

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
  // you can set transmitter powers from 5 to 23 dBm:
  // rf95.setTxPower(14, false);


  Wire.begin();

  if (atecc.begin() == true)
  {
    SerialUSB.println("Successful wakeUp(). I2C connections are good.");
  }
  else
  {
    SerialUSB.println("Device not found. Check wiring.");
    while (1); // stall out forever
  }

  if (!relay.begin())
  {
    Serial.println("Check connections to Qwiic Relay.");
    while (1); // stall out forever
  }
  else
  {
    Serial.println("Qwiic Relay is ready to go.");
  }

}

void loop()
{
  if (rf95.available()) {
    // Should be a message for us now

    uint8_t len = sizeof(buf);

    if (rf95.recv(buf, &len)) {
      digitalWrite(LED, HIGH); //Turn on status LED
      timeSinceLastPacket = millis(); //Timestamp this packet

      SerialUSB.print("Got message: ");
      printBuf64();
      //SerialUSB.print(" RSSI: ");
      //SerialUSB.print(rf95.lastRssi(), DEC);
      SerialUSB.println();

      // if message from Alice is "$$$", Send a random token for her to sign.
      if (buf[0] == '$' && buf[1] == '$' && buf[2] == '$')
      {
        SerialUSB.println("Received $$$. Creating a new random TTL-token now...");

        // update library instance public variable.
        atecc.updateRandom32Bytes();

        uint8_t toSend[32];
        // copy from library public variable into our local variable
        for (int i = 0 ; i < 32 ; i++)
        {
          token[i] = atecc.random32Bytes[i]; // store locally
        }

        rf95.send(token, sizeof(token));
        rf95.waitPacketSent();
        SerialUSB.println("Sent token");
        digitalWrite(LED, LOW); //Turn off status LED
      }
      else // this means Alice just sent us a signature
      {
        SerialUSB.println("Received signature. Verifying now...");
        for (int i = 0 ; i < 64 ; i++) signature[i] = buf[i]; // read in signature from buffer.
        printSignature();
        // Let's verirfy!
        if (atecc.verifySignature(token, signature, AlicesPublicKey))
        {
          SerialUSB.println("Success! Signature Verified.");
          // Let's turn on the relay...
          relay.turnRelayOn();
          delay(1000);
          // Let's turn that relay off...
          relay.turnRelayOff();
          blinkStatus(successLED);
        }
        else
        {
          SerialUSB.println("Verification failure.");
          blinkStatus(failLED);
        }
      }

    }
    else
      SerialUSB.println("Recieve failed");
  }
  //Turn off status LED if we haven't received a packet after 1s
  if (millis() - timeSinceLastPacket > 1000) {
    digitalWrite(LED, LOW); //Turn off status LED
    timeSinceLastPacket = millis(); //Don't write LED but every 1s
    clearBuf();
    // destory token, to require a new cycle if this doesn't complete within 1 second
    for (int i = 0 ; i < 32 ; i++)
    {
      token[i] = 0x00;
    }
  }
}


void printSignature()
{
  SerialUSB.println("uint8_t signature[64] = {");
  for (int i = 0; i < sizeof(signature) ; i++)
  {
    SerialUSB.print("0x");
    if ((signature[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(signature[i], HEX);
    if (i != 63) SerialUSB.print(", ");
    if ((63 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void printBuf64()
{
  SerialUSB.println();
  SerialUSB.println("uint8_t buf[64] = {");
  for (int i = 0; i < 64 ; i++)
  {
    SerialUSB.print("0x");
    if ((buf[i] >> 4) == 0) SerialUSB.print("0"); // print preceeding high nibble if it's zero
    SerialUSB.print(buf[i], HEX);
    if (i != 63) SerialUSB.print(", ");
    if ((63 - i) % 16 == 0) SerialUSB.println();
  }
  SerialUSB.println("};");
  SerialUSB.println();
}

void clearBuf()
{
  for (int i = 0; i < 64 ; i++) buf[i] = 0x00;
}

void blinkStatus(int LED)
{
  digitalWrite(LED, HIGH);
  delay(2000);
  digitalWrite(LED, LOW);
  delay(500);
}

Resources & Going Further

Now that you've incorporated ECC authentication security into your garage door opener, you can add security to any future project they may need it. How about your internet-connected front door?

For more information, check out the resources below:

Project Source Code:

Hookup Guides:

Arduino Libraries:

Videos:

Need inspiration? Check out some of the Qwiic or IoT related tutorials!

Qwiic Human Presence Sensor (AK9753) Hookup Guide

How to get started with your Qwiic enabled AK9753 Human Presence Sensor.

XBee3 Thing Plus Hookup Guide

Get started with SparkFun's XBee3 Thing Plus - both the u.FL as well as the PCB antenna versions.

TFMini - Micro LiDAR Module (Qwiic) Hookup Guide

The TFMini is a ToF (Time of Flight) LiDAR sensor capable of measuring the distance to an object as close as 30 cm and as far as 12 meters! The TFMini allows you to easily integrate LiDAR into applications traditionally reserved for smaller sensors such as the SHARP GP-series infrared rangefinders. With the added Qwiic feature, you can quickly connect to the sensor via I2C!

Using SparkFun Edge Board with Ambiq Apollo3 SDK

We will demonstrate how to get started with your SparkFun Edge Board by setting up the toolchain on your computer, examining an example program, and using the serial uploader tool to flash the chip.

Photon OLED Shield Hookup Guide

The Photon OLED Shield has everything you need to add a small yet crisp OLED screen to your Photon projects. This hookup guide will show you how to get started.

Experiment Guide for the Johnny-Five Inventor's Kit

Use the Tessel 2 and the Johnny Five Inventors kit to explore the world of JavaScript enabled hardware through 14 awesome experiments!

Using Home Assistant to Expand Your Home Automations

An introduction to Home Assistant, an open source home automation hub.

Qwiic Kit for Raspberry Pi Hookup Guide

Get started with the CCS811, BME280, VCNL4040, and microOLED via I2C using the Qwiic system and Python on a Raspberry Pi! Take sensor readings from the enviroment and display them on the microOLED, serial terminal, or the cloud with Cayenne!

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

RED-V RedBoard Hookup Guide

$
0
0

RED-V RedBoard Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1032

Introduction

SparkFun is pleased to welcome a whole new instruction set architecture (ISA) to its family, the RISC-V ISA (pronounced “risk-five”), and along with it, introduce the RED-V RedBoard (pronounced “red-five”). In this tutorial, we'll be focusing on the hardware.

 SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

DEV-15594
$39.95
2

"The force is strong with this one." (Star Wars: A New Hope, 1977)

What sets the RISC-V ISA from the rest is that it is completely open-source; including the instruction set architecture (ISA). That means anyone can make full use the microcontroller without requiring royalties, licenses, or non-disclosure agreements (NDAs). The RED-V comes in the familiar Arduino Uno form factor and includes the SiFive Freedom E310 core, 32MB of QSPI flash, an NXP K22 ARM Cortex-M4 for USB connectivity and operating as a JTAG interface, and a Qwiic connector.

Required Materials

To follow along with this tutorial, you will need the following materials and software. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary. Here is what you would need to get started:

 SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

DEV-15594
$39.95
2
USB 3.1 Cable A to C - 3 Foot

USB 3.1 Cable A to C - 3 Foot

CAB-14743
$4.95
2
  • RED-V - You'll definitely need this; otherwise, you are probably on the wrong tutorial page (wink).
  • USB 3.1 Cable A to C - 3 Foot - The USB interface serves two purposes: it powers the board and allows you to upload programs to it. (You might even have a few of these in you drawer!)

You Will Also Need

To utilize all the features of the development board, you may need the following tools and accessories. If you would like to modify the jumpers on the board, you will need soldering equipment.

Solder Lead Free - 100-gram Spool

Solder Lead Free - 100-gram Spool

TOL-09325
$7.95
7
Chip Quik No-Clean Flux Pen  - 10mL

Chip Quik No-Clean Flux Pen - 10mL

TOL-14579
$7.95
2
Weller WLC100 Soldering Station

Weller WLC100 Soldering Station

TOL-14228
$44.95
1


Jumper Modification

If you would like to modify the jumpers on the board, you will need soldering equipment.

Solder Lead Free - 100-gram Spool

Solder Lead Free - 100-gram Spool

TOL-09325
$7.95
7
Chip Quik No-Clean Flux Pen  - 10mL

Chip Quik No-Clean Flux Pen - 10mL

TOL-14579
$7.95
2
Weller WLC100 Soldering Station

Weller WLC100 Soldering Station

TOL-14228
$44.95
1

Qwiic Example

If you would like to follow along with the examples below to interact with the physical world, you will also need the following items:

Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
SparkFun Qwiic 12 Bit ADC - 4 Channel (ADS1015)

SparkFun Qwiic 12 Bit ADC - 4 Channel (ADS1015)

DEV-15334
$9.95
Magnetic Screwdriver Set (20 Piece)

Magnetic Screwdriver Set (20 Piece)

TOL-15003
$6.95
1

Segger Programmers

If you would like to debug or flash your processor on your own, here are some of our SEGGER Programmers. We also recommend getting the 1.27mm header pins with some jumper wires to connect. Depending on the programmer that you use, you may need to use a combination of wire wrap and IC hooks to connect.

J-Link EDU Mini Programmer

J-Link EDU Mini Programmer

PGM-15345
$18.00
1
J-Link EDU Base Programmer

J-Link EDU Base Programmer

PGM-15346
$60.00
J-Link BASE Compact Programmer

J-Link BASE Compact Programmer

PGM-15347
$378.00
Header - 2x5 Pin (Male, 1.27mm)

Header - 2x5 Pin (Male, 1.27mm)

PRT-15362
$1.50

Suggested Reading

Before continuing on with this tutorial, you may want to familiarize yourself with some of these topics if they’re unfamiliar to you.

How to Solder: Through-Hole Soldering

This tutorial covers everything you need to know about through-hole soldering.

Logic Levels

Learn the difference between 3.3V and 5V devices and logic levels.

Hardware Overview

Power & Programming

There are a few different ways to power the SparkFun RED-V RedBoard:

  • USB-C
  • barrel jack connector
  • power pins broken out on the edge of the board

The easiest way (which will also allow you to program your board) is to simply plug it into your computer via USB-C. This will provide 5V to the board and will also allow you access to the super cool USB-to-JTAG interface for programming. Once you've programmed your RED-V however, you may want to have it running off of a different power supply. If you use a wall wart on the USB-C connector, make sure it outputs a regulated 5V DC. You can also use the black barrel jack, in which case you'll need any wall adapter between 7 & 15 Volts DC. Or you can also power the board through the header pins broken out on the edge of the board. If you are using VIN and GND, follow the same practice as using a wall adapter and stick to between 7 & 15 Volts. If you are using 5V and GND or 3v3 and GND, make sure that your voltage is regulated when applying power to the 5V or 3.3V pins, respectively.

USB, Barrel Jack, and Power Pins

Always-On Core

The FE310 contains an Always-On (AON) block that allows easy power control of the FE310. It includes its own real-time clock and is also attached to the WAKE button on the board. This allows you to put the FE310 to sleep and wake it up upon a time-generated or user-generated interrupt.

FE310 IC

Buttons

The RED-V has two buttons: a RESET button and a WAKE button. The RESET button is pretty self explanatory and is used to reset the FE310. A single tap of the RESET button will run the code loaded onto the FE310's QSPI flash. A quick double tap will put the FE310 into safe bootloader mode, which will allow you to flash new code to the RED-V if you've managed to really mess things up (i.e. Oops I put the core to sleep and forgot to add a way to wake it up). The pin is also broken out on the edge of the board. Adding a jumper wire from this pin to GND will reset the board as well.

Reset Button and Pin

The RED-V is also equipped with an Always-On or AON core (mentioned above) which can be programmed to shut down the main core of the FE310 and wake it up upon a button-generated or user-generated interrupt. The WAKE button can be configured in software to wake the FE310 from deep sleep. This button is also broken out to the header pin nearest the barrel jack if you'd like to use an external source to wake the FE310. Adding a jumper wire from this pin to GND will wake the board as well.

Wake Button and Pin

Jumpers

The FE310 has a few jumpers as well, all of which are open by default. The two jumpers located next to the I2C label is for the I2C pull-up resistors. These resistors are not attached by default as there are I2C pull-up resistors on all SparkFun Qwiic slaves. If you're using a 3rd party board, you may need to close these jumper by the Qwiic connector to attach the pull-ups to the I2C bus. The jumper by the USB-C connector is for bypassing the 0.5A PTC fuse. This is for special cases where you need a lot current. Most of the time, you can leave this jumper open.

Pull-Up Resistors and By-Pass jumper

Dimensions

The RED-V RedBoard uses the Arduino Uno footprint. There are four mounting holes on the board.

Dimensions

Hardware Hookup

For the scope of the tutorial, you'll use a USB C cable to power, upload code, and send serial to the board. Simply connect the computer's USB port and the RED-V. The board uses standard Arduino Uno R3 footprint with female headers to stack Arduino shields and easily connect prototyped circuits on breadboards with jumper wires.

USB Cable to RED-V

Software Development Guide

There are a few environments to get started with the RED-V. For information about programming the RED-V RedBoard, check out the following tutorial.

RED-V Development Guide

November 27, 2019

This guide will help you get the RED-V RedBoard or Thing Plus up and running for the exhaust port. Depending on personal preference, there are a few environments to get started with the boards. All wings report in... we're going in full-throttle.

Resources and Going Further

Now that you've successfully got started with your RED-V RedBoard, it's time to incorporate it into your own project! For more information, check out the resources below:


learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

RED-V Thing Plus Hookup Guide

$
0
0

RED-V Thing Plus Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1099

Introduction

SparkFun is pleased to welcome its a whole new instruction set architecture (ISA) to its family, the RISC-V ISA (pronounced “risk-five”), and along with it, introduce the RED-V Thing Plus (pronounced “red-five”). In this tutorial, we'll be focusing on the hardware.

SparkFun RED-V Thing Plus - SiFive RISC-V FE310 SoC

SparkFun RED-V Thing Plus - SiFive RISC-V FE310 SoC

DEV-15799
$29.95

"The force is strong with this one." (Star Wars: A New Hope, 1977)

What sets the RISC-V ISA from the rest is that it is completely open-source; including the instruction set architecture (ISA). That means anyone can make full use the microcontroller without requiring royalties, licenses, or non-disclosure agreements (NDAs). The RED-V comes in the familiar SparkFun Thing Plus form factor and includes the SiFive Freedom E310 core, 32MB of QSPI flash, an NXP K22 ARM Cortex-M4 for USB connectivity and operating as a JTAG interface, and a Qwiic connector.

Required Materials

To follow along with this tutorial, you will need the following materials and software. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary. Here is what you would need to get started:

SparkFun RED-V Thing Plus - SiFive RISC-V FE310 SoC

SparkFun RED-V Thing Plus - SiFive RISC-V FE310 SoC

DEV-15799
$29.95
USB 3.1 Cable A to C - 3 Foot

USB 3.1 Cable A to C - 3 Foot

CAB-14743
$4.95
2
  • RED-V Thing Plus - You'll definitely need this; otherwise, you are probably on the wrong tutorial page (wink).
  • USB 3.1 Cable A to C - 3 Foot - The USB interface serves two purposes: it powers the board and allows you to upload programs to it. (You might even have a few of these in you drawer!)

You Will Also Need

To utilize all the features of the development board, you may need the following tools and accessories.

Click the buttons above to toggle the additional materials based on the tasks you
wish to perform. Feel free to modify the items in your cart to fit your needs.

Jumper Modification

If you would like to modify the jumpers on the board, you will need soldering equipment.

Solder Lead Free - 100-gram Spool

Solder Lead Free - 100-gram Spool

TOL-09325
$7.95
7
Weller WLC100 Soldering Station

Weller WLC100 Soldering Station

TOL-14228
$44.95
1
Chip Quik No-Clean Flux Pen  - 10mL

Chip Quik No-Clean Flux Pen - 10mL

TOL-14579
$7.95
2

Qwiic Example

If you would like to follow along with the examples below to interact with the physical world, you will also need the following items:

Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
SparkFun Qwiic 12 Bit ADC - 4 Channel (ADS1015)

SparkFun Qwiic 12 Bit ADC - 4 Channel (ADS1015)

DEV-15334
$9.95
Magnetic Screwdriver Set (20 Piece)

Magnetic Screwdriver Set (20 Piece)

TOL-15003
$6.95
1

Headers & Accessories

If you would like to add headers to your board, check out some of the following items:

Break Away Headers - Straight

Break Away Headers - Straight

PRT-00116
$1.50
20
SparkFun Beginner Tool Kit

SparkFun Beginner Tool Kit

TOL-14681
$54.95
Feather Stackable Header Kit

Feather Stackable Header Kit

PRT-15187
$1.50

Below is a sample selection of our other headers and soldering tools in our catalog. For a full selection of our available Headers or Soldering Tools, click on the associated link.

Break Away Headers - Straight

Break Away Headers - Straight

PRT-00116
$1.50
20
Female Headers

Female Headers

PRT-00115
$1.50
7
Arduino Stackable Header Kit - R3

Arduino Stackable Header Kit - R3

PRT-11417
$1.50
12
Break Away Male Headers - Right Angle

Break Away Male Headers - Right Angle

PRT-00553
$1.95
4
Insulated Silicone Soldering Mat

Insulated Silicone Soldering Mat

TOL-14672
$9.95
5
Weller WE1010 Soldering Station

Weller WE1010 Soldering Station

TOL-14734
$129.00
1
Solder Lead Free - 100-gram Spool

Solder Lead Free - 100-gram Spool

TOL-09325
$7.95
7
Solder - 1/4lb Spool (0.020") Special Blend

Solder - 1/4lb Spool (0.020") Special Blend

TOL-10242
$29.95
7

Segger Programmers

If you would like to debug or flash your processor on your own, here are some of our SEGGER Programmers. Depending on the programmer that you use, you may need to use a combination of wire wrap and IC hooks to connect.

J-Link EDU Mini Programmer

J-Link EDU Mini Programmer

PGM-15345
$18.00
1
J-Link EDU Base Programmer

J-Link EDU Base Programmer

PGM-15346
$60.00
J-Link BASE Compact Programmer

J-Link BASE Compact Programmer

PGM-15347
$378.00

Suggested Reading

Before continuing on with this tutorial, you may want to familiarize yourself with some of these topics if they’re unfamiliar to you.

How to Solder: Through-Hole Soldering

This tutorial covers everything you need to know about through-hole soldering.

Logic Levels

Learn the difference between 3.3V and 5V devices and logic levels.

Hardware Overview

Power & Programming

There are a few different ways to power the SparkFun RED-V Thing Plus:

  • USB-C
  • JST connector (battery power)
  • power pins broken out on the edge of the board

The easiest way (which will also allow you to program your board) is to simply plug it into your computer via USB-C. This will provide 5V to the board and will also allow you access to the super cool USB-to-JTAG interface for programming. Once you've programmed your RED-V however, you may want to have it running off of a different power supply. If you use a wall wart on the USB-C connector, make sure it outputs a regulated 5V DC. You can also use the black JST connector to provide battery power from a LiPo battery. There is an on-board LiPo charger with the current rate set to 500mA. Make sure to use LiPo batteries that have a capacity greater than 500mAh when charging. If you decide to power the board via the VUSB or VBAT pins, make sure to not exceed 6.5V since this is the absolute maximum for the 3.3V voltage regulator. Or you can power the board through the breakout pins on the edge of the board. If you are using 3V3 and GND, make sure that your voltage is regulated when applying power to the pin.

USB, JST, and Power Pins

Always-On Core

The FE310 contains an Always-On (AON) block that allows easy power control of the FE310. It includes its own real-time clock and is also attached to the WAKE button on the board. This allows you to put the FE310 to sleep and wake it up upon a time-generated or user-generated interrupt.

alt text

Buttons

The RED-V has two buttons: a RESET button and a WAKE button. The RESET button is pretty self explanatory and is used to reset the FE310. A single tap of the RESET button will run the code loaded onto the FE310's QSPI flash. A quick double tap will put the FE310 into safe bootloader mode, which will allow you to flash new code to the RED-V if you've managed to really mess things up (i.e. Oops I put the core to sleep and forgot to add a way to wake it up). The pin is also broken out on the edge of the board. Adding a jumper wire from this pin to GND will reset the board as well.

Reset Button and Pin

The RED-V is also equipped with an Always-On or AON core (mentioned above) which can be programmed to shut down the main core of the FE310 and wake it up upon a button-generated or user-generated interrupt. The WAKE button can be configured in software to wake the FE310 from deep sleep.

Wake Button

Jumpers

The FE310 has a few jumpers as well, all of which are open by default. The two jumpers located next to the I2C label is for the I2C pull-up resistors. These resistors are not attached by default as there are I2C pull-up resistors on all SparkFun Qwiic slaves. If you're using a 3rd party board, you may need to close these jumper by the Qwiic connector to attach the pull-ups to the I2C bus. The jumper by the USB-C connector (next to the Segger logo) is for bypassing the 0.5A PTC fuse. This is for special cases where you need a lot current. If you need to connect the NC pin to GND, you can also add a solder jumper on the pads as well. Most of the time, you can leave the bypass and NC jumpers open.

Pull-Up Resistors and By-Pass jumper

Dimensions

The RED-V Thing Plus measures at 2.3"x0.90".

Dimensions

Hardware Hookup

For the scope of the tutorial, you'll use a USB C cable to power, upload code, and send serial to the board. Simply connect the computer's USB port and the RED-V Thing Plus. The board uses standard Thing Plus footprint.

RED-V Thing Plus Connected to USB C Cable

The headers were left off the board to allow users the flexibility of connecting any type of 0.1" header to the board. For temporary connections to the I/O pins, you could use IC hooks to test out the pins. However, you'll need to solder headers or wires of your choice to the board for a secure connection. Here are a few tutorials to connect to the PTH pads depending on your personal preference.

How to Solder: Through-Hole Soldering

September 19, 2013

This tutorial covers everything you need to know about through-hole soldering.

Working with Wire

February 8, 2013

How to strip, crimp, and work with wire.

Software Development Guide

There are a few environments to get started with the RED-V. For information about programming the RED-V Thing Plus, check out the following tutorial.

RED-V Development Guide

November 27, 2019

This guide will help you get the RED-V RedBoard or Thing Plus up and running for the exhaust port. Depending on personal preference, there are a few environments to get started with the boards. All wings report in... we're going in full-throttle.

Resources and Going Further

Now that you've successfully got started with your RED-V Thing Plus, it's time to incorporate it into your own project! For more information, check out the resources below:


learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

RED-V RedBoard Hookup Guide

$
0
0

RED-V RedBoard Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1032

Introduction

SparkFun is pleased to welcome a whole new instruction set architecture (ISA) to its family, the RISC-V ISA (pronounced “risk-five”), and along with it, introduce the RED-V RedBoard (pronounced “red-five”). In this tutorial, we'll be focusing on the hardware.

 SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

DEV-15594
$39.95
2

"The force is strong with this one." (Star Wars: A New Hope, 1977)

What sets the RISC-V ISA from the rest is that it is completely open-source; including the instruction set architecture (ISA). That means anyone can make full use the microcontroller without requiring royalties, licenses, or non-disclosure agreements (NDAs). The RED-V comes in the familiar Arduino Uno form factor and includes the SiFive Freedom E310 core, 32MB of QSPI flash, an NXP K22 ARM Cortex-M4 for USB connectivity and operating as a JTAG interface, and a Qwiic connector.

Required Materials

To follow along with this tutorial, you will need the following materials and software. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary. Here is what you would need to get started:

 SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

SparkFun RED-V RedBoard - SiFive RISC-V FE310 SoC

DEV-15594
$39.95
2
USB 3.1 Cable A to C - 3 Foot

USB 3.1 Cable A to C - 3 Foot

CAB-14743
$4.95
2
  • RED-V - You'll definitely need this; otherwise, you are probably on the wrong tutorial page (wink).
  • USB 3.1 Cable A to C - 3 Foot - The USB interface serves two purposes: it powers the board and allows you to upload programs to it. (You might even have a few of these in you drawer!)

You Will Also Need

To utilize all the features of the development board, you may need the following tools and accessories. If you would like to modify the jumpers on the board, you will need soldering equipment.

Solder Lead Free - 100-gram Spool

Solder Lead Free - 100-gram Spool

TOL-09325
$7.95
7
Weller WLC100 Soldering Station

Weller WLC100 Soldering Station

TOL-14228
$44.95
1
Chip Quik No-Clean Flux Pen  - 10mL

Chip Quik No-Clean Flux Pen - 10mL

TOL-14579
$7.95
2


Jumper Modification

If you would like to modify the jumpers on the board, you will need soldering equipment.

Solder Lead Free - 100-gram Spool

Solder Lead Free - 100-gram Spool

TOL-09325
$7.95
7
Weller WLC100 Soldering Station

Weller WLC100 Soldering Station

TOL-14228
$44.95
1
Chip Quik No-Clean Flux Pen  - 10mL

Chip Quik No-Clean Flux Pen - 10mL

TOL-14579
$7.95
2

Qwiic Example

If you would like to follow along with the examples below to interact with the physical world, you will also need the following items:

Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
SparkFun Qwiic 12 Bit ADC - 4 Channel (ADS1015)

SparkFun Qwiic 12 Bit ADC - 4 Channel (ADS1015)

DEV-15334
$9.95
Magnetic Screwdriver Set (20 Piece)

Magnetic Screwdriver Set (20 Piece)

TOL-15003
$6.95
1

Segger Programmers

If you would like to debug or flash your processor on your own, here are some of our SEGGER Programmers. We also recommend getting the 1.27mm header pins with some jumper wires to connect. Depending on the programmer that you use, you may need to use a combination of wire wrap and IC hooks to connect.

J-Link EDU Mini Programmer

J-Link EDU Mini Programmer

PGM-15345
$18.00
1
J-Link EDU Base Programmer

J-Link EDU Base Programmer

PGM-15346
$60.00
J-Link BASE Compact Programmer

J-Link BASE Compact Programmer

PGM-15347
$378.00
Header - 2x5 Pin (Male, 1.27mm)

Header - 2x5 Pin (Male, 1.27mm)

PRT-15362
$1.50

Suggested Reading

Before continuing on with this tutorial, you may want to familiarize yourself with some of these topics if they’re unfamiliar to you.

How to Solder: Through-Hole Soldering

This tutorial covers everything you need to know about through-hole soldering.

Logic Levels

Learn the difference between 3.3V and 5V devices and logic levels.

Hardware Overview

Power & Programming

There are a few different ways to power the SparkFun RED-V RedBoard:

  • USB-C
  • barrel jack connector
  • power pins broken out on the edge of the board

The easiest way (which will also allow you to program your board) is to simply plug it into your computer via USB-C. This will provide 5V to the board and will also allow you access to the super cool USB-to-JTAG interface for programming. Once you've programmed your RED-V however, you may want to have it running off of a different power supply. If you use a wall wart on the USB-C connector, make sure it outputs a regulated 5V DC. You can also use the black barrel jack, in which case you'll need any wall adapter between 7 & 15 Volts DC. Or you can also power the board through the header pins broken out on the edge of the board. If you are using VIN and GND, follow the same practice as using a wall adapter and stick to between 7 & 15 Volts. If you are using 5V and GND or 3v3 and GND, make sure that your voltage is regulated when applying power to the 5V or 3.3V pins, respectively.

USB, Barrel Jack, and Power Pins

Always-On Core

The FE310 contains an Always-On (AON) block that allows easy power control of the FE310. It includes its own real-time clock and is also attached to the WAKE button on the board. This allows you to put the FE310 to sleep and wake it up upon a time-generated or user-generated interrupt.

FE310 IC

Buttons

The RED-V has two buttons: a RESET button and a WAKE button. The RESET button is pretty self explanatory and is used to reset the FE310. A single tap of the RESET button will run the code loaded onto the FE310's QSPI flash. A quick double tap will put the FE310 into safe bootloader mode, which will allow you to flash new code to the RED-V if you've managed to really mess things up (i.e. Oops I put the core to sleep and forgot to add a way to wake it up). The pin is also broken out on the edge of the board. Adding a jumper wire from this pin to GND will reset the board as well.

Reset Button and Pin

The RED-V is also equipped with an Always-On or AON core (mentioned above) which can be programmed to shut down the main core of the FE310 and wake it up upon a button-generated or user-generated interrupt. The WAKE button can be configured in software to wake the FE310 from deep sleep. This button is also broken out to the header pin nearest the barrel jack if you'd like to use an external source to wake the FE310. Adding a jumper wire from this pin to GND will wake the board as well.

Wake Button and Pin

Jumpers

The FE310 has a few jumpers as well, all of which are open by default. The two jumpers located next to the I2C label is for the I2C pull-up resistors. These resistors are not attached by default as there are I2C pull-up resistors on all SparkFun Qwiic slaves. If you're using a 3rd party board, you may need to close these jumper by the Qwiic connector to attach the pull-ups to the I2C bus. The jumper by the USB-C connector is for bypassing the 0.5A PTC fuse. This is for special cases where you need a lot current. Most of the time, you can leave this jumper open.

Pull-Up Resistors and By-Pass jumper

Dimensions

The RED-V RedBoard uses the Arduino Uno footprint. There are four mounting holes on the board.

Dimensions

Hardware Hookup

For the scope of the tutorial, you'll use a USB C cable to power, upload code, and send serial to the board. Simply connect the computer's USB port and the RED-V. The board uses standard Arduino Uno R3 footprint with female headers to stack Arduino shields and easily connect prototyped circuits on breadboards with jumper wires.

USB Cable to RED-V

Software Development Guide

There are a few environments to get started with the RED-V. For information about programming the RED-V RedBoard, check out the following tutorial.

RED-V Development Guide

November 27, 2019

This guide will help you get the RED-V RedBoard or Thing Plus up and running for the exhaust port. Depending on personal preference, there are a few environments to get started with the boards. All wings report in... we're going in full-throttle.

Resources and Going Further

Now that you've successfully got started with your RED-V RedBoard, it's time to incorporate it into your own project! For more information, check out the resources below:


learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

SparkFun Qwiic Button Hookup Guide

$
0
0

SparkFun Qwiic Button Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1108

Introduction

Buttons are a great way to add a tactile input to your project but dealing with pull-up resistors, debouncing, polling, and using GPIO pins for each button can be a hassle. Enter the Qwiic Button (Red) and the Qwiic Button Breakout! These breakouts eliminate nearly all the inconvenience of using buttons by converting everything to an easy-to-use I2C connection using the Qwiic Interface.

SparkFun Qwiic Button - Red LED

SparkFun Qwiic Button - Red LED

BOB-15932
$7.50
SparkFun Qwiic Button Breakout

SparkFun Qwiic Button Breakout

BOB-15931
$4.95

We have two versions of the Qwiic Button available. The Qwiic Button (Red) comes with a pre-populated red pushbutton with a built in LED to illuminate the button and the Qwiic Button Breakout leaves the button unpopulated so you can choose your own color for your tactile button.

Using the Qwiic Button is as simple as sending the command button.isPressed() to check the status of the button. In addition to handling status checks and debouncing, the Qwiic Button has a configurable interrupt pin which can be adjusted to activate upon a button press or click. This allows you to trigger specific behavior or functions in your code when the button is used and frees up processing time that would normally be used to constantly poll a button's state.

The Qwiic Button also includes a First-in First-Out (FIFO Queue) which keeps track of when the button was pressed so if you are hosting a game show you can easily keep track of which contestant pressed their button first without needing to constantly poll the buttons!

Required Materials

The Qwiic Button requires a Qwiic-enabled microcontroller:

SparkFun Thing Plus - ESP32 WROOM

SparkFun Thing Plus - ESP32 WROOM

WRL-14689
7
SparkFun RedBoard Artemis

SparkFun RedBoard Artemis

DEV-15444
$19.95
SparkFun RedBoard Qwiic

SparkFun RedBoard Qwiic

DEV-15123
$19.95
5
SparkFun Qwiic Micro - SAMD21 Development Board

SparkFun Qwiic Micro - SAMD21 Development Board

DEV-15423
$19.95
1

And you will also need a Qwiic cable:

Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
Qwiic Cable - 200mm

Qwiic Cable - 200mm

PRT-14428
$1.50
Qwiic Cable - 50mm

Qwiic Cable - 50mm

PRT-14426
$0.95
Qwiic Cable - 500mm

Qwiic Cable - 500mm

PRT-14429
$1.95

Or, if you want to use a microcontroller without a Qwiic connector, you can add one using one of our Qwiic Shields, the Qwiic Adapter board, or adapter cables:

Qwiic Cable - Breadboard Jumper (4-pin)

Qwiic Cable - Breadboard Jumper (4-pin)

PRT-14425
$1.50
SparkFun Qwiic Shield for Arduino

SparkFun Qwiic Shield for Arduino

DEV-14352
$6.95
SparkFun Qwiic Adapter

SparkFun Qwiic Adapter

DEV-14495
$1.50
Qwiic Cable - Female Jumper (4-pin)

Qwiic Cable - Female Jumper (4-pin)

CAB-14988
$1.50

Finally, if you are using the Qwiic Button Breakout you'll need to solder a button to the board:

Momentary Pushbutton Switch - 12mm Square

Momentary Pushbutton Switch - 12mm Square

COM-09190
$0.50
4
LED Tactile Button- White

LED Tactile Button- White

COM-10439
$2.10
1
LED Tactile Button - Green

LED Tactile Button - Green

COM-10440
$2.10
LED Tactile Button - Blue

LED Tactile Button - Blue

COM-10443
$2.10

Realistically, you can solder any pushbutton to the Qwiic Button Breakout so long as it fits the button footprint. We have a couple other options available in our Button Category that will work perfectly with the Qwiic Button Breakout.

Suggested Reading

If you aren't familiar with the Qwiic system, we recommend reading here for an overview:

Qwiic Connect System
Qwiic Connect System

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

Switch Basics

A tutorial on electronics' most overlooked and underappreciated component: the switch! Here we explain the difference between momentary and maintained switches and what all those acronyms (NO, NC, SPDT, SPST, ...) stand for.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

Processor Interrupts with Arduino

What is an interrupt? In a nutshell, there is a method by which a processor can execute its normal program while continuously monitoring for some kind of event, or interrupt. There are two types of interrupts: hardware and software interrupts. For the purposes of this tutorial, we will focus on hardware interrupts.

Qwiic Shield for Arduino & Photon Hookup Guide

Get started with our Qwiic ecosystem with the Qwiic shield for Arduino or Photon.

Hardware Overview

Tactile Button

This is a standard pushbutton with a built in red LED. The LED's anode (positive pin) is connected to an I/O pin on the ATtiny84 so you can turn it on and off as well as control the brightness. If you have the Qwiic Button Breakout, you can choose your own color of button from the selection listed in the Introduction of this guide or any tactile button that fits the footprint on the breakout.

Highlighting the Red Tactile ButtonHighlighting the Button Footprint
Red Tactile ButtonButton Footprint

Qwiic and I2C Interface

The easiest way to use the Qwiic Button is with the Qwiic connect system. Simply plug in a Qwiic Cable to start talking to it.

Highlighting the Qwiic ConnectorsHighlighting the I2C Pins
Qwiic ConnectorsI2C Pins

Alternatively, you can solder to the I2C pins broken out on the board.

ATtiny84

The ATtiny84 has pre-installed firmware to handle the various functions of the Qwiic Button. It acts as an intermediary device to send and receive I2C data for things like button presses, clicks, the FIFO queue and it allows you to set a custom I2C address for the Qwiic Button.

Image highlighting ATTiny85 Integrated Circuit

Jumpers

Note: Never worked with solder jumpers before? Or maybe just need some tips or a quick refresher? Check out our How to Work with Jumpers and PCB Traces tutorial.

I2C Address Jumpers

There are four solder jumpers on the board (labeled A0, A1, A2 and A3) you can close to set the I2C address. The firmware reads the logic of each address pin so, by closing multiple jumpers, you can modify the Qwiic Button with up to sixteen unique addresses! If you do not want to use the address pins, the address can also be configured using the ChangeI2CAddress Example from our Arduino Library.

  • All Open: Factory or User Set I2C Slave Address: 0x6F (Factory Set) or 0x## (User Set)
  • Alternate Address Jumpers: Closing an address jumper sets the pin LOW. On boot-up, the firmware checks the state of these four pins and adjusts the I2C address following this logic: 0b0110,A3,A2,A1,A0 For example, with both A0 and A1 jumpers closed, (A0 = 0, A1 = 0, A2 = 1, A3 = 1) the I2C address of the Qwiic Button is set to 0x6C (0b01101100).
Image highlighting I2C address jumpers

I2C Pull-Up Resistors

Severing the trace on the I2C jumper will remove the 2.2kΩ pull-up resistors from the I2C bus. If you have many devices on your I2C bus you may want to open these jumpers by severing the trace in between the pads.

Image highlighting pull up resistor solder jumper.

Interrupt Pin

The Interrupt Pin can be used to trigger events on your microcontroller. It is active LOW and can be configured to activate on either a button press (held down) and click (press-and-release). By default, the Interrupt Pin is pulled to 3.3V via a 10K resistor through this jumper. Just like the I2C pull-up resistors, you can open it by severing the trace in between the pads. This may come in handy for low-power projects that do not require the Interrupt Pin.

Image highlighting Interrupt pin and Interrupt pin solder jumper.

Board Dimensions

The breakout board is the standard Qwiic size of 1" x 1" and has two mounting holes that fit a standard 4-40 screw.

Qwiic Button Dimensions.

Hardware Assembly

With the Qwiic connector system, assembling the hardware is simple. All you need to do is connect your Qwiic Button to Qwiic-enabled microcontroller with a Qwiic cable. Otherwise, you can use the I2C pins if you don't have a Qwiic connector on your microcontroller board. Just be aware of your input voltage and any logic level shifting you may need to do since the Qwiic system runs at 3.3V.

Image showing the Qwiic Button connected to the RedBoard Qwiic

If you have the Qwiic Button Breakout, you will need to solder a button into place. If you are using a Tactile Button with an integrated LED, remember to pay close attention to the polarity marks on your button and match them to the markings on the top of the Qwiic Button Breakout. If you purchased a tactile button from SparkFun, the anode will be marked with a small "+" on the top of the button.

Image highlighting positive marking for LED Button.

Having a hard time seeing the "+" symbol? Click the image for a closer look.

Once your button(s) are soldered into place and you're certain all pins are well connected, you're ready to go! The image below shows two of the several options for buttons on the Qwiic Button. One is the standard Red LED Tactile Button and the other is from our Multicolor Button 4-Pack:

Image showing two Qwiic Buttons. One with a RED LED Button and another with a Yellow Tactile Button with no LED.

Qwiic Button Arduino Library

Note: This tutorial assumes you are familiar with Arduino products and you are using the latest stable version of the Arduino IDE on your desktop. If this is your first time using the Arduino IDE, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

The easiest way to install the library is to search for SparkFun Qwiic Button in the Arduino Library Manager tool. You can also manually install the Qwiic Button Library from the GitHub Repository or you can download it by clicking the button below.

Library Functions

Here is a list of the functions of the library with some quick descriptions of what they do. The examples cover most of the functions so we recommend going through them first.

Device Status

  • begin(uint8_t address = DEFAULT_ADDRESS, TwoWire &wirePort = Wire);- Sets device I2C address to a user-specified address, over whatever port the user specifies.
  • isConnected();- Returns true if the button will acknowledge over I2C, false otherwise.
  • uint8_t deviceID();- Return the 8-bit device ID of the attached device.
  • checkDeviceID();- Returns true if the device ID matches that of either the button or the switch
  • uint8_t getDeviceType();- Returns 1 if a button is attached, 2 if a switch is attached. Returns 0 if there is no device attached.
  • uint16_t getFirmwareVersion();- Returns the firmware version of the attached device as a 16-bit integer. The leftmost (high) byte is the major revision. The rightmost (low) byte is the minor version number. (Ex. 0x0202 is v2.02)
  • setI2Caddress(uint8_t address);- Configures the attached device to attach to the I2C bus using the specified address.
  • uint8_t getI2Caddress();- Returns the I2C address of the device.
Note: The "setI2Caddress();" function will not work if any of the I2C address jumpers are closed. Assuming the code is able to connect to the device, the library function may change the I2C address stored in EEPROM. However, by default the firmware will stay at the alternate I2C jumper address and the last part of this function won't be able to connect to the button for the firmware printout and future I2C address changes.

Button Status/Configuration

  • isPressed();- Returns 1 if the button is pressed, and 0 otherwise.
  • hasBeenClicked();- Returns 1 if the button was clicked, and 0 otherwise.
  • uint8_t setDebounceTime(uint16_t time);- Sets the time that the button waits for the mechanical contacts to settle (in ms) and checks if the register was set properly. Returns 0 on success, 1 on register I2C write fail, and 2 if the value didn't get written into the register properly.
  • uint16_t getDebounceTime();- Returns the value set to wait for the button's the mechanical contacts to settle, (in ms).
Note: You may notice there are two button status functions listed: isPressed(); and hasBeenClicked();. The isPressed(); function returns true while the button is pressed/held down and false when the button is unpressed/released. The hasBeenClicked(); function will only return true when the button is pressed and then released.

Interrupt Status/Configuration

  • uint8_t enablePressedInterrupt();- Configure the interrupt pin to go LOW while the button is pressed (held down).
  • uint8_t disablePressedInterrupt();- Sets the interrupt to no longer trigger while the button is pressed.
  • uint8_t enableClickedInterrupt();- Configure the interrupt pin to go LOW when the button is clicked.
  • uint8_t disableClickedInterrupt();- Configures the interrupt pin to no longer go low when the button is clicked.
  • uint8_t clearEventBits();- Sets "isPressed", "hasBeenClicked", and "eventAvailable" to zero.
  • uint8_t resetInterruptConfig();- Resets all interrupt configuration settings back to defaults.

FIFO Queue

  • isPressedQueueFull();- Checks the queue of button press timestamps and returns true if full, false otherwise.
  • isPressedQueueEmpty();- Opposite of the above function. Checks if the timestamp queue is empty.
  • unsigned long timeSinceLastPress();- Returns the time (in ms) since the last button press.
  • unsigned long timeSinceFirstPress();- Returns time (in ms) since the first button press.
  • popPressedQueue();- Returns the oldest value in the Pressed Queue (ms since first button press), and then removes it.
  • isClickedQueueFull();- Checks the queue of button click timestamps and returns true if full, false otherwise.
  • isClickedQueueEmpty();- Opposite of the above function. Checks if the timestamp queue is empty.
  • unsigned long timeSinceLastClick();- Returns the time (in ms) since the last button click.
  • unsigned long timeSinceFirstClick();- Returns the time (in ms) since the first button click.
  • popClickedQueue();- Returns the oldest value in the Clicked Queue (ms since first button click), and then removes it.

Button LED Configuration

  • LEDoff();- Turn the button LED off.
  • LEDon(uint8_t brightness = 255);- Turn the button LED on and set the brightness.
  • LEDconfig(uint8_t brightness, uint16_t cycleTime, uint16_t offTime, uint8_t granularity = 1);- Configures the button LED.
    • Brightness: Stores the brightness of the LED. Accepts values between 0 and 255.
    • cycleTime: Total pulse cycle time (in ms). Does not include off time.
    • offTime: Off time between pulses (in ms). Default is 500 ms.
    • granularity: Amount of steps it takes to get to the set brightness level.

Internal I2C Abstraction

Advanced Functions! This list of functions is for reading/writing to one or more registers. They are beyond the scope of this tutorial and are included primarily for users to implement in custom code.
  • uint8_t readSingleRegister(Qwiic_Button_Register reg); - Reads a single 8-bit register.
  • uint16_t readDoubleRegister(Qwiic_Button_Register reg); - Reads a 16-bit register (little endian).
  • unsigned long readQuadRegister(Qwiic_Button_Register reg); - Reads a 32-bit register (little endian).
  • writeSingleRegister(Qwiic_Button_Register reg, uint8_t data); - Attempts to write data into a single 8-bit register. Does not check to make sure it was written successfully. Returns 0 if there was no error on I2C transmission, and 1 otherwise.
  • writeDoubleRegister(Qwiic_Button_Register reg, uint16_t data); - Attempts to write data into a double (two 8-bit) registers. Does not check to make sure it was written successfully. Returns 0 if there was no error on I2C transmission, and 1 otherwise.
  • uint8_t writeSingleRegisterWithReadback(Qwiic_Button_Register reg, uint8_t data); - Writes data into a single 8-bit register, and checks to make sure the data was written successfully. Returns 0 on no error, 1 on I2C write fail, and 2 if the register doesn't read back the same value that was written.
  • uint16_t writeDoubleRegisterWithReadback(Qwiic_Button_Register reg, uint16_t data); - Writes data into a double (two 8-bit) registers, and checks to make sure the data was written successfully. Returns 0 on no error, 1 on I2C write fail, and 2 if the register doesn't read back the same value that was written.

Arduino Examples

In this section we will go over a few of the examples from our Qwiic Button Arduino Library. Here is a full list of all the examples included in the library:

  • Example 1 - Prints the button status.
  • Example 2 - Turns the button LED on while the button is pressed.
  • Example 3 - Pulses the button LED while the button is pressed.
  • Example 4 - Demonstrates how to use the FIFO Queue and returns time elapsed since button presses.
  • Example 5 - Details how to identify and change the I2C address.
  • Example 6 - I2C Bus Configuration. Useful for devices with multiple I2C ports.
  • Example 7 - Sets up 2 Qwiic Buttons and reads their statuses.
  • Example 8 - Configures the button to toggle the interrupt pin when pressed.

Example 1: Print Button Status

The code for Example1_PrintButtonStatus connects the Qwiic Button to the I2C bus and prints the status of the button (pressed or not pressed) to the Serial Monitor.

Example 1 Serial Print Out

Example 3 Pulse When Pressed

Example3_PulseWhenPressed connects the Qwiic Button to the I2C bus and runs the Button LED through a configured sequence when the button is pressed. The code configures the LED settings for brightness, cycleTime and offTime to pulse the Button LED while it is pressed. Try playing around with these settings to change the behavior of the LED.

Example 4 Queue Usage

Example4_QueueUsage demonstrates how to call, check, and alter the FIFO Queue for a button press and button click. The code will check both the Pressed and Clicked queues and, if the queue is not empty, prints over serial the time since the first press (since the queue was last cleared) and the time since the last press. Entering "P" in the serial monitor will "pop" the Pressed Queue to return the oldest value stored in the queue and then remove it. Entering "C" will perform the same action for the Clicked Queue.

Example 5 Change I2C Address

Heads up! This example will not change the I2C address if one of the address jumpers is closed. The Qwiic Button will remain at the alternate address set by the address jumpers.

Example5_ChangeI2CAddress checks to initialize the Qwiic Button on the I2C bus. If the device ID matches what is expected (0x6F by default), it then will print some helpful information for changing the I2C address and prompt you for an input to change the address. Once a new device ID is input and is valid, the code writes the new I2C address to EEPROM on the ATtiny84 and prints out a success note along with the new device ID. If the entered address is invalid or for some reason the write fails, the code will print out an error detailing what failed.

If the device ID does not match what is expected, it runs a scan for devices on the bus and prints out the ID of any attached device. Make sure to set up the Serial Monitor for the correct baud rate and enable both Newline and Carriage Return. Also, do not enter the "0x" prefix. For example, you want to set the address to "0x5B", type in "5B" and press enter. The gif below shows the serial printout of a successful initialization and device address change to 0x5B:

Example 1 Serial Print Out
Changing I2C Address Again: If you need to change the I2C address of your Qwiic button after altering it using the above example, you will need to modify the button.begin(); function to include the alternate address. For example, if the new address is 0x5B, your begin function should look like this: button.begin(0x5B);

Example 8 External Interrupt

Example8_ExtInterrupt demonstrates how to use the external interrupt pin to trigger an event on an attached microcontroller. You will want to solder to the INT pin and connect it to an interrupt-capable pin. If you just need to quickly prototype a circuit using the INT pin on the Qwiic Button, you can connect to it using something like these IC Hooks. The photo below demonstrates how to use the IC Hook for a temporary connection.

The code initializes the Qwiic Button on the I2C bus, attaches an interrupt to the selected pin (D2 by default), and configures the interrupt function for any button event (pressed or clicked). The INT pin will go LOW whenever a button event is registered and the selected interrupt pin on the microcontroller will fire whenever it sees a FALLING edge (going from HIGH to LOW). If you want to see it in action, you could attach an LED to the selected interrupt pin or you can modify the code to toggle all sorts of functions whenever the interrupt pin goes LOW.

The example attaches an interrupt to D2 by default. This works fine for a RedBoard Qwiic or Arduino Uno but may not work on other Arduinos. The Arduino attachInterrupt Reference Page will have a list of interrupt-capable pins for common Arduinos. Check that table or, if your chosen Arduino microcontroller is not on that list, check the documentation for your specific microcontroller and adjust the int interruptPin = 2; call to the appropriate I/O pin.

Image

Register Map

If you would like to use a different development environment than Arduino, you can use the register map below to communicate with the Qwiic Button.

The Qwiic Button Register Map

You can also download the PDF.

The Qwiic Button behaves as a normal I2C slave. First write the address of the register you would like to read or write, then follow that I2C command with a Read to read the given register or a Write and a data byte to write to a register.

Resources and Going Further

For more information, check out the resources below:

Need help getting started with Arduino and I2C? Check out these resources:

Looking for some inspiration for a project using the Qwiic Button? Check out this GPS Geo-Mapping project by Brandon J. Williams.

Before you go, here are some other tutorials using the Qwiic Connect System you may want to look through:

SparkFun SAMD21 Pro RF Hookup Guide

Using the super blazing, nay blinding, fast SAMD21 whipping clock cycles at 48MHz and the RFM96 module to connect to the Things Network (and other Radio woodles).

Keyboard Shortcut, Qwiic Keypad

A simple project using the Qwiic Keypad and the RedBoard Turbo to create your own custom hotkey-pad.

Build a Qwiic Jukebox that is Toddler Approved!

Follow this tutorial to build your own custom jukebox. Note, this is designed simple and tough for use primarily with toddlers. It's also a great introduction to SparkFun's Qwiic products!

Hookup Guide for the SparkFun RedBoard Artemis ATP

Get started with the RedBoard Artemis ATP - all the functionality of the SparkFun Artemis module wrapped in the Mega Arduino Footprint

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

SparkFun Qwiic Shield for Arduino Nano Hookup Guide

$
0
0

SparkFun Qwiic Shield for Arduino Nano Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1106

Introduction

The SparkFun Qwiic Shield for Arduino Nano allows you to add the SparkFun Qwiic ecosystem to development boards that use the Arduino Nano Footprint in an easy-to-assemble shield. It connects the I2C bus (GND, 3.3V, SDA, and SCL) on your Arduino Nano to four SparkFun Qwiic connectors. The Qwiic ecosystem allows for easy daisy chaining so, as long as your devices are on different addresses, you can connect as many Qwiic devices as you'd like.

SparkFun Qwiic Shield for Arduino Nano

SparkFun Qwiic Shield for Arduino Nano

DEV-16130
$3.50

Required Materials

To follow along with this guide, you will need an Arduino with the Nano footprint. This includes the all variants of the Arduino Nano and many other Arduino Nano-compatible boards! Here are just a few of the compatible boards.

Arduino Nano 33 BLE Sense

Arduino Nano 33 BLE Sense

DEV-15580
Arduino Nano 33 BLE

Arduino Nano 33 BLE

DEV-15588
$24.95
Arduino Nano 33 IoT with Headers

Arduino Nano 33 IoT with Headers

DEV-15589
$25.95
Arduino Nano Every

Arduino Nano Every

DEV-15590
$14.95

You will also need some headers to solder to both your Arduino Nano and Qwiic Shield:

Break Away Headers - Straight

Break Away Headers - Straight

PRT-00116
$1.50
20
Female Headers

Female Headers

PRT-00115
$1.50
7
Break Away Headers - Long

Break Away Headers - Long

PRT-10158
$2.95
3
We currently carry these header options but have a custom set specifically for the Arduino Nano pinout coming soon. If you would like to use stackable headers, you can combine two headers to a 15-pin one or you can cut down a larger header like the ESP32 Thing Stackable Headers.

Now you probably would not want the Qwiic Shield for Arudino Nano if you didn't have any Qwiic products to use with it, right? Well, if you don't have any Qwiic products, the following might not be a bad place to start.

SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic)

SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic)

GPS-15712
$64.95
2
SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SEN-15805
$13.95
1
SparkFun Qwiic Motor Driver

SparkFun Qwiic Motor Driver

ROB-15451
$14.95
1
SparkFun Qwiic Keypad - 12 Button

SparkFun Qwiic Keypad - 12 Button

COM-15290
$9.95
3

You will need some of our Qwiic cables to connect your devices to the shield. Below are a few options:

Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
Qwiic Cable - 200mm

Qwiic Cable - 200mm

PRT-14428
$1.50
Qwiic Cable - 50mm

Qwiic Cable - 50mm

PRT-14426
$0.95
Qwiic Cable - 500mm

Qwiic Cable - 500mm

PRT-14429
$1.95

Lastly, if you want to use a non-Qwiic I2C device, these adapters help to convert it to a Qwiic connector:

Qwiic Cable - Breadboard Jumper (4-pin)

Qwiic Cable - Breadboard Jumper (4-pin)

PRT-14425
$1.50
SparkFun Qwiic Adapter

SparkFun Qwiic Adapter

DEV-14495
$1.50
Qwiic Cable - Female Jumper (4-pin)

Qwiic Cable - Female Jumper (4-pin)

CAB-14988
$1.50

Required Tools

You will need a soldering iron, solder, and general soldering accessories to solder the header pins to the Qwiic shields.

Solder Lead Free - 15-gram Tube

Solder Lead Free - 15-gram Tube

TOL-09163
$3.50
2
Soldering Iron - 30W (US, 110V)

Soldering Iron - 30W (US, 110V)

TOL-09507
$9.95
7

Suggested Reading

If you aren't familiar with the Qwiic ecosystem, we recommend reading here for an overview:

Qwiic Connect System
Qwiic Connect System

We would also recommend taking a look at the following tutorials if you aren't familiar with them:

How to Solder: Through-Hole Soldering

This tutorial covers everything you need to know about through-hole soldering.

Arduino Shields

All things Arduino Shields. What they are and how to assemble them.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

Hardware Overview

The Qwiic Shield for Arduino Nano is pretty straight forward shield but has a few extra bits we'll cover in this section.

Qwiic Connectors

Just like our other Qwiic adapter boards, the Qwiic Shield for Arduino Nano comes with several Qwiic connectors. There are two horizontal Qwiic connectors on the edges of the board and two vertical ones in the center.

Image highlighting Qwiic Connectors on Qwiic Shield for Arduino Nano.

Logic Shifting Circuit and IOREF Jumper

The Qwiic Shield for Arduino Nano has a configurable logic shifting circuit depending on the voltage your Arduino Nano runs at. There is a jumper on the shield to set the IOREF voltage for the logic shifting circuit. The jumper defaults to 3.3V which works fine for 33 Nanos like the Arduino 33 Nano BLE but you will need to switch the jumper to 5V for Arduino Nanos that run at 5V like the Arduino Nano Every.

Image Highlighting logic circuit for Qwiic Shield for Arduino Nano.
Never worked with solder jumpers before just need some tips or a quick refresher? Check out our How to Work with Jumpers and PCB Traces tutorial.


How to Work with Jumper Pads and PCB Traces

April 2, 2018

Handling PCB jumper pads and traces is an essential skill. Learn how to cut a PCB trace, add a solder jumper between pads to reroute connections, and repair a trace with the green wire method if a trace is damaged.

I2C Jumper

The I2C jumper pulls the Qwiic SDA and SCL lines up to 3.3V through 4.7K resistors. The reference voltage set by the IOREF Jumper has no effect on the voltage of the pull up resistors. You can disable them by severing the trace in between the pads if you have many devices on your I2C bus.

Image highlighting I2C Jumper on the Qwiic Shield for Arduino Nano.

Board Dimensions

The shield measures 1.7in. x 0.7in. (43.18mm x 17.78mm) and has four mounting holes with a 0.07in diameter that match those on the Nano footprint.

Dimensional Drawing for Qwiic Shield for Arduino Nano

Hardware Assembly

All that is needed to get started using the Qwiic Shield for Arduino Nano is to solder your chosen headers to the shield and, if necessary, to your Arduino Nano. If you have never worked with an Arduino Shield before or need some tips, our Arduino Shields Tutorial provides detailed instructions on how to assemble and use them. Take care to match the markings on the Qwiic Shield to the appropriate pins on your Nano to avoid shorting anything out and possibly damaging your Nano. Also, some variants of the Nano like the Nano 33 BLE Sense have sensors or antennas that can be affected by the Qwiic Shield's placement on top such that you may want to consider placing the Qwiic Shield below your Arduino Nano.

Once you have soldered headers to your shield and connected it to your Nano, it's time to start connecting some Qwiic devices! Below you can see the Qwiic Shield attached to an Arduino Nano Every using some female and male headers with a couple of Qwiic devices attached.

Qwiic Shield connected to an Arduino Nano with two Qwiic Devices.

Resources and Going Further

For more information, take a look at the resources below.

If you are having trouble getting your Qwiic devices to connect using your newly assembled Qwiic Shield, you may want to take a look at these tutorials for help troubleshooting and reworking your shield.

Now that you have your Qwiic Shield ready to go, it's time to check out some Qwiic-enabled products. Below are a few to get started.

SparkFun RedBoard Turbo - SAMD21 Development Board

SparkFun RedBoard Turbo - SAMD21 Development Board

DEV-14812
$24.95
3
SparkFun Capacitive Touch Slider - CAP1203 (Qwiic)

SparkFun Capacitive Touch Slider - CAP1203 (Qwiic)

SEN-15344
$5.95
SparkFun Thing Plus - XBee3 Micro (Chip Antenna)

SparkFun Thing Plus - XBee3 Micro (Chip Antenna)

WRL-15454
$49.95
1
SparkFun Qwiic pHAT V2.0 for Raspberry Pi

SparkFun Qwiic pHAT V2.0 for Raspberry Pi

DEV-15945
$5.95

Before you go, here are some other tutorials using the Qwiic Connect System you may want to look through:

SparkFun GPS Breakout - XA1110 (Qwiic) Hookup Guide

Figure out where in the world you are with the Qwiic SparkFun GPS Breakout - XA1110.

Qwiic IR Array (MLX90640) Hookup Guide

The Melexis MLX90640 contains a 32x24 array of thermopile sensors creating, in essence, a low resolution thermal imaging camera. In this guide, we’ll go over how to connect your Qwiic Infrared Array with MLX90640 and get it communicating with Processing to produce a nice thermal image.

Qwiic Transparent OLED HUD Hookup Guide

Learn how to connect that sweet transparent OLED.

Qwiic Pro Kit Project Guide

The Qwiic Pro Kit was designed to allow users to get started with Arduino without the need for soldering or a breadboard. We've included three inputs (a joystick, accelerometer, and proximity sensor) and one display that can be daisy chained to the RedBoard Turbo (SAMD21) Development Board.

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

SparkFun Qwiic Shield for Thing Plus Hookup Guide

$
0
0

SparkFun Qwiic Shield for Thing Plus Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1107

Introduction

The SparkFun Qwiic Shield for Thing Plus provides an easy-to-assemble way to add the SparkFun Qwiic ecosystem to any development board with the Thing Plus Footprint. This shield is also compatible with the Feather Footprint so you can add Qwiic functionality to any development board that uses the Thing Plus or Feather Footprints! It connects the I2C bus (GND, 3.3V, SDA, and SCL) on your Thing Plus to four SparkFun Qwiic connectors. The Qwiic ecosystem allows for easy daisy chaining so, as long as your devices are on different addresses, you can connect as many Qwiic devices as you'd like.

SparkFun Qwiic Shield for Thing Plus

SparkFun Qwiic Shield for Thing Plus

DEV-16138
$3.50

Required Materials

To follow along with this tutorial, you will need an Arduino development board with the Thing Plus footprint. This includes the all variants of the SparkFun Thing Plus boards and many other Thing Plus-compatible boards! Here are a few of the compatible boards:

SparkFun Thing Plus - ESP32 WROOM

SparkFun Thing Plus - ESP32 WROOM

WRL-15663
$20.95
SparkFun Thing Plus - Artemis

SparkFun Thing Plus - Artemis

WRL-15574
$20.95
SparkFun Thing Plus - SAMD51

SparkFun Thing Plus - SAMD51

DEV-14713
$19.95
1

You will also need some headers to solder to both your Thing Plus and Qwiic Shield:

Break Away Headers - Straight

Break Away Headers - Straight

PRT-00116
$1.50
20
Female Headers

Female Headers

PRT-00115
$1.50
7
Break Away Headers - Long

Break Away Headers - Long

PRT-10158
$2.95
3
Feather Stackable Header Kit

Feather Stackable Header Kit

PRT-15187
$1.50

Now you probably would not want the Qwiic Shield for Thing Plus if you didn't have any Qwiic products to use with it, right? Well, if you don't have any Qwiic products, the following might not be a bad place to start:

SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic)

SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic)

GPS-15712
$64.95
2
SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SEN-15805
$13.95
1
SparkFun Qwiic Motor Driver

SparkFun Qwiic Motor Driver

ROB-15451
$14.95
1
SparkFun Proximity Sensor Breakout - 20cm, VCNL4040 (Qwiic)

SparkFun Proximity Sensor Breakout - 20cm, VCNL4040 (Qwiic)

SEN-15177
$6.95

You will need some of our Qwiic cables to connect your devices to the shield. Below are a few options:

Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
Qwiic Cable - 200mm

Qwiic Cable - 200mm

PRT-14428
$1.50
Qwiic Cable - 50mm

Qwiic Cable - 50mm

PRT-14426
$0.95
Qwiic Cable - 500mm

Qwiic Cable - 500mm

PRT-14429
$1.95

Lastly, if you want to use a non-Qwiic I2C device, these adapters help to convert it to a Qwiic connector:

Qwiic Cable - Breadboard Jumper (4-pin)

Qwiic Cable - Breadboard Jumper (4-pin)

PRT-14425
$1.50
SparkFun Qwiic Adapter

SparkFun Qwiic Adapter

DEV-14495
$1.50
Qwiic Cable - Female Jumper (4-pin)

Qwiic Cable - Female Jumper (4-pin)

CAB-14988
$1.50

Required Tools

You will need a soldering iron, solder, and general soldering accessories to solder the header pins to the Qwiic shields:

Solder Lead Free - 15-gram Tube

Solder Lead Free - 15-gram Tube

TOL-09163
$3.50
2
Soldering Iron - 30W (US, 110V)

Soldering Iron - 30W (US, 110V)

TOL-09507
$9.95
7

Suggested Reading

If you aren't familiar with the Qwiic system, we recommend reading here for an overview:

Qwiic Connect System
Qwiic Connect System

We would also recommend taking a look at the following tutorials if you aren't familiar with them:

How to Solder: Through-Hole Soldering

This tutorial covers everything you need to know about through-hole soldering.

Arduino Shields

All things Arduino Shields. What they are and how to assemble them.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

Hardware Overview

Qwiic Connectors

The Qwiic Shield for Thing Plus has four Qwiic connectors on it. The two on the edges are the standard horizontal connectors and the two in the middle are vertical connectors.

Image highlighting Qwiic Connectors

I2C Jumper

This jumper is a little different than our normal I2C pull up jumpers as it is open by default. The jumper only needs to be closed if your slave device does not have pull up resistors. Essentially all SparkFun I2C breakouts come with pull up resistors on them so if you are using a Qwiic I2C device or another SparkFun I2C device, you can most likely leave it open. When closed, the SDA and SCL lines are pulled to 3.3V by 4.7K resistors. If you have never worked with solder jumpers before, check out this tutorial for some tips and tricks for working with them.

Image higlighting I2C Jumper

Board Dimensions

The shield measures 2.00in x 0.90in (50.8mm x 22.86mm) and has four mounting holes that fit a 4-40 screw.

Dimensional Drawing for Qwiic Shield for Thing Plus

Hardware Assembly

All you need to get started using the Qwiic Shield for Thing Plus is to solder whichever headers you choose to the shield and, if necessary, to your Thing Plus (or compatible board). If you have never worked with an Arduino Shield before or need some tips, our Arduino Shields Tutorial provides detailed instructions on how to assemble and use them.

Once you have soldered headers to your shield and connected it to your Thing Plus, it's time to start connecting Qwiic devices! Below you can see the Qwiic Shield connected to a SparkFun Thing Plus - SAMD51 using the Feather Stackable Header Kit along with a couple of Qwiic Devices chained to it.

Qwiic Shield connected to a Thing Plus board with two Qwiic devices.

Resources and Going Further

For more information, take a look at the resources below.

If you are having trouble getting your Qwiic devices to connect using your newly assembled Qwiic Shield, you may want to take a look at these tutorials for help troubleshooting and reworking your shield.

Now that you have your Qwiic Shield ready to go, it's time to check out some Qwiic-enabled products. Below are a few to get started.

SparkFun Differential I2C Breakout - PCA9615 (Qwiic)

SparkFun Differential I2C Breakout - PCA9615 (Qwiic)

BOB-14589
$10.95
7
SparkFun 9DoF IMU Breakout - ICM-20948 (Ding and Dent)

SparkFun 9DoF IMU Breakout - ICM-20948 (Ding and Dent)

DD-15182
$8.95
SparkFun Inventor's Kit - v4.1

SparkFun Inventor's Kit - v4.1

KIT-15267
$99.95
3
SparkFun Inventor's Kit Bridge Pack - v4.1

SparkFun Inventor's Kit Bridge Pack - v4.1

KIT-15476
$24.95
1

Before you go, here are some other tutorials using the Qwiic Connect System you may want to look through:

Qwiic Keypad Hookup Guide

If you are tired of taking up GPIO pins, wiring a bunch of pull up resistors, and using firmware that scans the keys taking up valuable processing time... check out the new Qwiic Keypad.

Qwiic Distance Sensor (RFD77402) Hookup Guide

The RFD77402 uses an infrared VCSEL (Vertical Cavity Surface Emitting Laser) TOF (Time of Flight) module capable of millimeter precision distance readings up to 2 meters. It’s also part of SparkFun’s Qwiic system, so you won’t have to do any soldering to figure out how far away things are.

SparkFun LoRa Gateway 1-Channel Hookup Guide

How to setup and use the LoRa Gateway 1-Channel in Arduino.

Cryptographic Co-Processor ATECC508A (Qwiic) Hookup Guide

Learn how to use some of the standard features of the SparkFun Cryptographic Co-processor.

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado


Qwiic Pro Micro USB-C (ATmega32U4) Hookup Guide

$
0
0

Qwiic Pro Micro USB-C (ATmega32U4) Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1114

Introduction

Heads up! This is for the Qwiic Pro Micro USB-C (ATmega32U4) version. If you are looking for information about hardware on the Pro Micros with the micro-b USB connector, make sure to check out the older Pro Micro & Fio V3 Hookup Guide.

The SparkFun Qwiic Pro Micro USB C is a really cool, little development board. It's an Arduino-compatible microcontroller, micro-sized, and it accomplishes with one single chip what old Arduino Unos, Duemilanoves, and Diecimeillas could never dream of: true USB functionality. In this tutorial, we'll check out the updated Qwiic Pro Micro and go through a few examples to get you started!

SparkFun Qwiic Pro Micro - USB-C (ATmega32U4)

SparkFun Qwiic Pro Micro - USB-C (ATmega32U4)

DEV-15795
$19.95

Required Materials

To follow along with this tutorial, you will need the following materials at a minimum. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Reversible USB A to C Cable - 0.8m

Reversible USB A to C Cable - 0.8m

CAB-15425
$4.95
1
SparkFun Qwiic Pro Micro - USB-C (ATmega32U4)

SparkFun Qwiic Pro Micro - USB-C (ATmega32U4)

DEV-15795
$19.95

Tools

You will need a soldering iron, solder, and general soldering accessories for a secure connection when using the plated through hole pads.

Soldering Iron - 60W (Adjustable Temperature)

Soldering Iron - 60W (Adjustable Temperature)

TOL-14456
$14.95
8
Solder Lead Free - 15-gram Tube

Solder Lead Free - 15-gram Tube

TOL-09163
$3.50
2

Prototyping Accessories

Depending on your setup, you may want to use IC hooks for a temporary connection. However, you will want to solder header pins to connect devices to the plated through holes for a secure connection.

Breadboard - Self-Adhesive (White)

Breadboard - Self-Adhesive (White)

PRT-12002
$4.95
41
Break Away Headers - Straight

Break Away Headers - Straight

PRT-00116
$1.50
20
IC Hook with Pigtail

IC Hook with Pigtail

CAB-09741
$4.95
8
Photon Stackable Header - 12 Pin

Photon Stackable Header - 12 Pin

PRT-14322
$0.50

For those that want to take advantage of the Qwiic enabled devices, you'll want to grab a Qwiic cable.

SparkFun Qwiic Cable Kit

SparkFun Qwiic Cable Kit

KIT-15081
$7.95
1
Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
Qwiic Cable - Breadboard Jumper (4-pin)

Qwiic Cable - Breadboard Jumper (4-pin)

PRT-14425
$1.50
Qwiic Cable - 500mm

Qwiic Cable - 500mm

PRT-14429
$1.95

Suggested Reading

If you aren't familiar with the Qwiic system, we recommend reading here for an overview if you decide to take advantage of the Qwiic connector.

Qwiic Connect System
Qwiic Connect System

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

Serial Communication

Asynchronous serial communication concepts: packets, signal levels, baud rates, UARTs and more!

What is an Arduino?

What is this 'Arduino' thing anyway?

Installing Arduino IDE

A step-by-step guide to installing and testing the Arduino software on Windows, Mac, and Linux.

Hardware Overview

Before we get into installing and using the Qwiic Pro Micro, let's quickly look at the board -- examine its inputs, outputs, and other hardware quirks.

Old School to New School

The Qwiic Pro Micro USBC is a revision of the original Pro Micro. Overall, it is functionally the same as the previous version. The board is the same size as the original Pro Micro but we added a few additional features by shrinking down some components on the board. The major changes to the board that you will notice include:

  • Reset Button
  • USB C
  • Castellated Pads
  • Qwiic Connector
  • AP2112 3.3V Voltage Regulator

The benefit of the reset button is to quickly reset the board or place it into bootloader mode without the need to take out a piece of jumper wire. The USB micro-b connector has been replaced with the USB type C connector. The through hole pads have castellated edges for each pin to add a lower profile in your projects should you decide build it into another assembly during production. Finally, a Qwiic connector is populated on the bottom of the board to easily add Qwiic enabled I2C devices.

Older 5V/16MHz Pro MicroNewer 5V/16MHz Qwiic Pro Micro
Older 5V/16MHz
Pro Micro
Newer 5V/16MHz
Qwiic Pro Micro USB C

A subtle difference that you may not notice is the old Pro Micro used the MIC5219, which was able to handle a maximum voltage input of 16VDC. The new Qwiic Pro Micro uses the AP2112 3.3V voltage regulator which can handle a maximum of 6V. The output current is slightly higher in the Qwiic Pro Micro which peaks at about 600mA. You'll need to make sure to use an appropriate voltage regulator and components and regulate the voltage down.

For more information about the differences between the boards, make sure to pull up the schematic for both boards and read further below!

The Pinout

All of the Qwiic Pro Micro's I/O and power pins are broken out to two, parallel headers. Some pins are for power input or output, other pins are dedicated I/O pins. Further, the I/O pins can have special abilities, like analog input. Here's a map of which pin is where, and what special hardware functions it may have:

Graphical Datasheet for Qwiic Pro Micro

Click on image for a closer view

Power

There are a variety of power and power-related nets broken out to connectors and through hole pads. Each pad has a castellated edge. The back of the board also has the USB pins broken out for power.

Castellated Power and Reset Pins
Castellated Power and Reset PinsUSB Power Pins

These nets consist of the following:

  • V is the voltage provided from the USB connector.
  • RAW is the unregulated voltage input for the Qwiic Pro Micro. If the board is powered via USB (i.e. V), the voltage at this pin will be about 4.8V (USB's 5V minus a Schottky diode drop). On the other hand, if the board is powered externally, through this pin, the applied voltage can be up to 6V.
  • 5V is the voltage supplied to the on-board ATmega32U4. This voltage will depend on whether you have the jumper set to 5V (by default) or 3.3V.
    • When the jumper is set to 5V, it is the voltage applied to the RAW pin. We suggest using a clean 5V power supply if you are connecting 5V devices to the I/O. If the board is powered through the 'RAW' pin (or USB), this pin can be used as an output to 5V supply other devices.
    • When the jumper is set to 3.3V, the output is 3.3V. If the board is powered through the 'RAW' pin (or USB), this pin can be used as an output to 3.3V supply other devices.
  • RST can be used to restart the Qwiic Pro Micro. There is a built-in reset button to reset the Pro Micro. However, the pin is broken out if you need to access this pin externally. This pin is pulled high by a 10k&ohm; resistor on the board, and is active-low, so it must be connected to ground to initiate a reset. The Qwiic Pro Micro will remain "off" until the reset line is pulled back to high.
  • GND, of course, is the common, ground voltage (0V reference) for the system.

I/O Pins

The Qwiic Pro Micro breaks out the I/O pins to plated through hole pads on the edge of the board. Each pad is castellated as well. On the back, there are additional pins to connect to the USB data pins.

Castellated IO PinsUSB Pins
Castellated I/O PTH PadsUSB Pads

The Pro Micro's I/O pins -- 18 in all -- are multi-talented. Every pin can be used as a digital input or output, for blinking LEDs or reading button presses. These pins are referenced in the Arduino IDE via an integer value between 0 and 21. (The A0-A3 pins can be referenced digitally using either their analog or digital pin number).

Nine pins feature analog to digital converters (ADCs) and can be used as analog inputs. These are useful for reading potentiometers or other analog devices using the analogRead([pin]) function.

There are five pins with pulse width modulation (PWM) functionality, which allows for a form of analog output using the analogWrite([pin], [value]) function. These pins are indicated on-board with a faint, white circle around the square pads.

There are hardware UART (serial), I2C, and SPI pins available as well. These can be used to interface with digital devices like serial LCDs, XBees, IMUs, and other serial sensors.

The Pro Micro has five external interrupts, which allow you to instantly trigger a function when a pin goes either high or low (or both). If you attach an interrupt to an interrupt-enabled pin, you'll need to know the specific interrupt that pin triggers: pin 3 maps to interrupt 0 (INT0), pin 2 is interrupt 1 (INT1), pin 0 is interrupt 2 (INT2), pin 1 is interrupt 3 (INT3), and pin 7 is interrupt 4 (INT6).

On-Board LEDs

There are three LEDs on the Pro Micro. One red LED indicates whether power is present. The other two LEDs help indicate when data is transferring over USB. A yellow LED represents USB data coming into (RX) the the Pro Micro, and a green LED indicates USB data going out (TX).

On Board LEDS

Jumpers

On the back of the board is a jumper that is able to select the system voltage. The default voltage for the board defautls to 5V. By cutting the jumper pad and adding a solder to the between the center and right jumper pads, the system voltage will be set to 3.3V.

Selectable Power Jumpers

Board Dimensions

The board measures 1.30" x 0.70". Not included in the image below is the PCB thickness, which is 0.8mm. This is thinner than a majority of the PCBs used for SparkFun original designs.

Board Dimensions

How to Power the Qwiic Pro Micro USB C

As the Pro Micro's main feature is its innate USB functionality, the most common way to power it is via USB. If the jumper is set to the default 5V, the Qwiic Pro Micro will be powered directly from the USB bus. If the jumper is set to 3.3V, the board will regulate the 5V supply coming in from USB down to 3.3V. The other end of the USB cable can be connected to either a computer, USB hub, USB batteries, or a USB wall adapter, which can (in most cases) provide more power.

Alternatively, if your Qwiic Pro Micro is living out in the wild, out of reach of USB cables, it can be powered through either the 'RAW' or '5V' pins. A supply going into those pins will provide power to the Qwiic Pro Micro. To be safe, it shouldn't be any higher than 6V. If the jumper is set to 3.3V, the voltage will be regulated down to 3.3V.

How, exactly, you power your project is up to you and the demands of your project. If you're making something battery powered, you could use a LiPo boost converter to power the board at 5V. Or you may want to set the jumper to 3.3V, which could be powered by a LiPo battery or a couple alkalines. Make sure to check out the following tutorials for more information.

Battery Technologies

February 6, 2013

The basics behind the batteries used in portable electronic devices: LiPo, NiMH, coin cells, and alkaline.

How to Power a Project

February 7, 2013

A tutorial to help figure out the power requirements of your project.

Hardware Hookup

Header pins were left off the Qwiic Pro Micro to allow users the flexibility of connecting any type of 0.1" header to the board. For temporary connections to the I/O pins, you could use IC hooks to test out the pins. However, you'll need to solder headers or wires of your choice to the board for a secure connection. For advanced users, you could also design a PCB to take advantage of the castellated edges for a lower profile. Here are a few tutorials to connect to the pads depending on your personal preference.

How to Solder: Through-Hole Soldering

September 19, 2013

This tutorial covers everything you need to know about through-hole soldering.

Working with Wire

February 8, 2013

How to strip, crimp, and work with wire.

How to Solder: Castellated Mounting Holes

May 12, 2015

Tutorial showing how to solder castellated holes (or castellations). This might come in handy if you need to solder a module or PCB to another PCB. These castellations are becoming popular with integrated WiFi and Bluetooth modules.

In order to power and upload to the board, you will simply need a USB C cable connected to your computer. For the scope of this tutorial, you'll get as far as example 1.

USB Cable connected to the Qwiic Pro Micro

To take advantage of the board's HID, we recommend some sort of input. The analog joystick provides a few inputs to test our the keyboard and mouse in example 2.

Example 2: HID Keyboard and Mouse using the Button and Analog Joystick Example

HID JoystickJoystick

Qwiic Enabled Device

You can also easily connect a Qwiic enabled device to the Qwiic connector. Below is an example of a distance sensor connected to the Qwiic Pro Micro. If you have an installation with a kiosk with the screensaver turned on, you could use the Qwiic Pro Micro to wake it up by moving a mouse if there is someone within a certain distance of the VL53L1X sensor.

Qwiic Device Connected to the Qwiic Pro Micro

Installing Drivers (Windows)

Getting the Qwiic Pro Micro set up on your computer and in your Arduino environment can be difficult. Follow along on this page for a step-by-step guide through the driver installation and Arduino-enabling process.

Windows Driver Installation

Step 1: Download the Driver

Before plugging your board in, get a head start by downloading the drivers. Check the GitHub Repository for the latest files. The same driver file works for both the Pro Micro and the Fio v3. The drivers for both the Fio and the Pro Micro are signed for Windows users. You can download them directly using the link below.

Unzip that zip file, and don't forget where you've left its contents. In that zip file, you should find the .inf and .cat files, which contains all the information Windows needs to install the Pro Micro's driver. The sparkfun.inf driver and sparkfun.cat digitally signed catalog file will be found in ...Arduino_Boards-master/sparkfun/avr/signed_driver .

Step 2: Plug in the Qwiic Pro Micro

When you initially plug the board in, an "Installing device driver software" bubble notification should pop up in the lower-right corner of your taskbar. After the green dot circles the grey box a number of times, you’ll probably get a sad bubble like this:

Driver install failed

Never fear! Windows just doesn't know where to find our driver.

Step 3: Open the Device Manager

From here, the most straightforward way to install the driver is through the Device Manager. To get to the Device Manager, click the Start button, then open the Control Panel. In the Control Panel, click System and Maintenance, and then open the Device Manager.

Alternatively, you can open the Run prompt (Windows key+R) and type 'devmgmt.msc' and click OK.

Run prompt opening device manager

In the Device Manager, expand the 'Other devices' tree, where you should find a 'USB IO Board' with a yellow warning sign over its icon. Right-click the 'USB IO Board' and select Update Driver Software....

Updating driver in device manager

This should spawn an 'Update Driver Software - USB IO Board' window.

Step 4: Finding the Driver

In the first window that pops up, click 'Browse my computer for driver software'. On the next window, click 'Browse...' to search for the driver you just downloaded. It should be a folder named 'Arduino_Boards-master', in a subdirectory noted in step 1. After you’ve selected the 'driver' folder, click OK, then select Next.

Driver install steps 1 through 5

Click on image for a closer view.

Windows will attempt to do its driver install thing, but not before complaining about the driver being unsigned. It’s safe to select 'Install this driver software anyway' on the warning dialog.

After watching the progress bar beam by a few times, you should get a happy 'Windows has successfully updated your driver software' window. And the 'Device Manager' should have a new entry for the 'SparkFun Pro Micro (COM ##)' if you have one of those) under the 'Ports (COM & LPT)' tree.

Atmega-32U4 based Arduino Driver Installation

Click on image for a closer view.

Take note of which COM port your Qwiic Pro Micro was assigned. We’ll need it soon.

Installing Drivers (Mac and Linux)

If you're using Mac or Linux, follow the steps below to get your Pro Micro ready to go on your computer. We're not going to name names here, but installing the Qwiic Pro Micro on Mac OS X and Linux is a lot easier than on other OS's...

When you initially plug your Qwiic Pro Micro into a Mac, it'll pop up a "Keyboard Setup Assistant" window. This stems from the Qwiic Pro Micro's ability to emulate an HID USB device (e.g. keyboards and mice) -- the Mac thinks your Pro Micro is a human input device (which it could be! but isn't yet).

Mac keyboard setup assistant

There's nothing to configure in this window, so just click the big, red, 'X' to close it.

That's all there is to it! The CDC (communication device class) portion of your Qwiic Pro Micro (the part that handles USB-to-serial conversion) should automatically install on your computer.

Setting Up Arduino

Note: If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE.

We're still not completely ready for Arduino, but this is the final stretch. Before you can use the Qwiic Pro Micro in the Arduino IDE, you'll need to install the board (*.brd) files for the Qwiic Pro Micro so the Arduino IDE will know how to communicate with your board. Jump to the section based on your operating system for instructions on how to install the board files so that you can select the SparkFun Pro Micro, ATmega32U4 (5V, 16MHz).

Installing the Arduino AddonWindows

Using the Board Manager

Since the release of Arduino 1.6.4, adding third party boards to the Arduino IDE is easily achieved through the board manager. If you're running an older version of Arduino (v1.6.3 or earlier), we recommend upgrading now. As always, you can download the latest version of Arduino from arduino.cc.

To begin, you'll need to point the Arduino IDE board manager to a custom URL. Open up Arduino, then go to the Preferences (File>Preferences). Then, towards the bottom of the window, paste this URL into the "Additional Board Manager URLs" text box:

https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json

You can add multiple URLs by clicking the window icon, and pasting in one URL per line.

Adding Board Manager URL to Arduino preferences

Click OK. Then open the Board Manager by clicking Tools, then hovering over the Board selection tab and clicking Board Manager.

Select Arduino Board Manager

Search for 'sparkfun' in the Board Manager. You should see the SparkFun AVR Boards package appear. Click install, wait a few moments, and all the *.brd files you'll need should be installed, indicated by the blue 'Installed' that is printed next to the package.

Click on Install for the SparkFun AVR Boards

You should now be able to upload code to a number of SparkFun Arduino-compatible products, including the SparkFun Pro Micro.

Arduino SparkFun AVR Boards

Notice there are two options for the Pro Micro - 8MHz and 16MHz. It's very important that you select the Pro Micro option that matches your board's voltage and speed. This should be listed under the Tools>Processor. For the Qwiic Pro Micro, you will need to ensure that you select the ATmega32U4 (5V, 16MHz).

Atmega32U4 Processor Selection in Arduino IDE

You should also see your Pro Micro's COM port under the 'Tools>Serial Port' menu. Select it, and head over to the Example 1 page where we'll upload our first piece of code.

Manually Installing the *.brd Files

If you are using an older version of the Arduino IDE and do not have access to the Arduino Board Manager, then you'll need to install the *.brd files the old fashioned way.

To begin, download this zip folder, and unzip its contents into a 'hardware' directory within your Arduino sketchbook.

Note: These Arduino addon files only work with Arduino 1.5 and up. If you're using an earlier version of Arduino, either update (and get some cool new features), or download the older version of the Addon.

Where's your Arduino sketchbook? Well, by default, it should an 'Arduino' folder in your home directory, but to double check you can go to File>Preferences within Arduino and check the 'Sketchbook location' text box. Just make sure you close all Arduino windows once you're done.

Finding the sketchbook location

Once you've unzipped that folder into the 'hardware' folder within your Arduino sketchbook (you may actually have to create a hardware folder), your directory structure should look something like this:

Windows directory structure

The structure of this directory is critical -- it should look something like ".../Arduino/hardware/[manufacturer]/[architecture]", in this case [manufacturer] is "sparkfun", and [architecture] is "avr."

language:bash
.../Arduino/hardware/sparkfun/avr

There's a lot going on in that addon, but one of the most important files is 'boards.txt', which will add a few new entries to your 'Tools>Board' menu.

To double-check that the board definitions have been added to Arduino, open up Arduino, and check under the 'Tools>Board' menu. There should be some new entires for 'SparkFun Pro Micro', 'SparkFun FioV3', 'Qduino Mini', and other 32U4-based boards.

Pro Micros showing up in Arduino board selection

Notice there are two options for the Pro Micro - 8MHz and 16MHz. It's very important that you select the Pro Micro option that matches your board's voltage and speed. This should be listed under the Tools>Processor. For the Qwiic Pro Micro, you will need to ensure that you select the ATmega32U4 (5V, 16MHz).

Atmega32U4 Processor Selection in Arduino IDE

You should also see your Pro Micro's COM port under the 'Tools>Serial Port' menu. Select it, and head over to the Example 1 page where we'll upload our first piece of code.

Installing the Arduino AddonMac and Linux

Following these directions is critical to getting your Pro Micro supported within your Arduino environment!

Using the Board Manager

Since the release of Arduino v1.6.4, adding third party boards to the Arduino IDE is easily achieved through the board manager. If you're running an older version of Arduino (v1.6.3 or earlier), we recommend upgrading now. As always, you can download the latest version of Arduino from arduino.cc.

To begin, you'll need to point the Arduino IDE board manager to a custom URL. Open up Arduino, then go to the Preferences (File>Preferences). Then, towards the bottom of the window, paste this URL into the "Additional Board Manager URLs" text box:

https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json

You can add multiple URLs by clicking the window icon, and pasting in one URL per line.

Adding Board Manager URL to Arduino preferences

Click OK. Then open the Board Manager by clicking Tools, then hovering over the Board selection tab and clicking Board Manager.

alt text

Search for 'sparkfun' in the Board Manager. You should see the SparkFun AVR Boards package appear. Click install, wait a few moments, and all the *.brd files you'll need should be installed, indicated by the blue 'Installed' that is printed next to the package.

Installing Boards Using the Boards Manager

You should now be able to upload code to a number of SparkFun Arduino-compatible products, including Pro Micro.

Arduino Board Selection

Manually Installing the *.brd Files

If you are using an older version of the Arduino IDE and do not have access to the Arduino Board Manager, then you’ll need to install the *.brd files the old fashioned way.

In order to use the Pro Micro in your Arduino IDE, you need to add a few board definition files to it. That's what we'll do in this section. Begin by downloading the Pro Micro addon files.

Note: These Arduino addon files only work with Arduino 1.5 and up. If you're using an earlier version of Arduino, either update (and get some cool new features), or download the older version of the Addon.

With that downloaded, follow these steps to enable the Pro Micro in your Arduino environment:

  1. The addon files are supplied in a zip folder, so you'll need to extract the files within first.
  2. Find your Arduino sketchbook folder. If you don't know where it is, you can locate your sketchbook by looking at the preferences dialog in your Arduino IDE.
  3. If there isn't already one, create a folder in your sketchbook called 'hardware'.
  4. Copy the 'sparkfun' folder that was unzipped in the first step into the 'hardware' folder.
    • Your directory structure should look something like ".../Arduino/hardware/sparkfun/avr."
  5. Restart Arduino, and look under the Tools>Board menu. You should see a few new options, including SparkFun Pro Micro, SparkFun Fio V3, and Qduino Mini.

If the boards are visible, select the option that matches your board. If you have a Pro Micro, make sure you select the correct operating speed and voltage under Tools>Processor! At this point, select the COM port that the Pro Micro enumerated on. Then head over to the next page where we'll upload our first sketch!

Example 1: Blinkies and Hello World!

The Arduino-standard Blink sketch won't have any visible effect on the Pro Micro -- there's no LED on pin 13. In fact, the only LEDs on the board are the power indicator, and RX/TX blinkies. Unlike other Arduino boards, though, we can control the RX/TX LEDs in our sketch. So let's get blinking!

Upload the RX/TX Blinky, Hello World Sketch

Copy and paste the code below into the Arduino IDE. In the Tools, make sure to select Board>SparkFun Pro Micro and Processor>ATmega32U4 (5V, 16MHz). Also, don't forget to select the COM port that your board enumerated to. Finally, upload [1] it to your Qwiic Pro Micro USB-C.

language:c
/* Pro Micro Test Code
   by: Nathan Seidle
   modified by: Jim Lindblom
   SparkFun Electronics
   date: September 16, 2013
   license: Public Domain - please use this code however you'd like.
   It's provided as a learning tool.

   This code is provided to show how to control the SparkFun
   ProMicro's TX and RX LEDs within a sketch. It also serves
   to explain the difference between Serial.print() and
   Serial1.print().
*/

int RXLED = 17;  // The RX LED has a defined Arduino pin
// Note: The TX LED was not so lucky, we'll need to use pre-defined
// macros (TXLED1, TXLED0) to control that.
// (We could use the same macros for the RX LED too -- RXLED1,
//  and RXLED0.)

void setup()
{
  pinMode(RXLED, OUTPUT);  // Set RX LED as an output
  // TX LED is set as an output behind the scenes

  Serial.begin(9600); //This pipes to the serial monitor
  Serial.println("Initialize Serial Monitor");

  Serial1.begin(9600); //This is the UART, pipes to sensors attached to board
  Serial1.println("Initialize Serial Hardware UART Pins");
}

void loop()
{
  Serial.println("Hello world!");  // Print "Hello World" to the Serial Monitor
  Serial1.println("Hello! Can anybody hear me?");  // Print "Hello!" over hardware UART

  digitalWrite(RXLED, LOW);   // set the RX LED ON
  TXLED0; //TX LED is not tied to a normally controlled pin so a macro is needed, turn LED OFF
  delay(1000);              // wait for a second

  digitalWrite(RXLED, HIGH);    // set the RX LED OFF
  TXLED1; //TX LED macro to turn LED ON
  delay(1000);              // wait for a second
}

With the code uploaded you should see the RX and TX LEDs take turns blinking on and off every second.

LEDs Blinking

You can also open up the Arduino IDE's serial monitor (set to 9600 bps) and see every programmer's favorite two-word phrase.

Hello World

Understanding the Sketch

RX LED

The RX LED is tied to Arduino's pin 17. You can control it just as you would any other digital pin. Set it as an OUTPUT, and digitalWrite([pin], [level]) it HIGH to turn the LED off or LOW to turn the LED on. Here's part of the code highlighted.

language:c
int RXLED = 17;  // The RX LED has a defined Arduino pin
void setup(){
  pinMode(RXLED, OUTPUT);  // Set RX LED as an output
}
.
.
.
  digitalWrite(RXLED, LOW);   // set the RX LED ON
  digitalWrite(RXLED, HIGH);    // set the RX LED OFF

TX LED

The TX LED was not provided as an Arduino-defined pin, unfortunately, so you'll have to use a pair of macros to control it. TXLED1 turns the LED on, and TXLED0 turns the LED off. We could use the same macros for the RX LED too -- RXLED1 and RXLED0. Here's part of the code highlighted.

language:c
TXLED0; //TX LED is not tied to a normally controlled pin so a macro is needed, turn LED OFF
TXLED1; //TX LED macro to turn LED ON

Serial Monitor (Serial) vs Hardware Serial UART (Serial1)

In that sketch, you'll also notice a pair of Serial initialization statements:

language:c
Serial.begin(9600); //This pipes to the serial monitor
Serial1.begin(9600); //This is the UART, pipes to sensors attached to board

That "1" makes a huge difference. Think of the Qwiic Pro Micro having two separate serial ports. The one without the "1" is for communication to and from the computer over USB; this is what is visible in the Serial Monitor. The Serial1 port is a bonafide, hardware UART, where your Qwiic Pro Micro can talk to any serial-enabled piece of hardware.

If you open up the Serial Monitor, you should only see 'Hello world!' printed. 'Hello! Can anybody hear me?' is being sent out over the hardware UART, where, presumably, nothing is listening. This begs the age-old question: "If a Qwiic Pro Micro is saying 'Hello!' over the hardware serial port, and nothing is there to hear it, does the Qwiic Pro Micro really say anything at all?"

Why Does My Board Re-Enumerate Every Upload?

In order to communicate serially, the Qwiic Pro Micro emulates a virtual serial port. Actually, it emulates two different serial ports -- one for the bootloader, and one for the sketch. Since the bootloader and sketch run individually. Only one of these serial ports is visible at any one time.

When you click 'Upload' in the Arduino IDE, the Qwiic Pro Micro resets itself and starts its bootloader program. (The bootloader is a low-level program on the Pro Micro which enables self-programming via serial.) To our operating system, the bootloader looks like a completely different device, so it gets its own serial port number. While the Qwiic Pro Micro is being programmed, the bootloader serial port will be open. When the sketch upload is finished, the bootloader will exit, that serial port will be closed, and the regular Qwiic Pro Micro serial port will open up.

What this all boils down to is the fact that you have to be patient with Pro Micros. Every time you upload a new sketch, your OS will need to work its driver magic before you can open up the COM port. This can take a few seconds after the code has finished uploading.


[1]Note for Windows users: The first time you upload a sketch, it may fail and give you an error. On top of that, Windows will pop up that familiar 'Device driver software was not successfully installed' notification. Don't let this worry you too much. If you get the error, wait about a minute, and try uploading again.

Hopefully the upload will succeed the second time, but if it continues to fail, check out the how to enter the bootloader section of the FAQ. Windows needs to install the same driver we've already installed for the Qwiic Pro Micro's bootloader, but it's unable to get everything set up before the bootloader exits.

Example 2: HID Mouse and Keyboard

When the Pro Micro's were released, the most revolutionary feature (as far as Arduinos go) is its true USB functionality. The Pro Micro can be programmed to emulate any USB device you could imagine. You can even program it to act just like a mouse, keyboard, or other HID-class USB device.

What is HID?

It's one of the many defined USB device classes. Every USB device is assigned a class, which defines what its general purpose is. There are loads of classes -- printers, hubs, speakers, and webcams to mention a few, but in this example we'll be emulating HID -- Human Interface Device. The ATmega32U4 takes care of the USB-hardware hurdle, but we've still got to clear the firmware one. Time for some example code! We broke up the HID example into two parts.

Example 2a: USB Keyboards Made Simple

To emulate a USB keyboard, we'll be making use of the Keyboard class. Here are some of the functions made available to us by this class:

  • Keyboard.write(char) - This function will send a single character over USB. The character passed can be any standard, printable, ASCII-defined character: 0-9, a-z, A-Z, space, symbols, etc. Here's an example line of code:

    Keyboard.write('z') // This will send a single 'z' character to your computer.
  • Keyboard.print(string) - If you need to perform a series a Keyboard.write()'s, consider using just a single Keyboard.print(). This works similar to Serial.print()– give it a string of characters and it'll send that stream of characters over USB. Keyboard.println(string) is also defined, if you want a newline/linefeed to close out your string. An example:

    Keyboard.print("Hello, world"); // This'll send your computer an 'H', followed by 'e', followed by...
  • Keyboard.press(byte) and Keyboard.release(byte) give you more precise control over key presses. They do exactly what you'd expect. One presses a button down, the other releases a button. Make sure you release any buttons you press, otherwise you'll encounter some wiggyness on your computer.

That's it. You don't need to include any libraries or anything, just invoke any of those functions. Here's an example sketch to try it out:

language:c
/* HID KeyBoard Example
by: Jim Lindblom
date: 1/12/2012
license: MIT License - Feel free to use this code for any purpose.
No restrictions. Just keep this license if you go on to use this
code in your future endeavors! Reuse and share. 

This is very simplistic code that allows you to send a 'z' with
a momentary pushbutton. 
*/

#include <Keyboard.h>
int buttonPin = 9;  // Set a button to any pin

void setup()
{
  pinMode(buttonPin, INPUT);  // Set the button as an input
  digitalWrite(buttonPin, HIGH);  // Pull the button high
}

void loop()
{
  if (digitalRead(buttonPin) == 0)  // if the button goes low
  {
    Keyboard.write('z');  // send a 'z' to the computer via Keyboard HID
    delay(1000);  // delay so there aren't a kajillion z's
  }
}

In this sketch, connecting pin 9 to ground will make the Qwiic Pro Micro spit out a 'z' character. If you have a simple, momentary button handy, tie one end to pin 9 and the other to ground. Otherwise, just use a wire to short 9 to GND.

After a Keyboard.write() or Keyboard.print() function has been performed by the Qwiic Pro Micro, your computer will have to decide what to do with it. What your computer does with that character, or string of characters, is entirely dependent on what program it's running at the time. If you have a text editor (Notepad, Word, TextEdit, etc.) open and active, it'll print it out there. Or you can try using the textbox below to test.

Example 2b: USB Mouse Functionality

That covers about half of USB HID library. How about we add a mouse to the mix now? Implementing a USB HID mouse requires a few more functions, but it's still crazy simple. There are five functions provided by Arduino's HID class that can be used to implement a mouse:

  • Mouse.move(x, y, wheel) tells the computer to move the mouse a certain number of pixels along either the x, y and/or wheel axis. Each variable can be any value between -128 and +127, with negative numbers moving the cursor down/left, positive numbers move the right/up.

  • Mouse.press(b) sends a down-click on a button or buttons. The button(s) will remain "pressed" until you call Mouse.release(b). The b variable is a single byte, each bit of which represents a different button. You can set it equal to any of the following, or OR (|) them together to click multiple buttons at once:

    • MOUSE_LEFT - Left mouse button
    • MOUSE_RIGHT - Right mouse button
    • MOUSE_MIDDLE - Middle mouse button
    • MOUSE_ALL - All three mouse buttons

  • Mouse.click(b) sends a down-click (press) followed immediately by an up-click (release) on button(s) b. For example, to click the left and right buttons simultaneously, try this:

    Mouse.click(MOUSE_LEFT | MOUSE_RIGHT); // Press and release the left and right mouse buttons

Here's some example code to show off these functions:

language:c
/* HID Joystick Mouse Example
   by: Jim Lindblom
   date: 1/12/2012
   license: MIT License - Feel free to use this code for any purpose.
   No restrictions. Just keep this license if you go on to use this
   code in your future endeavors! Reuse and share.

   This is very simplistic code that allows you to turn the 
   SparkFun Thumb Joystick (http://www.sparkfun.com/products/9032)
   into an HID Mouse. The select button on the joystick is set up
   as the mouse left click. 
 */
#include <Mouse.h>
int horzPin = A0;  // Analog output of horizontal joystick pin
int vertPin = A1;  // Analog output of vertical joystick pin
int selPin = 9;  // select button pin of joystick

int vertZero, horzZero;  // Stores the initial value of each axis, usually around 512
int vertValue, horzValue;  // Stores current analog output of each axis
const int sensitivity = 200;  // Higher sensitivity value = slower mouse, should be <= about 500
int mouseClickFlag = 0;

void setup()
{
  pinMode(horzPin, INPUT);  // Set both analog pins as inputs
  pinMode(vertPin, INPUT);
  pinMode(selPin, INPUT);  // set button select pin as input
  digitalWrite(selPin, HIGH);  // Pull button select pin high
  delay(1000);  // short delay to let outputs settle
  vertZero = analogRead(vertPin);  // get the initial values
  horzZero = analogRead(horzPin);  // Joystick should be in neutral position when reading these

}

void loop()
{
  vertValue = analogRead(vertPin) - vertZero;  // read vertical offset
  horzValue = analogRead(horzPin) - horzZero;  // read horizontal offset

  if (vertValue != 0)
    Mouse.move(0, vertValue/sensitivity, 0);  // move mouse on y axis
  if (horzValue != 0)
    Mouse.move(horzValue/sensitivity, 0, 0);  // move mouse on x axis

  if ((digitalRead(selPin) == 0) && (!mouseClickFlag))  // if the joystick button is pressed
  {
    mouseClickFlag = 1;
    Mouse.press(MOUSE_LEFT);  // click the left button down
  }
  else if ((digitalRead(selPin))&&(mouseClickFlag)) // if the joystick button is not pressed
  {
    mouseClickFlag = 0;
    Mouse.release(MOUSE_LEFT);  // release the left button
  }
}

This sketch is set up so that an analog joystick connected to analog pins A0 and A1 can be used to move your mouse cursor.

The loop() of this code continuously monitors the horizontal and vertical analog values of the joystick and sends the Mouse.move() command based on what it reads. It'll move the mouse in steps, depending on what the sensitivity variable is set to. With sensitivity set to 2, the cursor will move in either 1 or 2 pixel steps.

The select switch on the joystick is used to control the mouse left click. Notice this code is using Mouse.press() and Mouse.release(), rather than just calling a single Mouse.click(). This requires a bit more coding, but it allows you to do things like drag-and-drop, double click, etc.


For more HID example code, check out the Arduino-supplied examples under the File>Examples>09.USB menu. Or check out Arduino's reference language under USB for more information.

Example 3: Qwiic Enabled HID Mouse and Keyboard

Note: If you have not previously installed an Arduino library, please check out our installation guide.

As another option, you can try to use a Qwiic device to take advantage of the HID class. We broke up the Qwiic HID examples into three parts. Depending on your application and personal preference, you could essentially use a different Qwiic enabled device.

  • Example 3a: HID Mouse with Qwiic Joystick
  • Example 3b: HID Keyboard with Qwiic Keypad
  • Example 3c: Qwiic HID Mouse and Keyboard Combined

Example 3a: HID Mouse with Qwiic Joystick

For the scope of this tutorial example, we will be using the Qwiic Joystick so that we do not need to solder any pins. Make sure to check out the Qwiic Joystick Hookup Guide before continuing on with the examples below.

Qwiic Joystick Hookup Guide

February 21, 2019

Looking for an easy way to implement a joystick to your next Arduino or Raspberry Pi project? This hookup guide will walk you through using the Qwiic Joystick with the Arduino IDE on a RedBoard Qwiic and in Python on a Raspberry Pi.

Copy and paste the code below into the Arduino IDE. Make sure to select the correct board and COM port that your respective board enumerated to.

language:c
/******************************************************************************
  Qwiic_Joystick_HID_Mouse_Example.ino
  Written by: Ho Yun "Bobby" Chan
  Date: January 13, 2020
  Development Environment Specifics:
    Arduino IDE 1.8.9

  Description:
    Based on the Jim's Pro Micro "HID Mouse" and Wes' Qwiic Joystick "basic reading"
    examples, this example moves your computer's mouse based on the joystick's
    position. Pressing down on the joystick's will enable a mouse's left click.
    The left click will relese as soon as you stop pressing down on the joystick.

  Libraries:
    Mouse.h (included with Arduino IDE)
    Wire.h (included with Arduino IDE)
    SparkFun_Qwiic_Joystick_Arduino_Library.h (included in the src folder) http://librarymanager/All#SparkFun_joystick

  License:
    This code is released under the MIT License (http://opensource.org/licenses/MIT)

  ******************************************************************************/

#include <Mouse.h>
#include <Wire.h>

#include "SparkFun_Qwiic_Joystick_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_joystick
JOYSTICK joystick;                                   //Create instance of this object

int vertZero, horzZero;       // Stores the initial value of each axis, usually around 512
int vertValue, horzValue;     // Stores current analog output of each axis
const int sensitivity = 200;  // Higher sensitivity value = slower mouse, should be <= about 500
int mouseClickFlag = 0;

//int invertMouse = 1;        //Invert joystick based on orientation
int invertMouse = -1;         //Noninverted joystick based on orientation

//Debug mode, comment one of these lines out using a syntax
//for a single line comment ("//"):
#define DEBUG 0       //0 = HID only
//#define DEBUG 1     //1 = HID with serial output

void setup() {
#if DEBUG
  Serial.begin(9600);
  Serial.println("Example 3: HID Mouse w/ Qwiic Joystick");
#endif

  if (joystick.begin() == false)
  {
#if DEBUG
    Serial.println("Joystick does not appear to be connected. Please check wiring. Freezing...");
#endif
    while (1);
  }

  delay(1000);  // short delay to let outputs settle
  vertZero = joystick.getVertical();  // get the initial values
  horzZero = joystick.getHorizontal();  // Joystick should be in neutral position when reading these
}

void loop() {
#if DEBUG
  Serial.print("X: ");
  Serial.print(joystick.getHorizontal());

  Serial.print(" Y: ");
  Serial.print(joystick.getVertical());

  Serial.print(" Button: ");
  Serial.println(joystick.getButton());
#endif

  vertValue = joystick.getVertical() - vertZero; // read vertical offset
  horzValue = joystick.getHorizontal() - horzZero;  // read horizontal offset

  if (vertValue != 0)
    Mouse.move(0, (invertMouse * (vertValue / sensitivity)), 0); // move mouse on y axis
  if (horzValue != 0)
    Mouse.move((invertMouse * (horzValue / sensitivity)), 0, 0); // move mouse on x axis

  if ((joystick.getButton() == 0) && (!mouseClickFlag))  // if the joystick button is pressed
  {
    mouseClickFlag = 1;
    Mouse.press(MOUSE_LEFT);  // click the left button down
  }
  else if ((joystick.getButton()) && (mouseClickFlag)) // if the joystick button is not pressed
  {
    mouseClickFlag = 0;
    Mouse.release(MOUSE_LEFT);  // release the left button
  }

  //delay(200); //remove "//" on this line if you need a small delay
}

Moving the Qwiic joystick will move your mouse on the screen. Pressing down on the button will cause a left mouse click. Once you stop pressing down on the joystick, it will release the left mouse click. Depending on the orientation for the vertical, you can invert the mouse's movement using the invertMouse variable at the beginning of the example code..

Example 3b: HID Keyboard with Qwiic Keypad

For the scope of this tutorial example, we will be using the Qwiic Keypad so that we do not need to solder any pins. Make sure to check out the Qwiic Keypad Hookup Guide before continuing on with the examples below.

Qwiic Keypad Hookup Guide

April 25, 2019

If you are tired of taking up GPIO pins, wiring a bunch of pull up resistors, and using firmware that scans the keys taking up valuable processing time... check out the new Qwiic Keypad.

Copy and paste the code below into the Arduino IDE. Make sure to select the correct board and COM port that your respective board enumerated to.

language:c
/******************************************************************************
  Qwiic_Keypad_HID_Keyboard_Example.ino
  Written by: Ho Yun "Bobby" Chan
  Date: February 6, 2020
  Development Environment Specifics:
    Arduino IDE 1.8.9

  Description:
    Based on the Jim's Pro Micro "HID Mouse" and Pete' Qwiic Keypad "read button"
    examples, this example outputs keyboard presses associated with the keypad.

  Libraries:
   Keyboard.h (included with Arduino IDE)
   Wire.h (included with Arduino IDE)
   SparkFun_Qwiic_Keypad_Arduino_Library.h (included in the src folder) http://librarymanager/All#SparkFun_keypad

  License:
    This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

#include <Keyboard.h>
#include <Wire.h>
#include "SparkFun_Qwiic_Keypad_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_keypad
KEYPAD keypad1;                                    //Create instance of this object

void setup() {
  Serial.begin(9600);
  Serial.println("Qwiic KeyPad Example");

  if (keypad1.begin() == false)   // Note, using begin() like this will use default I2C address, 0x4B.
    // You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
  {
    Serial.println("Keypad does not appear to be connected. Please check wiring. Freezing...");
    while (1);
  }
  Serial.print("Initialized. Firmware Version: ");
  Serial.println(keypad1.getVersion());
  Serial.println("Press a button: * to do a space. # to go to next line.");

  //  Initializes keyboard functions
  Keyboard.begin();
}

void loop() {
  keypad1.updateFIFO();  // necessary for keypad to pull button from stack to readable register
  char button = keypad1.getButton();

  if (button == -1)
  {
    Serial.println("No keypad detected");
    delay(1000);
  }
  else if (button != 0)
  {
    if (button == '0') {//note that this is a keypad '0' not the button press itself
      Keyboard.write('0');
    }
    else if (button == '1') {
      Keyboard.write('1');
    }
    else if (button == '2') {
      Keyboard.write('2');
    }
    else if (button == '3') {
      Keyboard.write('3');
    }
    else if (button == '4') {
      Keyboard.write('4');
    }
    else if (button == '5') {
      Keyboard.write('5');
    }
    else if (button == '6') {
      Keyboard.write('6');
    }
    else if (button == '7') {
      Keyboard.write('7');
    }
    else if (button == '8') {
      Keyboard.write('8');
    }
    else if (button == '9') {
      Keyboard.write('9');
    }
    else if (button == '#') {
      Keyboard.write('#');
    }
    else if (button == '*') {
      Keyboard.write('*');
    }
  }

  //Do something else. Don't call your Keypad a ton otherwise you'll tie up the I2C bus
  delay(25); //25 is good, more is better
}

If you have a text editor (Notepad, Word, TextEdit, etc.) open and active from Example 2, press a button on the Qwiic Keypad. Or you can try using the textbox below to test. The outputs should be associated with each of the Qwiic keypad button press.

Example 3c: Qwiic HID Mouse and Keyboard Combined

This example combines 3a and 3b into one sketch. Copy and paste the code below into the Arduino IDE. Make sure to select the correct board and COM port that your respective board enumerated to.

language:c
/******************************************************************************
  Qwiic_Keypad_HID_Keyboard_Example.ino
  Written by: Ho Yun "Bobby" Chan
  Date: February 6, 2020
  Development Environment Specifics:
    Arduino IDE 1.8.9

  Description:
    Based on the following examples:
      - Jim's Pro Micro "HID Mouse/Keyboard"
      - Wes' Qwiic Joystick "basic reading"
      - Pete's Qwiic Keypad "read button"

    This example controls the mouse with the Qwiic Joystick
    and keyboard presses associated with the Qwiic Keypad.
    The serial output is turned off so that Qwiic Pro Micro
    can respond faster.

  Libraries:
   Mouse.h (included with Arduino IDE)
   Keyboard.h (included with Arduino IDE)
   Wire.h (included with Arduino IDE)
   SparkFun_Qwiic_Joystick_Arduino_Library.h (included in the src folder) http://librarymanager/All#SparkFun_joystick
   SparkFun_Qwiic_Keypad_Arduino_Library.h (included in the src folder) http://librarymanager/All#SparkFun_keypad

  License:
    This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

#include <Mouse.h>
#include <Keyboard.h>
#include <Wire.h>

#include "SparkFun_Qwiic_Joystick_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_joystick
JOYSTICK joystick;                                   //Create instance of this object

#include "SparkFun_Qwiic_Keypad_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_keypad
KEYPAD keypad1;                                    //Create instance of this object

int vertZero, horzZero;       // Stores the initial value of each axis, usually around 512
int vertValue, horzValue;     // Stores current analog output of each axis
const int sensitivity = 150;  // Higher sensitivity value = slower mouse, should be <= about 500
int mouseClickFlag = 0;

//int invertMouse = 1;        //Invert joystick based on orientation
int invertMouse = -1;         //Noninverted joystick based on orientation

//Debug mode, comment one of these lines out using a syntax
//for a single line comment ("//"):
#define DEBUG 0       //0 = HID only
//#define DEBUG 1     //1 = HID with serial output

void setup() {
#if DEBUG
  Serial.begin(9600);
  Serial.println("Qwiic KeyPad Example");
#endif

  if (joystick.begin() == false) {
#if DEBUG
    Serial.println("Joystick does not appear to be connected. Please check wiring. Freezing...");
#endif
    while (1);
  }
  if (keypad1.begin() == false) {  // Note, using begin() like this will use default I2C address, 0x4B.
    // You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
#if DEBUG
    Serial.println("Keypad does not appear to be connected. Please check wiring. Freezing...");
#endif
    while (1);
  }

  delay(1000);  // short delay to let outputs settle
  vertZero = joystick.getVertical();  // get the initial values
  horzZero = joystick.getHorizontal();  // Joystick should be in neutral position when reading these

#if DEBUG
  Serial.print("Initialized. Firmware Version: ");
  Serial.println(keypad1.getVersion());
  Serial.println("Press a button: * to do a space. # to go to next line.");
#endif

  //  Initializes mouse functions
  Mouse.begin();
  //  Initializes keyboard functions
  Keyboard.begin();

}//end setup

void loop() {
  keypad1.updateFIFO();  // necessary for keypad to pull button from stack to readable register
  char button = keypad1.getButton();

#if DEBUG
  Serial.print("X: ");
  Serial.print(joystick.getHorizontal());

  Serial.print(" Y: ");
  Serial.print(joystick.getVertical());

  Serial.print(" Button: ");
  Serial.println(joystick.getButton());
#endif

  vertValue = joystick.getVertical() - vertZero; // read vertical offset
  horzValue = joystick.getHorizontal() - horzZero;  // read horizontal offset

  if (vertValue != 0)
    Mouse.move(0, (invertMouse * (vertValue / sensitivity)), 0); // move mouse on y axis
  if (horzValue != 0)
    Mouse.move((invertMouse * (horzValue / sensitivity)), 0, 0); // move mouse on x axis

  if ((joystick.getButton() == 0) && (!mouseClickFlag))  // if the joystick button is pressed
  {
    mouseClickFlag = 1;
    Mouse.press(MOUSE_LEFT);  // click the left button down
  }
  else if ((joystick.getButton()) && (mouseClickFlag)) // if the joystick button is not pressed
  {
    mouseClickFlag = 0;
    Mouse.release(MOUSE_LEFT);  // release the left button
  }

  if (button == -1) {
#if DEBUG
    Serial.println("No keypad detected");
#endif
    delay(1000);
  }

  else if (button != 0) {
#if DEBUG
    Serial.print("Qwiic Keypad Button:  ");
    Serial.println(button);
#endif
    if (button == '0') {//note that this is a keypad '0' not the button press itself
      Keyboard.write('0');
    }
    else if (button == '1') {
      Keyboard.write('1');
    }
    else if (button == '2') {
      Keyboard.write('2');
    }
    else if (button == '3') {
      Keyboard.write('3');
    }
    else if (button == '4') {
      Keyboard.write('4');
    }
    else if (button == '5') {
      Keyboard.write('5');
    }
    else if (button == '6') {
      Keyboard.write('6');
    }
    else if (button == '7') {
      Keyboard.write('7');
    }
    else if (button == '8') {
      Keyboard.write('8');
    }
    else if (button == '9') {
      Keyboard.write('9');
    }
    else if (button == '#') {
      Keyboard.write('#');
    }
    else if (button == '*') {
      Keyboard.write('*');
    }
  }

  //Do something else. Don't call your Keypad a ton otherwise you'll tie up the I2C bus
  //Uncomment this if necessary but since we check the Qwiic Joystick it does not
  // appear to be an issue
  //delay(25); //25 is good, more is better

}//end loop

The functionality should be the same when moving the joystick or pressing on the keypad's key. The serial output is turned off so that Qwiic Pro Micro can respond faster.

Troubleshooting and FAQ

On this page you'll find troubleshooting tips and FAQs. Here's a directory of the subjects covered:


Serial Port Not Showing Up in 'Tools > Board' Menu

The Qwiic Pro Micro can be a finicky little thing. There are a few series of events that can lead to its serial port being removed from the Arduino IDE's Serial Port selection menu. If you can't see your Pro Micro's serial port, give these steps a try:

  1. Close all Arduino windows. (Don't forget to save!)
  2. Unplug Qwiic Pro Micro from your computer.
  3. Wait a few seconds for the device to be detached.
  4. Plug Qwiic Pro Micro back in.
  5. Open Arduino back up, check the Serial Ports menu again.

Reset to Bootloader

We ship the Qwiic Pro Micro with a modified version of the Arduino Leonardo bootloader, with one major enhancement. When a Leonardo (or any device using the "stock" bootloader) is externally reset, it goes back into the bootloader...and waits there eight seconds before it starts running the sketch. For some embedded projects, waiting eight seconds before a program runs isn't acceptable, so we modified the bootloader run time.

Arduino LeonardoLeonardo bootloader functionality
Arduino LeonardoLeonardo bootloader on
reset functionality.

When a Qwiic Pro Micro is externally reset (by pulling the RST pin low), it'll only briefly (<750ms) start the bootloader before continuing on to the sketch. If you need the bootloader to run longer, resetting twice quickly will get the Pro Micro to enter bootloader mode for eight seconds.

Qwiic Pro MicroPro Micro bootloader functionality
Qwiic Pro MicroQwiic Pro Micro reset functionality. Press reset twice, quickly to enter bootloader mode.

Resetting the Qwiic Pro Micro is now easier to reset with the built in reset button. Just press the reset button located next to the Qwiic connector two times. You can also connected the RST pin to ground to initiate a reset. This can be done with a small piece of wire, or an externally connected button.

Reset Button and Pin Locations

Why would you need to enter bootloader mode in the first place. Glad you asked...

How to Revive a "Bricked" Pro Micro

Incorporating all of the USB tasks on a single chip is an awesome feature that makes the Pro Micro and boards like it truly unique. But it also places more stress on a single chip, and if anything goes wrong with that chip, the board becomes nearly unusable. It's not uncommon for Qwiic Pro Micro's to become "bricked" and unprogrammable. But, in most cases, the bricking is reversible!

The most common source of Qwiic Pro Micro "bricking" is uploading code to it with an incorrectly set board (e.g. programming a 16MHz/5V Pro Micro with the board set to 8MHz/3.3V). Also, make sure your sketch doesn't mess with the ATmega32U4's PLLCSR register, or any other register that sets up USB functionality on the ATmega32U4. The Pro Micro will actually take code compiled for the wrong operating speed, but when it tries to re-enumerate, you'll be greeted with a notification like this:

USB device not recognized

To revive the Pro Micro, you'll need to find a way to upload a sketch to it with the board option correctly set. We can do this with a little help from the bootloader.

First, you'll need to set the serial port to the bootloader. But that port is only visible when the board is in bootloader mode, so hit the reset button or pull the reset line low twice quickly to invoke the bootloader reset feature discussed above. While the Pro Micro is in the bootloader change the 'Tools>Serial Port' menu to the bootloader COM port. Quick! You've only got eight seconds. On Windows, the bootloader's COM port number is usually one number higher than the Qwiic Pro Micro's regular port number.

With the serial port set, we're just about ready to re-upload our sketch. But first, double check that the board is correctly set. Then reset to bootloader again, and quickly upload your sketch. Again, you'll have to be quick...you've only got eight seconds. It may help to press the Upload keybind -- CTRL + U / CMD + U -- immediately after resetting.

It can take a few tries to get the timing right. Since the code has to compile first, it may help to hit upload first and then reset.

Code Runs After Upload But Fails to Start After Power Cycle

We found that an ATmega32U4 (like the Pro Micro 3.3V/8MHz) can brown out when outputting power to a boost converter. While code can run after uploading, a power cycle from the initial current draw to a boost converter is enough to cause the Pro Micro brown out. Thus causing the sketch to not run. This requires the user to toggle the reset button after a power cycle.


Frequently Asked Questions

If you're having technical difficulties with your Qwiic Pro Micro, see if any of the answers to these FAQs help. If not, please get in touch with our tech support team.

What are VID and PIDs?

VID is short for 'Vender Identification' and PID is short for 'Part Identification'. In other words, this pair of IDs defines the device. This is how your computer knows what you've plugged in, what drivers to use with it, what COM port is assigned to it, etc. All native USB devices have a VID/PID.

All SparkFun ATmega32U4 boards share the same VID -- 0x1B4F, and they all have unique PIDs. 5V Pro Micros lay claim to PIDs 0x9205 and 0x9206 (one for the bootloader, one for the sketch). 3.3V Pro Micros will show up as 0x9203 and 0x9204 for bootloader and sketch, respectively. And the Fio v3 has 0xF100 and 0xF101.

How Can I Change the VID and PID on an ATMega32U4 Board?

Every time you upload code the VID and PID are uploaded to the device. These values are located in the 'boards.txt' file and will therefore be determined by the board you have selected. Keep in mind that if you select the wrong board you will get the wrong VID/PID uploaded which means the computer can’t recognize, and program the board. The VID/PID for the bootloader is part of the bootloader file. To change this you will need to recompile the bootloader with the new VID/PID, and upload it.

Why Does my ATMega32U4 Board Show up Twice in Device Manager?

Both the bootloader and the sketch have their own VID/PIDs. When you plug in a board the bootloader starts running for a few seconds, and you will see the board show up in Device Manager based on those VID/PIDs. After a few seconds, the sketch will start running, and you will see Device Manager disconnect from the bootloader and connect to the sketch.

How Does the IDE Know Which COM Port to Use?

When the IDE resets the board, the COM port is disconnected from the computer. The IDE then looks for a new COM port. This is the port it uses. This is one of those weird things Arduino did to get things to work on this chip.

How Do I Reinstall the Bootloader?

Check out or reinstalling the bootloader tutorial, which should work for both ATMega32U4 and ATMega328 boards. If you have the tools to do so, reinstalling the bootloader is often easier then trying to stay in the bootloader. Since reinstalling the bootloader puts the board back in factory settings this will reset the VID/PID numbers allowing your board to work again.

Resources and Going Further

Thanks for checking out our Qwiic Pro Micro Hookup Guide! If you're looking for more resources related to these boards, here are some links:

Thanks for reading along with our Qwiic Pro Micro hookup guide! Hopefully now you're fully prepared to begin using the Pro Micro in a project of your own. Here are some tutorials that might be worth checking out as you continue down the rabbit hole:

Connecting Arduino to Processing

Send serial data from Arduino to Processing and back - even at the same time!

Cherry MX Switch Breakout Hookup Guide

How to assemble and use the Cherry MX Switch Breakout, allowing you to turn a matrix of mechanical switches into a full-size keyboard!

LilyPad ProtoSnap Plus Hookup Guide

The LilyPad ProtoSnap Plus is a sewable electronics prototyping board that you can use to learn circuits and programming with Arduino, then break apart to make an interactive fabric or wearable project.

Tech Prank: Hardware Mouse Jiggler

Create an innocuous-looking USB stick with an Arduino Pro Micro and a 3D printed case that moves your mouse pointer randomly every few seconds. Sure to anger your coworkers and friends!

Feeling ambitious? Try making your own custom keyboard! Check out the custom keyboard builds from Martin Knobel using Pro Micros and Cherry MX switches:

Or check out these blog posts for inspiration.


learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Power Delivery Board - USB-C (Qwiic) Hookup Guide

$
0
0

Power Delivery Board - USB-C (Qwiic) Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1104

Introduction

USB Type-C brought two significant changes to the USB standard. The reversible connector eliminated the problem of trying to plug the connector in the right way every time. The second major change was allowing the flexibility to have USB power with an adjustable USB voltage from anywhere between 5V and 20V and up to 100W of power. The SparkFun Power Delivery Board takes advantage of the power delivery standard with the use of a standalone controller from STMicroelectronics, the STUSB4500. The controller does all the heavy lifting of power negotiation and provides an easy way to configure over I2C.

SparkFun Power Delivery Board - USB-C (Qwiic)

SparkFun Power Delivery Board - USB-C (Qwiic)

DEV-15801
$24.95

Required Materials

To follow along with this guide, you will need the following materials. You may not need everything, depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Additional Tools

You will also need a USB Type-C power adapter that supports power delivery and a power delivery Type-C cable which has thicker power wires in the cable. This will minimize voltage drops across the cable and heat up less under high current loads. The Power Delivery Board's voltages and available current output are limited by the power delivery adapter used. The cable and power adapter used in this guide is a 87W USB-C Power Adapter made by Apple, and supports 5.2V, 9V, 14.5V, and 20.3V.

⚡ Note: During testing we noticed a significant delay changing voltages with some power adapters that have both a USB Type-A fast charging plug as well as USB Type-C power delivery plug. We recommend getting a power adapter that supports power delivery that only has a USB Type-C connector.

Power Adapter output voltages highlight

Power Adapter Output Voltages

Suggested Reading

Before continuing on with this guide, you may want to familiarize yourself with some of these topics if they're unfamiliar to you. If you aren't familiar with the Qwiic system, we recommend reading here for an overview.

Qwiic Connect System
Qwiic Connect System

If you aren't familiar with the following concepts, we recommend checking out these tutorials before continuing. Make sure to install the appropriate drivers before uploading code. In this case, we'll need to make sure the CH340 driver are installed for the RedBoard Qwiic.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

How to Use a Multimeter

Learn the basics of using a multimeter to measure continuity, voltage, resistance and current.

RedBoard Qwiic Hookup Guide

This tutorial covers the basic functionality of the RedBoard Qwiic. This tutorial also covers how to get started blinking an LED and using the Qwiic system.

How to Install CH340 Drivers

How to install CH340 drivers (if you need them) on Windows, Mac OS X, and Linux.

Hardware Overview

STUSB4500

When it comes to power delivery you have two types of power roles. The first is the provider, also known as the source, which is capable of providing power over the USB power bus. The other role is the consumer, also known as the sink, which draws power from the source.

The STUSB4500 is a USB Type-C and power delivery controller IC for sink applications. The controller is able to negotiate a power delivery contract with a source (ie a power delivery wall wart or power adapter) without the need for an external microcontroller, although you will need a microcontroller to configure the board. With this controller, we are taking advantage of STMicroelectronic's proprietary algorithms and configurable power data objects (PDOs) using integrated non-volatile memory (NVM). Its laundry list of features include:

  • "Attach detection" between two USB Type-C ports
  • Establish a valid source-to-sink connection
  • Negotiate a USB power delivery (PD) contract with a PD capable source
  • Monitor the VBUS power path and manage the VBUS voltage transitions
  • Manage high voltage protections
  • Dual high power charging path support

Understanding how the power negotiation will be covered in the USB-C Power Negotiation section, but for right now, let's go over the board itself.

Power

The Power Delivery board can be powered in one of two ways, either through the USB Type-C connector, or with 3.3V from the Qwiic Connector if you just need to configure a new power delivery profile.

Highlight of Qwiic and USB type c connectors

I2C Pins

To configure the board, you will need an I2C bus. The Qwiic system makes it easy to connect the Power Delivery board to a microcontroller to set the NVM parameters to power your project via the Qwiic connector. Depending on your application, you can also connect to the I2C bus via the plated through holes for SDA and SCL.

Highlight of the Qwiic Connector

Qwiic Connector



Top ViewBottom View

I2C PTH Pins

Pins

The board breaks out the following pins:

Pin NameDescription
VINThis is the input power pin, which is connected to VBUS on the Type-C connector.
VSNKPower output enabled after successful power negotiation
VDDOptional logic power input, 3.0V - 5.5V
GNDGround
SCLI2C clock input
SDAI2C data input/output
D-USB 2.0 differential pair, negative
D+USB 2.0 differential pair, positive
AlertI2C interrupt, active low open drain
ResetReset input, active high
GPIOGeneral purpose output, active low open drain
PDO2Power contract flag for PDO2, active low open drain
PDO3Power contract flag for PDO3, active low open drain

Image of the back of the board with the pins highlighted

IO Pins

Jumpers

The board has a few jumper pads to configure the I2C bus.

Address Select

The default address of the board is 0x28. If you need to adjust the address of the board, you can cut one or both of the address pads labels ADDR0 and ADDR1.

Highlight of the address select jumper

The table below lists the four jumper configurations along with the corresponding hexadecimal device address.

ADDR0ADDR1Device Address
ClosedClosed0x28 (default)
OpenClosed0x29
ClosedOpen0x2A
OpenOpen0x2B

Pull-Up Resistors

The board also includes jumpers to disable the pull-up resistors on the I2C bus. If you are using a few I2C devices on the same bus that already have pull-up resistors on their board, you may want to cut the jumpers to disconnect these pull-up resistors. The Power Delivery board utilizes non-volatile memory, the settings saved to device stay configured even if it loses power, so the only time this board needs to be connected over I2C is to modify the NVM parameters.

Highlighted section of the I2C Pullups

Dimensions

Dimensions of the Board exported from Eagle

USB-C Power Negotiation

Power Data Objects (PDOs)

The STUSB4500 has a set of user defined parameters that can be customized using the NVM re-programming through the I2C interface. This allows for changing the preset configuration of the power delivery interface and define new configurations based on specific application requirements.

On power-up, or after a reset, the NVM parameters are copied into the I2C registers and used by the controller during the system operation. The controller can store up to three PDOs, with PDO3 having the highest priority and PDO1 having the lowest. After the NVM parameters have been copied to the I2C registers, the STUSB4500 will ask the source for it's capabilities to find a PDO match.

Each PDO has four parameters as shown in the table below:

ParameterValue RangeNotes
Voltage5 - 20 (V)PDO1 is fixed at 5V and cannot be changed.
Over Voltage Tolerance5 - 20 (%)Sets the upper voltage tolerance. For example, say this parameter is set to 5% and the voltage is set to 9V. If the supply voltage goes above 9.45V, the output (VSNK) will turn off.
Under Voltage Tolerance5 - 20 (%)Sets the lower voltage tolerance for PDO2 and PDO3 only. For example, say this parameter is set to 5%, and the voltage is set to 9V. If the supply voltage drops below 8.55V, the output (VSNK) will turn off. PDO1 has a fixed under voltage limit of 3.3V and cannot be changed.
Current0 - 5 (A)16 possible values, see setCurrent function in Arduino Library secton for exact values.


Each source might have a slightly different voltages listed on the case. One charger might advertise 12V, while another might advertise 12.3V perhaps to compensate for voltage drop across the cable, while another might say 11.5V to indicate the voltage at the end of the cable under the full load. Most sources though will advertise some combination of 5V, 9V, 12V, 15V, or 20V when negotiating with the consumer.

The current should be the maximum amount of current that the Power Delivery board expects to draw from the source. If the current parameter is less than or equal to the max current the source advertised, the controller will send a request to source for that power profile. If the voltage or current parameters do not match with one of the capabilities of the source, the controller will try the next PDO to find a match with the source.

If the source accepts the contract, the source will switch from the defaulted VBUS voltage of 5V, to the voltage that was requested, and the VBUS_EN_SINK pin will be pulled low, and enable current to flow through the MOSFET which controls power to the VSNK power output pin.

Power Delivery Contract between Source and Sink

With the "U" in USB standing for Universal, when two devices are connected there are a ton of messages sent between them to figure out what each device is connected to, and what each device supports. For the sake of simplicity, we're only going to look at the power delivery contract from a high level to understand what's going on.

Image of USB-C's 24 pins

Image courtesy of Chindi.ap, CC BY-SA 4.0

Of the 24 pins of the USB Type-C connector (shown above), the STUSB4500 only connects directly to 10 of these: 4 pins are used for VBUS, another 4 pins to ground, and the 2 channel configuration, or CC, pins. Depending on the cable orientation, one of these CC pins is used to send and receive messages between the sink and source. When a sink device connects to a source, the voltage on the VBUS starts off at 5V, just like the old USB standard.

Shortly after the source and sink are connected, the source will advertise it's capabilities as a power source, such as 5V@3A, 9V@2A, and any other power delivery options it's capable of. After that message is received, the controller will look at the PDO options available to find a match. Upon a match, the controller will ask for one of the voltage and current options. After the source accepts, the voltage is then switched to the voltage requested.

To find a match, the STUSB4500 controller first looks at the SNK_PDO_NUMB parameter, which is an integer value between 1 and 3, which corresponds to the highest priority PDO number. If the SNK_PDO_NUMB has a value of 3, it will first check to see if the source is able to provide PDO3, if not it will check PDO2, followed by PDO1. If SNK_PDO_NUMB has a value of 2, it will start by checking PDO2, followed by PDO1, and ignore PDO3. Finally if SNK_PDO_NUMB has a value of 1, it will only check PDO1. The two values the controller looks at to find a match are the voltage and current. As previously mentioned, most of the power delivery adapters will have a combination of 5V, 9V, 12V, 15V, and 20V. The packaging might say 5.2V or 20.3V, but in the capabilities message they'll actually specify 5V or 20V.

The other portion of the contract is the current being requested. If the voltage is accepted, but is only capable of delivering 1.5A of current at that voltage, but 2.0A of current was requested, that contract will be rejected by the source even though the source was capable of supplying that voltage. Alternatively, requesting 0.5A of current with a source capable of delivering 1.5A will be accepted. The amount of current requested should be about is expected for the project, but the source will allow the sink to draw more current than requested, up to the limit of that power delivery option.

Hardware Hookup

This is an I2C based board, which allows us to include a Qwiic connector on the breakout board. Hooking up the device is easy, just plug one end of the Qwiic cable into the Power Delivery board and the other to your development board. In this case it's the RedBoard Qwiic.

redboard qwiic with power delivery board
Note: If you've never connected an CH340 device to your computer before, you may need to install drivers for the USB-to-serial converter. Check out our section on How to Install CH340 Drivers" for help with the installation.

How to Install CH340 Drivers

August 6, 2019

How to install CH340 drivers (if you need them) on Windows, Mac OS X, and Linux.

Suppling power to your project can be accomplished in couple of ways. The board provides breadboard friendly 0.1 inch spacing, along with 3.5mm screw terminal spacing. If you're new to soldering, refer to our How To Solder Tutorial.

Highlight of output power pins

After the board has been configured, the Qwiic connector can be removed, and the board will remember the settings even after power is disconnected. With those connections out of the way, it's time to configure the board!

Arduino Library

Note: This example assumes you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

SparkFun has written a library to control the Power Delivery board for the STUSB4500. You can obtain this library through the Arduino Library Manager. By searching for STUSB4500, you should see one written by SparkFun Electronics and you should be able to install the latest version. If you prefer downloading libraries manually, you can grab them from the GitHub Repository.

Functions

The library has a ton of functions available for reading each of the NVM parameters for the Power Delivery board. Below is a list of the functions available along with a description of what each function does and how to use it.

  • uint8_t begin( uint8_t deviceAddress, TwoWire &wirePort ) - Call at the beginning of the sketch to initialize the device. This function takes two optional parameters: deviceAddress and wirePort. This function will return true when the device is intialized, and false if it is unable to communicate with the device.

    • wirePort - By default, the library uses the standard Wire bus, but if your board has multiple I2C buses, you can define Wire1 here.

    • deviceAddress - If both of the address jumpers on the back of the board are closed, this parameter does not need to be provided. Otherwise, you can use the table below to get the I2C address of the Power Delivery Board.

ADDR0ADDR1Device Address
ClosedClosed0x28 (default)
OpenClosed0x29
ClosedOpen0x2A
OpenOpen0x2B


  • void read( void ) - This function reads the NVM parameters and loads them into memory. This function is called in the begin() function, and shouldn't need to be called in your program.

  • void write( uint8_t defaultVals ) - This function writes the NVM parameters to the STUSB4500. After all of the parameters have been changed, calling this function will save the parameters to the device. This function takes an optional argument of DEFAULT. When DEFAULT is passed to the write function, the default NVM parameters are written to the device.

  • float getVoltage( uint8_t pdo_numb ) - Returns the voltage requested for the PDO number (1-3).

  • float getCurrent( uint8_t pdo_numb ) - Returns the current requested for the PDO number (1-3).

  • uint8_t getLowerVoltageLimit( uint8_t pdo_numb ) - Returns the under voltage lockout parameter for the PDO number (1-3). PDO1 has a fixed value that cannot be changed and will always return 0. The under voltage limit is fixed at 3.3V. PDO2 and PDO3 will return a value between 5% and 20%.

  • uint8_t getUpperVoltageLimit( uint8_t pdo_numb ) - Returns the over voltage lockout parameter for the PDO number (1-3). The value returned will be between 5% and 20%.

  • float getFlexCurrent( void ) - Return the value for the flex current parameter, which is a global variable common to all PDOs. Refer to setFlexCurrent function for more information on how to use flex current.

  • uint8_t getPdoNumber( void ) - Returns value saved in memory for the highest priority PDO number (1-3).

  • uint8_t getExternalPower( void ) - Returns the value for the SNK_UNCONS_POWER parameter (0 or 1). SNK_UNCONS_POWER is the unconstrained power bit setting in capabilities message sent by the sink. A 0 means there is no external source of power (default), and a 1 means an external source of power is available and is sufficient to adequately power the system while charging external devices.

  • uint8_t getUsbCommCapable( void ) - Returns the value for the USB_COMM_CAPABLE parameter (0 or 1). USB_COMM_CAPABLE refers to USB2.0 or 3.x data communication capability by the sink system. A 0 means the sink device does not support data communication (default). A 1 means that the sink does support data communication.

  • uint8_t getConfigOkGpio( void ) - Returns the POWER_OK_CFG parameter value (0-3), which controls the behavior of the VBUS_EN_SNK, POWER_OK2, and POWER_OK3 pins. Refer to the setConfigOKGPIO function for more information.

    • 0 - Configuration 1
    • 1 - Not applicable
    • 2 - Configuration 2 (default)
    • 3 - Configuration 3
  • uint8_t getGpioCtrl( void ) - Returns the behavior setting for the GPIO pin (0-3). Refer to the setGpioCtrl function for more information.

    • 0 - Software controlled GPIO
    • 1 - Error recovery
    • 2 - Debug
    • 3 - Sink power
  • uint8_t getPowerAbove5vOnly( void ) - Returns the POWER_ONLY_ABOVE_5V parameter (0 or 1). If 0 is returned, the output will be enabled when the source is attached, regardless of the voltage. If 1 is returned, the output will be enabled only when the source is attached and VBUS voltage is negotiated to PDO2 or PDO3.

  • void setPdoNumber( uint8_t pdo_numb ) - Takes the parameter pdo_numb (1-3). There are three Power Data Objects (PDO) that the Power Delivery board can store. PDO3 has the highest priority, followed by PDO2, and finally PDO1. This function declares which of the three PDOs should be negotiated first. For example, if setPdoNumber is set to 3, PDO3 will be negotiated first, followed by PDO2 if a contract is not made, and finally PDO1 if PDO2 fails as well. If setPdoNumber is set to 2, PDO3 will be ignored and PDO2 will be negotiated, followed by PDO1. Lastly if setPdoNumber is set to 1, only PDO1 will be negotiated.

  • void setVoltage( uint8_t pdo_numb, float voltage ) - Takes two parameters: pdo_numb (1-3), and voltage (10-bit resolution). PDO1 is fixed at 5V and cannot be changed. PDO2 and PDO3 can be any voltage up to 20V.

    • The PDO3 has the highest priority and PDO1 has the lowest priority, starting at the number defined in the setPdoNumber()parameter. The source controls the voltage present on VBUS, or in the case of the Power Delivery board, VIN. Common voltages available from sources are: 5V, 9V, 12V, 15V, and 20V.
  • void setCurrent( uint8_t pdo_numb, float current ) - Takes two parameters: pdo_numb (1-3), and current (16 values). The current values are: 0 (Flex Current), 0.5A, 0.75A, 1.0A, 1.25A, 1.50A, 1.75A, 2.0A, 2.25A. 2.50A, 2.75A, 3.0A, 3.5A, 4.0A, 4.5A, and 5.0A.

    • The current value should be the amount that the source should be expected to output. If the current is higher than the source is able to provide, the contract will be rejected and the next PDO contract will be negotiated. The Power Delivery board will sink more current than negotiated if the source is able deliver it, but it's recommended to provide the maximum amount of current the project is expected to draw.
  • setFlexCurrent( float value ) - Takes a float value to set the current common to all PDOs. This value is only used in the power negotiation if the setCurrent value for that PDO is set to 0. The flex current has a resolution of 10mA. Just like the setCurrent function, the current value should be the amount that the source should be expected to deliver. If the current is higher than the source is able to provide, the contract will be rejected and the next PDO contract will be negotiated.

  • setLowerVoltageLimit (uint8_t pdo_numb, uint8_t value ) - Takes two parameters: pdo_numb (2-3), and a integer value (5-20%). Only PDO2 and PDO3 can be changed as PDO1 has a fixed value of 3.3V. In combination with the setUpperVoltageLimit function, this is used to define an acceptable window for the voltage output.

    • For example if the Power Delivery board requests 15V and has a under voltage tolerance of 5%, the controller will disable the output of the Power Delivery board if the voltage drops below 14.25V, which is 5% of 15V.
  • setUpperVoltageLimit( uint8_t pdo_numb, uint8_t value ) - Takes two parameters: pdo_numb (1-3), and a integer value (5-20%). In combination with the setLowerVoltageLimit function, this is used to define an acceptable window for the voltage output.

    • For example if the Power Delivery board requests 15V and has a over voltage tolerance of 5%, the controller will disable the output of the Power Delivery board if the voltage exceeds 15.75V, which is 5% of 15V.
  • setExternalPower( uint8_t value ) - Takes an integer value (0 or 1). Setting to 0, there is no external source of power. Setting to 1, means there is an external power source available, and is sufficient to adequately power the system while charging external devices.

  • setUsbCommCapable( uint8_t value ) - Takes an integer value (0 or 1). Setting to 0, there sink does not support data communication. Setting to 1, means the sink does support data communication.

  • setConfigOkGpio( uint8_t value ) - Takes an integer value (0-3):

    • 0 - Configuration 1
    • 1 - Not applicable
    • 2 - Configuration 2 (default)
    • 3 - Configuration 3
PinState
Description
Configuration1VBUS_EN_SNKHi-ZNo Source Attached
0Source Attached
POWER_OK2Hi-ZNo functionality
POWER_OK3Hi-ZNo functionality
Configuration2VBUS_EN_SNKHi-ZNo Source Attached
0Source Attached
POWER_OK2Hi-ZNo explicit PD contract
0PD explicit contract with PDO2
POWER_OK3Hi-ZNo explicit PD contract
0PD explicit contract with PDO3
Configuration3VBUS_EN_SNKHi-ZNo Source Attached
0Source Attached
POWER_OK2Hi-ZNo source attached or source supplies default USB Type-C current at 5V when source attached.
0Source supplies 3.0A USB Type-C current at 5V when source is attached.
POWER_OK3Hi-ZNo source attached or source supplies default USB Type-C current at 5V when source attached.
0Source supplies 1.5A USB Type-C current at 5V when source is attached.

*

Note: For configuration 3: "Source supplies 1.5A/3.0A USB Type-C current at 5V when source is attached" is based on what the source advertises when the cable is connected and does not indicate that the output voltage is actually 5V.
  • setGpioCtrl( uint8_t value ) - Takes an integer value (0-3) to control the GPIO pin (active LOW).
ValueGPIO FunctionFunctionValueDescription
0Software Controlled GPIOThe output state is controlled by the value stored in bit-0 of I2C register 0x2DHi-ZWhen the value of bit-0 is 0 (default at start-up)
0When the value of bit-0 is 1
1Error RecoveryHardware fault detection such as over temperature, over voltage on the CC pins, or after a hard resetHi-ZNo hardware fault detected
0Hardware fault detected
2DebugDebug accessory detection (Refer to section 3.8 of datasheet for more information)Hi-ZNo debug accessory detected
0Debug accessory detected
3Sink PowerIndicates USB Type-C current capability advertised by the sourceHi-ZSource supplies default or 1.5A USB Type-C current at 5V
0Source supplies 3.0A USB Type-C current at 5V

*

Note: For value 3 - Sink Power: "Source supplies 1.5A/3.0A USB Type-C current at 5V when source is attached" is based on what the source advertises when the cable is connected and does not indicate that the output voltage is actually 5V.
  • setPowerAbove5vOnly( uint8_t value ) - Takes an integer value (0 or 1). Setting to 0, the output is enabled regardless of the of the negotiated voltage. When set to 1, the output is enabled only when the source is attached, and the voltage is negotiated for PDO2 or PDO3.

  • setReqSrcCurrent( uint8_t value ) - Takes an integer value (0 or 1). Setting to 0 requests the sink current as operating current in the RDO message. Setting to 1 requests the source current as operating current in the RDO message.

Arduino Library Examples

In these examples, we'll connect our Power Delivery board to a RedBoard Qwiic using a Qwiic cable. The Type-C power adapter used in these examples is an Apple 87W USB-C Power Adapter which has an output of 20.3V/4.3A, or 14.5V/2A, or 9V/3A, or 5.2V/2.4A.

Example 1: Reading the NVM Values

In this first example we'll see what settings are currently saved in the board. For this example you don't need to connect to your USB cable, the only connection needed is VDD, GND, SCL, and SDA (which the Qwiic cable will provide).

After the library has been installed, access the first example from your Arduino menu by clicking on: File > Examples > SparkFun STUSB4500 > Example1-ReadParameters. Select your board (in this case SparkFun RedBoard and COM port that the board enumerated to. Hit the upload button. Open the serial monitor at 115200 baud to see what the current settings are.

Photo of COM port after read parameters example has been uploaded

The STUSB4500 is able to store up to three power data objects, or PDOs. Each PDO contains the voltage and current to be requested, along with the voltage tolerance. We can see that the PDO number parameter is set to 3, which means that when we plug in the power adapter, the board will first try to find a power option that matches PDO3, which has a voltage of 20.00V, and maximum current draw of 1.0A. If the power adapter is able to provide at least 1.0A of current at 20.00V, the contract will be accepted by the source and switch to the higher voltage. If the output voltage falls outside of the tolerance window of +10% or -20% (16-22V), the sink controller will disconnect from the source and reset. However, if PDO3 does not match with the source, it will try PDO2's parameters, and if a match is still not made the voltage would stay at 5V.

Flex current is set to 2.00A, but since none of the PDOs have a current set to 0, that value will not be used. We also see that the board is not expecting an external source of power, nor does it expect the source to support USB communication. The Configuration OK GPIOs are set to 2, which will mean that when a source is connected, if the contract for PDO2 or PDO3 is accepted, the LED corresponding to that PDO will turn on. GPIO control is set to 1, which means the GPIO LED is currently configured for error recovery indication. The enable power only above 5V bit is not set, so the output voltage will briefly be at 5V, but will increase after a contract is accepted. Lastly we see that the request source current bit is not set.

Now that we know what the board is configured for, in our next example we'll configure the board based on the capabilities of our power adapter.

Example 2: Setting NVM Values

In this example we'll modify the NVM values. The code listed below is NOT the same as the SetParameters example in Arduino - below we set actual values, whereas the SetParameters example is a template for your future use.

For this example we'll need to use a power delivery source, which is a 87W USB-C Power Adapter made by Apple, but there are plenty of other adapters available that provide a range of voltages. The power adapter should have a label that describes the input and output power capabilities as shown below.

Photo of apple charger

The input power is 100-240 VAC and up to 1.5A of primary current. The output can provide one of the following: 20V/4.3A, or 15V/2A, or 9V/3A, or 5V/2.4A. Based on these options, let's change the voltage to 15V. That voltage option is able to draw up to 2A of current. The current requested can only go up to that value for the power delivery contract to be accepted. The increased voltage of 15.3V instead of 15.0V is labeled based on the actual output voltage, but the source should advertise 15.0V. The increase is to compensate for voltage drop across the cable under heavy current draw. The settings we're going to change though are:

  • PDO Number: 3
  • PDO3 Voltage: 15.0V
  • PDO3 Current: 2A
  • PDO3 Upper Voltage Tolerance: 20%
  • PDO3 Lower Voltage Tolerance: 20%

Copy the code below into your Arduino IDE and upload it to your board. After the code has been uploaded, open your serial port and verify the changes were applied.

language:c
/*
  Writing New Settings to the STUSB4500 Power Delivery Board
  By: Alex Wende
  SparkFun Electronics
  Date: February 6th, 2020
  License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
  Feel like supporting our work? Buy a board from SparkFun!
  https://www.sparkfun.com/products/15801

  This example demonstrates how to write new NVM settings to the STUSB4500

  Quick-start:
  - Use a SparkFun RedBoard Qwiic -or- attach the Qwiic Shield to your Arduino/Photon/ESP32 or other
  - Upload example sketch
  - Plug the Power Delivery Board onto the RedBoard/shield
  - Open the serial monitor and set the baud rate to 115200
  - The RedBoard will connect to the Power Delivery Board over I2C write the settings:
    * PDO Number: 3
    * PDO3 Voltage: 15.00V
    * PDO3 Current: 0.5A
    * PDO3 Under Voltage Lock Out: 20%
    * PDO3 Over Voltage Lock Out: 20%
  - After the settings are written, the old settings are printed out and then the new settings are printed  
*/
// Include the SparkFun STUSB4500 library.
// Click here to get the library: http://librarymanager/All#SparkFun_STUSB4500

#include <Wire.h>
#include <SparkFun_STUSB4500.h>

STUSB4500 usb;

void setup()
{
  Serial.begin(115200);
  delay(500);

  /* The Power Delivery board uses the default settings with address 0x28 using Wire.

     Opionally, if the address jumpers are modified, or using a different I2C bus,
     these parameters can be changed here. E.g. usb.begin(0x29,Wire1)

     It will return true on success or false on failure to communicate. */
  if(!usb.begin())
  {
    Serial.println("Cannot connect to STUSB4500.");
    Serial.println("Is the board connected? Is the device ID correct?");
    while(1);
  }

  Serial.println("Connected to STUSB4500!");
  delay(100);

  float voltage, current;
  byte lowerTolerance, upperTolerance, pdoNumber;

  pdoNumber = usb.getPdoNumber();
  voltage = usb.getVoltage(3);
  current = usb.getCurrent(3);
  lowerTolerance = usb.getLowerVoltageLimit(3);
  upperTolerance = usb.getUpperVoltageLimit(3);

  /* Since we're going to change PDO3, we'll make sure that the
     STUSB4500 tries PDO3 by setting PDO3 to the highest priority. */
  usb.setPdoNumber(3);

  /* PDO3
   - Voltage 5-20V
   - Current value for PDO3 0-5A, if 0 used, FLEX_I value is used
   - Under Voltage Lock Out (setUnderVoltageLimit) 5-20%
   - Over Voltage Lock Out (setUpperVoltageLimit) 5-20%
  */
  usb.setVoltage(3,15.0);
  usb.setCurrent(3,0.5);
  usb.setLowerVoltageLimit(3,20);
  usb.setUpperVoltageLimit(3,20);

  /*Write and save settings to STUSB4500*/
  usb.write();

  /*Read settings saved to STUSB4500*/
  usb.read();

  Serial.println();

  /*Print old setting*/
  Serial.println("Original Values:");
  Serial.print("PDO Number: ");
  Serial.println(pdoNumber);
  Serial.print("Voltage3 (V): ");
  Serial.println(voltage);
  Serial.print("Current3 (A): ");
  Serial.println(current);
  Serial.print("Lower Voltage Tolerance3 (%): ");
  Serial.println(lowerTolerance);
  Serial.print("Upper Voltage Tolerance3 (%): ");
  Serial.println(upperTolerance);

  Serial.println();

  /*Print new settings*/
  Serial.println("New Values:");
  Serial.print("PDO Number: ");
  Serial.println(usb.getPdoNumber());
  Serial.print("Voltage3 (V): ");
  Serial.println(usb.getVoltage(3));
  Serial.print("Current3 (A): ");
  Serial.println(usb.getCurrent(3));
  Serial.print("Lower Voltage Tolerance3 (%): ");
  Serial.println(usb.getLowerVoltageLimit(3));
  Serial.print("Upper Voltage Tolerance3 (%): ");
  Serial.println(usb.getUpperVoltageLimit(3));
}

void loop()
{
}

After the code has uploaded, open the serial monitor at 115200 baud and make sure the settings were applied, as shown below.

Photo of COM port after NVM parameters write example has been uploaded

Reset the Power Delivery board and connect the USB-C cable. If the contract was accepted, the yellow LED for PDO3 should be on. With a multimeter, verify the voltage is around 15V as shown below. If the LED turns off, press the reset button and board should switch to the correct voltage.

photo showing yellow led and 15V output

Click the image for a closer view.

Troubleshooting

Resources and Going Further

Can't get enough details of our Power Delivery Board? Check out these resources:

Need inspiration? Check out some of our power-related tutorials:

How Lithium Polymer Batteries are Made

We got the opportunity to tour the Great Power Battery factory. Checkout how LiPos are made!

FemtoBuck Constant Current LED Driver Hookup Guide V12

The FemtoBuck board is a high-efficiency, single-channel constant-current LED driver.

Adjustable LiPo Charger Hookup Guide

The SparkFun Adjustable LiPo Charger is a single-cell lithium polymer (LiPo) and lithium ion battery charger. Because it’s adjustable, this charger will be able to safely charge all of our singe-cell batteries.
New!

Secure DIY Garage Door Opener

Did you know that most garage doors are at risk of a roll jam attack? Here we make a DIY garage door remote-control system that is much more secure than most commercial-ready products using the latest in ECC cryptography.

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Non-Addressable RGB LED Strip Hookup Guide

$
0
0

Non-Addressable RGB LED Strip Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t731

Introduction

Add color to your projects with the non-addressable LED strips! These are perfect if you want to add uniform lighting for your props, car, fish tank, or perhaps under cabinet lighting in your home.

LED RGB Strip - Bare (5m)

LED RGB Strip - Bare (5m)

COM-12022
$49.95
2
LED RGB Strip - Bare (1m)

LED RGB Strip - Bare (1m)

COM-12021
$9.95
1
LED RGB Strip - Sealed (5m)

LED RGB Strip - Sealed (5m)

COM-12024
$74.95
1
LED RGB Strip - Sealed (1m)

LED RGB Strip - Sealed (1m)

COM-12023
$14.95

Required Materials

To follow along with this tutorial, you will need the following materials. The partial wishlist on the left is for a basic connection with an Arduino. It does not include the potentiometer and buttons. The full wishlist on the right is for the full circuit for additional functionality. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Microcontroller

To make the most out of your LED strip, you will need a microcontroller. The easiest would be to use the RedBoard Qwiic but you can use any Arduino microcontroller as long as it has a minimum of three PWM pins.

Arduino Pro Mini 328 - 3.3V/8MHz

Arduino Pro Mini 328 - 3.3V/8MHz

DEV-11114
$9.95
46
SparkFun RedBoard Qwiic

SparkFun RedBoard Qwiic

DEV-15123
$19.95
5
USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13

Power Supply

To power your LEDs, you will need a 12V power supply. The amount of current needed depends on the length and density of the LED strip. Below are a few options if you are powering the LEDs from a wall outlet in an installation. You could also use a 9V power supply. It may not be as bright but your LED strip will not be as hot.

SparkFun ATX Power Connector Breakout Kit - 12V/5V (4-pin)

SparkFun ATX Power Connector Breakout Kit - 12V/5V (4-pin)

KIT-15701
$14.95
1
Wall Adapter Power Supply - 12VDC, 600mA (Barrel Jack)

Wall Adapter Power Supply - 12VDC, 600mA (Barrel Jack)

TOL-15313
$5.95

Wires and Connectors

The stranded wires from the non-addressable do not have a connector. For prototyping you could use alligator clips with male headers. However, it would be easier to use a polarized connector like the ones from the 4-wire pigtail connector to easily connect and disconnect from your controller.

Hook-Up Wire - Assortment (Stranded, 22 AWG)

Hook-Up Wire - Assortment (Stranded, 22 AWG)

PRT-11375
$16.95
18
Alligator Clip with Pigtail (10 Pack)

Alligator Clip with Pigtail (10 Pack)

CAB-14303
$6.95
4
LED Strip Pigtail Connector (4-pin)

LED Strip Pigtail Connector (4-pin)

CAB-14576
$1.50

Transistors

If you are using a microcontroller to control the strip, you will need transistors to control each channel. For small lengths, you could use NPN transistors. For longer lengths, you could use n-channel mosfets. Just make sure to get the associated resistors depending on your transistor.

N-Channel MOSFET 60V 30A

N-Channel MOSFET 60V 30A

COM-10213
$0.95
3
SparkFun MOSFET Power Control Kit

SparkFun MOSFET Power Control Kit

COM-12959
$4.95
14
Transistor - NPN, 60V 200mA (2N3904)

Transistor - NPN, 60V 200mA (2N3904)

COM-00521
$0.50
Transistor -  NPN, 60V 4A (2N5192G)

Transistor - NPN, 60V 4A (2N5192G)

COM-13951
$0.95

Input

For options to adjust the color and brightness of your LED strip, you could use the following with a microcontroller.

Trimpot 10K Ohm with Knob

Trimpot 10K Ohm with Knob

COM-09806
$0.95
6
Multicolor Buttons - 4-pack

Multicolor Buttons - 4-pack

PRT-14460
$1.60

Tools

You will need a soldering iron, solder, and general soldering accessories. You may also need some wire strippers if you are cutting and reusing parts of the strip.

Soldering Iron - 60W (Adjustable Temperature)

Soldering Iron - 60W (Adjustable Temperature)

TOL-14456
$14.95
8
Wire Strippers - 22-30AWG

Wire Strippers - 22-30AWG

TOL-14762
$12.95
Solder Lead Free - 15-gram Tube

Solder Lead Free - 15-gram Tube

TOL-09163
$3.50
2

Suggested Reading

If you aren’t familiar with the following concepts, we recommend checking out these tutorials before continuing. If you are looking to customize the control by programming a microcontroller, we recommend looking at the SparkFun Inventor's Kit for Arduino.

Pulse Width Modulation

An introduction to the concept of Pulse Width Modulation.

Light-Emitting Diodes (LEDs)

Learn the basics about LEDs as well as some more advanced topics to help you calculate requirements for projects containing many LEDs.

LED Light Bar Hookup

A quick overview of SparkFun's LED light bars, and some examples to show how to hook them up.

Transistors

A crash course in bi-polar junction transistors. Learn how transistors work and in which circuits we use them.

SparkFun Inventor's Kit Experiment Guide - v4.1

The SparkFun Inventor's Kit (SIK) Experiment Guide contains all of the information needed to build all five projects, encompassing 16 circuits, in the latest version of the kit, v4.1.

Hardware Overview

The non-addressable RGB LED strips are also referred to as analog LED strips. Each channel has three LEDs wired in series with a current limiting resistor. Each segment contains three common anode RGB LED ICs that are connected in parallel. These are used more on strips. While these operate at 12V, they can also light up with 9V.

Schematic of Analog RGB LED Strip

Hardware Hookup

We'll be using a common anode RGB LED strip. There are a few methods of lighting the LED strip:

  • straight power
  • 555 Timer
  • pre-programmed controller box
  • microcontroller/single board computer

Below are three of these methods. For the scope of this tutorial, we will be using the third circuit diagram.

Hookup 1: Straight Power!

The simplest method of using non-addressable LEDs to illuminate your project is to add power to your LED strip. You will just need to make a connection between the female barrel jack adapter and the non-addressable LED strip. Simply insert the black wire connecting the "12V" pin to the "+" of the barrel jack adapter's screw terminal for power. Then insert the wire or your choice into the "-" screw terminal. In the following hookup, all channels were connected to ground to mix the color of white.

Fritzing Diagram for Adapter and LED Strip

Click the image for a closer look.

Depending on your project and color that you are illuminating, you will need to ground each respective channel. Here are some basic colors that you could mix by grounding different pins. The tradeoff is that you are limited to seven colors and will need to adjust the connection every time you need to change the color. For projects that do not require that many colors, this would be the best setup.

Basic Color Mixing

Hookup 2: Preprogrammed Controller Box

For those that are interested in a preprogrammed controller to easily control the non-addressable LED strip with a controller, you could use the Mi-Light remote and controller box. You will simply need to connect power through the barrel jack and tighten the screws for each channel. The controller box includes an additional "white" channel for LED strips with that have an the color.

Mi-Light 4-Zone LED Remote Controller

Mi-Light 4-Zone LED Remote Controller

COM-14711
$14.95
1
Mi-Light RGBW LED Controller Box

Mi-Light RGBW LED Controller Box

COM-14710
$14.95
2

For more information, check out the video below!

Hookup 3: Microcontroller

For those that want a little bit more flexibility and control over the LEDs, you can use a microcontroller. We'll be using a RedBoard Qwiic with the ATmega328P. You can use different microcontollers (i.e. AVR, ARM, micro:bit, ESP8266, ESP32, etc.) or single board computer (i.e. Raspberry Pi) as long as it can output a PWM signal. You just need a transistor since the logic level is lower than the voltage of the LED strip and the pins are not able to source enough current. The code (i.e. MakeCode, Python, etc.) depends on the microcontroller or single board computer. For the scope of the tutorial, we will be using the Arduino language to control the LEDs.

Typically for common anode RGB LED strips, you could use NPN BJTs or N-channel MOSFETs as a switch. N-channel mosfets usually can handle more power and they are more power efficient. Therefore, we'll be adding the load on the high side. Each color channel requires a transistor to switch. The hookup diagram for a basic connection is shown on the left. For additional functionality, you could add buttons and a potentiometer to control the LEDs. For testing purposes, we'll use a breadboard, jumper wires, and alligator clips to connect. You'll eventually want to solder the LED strip to header pins, a prototyping board, or splice a 4-pin pigtail connector for a secure connection when using it in an installation.

Basic Arduino Hookup w/ N-Channel MOSFETSButtons and Potentiometers Added for Additional Functionality
Basic Arduino Hookup w/ N Channel MOSFETSButtons and Potentiometers Added for Additional Functionality

Click image for a closer look

By using a PWM output from a microcontroller and transistor to adjust the brightness of each color channel individually, the RGB LED can display almost any color you choose! For simplicity, we'll limit the colors to twelve colors and white on an Arduino. The following values in the diagram will create the primary, secondary, and tertiary colors.

Primary, secondary, and teriary colors with Arduino

When using long strands, it is recommended to have a separate power supply for the Arduino and LEDs. Your setup should look similar to the image below on a breadboard if you are using a 12V/5V, 2A power supply and a 5M LED strip. The setup is the same except VIN is disconnected on the 12V. The Arduino is using its own 5V power. When programming the Arduino, it is recommended to disconnect the 5V pin so that you do not have conflicting power sources.

12V/5V power supply and a USB cable connected to an Arduino and the Non-Addressable RGB LED Strip

After you are done programming, you can remove the USB cable and connect the 12V/5V power supply's 5V pin to the circuit.

12V/5V power supply connected to an Arduino and the Non-Addressable RGB LED Strip when powering the board Remotely in an Installation

Arduino Example Code

Note: This example assumes you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE.

To follow along, check out the GitHub repository. There are five examples in the repo. Two of which are simple examples to turn on a certain color based on the type of LED that you are using. We'll go over the other three examples.

The three examples from this GitHub Repo that we will go over are listed below. Click on one of the links below to jump to the example!


Example 1: Custom Color Cycling

This code will cycle through 12 colors and white. This is useful to test to see if you wired the colors correctly or want to show a color. There are options to adjust the brightness, type of LED, and rate at which the colors cycle.

If you have not already, unzip the GitHub repo and open the example code called Example1_RGB-CycleLED.ino. The path of the example code will probably look similar to: ... \ Non-Addresssable_RGB_LED_Strip_Code \ Firmware \ Arduino \ Example1_RGB-CycleLED. You can also copy the code below and paste it into the Arduino IDE. Select the board (in this case the Arduino/Genuino Uno) and COM port that the board enumerated to. Then hit the upload button to upload to your Arduino.

language:c
/******************************************************************************
  Example1_RGB-CycleLED.ino

  Non-Addressable RGB LED Custom Color Cycle
  WRITTEN BY: Ho Yun "Bobby" Chan @ SparkFun Electronics
  DATE: November 4, 2019
  GITHUB REPO: https://github.com/sparkfun/Non-Addresssable_RGB_LED_Strip_Code
  DEVELOPMENT ENVIRONMENT SPECIFICS:
    Firmware developed using Arduino IDE v1.8.9

  ============================== DESCRIPTION ==============================
  Expand your color options using analogWrite() and a non-addressable RGB LED.
  This code will cycle through 12 colors and white. There are options to adjust
  the brightness, type of LED, and rate at which the colors cycle.

  This example code works with an individual common anode and common cathode
  RGB LED. If you have a transistor or constant current LED driver, you can
  also use it to control an RGB LED strip or a higher power RGB LED.
  We'll assume that you are using a common anode LEDs in the strip. For more
  information checkout our tutorial: https://learn.sparkfun.com/tutorials/731

  Notes: There are twelve rainbow colors (primary, secondary, tertiary).
  Unlike digitalWrite(), which can be only HIGH (on) or LOW (off),
  analogWrite() lets you smoothly change the brightness from 0 (off) to 255 (fully on).
  When analogWrite() is used with the RGB LED, you can create millions of colors!
  For simplicity, we'll use 12 rainbow colors and white.  We will be blinking
  between each color.

  In the analogWrite() functions:
    0 is off
    128 is halfway on (used for the tertiary colors)
    255 is full brightness.

  ========== TUTORIAL ==========
  Non-Addressable RGB LED Strip Hookup Guide
  https://learn.sparkfun.com/tutorials/731

  Transistors | Applictions I: Switches
  https://learn.sparkfun.com/tutorials/transistors/all#applications-i-switches

  ==================== PRODUCTS THAT USE THIS CODE ====================
    LED RGB Strip (1M Bare) - https://www.sparkfun.com/products/12021
    LED RGB Strip (1M Sealed) - https://www.sparkfun.com/products/12023
    LED RGB Strip (5B Bare) - https://www.sparkfun.com/products/12022
    LED RGB Strip (5M Sealed) - https://www.sparkfun.com/products/12024
    Triple Output High Power RGB LED - https://www.sparkfun.com/products/15200

    PicoBuck LED Driver - https://www.sparkfun.com/products/13705
    N-Channel MOSFET Power Control Kit - https://www.sparkfun.com/products/12959

  ==================== HARDWARE CONNECTIONS ====================
  The hardware connection depends on your hardware and setup. Below is one possible
  arrangement.

  RGB Common Anode LED Strip => BJT/MOSFET => Arduino PWM Pin
      R pin => transistor => 5
      G pin => transistor => 6
      B pin => transistor => 9
      - pin                  -

  LICENSE: This code is released under the MIT License (http://opensource.org/licenses/MIT)

  ******************************************************************************/

//Debug mode, comment one of these lines out using a syntax
//for a single line comment ("//"):
//#define DEBUG 0     //0 = LEDs only
#define DEBUG 1     //1 = LEDs w/ serial output

// Define our LED pins to a PWM Pin
#define redPin 5
#define greenPin 6
#define bluePin 9

// Create integer variables for our LED color value
int redValue = 0;
int greenValue = 0;
int blueValue = 0;

//Create brightness variable
//Ranging from 0.0-1.0:
//  0.0 is off
//  0.5 is 50%
//  1.0 is fully on
float brightnessLED = 0.1;

//Create variables for type of LED and if it is used with a transistor
boolean commonAnode = false;
boolean commonCathode = true; //i.e.) When pin is HIGH, LED will also go HIGH without a transistor/PicoBuck

// Note:
//  Common Anode is `commonAnode`
//  Common Cathode LED is `commonCathode`
//  Common Anode RGB LED Strip with transistor is `!commonAnode`
//  RGB High Power LED with PicoBuck is also  `!commonAnode`
boolean rgbType = !commonAnode;

int blinkRate = 1000; //in milliseconds



void setup() {

  // Make all of our LED pins outputs:
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  allOFF(); //initialize LEDs with it turned off
  rgbCalc();//calculate for RGB type
  rgbShow(); //make sure to show it happening

#if DEBUG
  Serial.begin(9600); //initialize Serial Monitor
  //while (!Serial); // Comment out to wait for serial port to connect to Serial Monitor. Option for native USB.
  Serial.println("Custom Color Cycling w/ an RGB LED. This example will cycle through 13 colors.");
  Serial.println("");
  Serial.println("Note: Make sure to adjust the code for a common cathode or common anode.");
  Serial.println("");
#endif

}//end setup()




void loop()
{
  //used to visually check when Arduino is initialized
#if DEBUG
  Serial.print("RED");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  redON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("ORANGE");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  orangeON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("YELLOW");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  yellowON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("CHARTRUESE");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  chartrueseON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("GREEN");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  greenON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("SPRING GREEN");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  springGreenON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("CYAN");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  cyanON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("AZURE");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  azureON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("BLUE");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  blueON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("VIOLET");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  violetON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("MAGENTA");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  magentaON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("ROSE");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  roseON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("WHITE");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  whiteON();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

#if DEBUG
  Serial.print("OFF");
  Serial.print(" | Brightness % = ");
  Serial.println(brightnessLED * 100);
#endif
  allOFF();
  rgbCalc();
  rgbShow();
  delay(blinkRate);

}//end loop



// ==================== CUSTOM FUNCTIONS DEFINED BELOW ====================
void allOFF() {
  // Black (all LEDs off)
  // RGB LEDs:
  redValue = 0;
  greenValue =  0;
  blueValue = 0;
}

void redON() {
  // Red
  redValue = 255;
  greenValue =  0;
  blueValue = 0;
}

void orangeON() {
  // Orange
  redValue = 255;
  greenValue = 128;
  blueValue = 0;
}

void yellowON() {
  // Yellow
  redValue = 255;
  greenValue = 255;
  blueValue = 0;
}

void chartrueseON() {
  // Chartruese
  redValue = 128;
  greenValue = 255;
  blueValue = 0;
}

void greenON() {
  // Green
  redValue = 0;
  greenValue = 255;
  blueValue = 0;
}

void springGreenON() {
  // Spring Green
  redValue = 0;
  greenValue = 255;
  blueValue = 128;
}

void cyanON() {
  // Cyan
  redValue = 0;
  greenValue = 255;
  blueValue = 255;
}

void azureON() {
  // Azure
  redValue = 0;
  greenValue = 128;
  blueValue = 255;
}

void blueON() {
  // Blue
  redValue = 0;
  greenValue = 0;
  blueValue = 255;
}

void violetON() {
  // Violet
  redValue = 128;
  greenValue = 0;
  blueValue = 255;
}

void magentaON() {
  // Magenta
  redValue = 255;
  greenValue = 0;
  blueValue = 255;
}

void roseON() {
  // Rose
  redValue = 255;
  greenValue = 0;
  blueValue = 128;
}

void whiteON() {
  // White (all LEDs on)
  redValue = 255;
  greenValue = 255;
  blueValue = 255;
}



void rgbCalc() {
  //use this to correctly light up LED depending on the setup
  if (rgbType == commonAnode) {
    /* If using a common anode LED, a pin
       should turn ON the LED when the pin is LOW.*/
    redValue = 255 - redValue;
    greenValue = 255 - greenValue;
    blueValue = 255 - blueValue;

  }
  else {
    /* If using a common cathode LED, an analog pin
       should turn on the LED when the pin is HIGH. The
       logic is flipped when using a Common Anode RGB LED
       strip, NPN BJT/N-Channel MOSFET, and microcontroller

       Leave RGB values as is, we're good!*/
  }

  redValue = int(redValue * brightnessLED);
  greenValue = int(greenValue * brightnessLED);
  blueValue = int(blueValue * brightnessLED);
}

void rgbShow() {
  //once value is calculated, show the LED color
  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

Once the code has been uploaded, the RGB LED will cycle through each of the 12 colors, white, and then turn off. Each color has its own function. When the function is called, the custom color will have a certain analog value for red, green, and blue. Before displaying the color, the values are calculated depending on the type of LED being used (either a common cathode or common anode). By default, we are assuming that the strip uses common anode LEDs but we are using a transistor to control them so rgbType is set to !commonAnode. The color is further calculated based on the intensity of the LED. After calculating the LED color lights up whenever the function rgbShow() is called.

Open the Arduino Serial Monitor set to 9600 baud to see the output as the color changes. Try adjusting the brightness or blink rate. If you are not seeing the correct color associated with the output, make sure to check your connections and ensure that the correct type of RGB LED is selected.

Custom Color Cycling

Example 2: Fading

This code will fade through 12 colors and white. There are options to adjust the brightness, type of LED, and rate at which the colors fade.

If you have not already, unzip the GitHub repo and open the example code called Example2_RGB-FadeLED.ino. The path of the example code will probably look similar to: ...Non-Addresssable_RGB_LED_Strip_Code\Firmware\Arduino\Example2_RGB-FadeLED.ino. You can also copy the code below and paste it into the Arduino IDE. Select the board (in this case the Arduino/Genuino Uno) and COM port that the board enumerated to. Then hit the upload button to upload to your Arduino.

language:c
/******************************************************************************
  Example2_RGB-FadeLED.ino

  Non-Addressable RGB LED Custom Color Fade
  WRITTEN BY: Ho Yun "Bobby" Chan @ SparkFun Electronics
  DATE: November 4, 2019
  GITHUB REPO: https://github.com/sparkfun/Non-Addresssable_RGB_LED_Strip_Code
  DEVELOPMENT ENVIRONMENT SPECIFICS:
    Firmware developed using Arduino IDE v1.8.9

  ============================== DESCRIPTION ==============================
  Expand your color options using analogWrite() and a non-addressable RGB LED.
  This code will fade through 12 colors and white. There are options to adjust
  the brightness, type of LED, and rate at which the colors fade.

  This example code works with an individual common anode and common cathode
  RGB LED. If you have a transistor or constant current LED driver, you can
  also use it to control an RGB LED strip or a higher power RGB LED.
  We'll assume that you are using a common anode LEDs in the strip. For more
  information checkout our tutorial: https://learn.sparkfun.com/tutorials/731

  Notes: There are twelve rainbow colors (primary, secondary, tertiary).
  Unlike digitalWrite(), which can be only HIGH (on) or LOW (off),
  analogWrite() lets you smoothly change the brightness from 0 (off) to 255 (fully on).
  When analogWrite() is used with the RGB LED, you can create millions of colors!
  For simplicity, we'll use 12 rainbow colors and white.  We will be fading
  between each color.

  In the analogWrite() functions:
    0 is off
    128 is halfway on (used for the tertiary colors)
    255 is full brightness.

  ========== TUTORIAL ==========
  Non-Addressable RGB LED Strip Hookup Guide
  https://learn.sparkfun.com/tutorials/731

  Transistors | Applictions I: Switches
  https://learn.sparkfun.com/tutorials/transistors/all#applications-i-switches

  ==================== PRODUCTS THAT USE THIS CODE ====================
    LED RGB Strip (1M Bare) - https://www.sparkfun.com/products/12021
    LED RGB Strip (1M Sealed) - https://www.sparkfun.com/products/12023
    LED RGB Strip (5B Bare) - https://www.sparkfun.com/products/12022
    LED RGB Strip (5M Sealed) - https://www.sparkfun.com/products/12024
    Triple Output High Power RGB LED - https://www.sparkfun.com/products/15200

    PicoBuck LED Driver - https://www.sparkfun.com/products/13705
    N-Channel MOSFET Power Control Kit - https://www.sparkfun.com/products/12959

  ==================== HARDWARE CONNECTIONS ====================
  The hardware connection depends on your hardware and setup. Below is one possible
  arrangement.

  RGB Common Anode LED Strip => BJT/MOSFET => Arduino PWM Pin
      R pin => transistor => 5
      G pin => transistor => 6
      B pin => transistor => 9
      - pin                  -

  LICENSE: This code is released under the MIT License (http://opensource.org/licenses/MIT)

  ******************************************************************************/

//Debug mode, comment one of these lines out using a syntax
//for a single line comment ("//"):
//#define DEBUG 0     //0 = LEDs only
#define DEBUG 1     //1 = LEDs w/ serial output

// Define our LED pins to a PWM Pin
#define redPin 5
#define greenPin 6
#define bluePin 9

// Create integer variables for our LED color value
int redValue = 0;
int greenValue = 0;
int blueValue = 0;

//Create brightness variable
//Ranging from 0.0-1.0:
//  0.0 is off
//  0.5 is 50%
//  1.0 is fully on
float brightnessLED = 0.1;

//Create variables for type of LED and if it is used with a transistor
boolean commonAnode = false;
boolean commonCathode = true;//i.e.) When pin is HIGH, LED will also go HIGH without a transistor/PicoBuck

// Note:
//  Common Anode is `commonAnode`
//  Common Cathode LED is `commonCathode`
//  Common Anode RGB LED Strip with transistor is `!commonAnode`
//  RGB High Power LED with PicoBuck is also  `!commonAnode`
boolean rgbType = !commonAnode;

int colorMode = 1; //color mode to control LED color

//Variables for fading LED
int prevFadeVal = 0;
int currentFadeVal = 0;
boolean increasing = true;
int fadeVal = 5; //value to step when increasing/decreasing, recommended to be 1 or 5, larger numbers will have problems lighting up
int fadeMAX = 255; //maximum fade value
int fadeMIN = 0;   //minimum fade value
int fadeDelay = 30;//delay between each step




void setup() {

  // Make all of our LED pins outputs
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  allOFF(); //make sure to initialize LEDs with it turned off
  rgbCalc();//calculate for RGB type
  rgbShow(); //make sure to show it happening

#if DEBUG
  Serial.begin(9600); //initialize Serial Monitor
  //while (!Serial); // Comment out to wait for serial port to connect to Serial Monitor. Option for native USB.
  Serial.println("Custom Color Fading w/ an RGB LED.");
  Serial.println("");
  Serial.println("Note: Make sure to adjust the code for a common cathode or common anode.");
  Serial.println("");
#endif

}//end setup()

void loop()
{


  switch (colorMode) {
    case 1://FADE RED
      redValue = currentFadeVal;
      greenValue = 0;
      blueValue = 0;

      rgbCalc();
      break;
    //========== END FADE RED ==========

    case 2://FADE ORANGE
      redValue = currentFadeVal;
      greenValue = currentFadeVal * 0.498; // 128/255 = ~0.498039
      blueValue = 0;

      rgbCalc();

      if (redValue > 0 && greenValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        redValue = 0;
      }

      // takes x amount of steps if you do not set it to zero for certain brightness (i.e. takes 8 more steps to turn off for 0.1)
      //Serial.print("Red Value =");
      //Serial.println( int((currentFadeVal) * brightnessLED));

      //Serial.print("Green Value =");
      //Serial.println( int((currentFadeVal * 0.498) * brightnessLED));
      break;
    //========== END FADE ORANGE ==========

    case 3://FADE YELLOW
      redValue = currentFadeVal;
      greenValue = currentFadeVal;
      blueValue = 0;

      rgbCalc();
      break;
    //========== END FADE YELLOW ==========

    case 4://FADE CHARTRUESE
      redValue = currentFadeVal * 0.498; // 128/255 = ~0.498039
      greenValue = currentFadeVal;
      blueValue = 0;

      rgbCalc();

      if (greenValue > 0 && redValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        greenValue = 0;
      }
      break;
    //========== END FADE CHARTRUESE ==========

    case 5://FADE GREEN
      redValue = 0;
      greenValue = currentFadeVal;
      blueValue = 0;

      rgbCalc();
      break;
    //========== END FADE GREEN ==========

    case 6://FADE SPRING GREEN
      redValue = 0;
      greenValue = currentFadeVal;
      blueValue = currentFadeVal * 0.498; // 128/255 = ~0.498039

      rgbCalc();

      if (greenValue > 0 && blueValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        greenValue = 0;
      }
      break;
    //========== END FADE SPRING GREEN ==========

    case 7://FADE CYAN
      redValue = 0;
      greenValue = currentFadeVal;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE CYAN ==========

    case 8://FADE AZURE
      redValue = 0;
      greenValue = currentFadeVal * 0.498; // 128/255 = ~0.498039
      blueValue = currentFadeVal;

      rgbCalc();

      if (blueValue > 0 && greenValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        blueValue = 0;
      }
      break;
    //========== END FADE AZURE ==========

    case 9://FADE BLUE
      redValue = 0;
      greenValue = 0;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE BLUE ==========

    case 10://FADE VIOLET
      redValue = currentFadeVal * 0.498;
      greenValue = 0;
      blueValue = currentFadeVal;

      rgbCalc();

      if (blueValue > 0 && redValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        blueValue = 0;
      }
      break;
    //========== END FADE VIOLET ==========

    case 11://FADE MAGENTA
      redValue = currentFadeVal;
      greenValue = 0;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE MAGENTA ==========

    case 12://FADE ROSE
      redValue = currentFadeVal;
      greenValue = 0;
      blueValue = currentFadeVal * 0.498;

      rgbCalc();

      if (redValue > 0 && blueValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        redValue = 0;
      }
      break;
    //========== END FADE ROSE ==========

    case 13://FADE WHITE
      redValue = currentFadeVal;
      greenValue = currentFadeVal;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE WHITE ==========

    default:
      allOFF();
      rgbCalc();
      break;
  }



#if DEBUG
  Serial.print("Color Fading = ");
  if (colorMode == 1) {
    Serial.print("RED");
  }
  else if (colorMode == 2) {
    Serial.print("ORANGE");
  }
  else if (colorMode == 3) {
    Serial.print("YELLOW");
  }
  else if (colorMode == 4) {
    Serial.print("CHARTRUESE");
  }
  else if (colorMode == 5) {
    Serial.print("GREEN");
  }
  else if (colorMode == 6) {
    Serial.print("SPRING GREEN");
  }
  else if (colorMode == 7) {
    Serial.print("CYAN");
  }
  else if (colorMode == 8) {
    Serial.print("AZURE");
  }
  else if (colorMode == 9) {
    Serial.print("BLUE");
  }
  else if (colorMode == 10) {
    Serial.print("VIOLET");
  }
  else if (colorMode == 11) {
    Serial.print("MAGENTA");
  }
  else if (colorMode == 12) {
    Serial.print("ROSE");
  }
  else if (colorMode == 13) {
    Serial.print("WHITE");
  }
  else {
    Serial.print("OFF");
  }
  Serial.print(" | Brightness % = ");
  Serial.print(brightnessLED * 100);
  Serial.print("%");

  Serial.print(" | Fade Val Before Calc= ");
  Serial.println(currentFadeVal);
#endif

  rgbShow();
  delay(fadeDelay);


  if (increasing == true) {
    //increasing
    currentFadeVal += fadeVal;
  }
  else {
    //decreasing
    currentFadeVal -= fadeVal;
  }

  if (currentFadeVal > fadeMAX) {
    increasing = false;
    prevFadeVal -= fadeVal;//undo addition

    currentFadeVal = prevFadeVal;
  }
  else if (currentFadeVal < fadeMIN) {
    increasing = true;
    prevFadeVal += fadeVal;//undo subtraction

    currentFadeVal = prevFadeVal;

    colorMode += 1;//next color
    if (colorMode > 13) {
      colorMode = 0;
    }
  }

  prevFadeVal = currentFadeVal;

}//END LOOP




// ==================== CUSTOM FUNCTIONS DEFINED BELOW ====================
void allOFF() {
  // Black (all LEDs off)
  // RGB LEDs:
  redValue = 0;
  greenValue =  0;
  blueValue = 0;

  rgbCalc();
}

void redON() {
  // Red
  redValue = 255;
  greenValue =  0;
  blueValue = 0;

  rgbCalc();
}

void orangeON() {
  // Orange
  redValue = 255;
  greenValue = 128;
  blueValue = 0;

  rgbCalc();
}

void yellowON() {
  // Yellow
  redValue = 255;
  greenValue = 255;
  blueValue = 0;

  rgbCalc();
}

void chartrueseON() {
  // Chartruese
  redValue = 128;
  greenValue = 255;
  blueValue = 0;

  rgbCalc();
}

void greenON() {
  // Green
  redValue = 0;
  greenValue = 255;
  blueValue = 0;

  rgbCalc();
}

void springGreenON() {
  // Spring Green
  redValue = 0;
  greenValue = 255;
  blueValue = 128;

  rgbCalc();
}

void cyanON() {
  // Cyan
  redValue = 0;
  greenValue = 255;
  blueValue = 255;

  rgbCalc();
}

void azureON() {
  // Azure
  redValue = 0;
  greenValue = 128;
  blueValue = 255;

  rgbCalc();
}

void blueON() {
  // Blue
  redValue = 0;
  greenValue = 0;
  blueValue = 255;

  rgbCalc();
}

void violetON() {
  // Violet
  redValue = 128;
  greenValue = 0;
  blueValue = 255;

  rgbCalc();
}

void magentaON() {
  // Magenta
  redValue = 255;
  greenValue = 0;
  blueValue = 255;

  rgbCalc();
}

void roseON() {
  // Rose
  redValue = 255;
  greenValue = 0;
  blueValue = 128;

  rgbCalc();
}

void whiteON() {
  // White (all LEDs on)
  redValue = 255;
  greenValue = 255;
  blueValue = 255;

  rgbCalc();
}



void rgbCalc() {
  //use this to correctly light up LED depending on the setup
  if (rgbType == commonAnode) {
    /* If using a common anode LED, a pin
       should turn ON the LED when the pin is LOW.*/
    redValue = 255 - redValue;
    greenValue = 255 - greenValue;
    blueValue = 255 - blueValue;

  }
  else {
    /* If using a common cathode LED, an analog pin
       should turn on the LED when the pin is HIGH. The
       logic is flipped when using a Common Anode RGB LED
       strip, NPN BJT/N-Channel MOSFET, and microcontroller

       Leave RGB values as is, we're good!*/
  }

  redValue = int(redValue * brightnessLED);
  greenValue = int(greenValue * brightnessLED);
  blueValue = int(blueValue * brightnessLED);
}

void rgbShow() {
  //once value is calculated, show the LED color
  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

Once the code has been uploaded, you should see the colors fading in and out. Open the serial monitor at 9600 to see what color is fading and its respective fade value. Due to the calculations and serial output, the fading can appear to be slow. You may want to adjust the baud rate to a higher value like 115200, adjust the fade delay, or turn off the debugging by defining DEBUG as 0. Additionally, the LEDs may turn off if the fade value and brightness is too small. This is due to the minimum voltage required to turn on the LEDs. You should see something similar to the GIF below. The GIF repeats a small sample of the colors fading. You will see all of the colors cycling in your setup.

Custom Color Fading

Example 3: Full Demo

This code will turn on a color, blink, fade, or cycle through 12 colors depending on the button input. The color cycle used in this demo will fade between each of the 12 colors. There are options to adjust the brightness, type of LED, and rate at which the colors cycle. The RedBoard will only change the color and pattern after pressing the button again.

If you have not already, unzip the GitHub repo and open the example code called Example3_RGB-FullDemoLED.ino. The path of the example code will probably look similar to: ...Non-Addresssable_RGB_LED_Strip_Code\Firmware\Arduino\Example3_RGB-FullDemoLED. You can also copy the code below and paste it into the Arduino IDE. Select the board (in this case the Arduino/Genuino Uno) and COM port that the board enumerated to. Then hit the upload button to upload to your Arduino.

language:c
/******************************************************************************
  Example3_RGB-FullDemoLED.ino

  Non-Addressable RGB LED Full Demo
  WRITTEN BY: Ho Yun "Bobby" Chan @ SparkFun Electronics
  DATE: November 4, 2019
  GITHUB REPO: https://github.com/sparkfun/Non-Addresssable_RGB_LED_Strip_Code
  DEVELOPMENT ENVIRONMENT SPECIFICS:
    Firmware developed using Arduino IDE v1.8.9

  ============================== DESCRIPTION ==============================
  Expand your color options using analogWrite() and a non-addressable RGB LED.
  This code will either turn on a color, blink, fade, or cycle through 12
  colors and white depending on the button input. There are options to adjust
  the brightness, type of LED, and rate at which the colors blink/fade/cycle.

  This example code works with an individual common anode and common cathode
  RGB LED. If you have a transistor or constant current LED driver, you can
  also use it to control an RGB LED strip or a higher power RGB LED.
  We'll assume that you are using a common anode LEDs in the strip. For more
  information checkout our tutorial: https://learn.sparkfun.com/tutorials/731

  Notes: There are twelve rainbow colors (primary, secondary, tertiary).
  Unlike digitalWrite(), which can be only HIGH (on) or LOW (off),
  analogWrite() lets you smoothly change the brightness from 0 (off) to 255 (fully on).
  When analogWrite() is used with the RGB LED, you can create millions of colors!
  For simplicity, we'll use 12 rainbow colors and white.

  In the analogWrite() functions:
    0 is off
    128 is halfway on (used for the tertiary colors)
    255 is full brightness.

  ========== TUTORIAL ==========
  Non-Addressable RGB LED Strip Hookup Guide
  https://learn.sparkfun.com/tutorials/731

  Transistors | Applictions I: Switches
  https://learn.sparkfun.com/tutorials/transistors/all#applications-i-switches

  ==================== PRODUCTS THAT USE THIS CODE ====================
    LED RGB Strip (1M Bare) - https://www.sparkfun.com/products/12021
    LED RGB Strip (1M Sealed) - https://www.sparkfun.com/products/12023
    LED RGB Strip (5B Bare) - https://www.sparkfun.com/products/12022
    LED RGB Strip (5M Sealed) - https://www.sparkfun.com/products/12024
    Triple Output High Power RGB LED - https://www.sparkfun.com/products/15200

    PicoBuck LED Driver - https://www.sparkfun.com/products/13705
    N-Channel MOSFET Power Control Kit - https://www.sparkfun.com/products/12959

  ==================== HARDWARE CONNECTIONS ====================
  The hardware connection depends on your hardware and setup. Below is one possible
  arrangement.

  RGB Common Anode LED Strip => BJT/MOSFET => Arduino PWM Pin
      R pin => transistor => 5
      G pin => transistor => 6
      B pin => transistor => 9
      - pin                  -

  LICENSE: This code is released under the MIT License (http://opensource.org/licenses/MIT)

  ******************************************************************************/

//Debug mode, comment one of these lines out using a syntax
//for a single line comment ("//"):
//#define DEBUG 0     //0 = LEDs only
#define DEBUG 1     //1 = LEDs w/ serial output

// Define our LED pins to a PWM Pin
#define redPin 5
#define greenPin 6
#define bluePin 9

// Create integer variables for our LED color value
int redValue = 0;
int greenValue = 0;
int blueValue = 0;

// Define our Potentiometer to a Analog Pin for Brightness
// This is needed if you use a Potentiometer
#define knobPin A0

//Create brightness variable
//Ranging from 0.0-1.0:
//  0.0 is off
//  0.5 is 50%
//  1.0 is fully on
float brightnessLED = 0.1;

//Create variables for type of LED and if it is used with a transistor
boolean commonAnode = false;
boolean commonCathode = true;//i.e.) When pin is HIGH, LED will also go HIGH without a transistor/PicoBuck

// Note:
//  Common Anode LED is `commonAnode`
//  Common Cathode LED is `commonCathode`
//  Common Anode RGB LED Strip with transistor is `!commonAnode`
//  RGB High Power LED with PicoBuck is also  `!commonAnode`
boolean rgbType = !commonAnode;

//Variables to keep track of color and pattern
int colorMode = 0; //color mode to control LED color
int pattern = 0; //pattern to turn off, stay on, fade, blink

//Variables for fading LED
int prevFadeVal = 0;
int currentFadeVal = 0;
boolean increasing = true;
int fadeVal = 5; //value to step when increasing/decreasing, recommended to be 1 or 5, larger numbers will have problems lighting up
int fadeMAX = 255; //maximum fade value
int fadeMIN = 0;   //minimum fade value
int fadeDelay = 30;//delay between each step

//Variables for blinking LED
int blinkVal = 0;
boolean blinkON = false;
int counter = 0; //use as a "delay"
int blinkRate = 750; //in milliseconds

//Variables to transition between RGB in a rainbow
int rainbowRedVal = 0;
int rainbowGreenVal = 0;
int rainbowBlueVal = 0;
int rainbowTransitionVal = 0;
int rainbowDelay = 5; //in milliseconds to transition between colors

//Note: You'll want to not make `rainbowDelay` too long as this will
//      cause delays with button presses

//Button variables for color
const int button1Pin = 2;
boolean button1State = false;
boolean prevbutton1State = false;
boolean currentbutton1State = false;

//Button variables for pattern
const int button2Pin = 3;
boolean button2State = false;
boolean prevbutton2State = false;
boolean currentbutton2State = false;




void setup() {

  // Make all of our LED pins outputs:
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  if (rgbType == commonAnode) {
    //set values 255 to turn off OFF if common anode
    rainbowRedVal = 255;
    rainbowGreenVal = 255;
    rainbowBlueVal = 255;
  }

  sequenceTest();//visually initialization
  allOFF(); //make sure to initialize LEDs with it turned off
  rgbCalc();//calculate for RGB type
  rgbShow(); //make sure to show it happening

  pinMode(button1Pin, INPUT_PULLUP); //use internal pullup resistor with button
  pinMode(button2Pin, INPUT_PULLUP); //use internal pullup resistor with button

#if DEBUG
  Serial.begin(9600); //initialize Serial Monitor
  //while (!Serial); // Comment out to wait for serial port to connect to Serial Monitor. Option for native USB.
  Serial.println("Custom Color Mixing Demo w/ an RGB LED. Toggling the buttons will adjust the color and pattern.");
  Serial.println("");
  Serial.println("Note: Make sure to adjust the code for a common cathode or common anode.");
  Serial.println("Default is set to no color and off!");
  Serial.println("");
#endif

}//end setup()




void loop()
{
  button1State = digitalRead(button1Pin);// button for Color Mode
  button2State = digitalRead(button2Pin);// button for Pattern

  //==================== CHECK POTENTIOMETER FOR BRIGHTNESS ====================
  //Uncomment the line below if you are using a potentiometer or photoresistor (i.e. light sensor)
  //brightnessLED = analogRead(knobPin) / 1023.0; //potentiometer for Brightness

  /* Note: If you do not have a potentiometer or analog sensor attached,
    the LEDs will flicker when the LED pulls a certain amount of power
    due to the pin floating. Make sure to also GND the sensor close to your
    Arduino to reduce the noise.

    The LEDs can flicker at low values when using the fade mode. Make sure
    to adjust the potentiometer to a certain brightness or fade values
    for smooth fading.*/

  /*
    #if DEBUG
    Serial.print(" Brightness Value % = ");
    Serial.println(brightnessLED * 100);
    #endif
  */
  //==================== END CHECK POTENTIOMETER FOR BRIGHTNESS ====================

  //==================== CHECK BUTTON FOR COLOR MODE ====================
  //if button is pressed, it will be pulled low
  if (button1State == LOW) {
    currentbutton1State = true; // button has been pressed once

    if (prevbutton1State != currentbutton1State) { //check to see if button is still being pressed
      colorMode = colorMode + 1; //change color MODE after button has been pressed
#if DEBUG
      Serial.print("Color Mode = ");
      if (colorMode == 1) {
        Serial.println("RED");
      }
      else if (colorMode == 2) {
        Serial.println("ORANGE");
      }
      else if (colorMode == 3) {
        Serial.println("YELLOW");
      }
      else if (colorMode == 4) {
        Serial.println("CHARTRUESE");
      }
      else if (colorMode == 5) {
        Serial.println("GREEN");
      }
      else if (colorMode == 6) {
        Serial.println("SPRING GREEN");
      }
      else if (colorMode == 7) {
        Serial.println("CYAN");
      }
      else if (colorMode == 8) {
        Serial.println("AZURE");
      }
      else if (colorMode == 9) {
        Serial.println("BLUE");
      }
      else if (colorMode == 10) {
        Serial.println("VIOLET");
      }
      else if (colorMode == 11) {
        Serial.println("MAGENTA");
      }
      else if (colorMode == 12) {
        Serial.println("ROSE");
      }
      else if (colorMode == 13) {
        Serial.println("WHITE");
      }
      else {
        Serial.println("OFF");
      }
#endif

      //Cycle through colors when pressing buttons
      if (colorMode < 0 || colorMode > 13) {
        //reset ledMode
        colorMode = 0;
        allOFF();
        rgbCalc();
        rgbShow();
      }
    }
    else { //do nothing because finger is still on button
    }
    prevbutton1State = currentbutton1State;//update button1 state
  }



  //button has not been pressed, it will be high
  else {
    currentbutton1State = false;
    prevbutton1State = currentbutton1State;//update button1 state
  }

  //==================== END CHECK BUTTON FOR COLOR MODE ====================

  //==================== CHECK BUTTON FOR PATTERN ====================
  if (button2State == LOW) {
    currentbutton2State = true; //button has been pressed once

    if (prevbutton2State != currentbutton2State) { //check to see if button is still being pressed
      pattern = pattern + 1; //change LED pattern after button has been pressed

#if DEBUG
      Serial.print("Pattern = ");
      if (pattern == 1) {
        Serial.println("ON");//print what pattern
      }
      else if (pattern == 2) {
        Serial.println("FADE");//print what pattern
      }
      else if (pattern == 3) {
        Serial.println("BLINK");//print what pattern
      }
      else if (pattern == 4) {
        Serial.println("RAINBOW");//print what pattern
      }
      else {
        Serial.println("OFF");//print what pattern
      }
#endif


      if (pattern < 0 || pattern > 4) {
        //reset pattern
        pattern = 0;
      }
    }



    else { //do nothing because finger is still on button
    }
    prevbutton2State = currentbutton2State; //update button2 state
  }

  //button has not been pressed, it will be high
  else {
    currentbutton2State = false;
    prevbutton2State = currentbutton2State; //update button2 state
  }
  switch (pattern) {
    case 1:
      patternON();
      break;
    case 2:
      patternFade();
      break;
    case 3:
      patternBlink();
      break;
    case 4:
      patternRainbow();
      break;
    default:
      allOFF();
      rgbCalc();
      rgbShow();
      break;
  }
  //==================== END CHECK BUTTON FOR PATTERN ====================


}//end loop




// ==================== CUSTOM FUNCTIONS DEFINED BELOW ====================
void allOFF() {
  // Black (all LEDs off)
  // RGB LEDs:
  redValue = 0;
  greenValue =  0;
  blueValue = 0;
}

void redON() {
  // Red
  redValue = 255;
  greenValue =  0;
  blueValue = 0;
}

void orangeON() {
  // Orange
  redValue = 255;
  greenValue = 128;
  blueValue = 0;
}

void yellowON() {
  // Yellow
  redValue = 255;
  greenValue = 255;
  blueValue = 0;
}

void chartrueseON() {
  // Chartruese
  redValue = 128;
  greenValue = 255;
  blueValue = 0;
}

void greenON() {
  // Green
  redValue = 0;
  greenValue = 255;
  blueValue = 0;
}

void springGreenON() {
  // Spring Green
  redValue = 0;
  greenValue = 255;
  blueValue = 128;
}

void cyanON() {
  // Cyan
  redValue = 0;
  greenValue = 255;
  blueValue = 255;
}

void azureON() {
  // Azure
  redValue = 0;
  greenValue = 128;
  blueValue = 255;
}

void blueON() {
  // Blue
  redValue = 0;
  greenValue = 0;
  blueValue = 255;
}

void violetON() {
  // Violet
  redValue = 128;
  greenValue = 0;
  blueValue = 255;
}

void magentaON() {
  // Magenta
  redValue = 255;
  greenValue = 0;
  blueValue = 255;
}

void roseON() {
  // Rose
  redValue = 255;
  greenValue = 0;
  blueValue = 128;
}

void whiteON() {
  // White (all LEDs on)
  redValue = 255;
  greenValue = 255;
  blueValue = 255;
}


//-------------------- sequenceTest() FUNCTION --------------------

void sequenceTest() {
  //used to visually check when Arduino is initialized
  redON();
  rgbCalc();
  rgbShow();
  delay(50);

  orangeON();
  rgbCalc();
  rgbShow();
  delay(50);

  yellowON();
  rgbCalc();
  rgbShow();
  delay(50);

  chartrueseON();
  rgbCalc();
  rgbShow();
  delay(50);

  greenON();
  rgbCalc();
  rgbShow();
  delay(50);

  springGreenON();
  rgbCalc();
  rgbShow();
  delay(50);

  cyanON();
  rgbCalc();
  rgbShow();
  delay(50);

  azureON();
  rgbCalc();
  rgbShow();
  delay(50);

  blueON();
  rgbCalc();
  rgbShow();
  delay(50);

  violetON();
  rgbCalc();
  rgbShow();
  delay(50);

  magentaON();
  rgbCalc();
  rgbShow();
  delay(50);

  roseON();
  rgbCalc();
  rgbShow();
  delay(50);

  whiteON();
  rgbCalc();
  rgbShow();
  delay(50);

  allOFF();
  rgbCalc();
  rgbShow();
  delay(50);
}//-------------------- END sequenceTest() FUNCTION --------------------

void rgbCalc() {
  //use this to correctly light up LED depending on the setup
  if (rgbType == commonAnode) {
    /* If using a common anode LED, a pin
       should turn ON the LED when the pin is LOW.*/
    redValue = 255 - redValue;
    greenValue = 255 - greenValue;
    blueValue = 255 - blueValue;

  }
  else {
    /* If using a common cathode LED, an analog pin
       should turn on the LED when the pin is HIGH. The
       logic is flipped when using a Common Anode RGB LED
       strip, NPN BJT/N-Channel MOSFET, and microcontroller

       Leave RGB values as is, we're good!*/
  }

  redValue = int(redValue * brightnessLED);
  greenValue = int(greenValue * brightnessLED);
  blueValue = int(blueValue * brightnessLED);
}

void rgbShow() {
  //once value is calculated, show the LED color
  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

//-------------------- patternON() FUNCTION --------------------

void patternON() {
  // button is pressed, change LED color/sequence
  switch (colorMode)
  {
    case 1:
      redON();
      rgbCalc();
      break;
    case 2:
      orangeON();
      rgbCalc();
      break;
    case 3:
      yellowON();
      rgbCalc();
      break;
    case 4:
      chartrueseON();
      rgbCalc();
      break;
    case 5:
      greenON();
      rgbCalc();
      break;
    case 6:
      springGreenON();
      rgbCalc();
      break;
    case 7:
      cyanON();
      rgbCalc();
      break;
    case 8:
      azureON();
      rgbCalc();
      break;
    case 9:
      blueON();
      rgbCalc();
      break;
    case 10:
      violetON();
      rgbCalc();
      break;
    case 11:
      magentaON();
      rgbCalc();
      break;
    case 12:
      roseON();
      rgbCalc();
      break;
    case 13:
      whiteON();
      rgbCalc();
      break;
    default:
      allOFF();
      rgbCalc();
      break;
  }//end switch

  rgbShow();
}//-------------------- end patternON() FUNCTION --------------------




//-------------------- patternFade() FUNCTION --------------------
void patternFade() {

  switch (colorMode) {
    case 1://FADE RED
      redValue = currentFadeVal;
      greenValue = 0;
      blueValue = 0;

      rgbCalc();
      break;
    //========== END FADE RED ==========

    case 2://FADE ORANGE
      redValue = currentFadeVal;
      greenValue = currentFadeVal * 0.498; // 128/255 = ~0.498039
      blueValue = 0;

      rgbCalc();

      if (redValue > 0 && greenValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        redValue = 0;
      }
      // takes x amount of steps if you do not set it to zero for certain brightness (i.e. takes 8 more steps to turn off for 0.1)
      //Serial.print("Red Value =");
      //Serial.println( int((currentFadeVal) * brightnessLED));

      //Serial.print("Green Value =");
      //Serial.println( int((currentFadeVal * 0.498) * brightnessLED));
      break;
    //========== END FADE ORANGE ==========

    case 3://FADE YELLOW
      redValue = currentFadeVal;
      greenValue = currentFadeVal;
      blueValue = 0;

      rgbCalc();
      break;
    //========== END FADE YELLOW ==========

    case 4://FADE CHARTRUESE
      redValue = currentFadeVal * 0.498; // 128/255 = ~0.498039
      greenValue = currentFadeVal;
      blueValue = 0;

      rgbCalc();

      if (greenValue > 0 && redValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        greenValue = 0;
      }
      break;
    //========== END FADE CHARTRUESE ==========

    case 5://FADE GREEN
      redValue = 0;
      greenValue = currentFadeVal;
      blueValue = 0;

      rgbCalc();
      break;
    //========== END FADE GREEN ==========

    case 6://FADE SPRING GREEN
      redValue = 0;
      greenValue = currentFadeVal;
      blueValue = currentFadeVal * 0.498; // 128/255 = ~0.498039

      rgbCalc();

      if (greenValue > 0 && blueValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        greenValue = 0;
      }
      break;
    //========== END FADE SPRING GREEN ==========

    case 7://FADE CYAN
      redValue = 0;
      greenValue = currentFadeVal;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE CYAN ==========

    case 8://FADE AZURE
      redValue = 0;
      greenValue = currentFadeVal * 0.498; // 128/255 = ~0.498039
      blueValue = currentFadeVal;

      rgbCalc();
      if (blueValue > 0 && greenValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        blueValue = 0;
      }
      break;
    //========== END FADE AZURE ==========

    case 9://FADE BLUE
      redValue = 0;
      greenValue = 0;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE BLUE ==========

    case 10://FADE VIOLET
      redValue = currentFadeVal * 0.498;
      greenValue = 0;
      blueValue = currentFadeVal;

      rgbCalc();

      if (blueValue > 0 && redValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        blueValue = 0;
      }
      break;
    //========== END FADE VIOLET ==========

    case 11://FADE MAGENTA
      redValue = currentFadeVal;
      greenValue = 0;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE MAGENTA ==========

    case 12://FADE ROSE
      redValue = currentFadeVal;
      greenValue = 0;
      blueValue = currentFadeVal * 0.498;

      rgbCalc();

      if (redValue > 0 && blueValue == 0) {
        //tertiary component is 1/2, so when it calculates to decimal with fade value,
        //it will be basically be off, make sure to turn off other color so that
        //it does not just show the other color
        redValue = 0;
      }
      break;
    //========== END FADE ROSE ==========

    case 13://FADE WHITE
      redValue = currentFadeVal;
      greenValue = currentFadeVal;
      blueValue = currentFadeVal;

      rgbCalc();
      break;
    //========== END FADE WHITE ==========

    default:
      allOFF();
      rgbCalc();
      break;
  }

  rgbShow();
  delay(fadeDelay);


  if (increasing == true) {
    currentFadeVal += fadeVal;
  }
  else { //decreasing
    currentFadeVal -= fadeVal;
  }

  if (currentFadeVal > fadeMAX) {
    increasing = false;
    prevFadeVal -= fadeVal;//undo addition

    currentFadeVal = prevFadeVal;

  }
  else if (currentFadeVal < fadeMIN) {
    increasing = true;
    prevFadeVal += fadeVal;//unto subtraction

    currentFadeVal = prevFadeVal;
  }

  prevFadeVal = currentFadeVal;
}//-------------------- END patternFade() FUNCTION --------------------




//-------------------- patternBlink() FUNCTION --------------------
void patternBlink() {

  switch (colorMode) {
    case 1://RED
      redValue = blinkVal;
      greenValue = 0;
      blueValue = 0;

      rgbCalc();
      break;

    case 2://ORANGE
      redValue = blinkVal;
      greenValue = blinkVal * 0.498;
      blueValue = 0;

      rgbCalc();
      break;

    case 3://YELLOW
      redValue = blinkVal;
      greenValue = blinkVal;
      blueValue = 0;

      rgbCalc();
      break;

    case 4://CHARTREUSE
      redValue = blinkVal * 0.498;
      greenValue = blinkVal;
      blueValue = 0;

      rgbCalc();
      break;

    case 5://GREEN
      redValue = 0;
      greenValue = blinkVal;
      blueValue = 0;

      rgbCalc();
      break;

    case 6://SRING GREEN
      redValue = 0;
      greenValue = blinkVal;
      blueValue = blinkVal * 0.498;

      rgbCalc();
      break;

    case 7://CYAN
      redValue = 0;
      greenValue = blinkVal;
      blueValue = blinkVal;

      rgbCalc();
      break;

    case 8://AZURE
      redValue = 0;
      greenValue = blinkVal * 0.498;
      blueValue = blinkVal;

      rgbCalc();
      break;

    case 9://BLUE
      redValue = 0;
      greenValue = 0;
      blueValue = blinkVal;

      rgbCalc();
      break;

    case 10://VIOLET
      redValue = blinkVal * 0.498;
      greenValue = 0;
      blueValue = blinkVal;

      rgbCalc();
      break;

    case 11://MAGENTA
      redValue = blinkVal;
      greenValue = 0;
      blueValue = blinkVal;

      rgbCalc();
      break;

    case 12://ROSE
      redValue = blinkVal;
      greenValue = 0;
      blueValue = blinkVal * 0.498;

      rgbCalc();
      break;
    case 13://WHITE
      redValue = blinkVal;
      greenValue = blinkVal;
      blueValue = blinkVal;

      rgbCalc();
      break;

    default:
      allOFF();
      rgbCalc();
      break;
  }

  rgbShow();

  if (counter == blinkRate) {
    if (blinkON == true) {
      blinkVal = 0;
      blinkON = false;
    }
    else { //it was on, so turn off
      blinkVal = 255;
      blinkON = true;
    }
    counter = 0;
  }
  else {
    counter = counter + 1;
  }
}//-------------------- patternBlink() FUNCTION //--------------------



//-------------------- patternRainbow() FUNCTION --------------------
void patternRainbow() {
  if (rgbType == commonCathode) {
    if (rainbowTransitionVal == 0) {
      //RED
      rainbowRedVal += 5;
      if (rainbowRedVal >= 255) {
        rainbowTransitionVal = 1;
      }
    }
    else if (rainbowTransitionVal == 1) {
      //RED TO ORANGE TO YELLOW
      rainbowGreenVal += 5;

      if (rainbowGreenVal >= 255) {
        rainbowTransitionVal = 2;
      }
    }
    else if (rainbowTransitionVal == 2) {
      //YELLOW to CHARTREUSE to GREEN
      rainbowRedVal -= 5;

      if (rainbowRedVal <= 0) {
        rainbowTransitionVal = 3;
      }
    }
    else if (rainbowTransitionVal == 3) {
      //GREEN to SPRING GREEN to CYAN
      rainbowBlueVal += 5;

      if (rainbowBlueVal >= 255) {
        rainbowTransitionVal = 4;
      }
    }
    else if (rainbowTransitionVal == 4) {
      //CYAN to AZURE to BLUE
      rainbowGreenVal -= 5;

      if (rainbowGreenVal <= 0) {
        rainbowTransitionVal = 5;
      }
    }
    else if (rainbowTransitionVal == 5) {
      //BLUE to VIOLET to MAGENTA
      rainbowRedVal += 5;

      if (rainbowRedVal >= 255) {
        rainbowTransitionVal = 6;
      }
    }
    else if (rainbowTransitionVal == 6) {
      //MAGENTA to ROSE to RED
      rainbowBlueVal -= 5;

      if (rainbowBlueVal <= 0) {
        rainbowTransitionVal = 1;
      }
    }
  }//end check for commonCathode



  else {
    if (rainbowTransitionVal == 0) {
      //RED
      rainbowRedVal -= 5;
      if (rainbowRedVal <= 0) {
        rainbowTransitionVal = 1;
      }
    }
    else if (rainbowTransitionVal == 1) {
      //RED TO ORANGE TO YELLOW
      rainbowGreenVal -= 5;

      if (rainbowGreenVal <= 0) {
        rainbowTransitionVal = 2;
      }
    }
    else if (rainbowTransitionVal == 2) {
      //YELLOW to CHARTREUSE to GREEN
      rainbowRedVal += 5;

      if (rainbowRedVal >= 255) {
        rainbowTransitionVal = 3;
      }
    }
    else if (rainbowTransitionVal == 3) {
      //GREEN to SPRING GREEN to CYAN
      rainbowBlueVal -= 5;

      if (rainbowBlueVal <= 0) {
        rainbowTransitionVal = 4;
      }
    }
    else if (rainbowTransitionVal == 4) {
      //CYAN to AZURE to BLUE
      rainbowGreenVal += 5;

      if (rainbowGreenVal >= 255) {
        rainbowTransitionVal = 5;
      }
    }
    else if (rainbowTransitionVal == 5) {
      //BLUE to VIOLET to MAGENTA
      rainbowRedVal -= 5;

      if (rainbowRedVal <= 0) {
        rainbowTransitionVal = 6;
      }
    }
    else if (rainbowTransitionVal == 6) {
      //MAGENTA to ROSE to RED
      rainbowBlueVal += 5;


      if (rainbowBlueVal >= 255) {
        rainbowTransitionVal = 1;
      }
    }
  }//end check for commonAnode

  redValue = int(rainbowRedVal * brightnessLED);
  greenValue = int(rainbowGreenVal * brightnessLED);
  blueValue = int(rainbowBlueVal * brightnessLED);

  // Note: the rainbow function calculates the function here so
  // we do not need to call the `rgbCalc()` function

  rgbShow();

  delay(rainbowDelay);
}//-------------------- END patternRainbow() FUNCTION --------------------


// ==================== END CUSTOM FUNCTIONS DEFINED ====================

Once the code has been uploaded, the demo will cycle through the defined colors. Pressing the buttons will cycle through the color or pattern. Opening the Arduino serial monitor at 9600 will show the current color mode or pattern after every button press.

Full Demo with Rainbow

Modifying RGB LED Strip

Depending on your project, you may not need to use all 1M or 5M of the LED strip. You can cut off the excess and use it for other projects. Or you may need to separate the strip and extend the wires to illuminate other parts of your project. You may even need to inject power at a certain length. Let's go over how to cut, rewire, clean, and reseal a sealed LED strip.

First, cut the LED strip at the center of the exposed pads using a diagonal cutter. The dot and dashed line in the image below is where you will need to perform the cut. Make sure to remove part of the silicone tube to access the LED strip's pads if you are using the sealed version.

Cut between the LED Strip's Pads

Cut half of the premium jumper wires and strip the insulation. Then solder the wires to each of the LED strip's pads.

Solder Wires to LED Strip

For a secure connection, you can braid the wires together to manage the connections. To braid your wires, twist a pair of wires in a counterclockwise pattern between your index finger and thumb using both hands. We'll be using the green and red wires that were soldered on.

Wire Management Braiding Counterclockwise 1

Then twist the other pair of wires in a counterclockwise pattern.

Wire Management Braiding Counterclockwise 2

Twist the pairs of wires in a clockwise pattern.

Wire Management Braiding Clockwise

Clean Solder Joints

If you were using water soluble flux, clean the solder joints with deionized water and a toothbrush. Dry the LED strips thoroughly using compressed air. Luckily, SparkFun has a PCB cleaning room. As an alternative, you could use water from the sink and towels. You can also use isopropyl alcohol.

Clean Solder Joints

Test LED Strips

Once dry, test the LED strips to ensure the colors are correct and the wires are connected to its respective pads. You can use a benchtop power supply set to output about 12V, a 12V wall adapter, or 9V battery to verify the connection. The image below shows all the channels turned on. Make sure to test each channel individually.

Testing LED Strip with Wiring

Secure w/ Hot Glue or Heat Shrink

Add hot glue to the terminals to secure the wires further. You can also use some heat shrink with hot glue as long as it does not cover the LED. The image below shows the wires being secured with hot glue. The LED strip was used with a silicone tube so additional hot glue was added to seal the exposed strip.

Hot Glue Terminals

Large Installation

For large installation projects, there may be voltage drops depending on the:

  • amount of LEDs connected
  • length of LED strip used
  • how bright the LEDs are set
  • animation

You may notice LEDs not able to fully turn on after a certain length due to the voltage drop. This is due to the increased resistance as you move further away from the power supply. You may notice that not all the colors are turned on or the strip becomes dim. You can also check the voltage after each meter using a multimeter to see if there are any voltage drops if you are not able to visually see the voltage drops. If you see voltage drops and the LED strip not properly turning on, you will need to inject power with the power supply between each LED strip's Vcc and GND after about 1, 2, or 5 meters.

Long lengths of LED strips can also pull a lot of current when fully turned on. If you are using a high amperage power supply with long lengths, make sure that there is enough air flow, a heat sink to dissipate the heat properly, and the wires can support the amperage. You may want to lower the brightness setting.

Resources and Going Further

Now that you've successfully got your non addressable LED strip up and running, it's time to incorporate it into your own project! For more information, check out the resources below:

Need some inspiration for your next project? Check out some of these related tutorials:

Prototype Wearable LED Dance Harness

A project tutorial to add an extra effect for dancers performing a choreographed piece. The harness can be added quickly under a costume.

Motion Controlled Wearable LED Dance Harness

Control LEDs based on your movement using an accelerometer! Make your LEDs breathe by fading in and out when laying on the floor, turn off the LEDs when moving to your side, or make the LEDs blink in a headstand!

Interactive 3D Printed LED Diamond Prop

In this tutorial, we will learn about how to create an interactive theatrical prop for a performance by 3D printing a translucent diamond prop using a non-addressable RGB LED strip and AT42QT1011 capacitive touch sensing.

Light Up Your 3D Printer's Bed

Having issues viewing your print in a dark lit room? In this tutorial, we will be using LED strips to light up a print bed's area on a LulzBot 3D printer!

Or try adding a button, potentiometer, or sensor to control the LEDs. Here are a few examples to control an individual RGB LED with different languages.

SparkFun Inventor's Kit for Photon Experiment Guide

Dive into the world of the Internet of Things with the SparkFun Inventor's Kit for Photon.

SparkFun Inventor's Kit for micro:bit Experiment Guide

This guide contains all the information you will need to explore the twelve circuits of the SparkFun Inventors Kit for micro:bit.

SparkFun Inventor's Kit Experiment Guide - v4.1

The SparkFun Inventor's Kit (SIK) Experiment Guide contains all of the information needed to build all five projects, encompassing 16 circuits, in the latest version of the kit, v4.1.

Or check out some of these blog posts for ideas:

LEDs

 


learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

micro:bot Kit Experiment Guide

$
0
0

micro:bot Kit Experiment Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t644

Introducing the micro:bot Kit

The micro:bit is a great platform for learning how to build and program robots! Combining the micro:bit with the SparkFun moto:bit - micro:bit Carrier Board (Qwiic) creates a flexible, low-cost robotics platform for anyone from students getting started with the micro:bit to the engineer looking to quickly prototype or build a proof of concept.

The micro:bot kit v2.0 is the extension of that idea: build simple robots quickly that leverage the capabilities of the micro:bit while implementing peripheral sensors and motor functions with simple programming in the Microsoft MakeCode environment as a gateway into robotics.

What's Included in the Kit?

SparkFun micro:bot kit - v2.0

SparkFun micro:bot kit - v2.0

KIT-16275
$59.95

The kit includes the following parts:

Note: The kit does not include the following and they will need to be purchased these separately:


USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13
micro:bit Board

micro:bit Board

DEV-14208
$14.95
7
Panasonic Alkaline Battery - AA

Panasonic Alkaline Battery - AA

PRT-15201
$0.50

How to Use This Guide?

This guide is designed to get you started with the moto:bit board and the SparkFun micro:bot kit in a straight forward and simple way. We demonstrate each component's functionality and the corresponding code to make it work.

While you explore this guide, we urge you to take your time and tinker with the sensors, code, and the ideas shared to build something tailored to your application and creativity. Our goal is to get you enough information and know-how to make you dangerous and then release you into the wild to do whatever you do with your robot.

Be sure to share your projects with us over Twitter or Facebook! We are excited to see you Start Something!

Suggested Reading

Before continuing with this guide, we recommend you be somewhat familiar with the concepts in the following tutorials:

Accelerometer Basics

A quick introduction to accelerometers, how they work, and why they're used.

Hobby Servo Tutorial

Servos are motors that allow you to accurately control the rotation of the output shaft, opening up all kinds of possibilities for robotics and other projects.

Getting Started with the micro:bit

The BBC micro:bit is a compact, powerful programming tool that requires no software installation. Read on to learn how to use it YOUR way!

Open Source

All of our experiments and guides are licensed under the Creative Commons Attribution Share-Alike 4.0 Unported License. Feel free to remix and reuse our work. But please, share the love and give us attribution for our hard work!

To view a copy of this license visit this link, or write: Creative Commons, 171 Second Street, Suite 300, San Francisco, CA 94105, USA.

About the moto:bit Board

The moto:bit is a carrier board for the micro:bit. Similar to an Arudino shield, it is designed to add functionality to the micro:bit without the hassle of a number of other boards, soldering, and all of those jumper wires.

SparkFun moto:bit - micro:bit Carrier Board (Qwiic)

SparkFun moto:bit - micro:bit Carrier Board (Qwiic)

DEV-15713
$15.95

In this case, the moto:bit takes a micro:bit and turns it into a full blown robotics platform. Wondering what you can do with it? Well here are a few things...

  • Control motors through an onboard H-Bridge
  • Read digital sensors such as line and bump sensors
  • Read analog sensors like light sensors, temperature sensors, etc
  • Control servo motors
  • I2C port for extending functionality

That is a lot of options in terms of bells and whistles! Let's take a closer look at the board and go over each section.

Edge Connector

The moto:bit connects to the micro:bit via an edge pin connector. This makes it handy to swap out micro:bits for programming, and it creates reliable connections to all of the different pins on the micro:bit.

Edge Connector

H-Bridge and Motor Pins

An H-Bridge is a chip that is the heart of a robot when it comes to driving motors and more specifically driving motors in both directions. Depending on the electrical state of specific pins on the H-Bridge, a motor drives forwards, backwards, and at different speeds. The good thing about this board is that if you are using Microsoft MakeCode, you actually don't really need to know a whole lot about the H-Bridge itself.

Hbridge

To connect the hobby motors that are included in the kit, you can insert them into the 2-pin female connectors just above the motor pins. The connectors are highlighted in the image below. Keep in mind that direction the hobby motors will move depends on the code to control the H-bridge motor driver, how the motors are attached to a chassis, and the way the motors are wired to the input pins.

MotorInputPins

Motor Control Switch

The moto:bit has a switch that controls the power supply to the motors. That way you can have the robot powered while working on it or programming it and know that the robot is not going to start moving and drive off of the table. Believe us... that happens all the time!

Motor Control Switch

Input and Output Pins

The male pins on the moto:bit are for hooking up various inputs and outputs on your robot without using a breadboard to build elaborate circuits.

I/O Pins

We have a number of sensors and actuators that are built in this pin formation and will work with this board.

SparkFun Line Follower Array

SparkFun Line Follower Array

SEN-13582
$31.95
7
Wheel Encoder Kit

Wheel Encoder Kit

ROB-12629
$12.95
5
SparkFun RedBot Sensor - Mechanical Bumper

SparkFun RedBot Sensor - Mechanical Bumper

SEN-11999
$5.95
2
SparkFun RedBot Buzzer

SparkFun RedBot Buzzer

ROB-12567
$4.95
SparkFun RedBot Sensor - Accelerometer

SparkFun RedBot Sensor - Accelerometer

SEN-12589
$6.95

Servo Ports

No robot is complete without an arm, a swiveling "head," or some other type of movement other than wheels. Notice that a couple of the pin groups are designated as "Servo". You can connect servo motors directly to these pins and use them right out of the box with Microsoft MakeCode.

Male Servo Pins

I2C Port

We broke out the I2C port of the micro:bit to an external port so that you can add any I2C capable sensor or actuator you can think of. It is standard pin arrangement to many of our I2C sensor breakout boards.

I<sup>2</sup>c

Qwiic Connector

With the updated moto:bit board, we've added a Qwiic connector so that our Qwiic line of products can be incorporated more easily.

Qwiic connector

Power

A standard barrel jack connector is used for easily powering your robot. We find that a 4xAA battery pack works great, but it will accept between 3V-11V at the barrel jack. That's a whole lot of robo-power!

Barrel Jack

Assembling Your Robot

This section will cover how to assemble your robot chassis.Assembly time: 30-60 minutes

The robot chassis requires the following pieces to build. You'll find most of them in your SparkFun micro:bot kit.

Note: Several of the parts need to be snapped out of the main chassis panels.

micro:bot chassis parts

Click on the image for a closer look.
LetterPartQty
ABottom Chassis Plate1
BTop Chassis Plate1
CFront Motor Mount2
DRear Motor Mount2
ESide Strut4
FEncoder Mount (Not Used in this Guide)2
Gmoto:bit Mount2
HBattery Pack Clip1
ILine Follower Mount1
JLine Follower Mount Plate1
KJumper Wire — 3-pin, 6"3
LWheels2
MNub Caster1
NDC Motors2
OLine Follower Boards3
P4xAA Battery Holder1
Q4xAA Batteries (Not Included)3

No Tools Necessary

The robot chassis does not require any additional tools.

WARNING: Do not attempt to remove chassis parts by squeezing them with pliers. If you try to muscle it too much you risk breaking them and compromising the structure of your robot. Handle with care. ;)

No Pliers

A Note About Orientation

When we talk about the "front,""left,""right," and "back" of the Shadow Chassis, we are referring to specific sides of the robot when viewed from above.

micro:bot Orientation

Notice that we consider the SparkFun moto:bit to be on the "back" of the bot and the Bumper Whiskers and Line Follower Boards to be in the "front."

Assembly

Installing Motors

Let's begin by installing the motors that will control the wheels. Locate the following:

Installing Motors Parts

Attach Rear Motor Mounts

Hold the wires near the middle of the Motor (N), and carefully slide a Rear Motor Mount (D) in from the side and over the two motor wires. Be careful not to snag the wires, the cable tie, or the clear plastic strap.

Attaching Rear Motor Mounts

Holding the motor wires, gently twist the Rear Motor Mount counter clockwise so that it snaps in place on the motor and the wires are centered in the gap of the motor mount. Again, be sure not to snag the wires under the motor mount.

Adjusting Rear Motor Mount

Repeat the process for the second motor, ensuring that it is a mirror image of the first.

Both Rear Motor Mounts

Attach the Front Motor Mounts

Slide a Front Motor Mount (C) onto the protruding eyelet on the front of a Motor (N). Ensure the rounded sides of the motor mounts are facing the same way.

Attaching Front Motor Mounts

Repeat the process for the second motor.

Both Front Motor Mounts

Attach the Motor Assemblies to the Chassis

Snap one of the motor assemblies into the left two horizontal slots of the Bottom Chassis Plate (A). Make sure that the rounded edges of the motor mounts and the wires are facing toward the center of the chassis. Repeat for the opposite motor.

Attaching Motor Assemblies to Chassis

Attach the Wheels

Slide one Wheel (L) onto the plastic shaft of a Motor (N). Look at the motor shaft. Notice it has two flat edges. Make sure to line up the flat edges of the motor shaft with the flat edges of the wheel.

Attaching Wheel

Repeat with the other wheel.

Two Wheels Ready to Roll

Installing the Line Sensors

This section will cover the Line Following Sensors array assembly. You'll first build the Line Following array and then attach it to the chassis. Locate the following:

Line Sensor Parts

Construct the Line Follower Assembly

Attach the three Line Follower Boards (O) to the Line Follower Mount (I) such that the rectangular pegs in the Line Follower Mount poke through the mounting holes in the Line Follower Boards. Make sure the sensors are facing away/down from the clip of the mount.

Line Follower Boards on Mount

Place the Line Follower Mount Plate (J) on top of the Line Follower Mount (I) so that the center clip of the mount is poking through the center slot of the plate.

Mount Plate on Top of Line Follower Boards

Attach the Cables

You will need to connect a 3-Wire Jumper Cable (K) to each of the Line Follower Boards (O). Note the color of the wire attached to each pin.

Line Follower Connections:

Jumper Wire ColorRedBot Sensor - Line Follower
RedGND
OrangeVCC
YellowOUT

Attach all 3 cables to the 3 Line Follower Boards. Notice that the yellow wire should be on the right (out) and the red wire should be on the left (ground).

Attach Cables to Line Follower Boards

Attach the Line Follower Assembly to the Chassis

Locate the wide, rectangular slot near the front of the chassis and snap the line follower assembly in from the bottom side of the chassis. Route the cables through the large hole in the bottom plate.

Attach Line Follower Assembly to Chassis

The bottom of your chassis should look like the following image allowing the line sensors to be facing down.

Line Followers Mounted Bottom View

Final Assembly

With the motors and a few sensors attached, we can assemble the main body of the robot. Locate the following:

Side Strut and Nub Caster Assembly

You will also need the Top Chassis Plate and Bottom Chassis Plate assemblies, which have any additional parts and sensors you attached in previous steps.

Attach the Nub Caster

Snap the Nub Caster (M) into the slot on the back of the Bottom Chassis Plate assembly. Make sure the Nub Caster is on the side opposite the motors (the bottom side).

Attach Nub Caster

Add the Side Struts

Snap the four Side Struts (E) into the diagonal slots on the four corners of the Bottom Chassis Plate assembly.

Attach Side Struts

Pull the cables through the cutouts on the chassis.

Cables through Cutouts

Route the Cables

Position the Top Chassis Plate over the Bottom Chassis Plate -- but do not snap the two plates together yet. Make sure that the front sides of each plate line up.

Route the wires and cables through the left and right oval slots in the Top Chassis Plate assembly as shown. For the center line follower sensor, route this cable through the left oval slot.

NOTE: It might be a good idea to use some pieces of masking tape to mark which cables go to which component. It's not necessary, but it might help keep things organized.

Cable Routing:

Cable ConnectionOval Side
Left Line FollowerLeft
Center Line FollowerLeft
Right Line FollowerRight
Left Motor Wires (red and black)Left
Right Motor Wires (red and black)Right

Pull Wires Through and Prepare Top Plate

Attach Top Chassis Plate Assembly

Line up the Top Chassis Plate on top of all the struts, and carefully snap the Top Chassis Plate assembly onto the side struts and motor mounts. Press gently above each side strut individually until they each snap into place. If you have the Bumpers installed, make sure the boards are between the top and bottom plates.

Snap Top Plate On

If you need to remove the plate to change anything, gently pull upward on each side strut individually. Do not attempt to use pliers or hand tools, or you may end up snapping the plastic clip.

Attaching the moto:bit

In this section, you will add brains of the robot: the micro:bit and SparkFun moto:bit. Locate the following:

Attaching moto:bit

You will also need the full chassis assembly, which contains any additional parts you attached in previous steps.

Attach the moto:bit Mounts

Snap the two moto:bit mounts (G) into the vertical slots in the back of the top chassis plate near the large rectangular opening.

Add Controller Board Mounts

Both of these mounts will enable your moto:bit board to be mounted to the chassis.

Both moto:bit Mounts

Add the moto:bit

Before you snap in the moto:bit board, insert your micro:bit into the moto:bit as shown here.

Inserting micro:bit into moto:bit

The moto:bit snaps into the lowest of the notches on the moto:bit Mounts (G). Make sure the power jack is facing the left side of the robot. Push gently and evenly until it snaps into place.

Snap In Main Board
Note: The other slots in the moto:bit mounts can be used to hold the Arduino Uno or the Sparkfun RedBoard.

Once snapped, your setup should look like the image below without the wires connected to the moto:bit board

Loose Wires

Connecting the Cables

It is time to connect the jumper wires; it is really important that these connections are right.

All Wire Connections Made

Follow along with the tables and annotated image with the cables connected for reference. Trace each cable poking through the top chassis plate to make sure you know what it is connected to.

micro:bot Annotated
Please Note: When you have the micro:bot upright and the front of the chassis facing away from you, "left" sensors/motors will be on the left side and "right" sensors/motors will be on the right side. Also, the motor wires are intentionally switched for the right motor -- see notes below.

Line Followers

Below is a table for each connection between moto:bit and analog line follower. Start with the left line follower.

Line Follower Connection

Left Line Follower:

SparkFun moto:bit PinsJumper WiresLeft Line Follower Board
P03-Wire Jumper Cable - YellowOUT
3.3V3-Wire Jumper Cable - OrangeVCC
GND3-Wire Jumper Cable - RedGND

Center Line Follower:

SparkFun moto:bit PinsJumper WiresCenter Line Follower Board
P13-Wire Jumper Cable - YellowOUT
3.3V3-Wire Jumper Cable - OrangeVCC
GND3-Wire Jumper Cable - RedGND

Right Line Follower:

SparkFun moto:bit PinsJumper WiresRight Line Follower Board
P23-Wire Jumper Cable - YellowOUT
3.3V3-Wire Jumper Cable - OrangeVCC
GND3-Wire Jumper Cable - RedGND

Once connected, the wires should look similar to the image below.

micro:bot Annotated

Motors

Choose a pair of motor wires to begin wiring up to the moto:bit. The way the motors are wired up to the moto:bit will affect how the micro:bot drives. Make sure to follow the color of the wire with the silkscreen on the board.

plugging motor cables in correctly

Below is a table for each connection between moto:bit and motor.

Left Motor:

SparkFun moto:bit PinsLeft Motor Jumper Wires
LEFT MOTOR - REDSoldered on Motor Jumper Wire - RED
LEFT MOTOR - BLACKSoldered on Motor Jumper Wire - BLACK

Right Motor:

moto:bit PinsRight Motor Jumper Wires
RIGHT MOTOR - REDSoldered on Motor Jumper Wire - BLACK
RIGHT MOTOR - BLACKSoldered on Motor Jumper Wire - RED

Once all wires are connected it should look like the following image.

micro:bot Annotated

Batteries

The last step is to provide a power source for the micro:bot. You will need to provide your own AA batteries (Q). Locate the following:

Batteries and Clip Parts

Insert Batteries

Insert the AA batteries into the Battery Holder (P). Makes sure the batteries are facing the correct direction, as per the markings inside of the Battery Holder.

Insert AA Batteries into Pack

Attach Battery Pack

Insert the Battery Holder (P) with batteries into the back cavity of the chassis. Position the Battery Holder so that the barrel jack cable comes out on the left side of the robot.

Insert Battery Pack

Insert the Battery Pack Clip (H) on top of the battery pack.

Insert Battery Pack Clip

Twist and position the clip so that it rests on top of the battery pack.

Attach Battery Pack Clip

Push the clip down into the vertical slots in the Bottom Chassis Plate so it snaps in place.

Snapping Battery Clip into Chassis

Route the barrel jack cable out of the left side of the chassis and up to the moto:bit.

Route Barrel Jack Cable

Plug the barrel jack cable into the barrel connector on the side of the moto:bit carrier board.

Plug into Barrel Connector

Changing the Batteries

If you find that you need to replace the batteries in the micro:bot, the process is simple. Unplug the battery pack from the moto:bit.

Unplug the Batteries

Turn the micro:bot over and push on the Battery Holder through the hole in the Bottom Chassis Plate. This will cause the Battery Pack Clip to unsnap from the Bottom Chassis Plate.

Push on battery pack to unsnap it

Slide the Battery Pack and Clip out from the back of the micro:bot.

Remove Battery Clip

Remove Battery Pack

Change the batteries, and follow the steps in Attach Battery Pack section above to put the Battery Pack back in the micro:bot.

Installing the moto:bit Extension in MakeCode

To make the most out of the moto:bit with the least amount of coding, use the Microsoft MakeCode extension we wrote for the moto:bit board.

Extension

If you have used Arduino before, you probably know about a thing called a library; which is a collection of code that extends the functionality of the core programming language. MakeCode extension work the same way.

There are some amazing differences between Arduino libraries and MakeCode extensions. One of them is that MakeCode extensions include JavaScript functions, which you can use when programming in text, as well as all of the blocks you need to program using the block method. This makes learning and using new extensions straightforward and shortens the time to awesome when setting out to build the project of your dreams.

Heads up! Previously, these libraries were referred to as MakeCode packages. They are now referred to as MakeCode extensions.

Installing a MakeCode Extensions

To install or add a new extension to your MakeCode toolbox (the list of different block groups), click on "Advanced" and then on "Add Extensions." This should be the last item on the list.

MakeCode Extensions

From here you can search for "SparkFun" or "SparkFun moto-bit," and it should show up as a public extension in the list. Go ahead and click on it.

SparkFun Extensions

This will add all of the blocks to your toolbox. In general, this is a bit tricky as, depending on how the extension was written, it may either have its own toolbox or just add blocks to the existing ones. Take a look at your toolbox; for the moto:bit you should see...

Closeup Moto:bit

Great! You have now installed the moto:bit extension and are ready to use the board as well as the components that come in the micro:bot kit. As a side note, for every new MakeCode project that you make, you will have to load extensions over again. Not a big deal, but noteworthy! Now, let's put your extension to good use and get your robot moving!!!

Experiment 1: Driving and Turning

Introduction

The "Hello World" for the robotics world is getting your robot moving! Driving forwards, backwards, and steering is goal #1 when you are dealing with wheeled / moving robots. This experiment will cover just that: getting your robot moving using our moto:bit software package for Microsoft MakeCode. Once you get through this first experiment you will be golden!

Parts Needed

You will need the following parts:

  • 1x micro:bit Board (Not Included with Kit)
  • 1x Micro-b USB Cable (Not Included with Kit)
  • 1x moto:bit Carrier Board
  • 2x Wheels
  • 1x Assembled Shadow Chassis
  • 2x Hobby Gear Motors
  • 1x 4xAA Battery Holder
  • 4x AA Batteries (Not Included with Kit)

Didn't get the kit? Have no fear! Here are the parts you will need to complete this experiment. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Hobby Gearmotor - 140 RPM (Pair)

Hobby Gearmotor - 140 RPM (Pair)

ROB-13302
$4.95$4.11
2
USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13
SparkFun moto:bit

SparkFun moto:bit

DEV-14213
$15.95
3
micro:bit Board

micro:bit Board

DEV-14208
$14.95
7
Wheel - 65mm (Rubber Tire, Pair)

Wheel - 65mm (Rubber Tire, Pair)

ROB-13259
$2.95
2
Battery Holder - 4xAA to Barrel Jack Connector

Battery Holder - 4xAA to Barrel Jack Connector

PRT-09835
$2.49
Shadow Chassis

Shadow Chassis

ROB-13301
$12.95
7
Panasonic Alkaline Battery - AA

Panasonic Alkaline Battery - AA

PRT-15201
$0.50

Suggested Reading

Before continuing on with this experiment, we recommend you be familiar with the concepts in the following tutorial:

Motors and Selecting the Right One

Learn all about different kinds of motors and how they operate.

Getting Started with the micro:bit

The BBC micro:bit is a compact, powerful programming tool that requires no software installation. Read on to learn how to use it YOUR way!

Introduction to the Motors and Controlling Them

Motors take electrical energy and turn it into mechanical energy through putting a current through a coil of wire that creates a magnetic field. This then interacts with magnets in the motor, causing a push / pull effect. If you do that in a proper spacing and timing, then you can spin a shaft.

motor pair

The hobby motors used with the micro:bot operate in a similar was as mentioned above, but they have a bit of help; a gear box. The ratio of the gearbox is 120:1, which means that for every 120 rotations of the motor shaft you get one rotation at the end of the gear box. This is a good thing because it gives our robot enough strength (torque) to turn wheels. In this case, our gearbox also changes the axis of the shaft so that we can easily use them to drive our robot.

Hardware Hookup

You should have already hooked up the motors during the assembly process of putting the robot together. But, we have a couple of things that we would like you to double check!

Initial Motor Assembly

First of all, make sure that your red and black wires are plugged into your moto:bit and that they are in the correct ports. If you look closely the right and left ports are opposite from one another.

Wires Plugged In

Why is that? Well, in robotics the right and left motors are mirrors of one another, which means they go in opposite directions from one another to go forward, hence the ports being backwards. If you plug them in as the same direction and tell both motors to spin in the sam direction, your robot would spin in a circle rather than drive forward! Weird, but true.

Running Your Script

We are going to use Microsoft MakeCode to program the micro:bit. Please open a browser window and navigate to makecode.microbit.org. This should open the MakeCode environment that you used to install the moto:bit package in.

Did you install the moto:bit package? To add the moto:bit package as instructed in the Installing the moto:bit Package in MakeCode section of this tutorial.

makecode screen shot
Note: If this is your first time programming a micro:bit please be sure to see our Getting Started with the micro:bit tutorial on how to get your MakeCode program onto your micro:bit.

Now, you can either download the following example script below and drag and drop it onto your micro:bit, or use it as an example and build it from scratch in MakeCode.

Code to Note

Let's take a look at the code and what to expect.

Experiment 1 Code to Drive Motors

On Start

The code starts by setting each motor channel in the on start code block. Depending on how the motors are wired to the moto:bit, your micro:bot may drive in the opposite direction than what you would expect. The set &lowbar;&lowbar;&lowbar;&lowbar; motor invert to &lowbar;&lowbar;&lowbar;&lowbar; provides the option to switch the motor wires in code without physically rewiring the motors to the moto:bit. Set the left or right motor that you would like to invert. If you want the motor to drive in the opposite direction relative to your setup, select either true or false.

On Button Pressed

The on button &lowbar;&lowbar; pressed code block is an event function. Any code blocks that are placed inside of the block will only execute when that event happens. In this block, when the A button is pressed on your micro:bit your robot will start moving. When it gets to the end of the program it will stop again until you press the A button again.

Turn Motors

The turn motors &lowbar;&lowbar; block gives you the ability to turn the motors ON or OFF in software. They are naturally OFF, so anytime you want to drive motors, you need to set them to ON. A good practice is to turn them OFF when your robot completes its task or should not be moving for long periods of time, this saves batteries and wasted power consumption.

Move Motors At

The move &lowbar;&lowbar;&lowbar;&lowbar; motor &lowbar;&lowbar;&lowbar;&lowbar;&lowbar;&lowbar;&lowbar; at &lowbar; % block is the basis of the moto:bit software package. You use this block by selecting the values in the drop down menu:

  • which motor you want to control (RIGHT or LEFT)
  • its direction (FORWARD or REVERSE)
  • the throttle / power percentage you would like the motor to spin at (0-100%)

For your bot to move forward you need to have both motors drive in the same direction. To turn, or pivot, you set the motor directions in an opposite configuration.

Pause

The pause (ms) &lowbar;&lowbar;&lowbar;&lowbar; block is like a code stop sign. It tells the micro:bit to wait for a given amount of time in milliseconds. While it is waiting, whatever you told before the pause will keep happening. So, if you want your robot to drive forward for 1 second, you set the robot's motors to drive forward and then pause for 1000 milliseconds and then have the motors do something else, like stop.

What You Should See

Once your script uploads to your micro:bit, make sure the motors switch is changed from "STOP MOTORS" to "RUN MOTORS." Press the A button on your micro:bit and your robot will drive forward for 1 second, pivot, and the drive forward for another second before stopping. Pressing the button again will have the robot repeat the sequence.

Pressing Button A

Here is a demo of the micro:bot driving.

But wait? The micro:bot appears to be driving in the reverse relative to the front of the robot even though we told the robot to move forward in the code?!? There are a few reasons why this may be happening. Depending on how the motors were manufactured, they wires may be switched. Or the wires were connected incorrectly.

One method is to use the set &lowbar;&lowbar;&lowbar;&lowbar; motor invert to &lowbar;&lowbar;&lowbar;&lowbar; block for each motor without rewiring the motors. Simply invert the motors setting each to true. The following experiments will invert the motor wire connection relative to how we assembled the robot earlier.

Motors Inverted

The other method is to physically rewire the motor wires. Simply flip the wire connections for each channel in order for the robot to move forward. Connect the "LEFT MOTOR" channel's red wire to the silkscreen labeled as "BLACK" and black wire wire to the silkscreen labeled as "RED". Then flip the wires for the "RIGHT MOTOR" channel with the right motor. The wiring may look similar to the image shown below on the right. If you flip the wires after this point, make sure to set left motor invert to &lowbar;&lowbar;&lowbar;&lowbar; and set right motor invert to &lowbar;&lowbar;&lowbar;&lowbar; back to false for future experiments.

Before Flipping the WiresAfter Flipping Wires
Go Further: Now that you have a moving robot, can you write a program that would tell your robot to drive in a square? How about a star? What about having it dance?

Troubleshooting

  • moto:bit package is not showing up - Try installing it again from the add package option in MakeCode

  • Micro:Bit Not Showing Up On My Machine - Try unplugging the USB cable and plugging it back in. Also, be sure that you have the cable inserted all the way into your micro:bit

  • Robot Not Moving - Make sure your motors are hooked up correctly in the motor ports and your motor power switch is set to "RUN Motors", the battery pack is plugged in, and you have fresh batteries.

  • micro:Bot Not Driving in a Straight Line - Try adjusting left or right motor's % to calibrate.

  • Moving in Reverse?! - There are two options if you notice the micro:bot moving in the wrong direction. As explained above, you can flip the wiring of your motors or use the set &lowbar;&lowbar;&lowbar;&lowbar; motor invert to &lowbar;&lowbar;&lowbar;&lowbar; block in your on start block to change what is forward vs. reverse.

Experiment 2: Staying in a Box

Introduction

Robots are smart! They are smart because they use sensors to detect what the world around them and then respond to those conditions. One of the conditions our robot can respond to is the darkness of the surface that it is driving on. It can detect lines, a gradient of darkness or a blacked out area. In this experiment you will program your robot to stay inside of a box that you have drawn on a surface.

Parts Needed

You will need the following parts:

  • 1x micro:bit board (Not Included with Kit)
  • 1x Micro-B USB Cable (Not Included with Kit)
  • 1x moto:bit Carrier Board
  • 2x Wheels
  • 1x Assembled Shadow Chassis
  • 2x Hobby Gear Motors
  • 1x 4xAA Battery Holder
  • 4x AA Batteries (Not Included with Kit)
  • 3x Analog Line Following Sensors
  • 3x 3-Pin Jumper Wires

Didn’t get the kit? Have no fear! Here are the parts you will need to complete this experiment. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Hobby Gearmotor - 140 RPM (Pair)

Hobby Gearmotor - 140 RPM (Pair)

ROB-13302
$4.95$4.11
2
USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13
SparkFun moto:bit

SparkFun moto:bit

DEV-14213
$15.95
3
micro:bit Board

micro:bit Board

DEV-14208
$14.95
7
Wheel - 65mm (Rubber Tire, Pair)

Wheel - 65mm (Rubber Tire, Pair)

ROB-13259
$2.95
2
SparkFun RedBot Sensor - Line Follower

SparkFun RedBot Sensor - Line Follower

SEN-11769
$2.95
7
Battery Holder - 4xAA to Barrel Jack Connector

Battery Holder - 4xAA to Barrel Jack Connector

PRT-09835
$2.49
Shadow Chassis

Shadow Chassis

ROB-13301
$12.95
7
Jumper Wire - 0.1", 3-pin, 6"

Jumper Wire - 0.1", 3-pin, 6"

PRT-10368
$1.50
Panasonic Alkaline Battery - AA

Panasonic Alkaline Battery - AA

PRT-15201
$0.50

Suggested Reading

Before continuing on with this experiment, we recommend you be familiar with the concepts in the following tutorial:

Getting Started with the micro:bit

The BBC micro:bit is a compact, powerful programming tool that requires no software installation. Read on to learn how to use it YOUR way!

Introduction to the Line Sensors

The line follower sensor is an add-on for your shadow chassis that gives your robot the ability to detect lines or nearby objects. The sensor works by detecting reflected light coming from its own infrared LED. By measuring the amount of reflected infrared light, it can detect transitions from light to dark (lines) or even objects directly in front of it.

Line sensor

The sensor has a 3-pin header which connects directly to the moto:bit carrier board via female to female jumper wires. A mounting hole lets you easily connect one or more of these to the front or back of your robot chassis.

The IR Reflectance sensors work best when they are close to the surface below the micro:bot. The sensor should be about 1/8" above the table. This is an optimal distance for the IR transmitter to illuminate the surface below and measure the reflected light. (Note: Human eyes are non sensitive to IR light, but if you use a CCD camera -- like the one in your phone -- you can see a small light shining out of the front element).

IR Light in Camera

Here, you can see a faint pink glow from the IR LED. This is picked up on most digital cameras and cell phones. Note that the cable wires for the micro:bot are different as opposed to the ones used in this image.

Hardware Hookup

Like the motors, you should have already hooked up the line sensors during the assembly portion of this guide. You can go there now for the full assembly instructions. Double check to make sure that the wires are hooked up to your line sensors correctly!

Line Sensor Wire Hookup

The line sensors hookup to your moto:bit via female / female jumper wires that snake through the chassis of your robot up to the moto:bit. The sensors hookup to the moto:bit in the following order:

  • LEFT =>P0
  • CENTER =>P1
  • RIGHT =>P2

Double check to make sure they are hooked up correctly and in the proper orientation:

Attached to moto:bit

Running Your Script

Be sure to add the moto:bit package as instructed in the Installing the moto:bit Package in MakeCode section of this tutorial.

Now, you can either download the following example script below and drag and drop it onto your micro:bit, or use it as an example and build it from scratch in MakeCode.

Calibration is very important with the line sensors to work accurately. Your environment will greatly affect the P1 analog readings and thresholds for the surface value so you might have to customize these numbers to suit your application.

Code to Note

Let's take a look at the code and what to expect.

Experiment 2 Code Screenshot

Click on image for a closer view.

Initialize Serial Output

When the code first starts, we initialize a serial output on the micro:bit to send serial to the USB. Using the serial redirect to USB code block defaults the 115200 baud. This is useful whenever we need to inspect the sensor readings and interpret the values in a serial terminal.

Set Motors

We will need to set the motors depending on how the motors are wired to the moto:bit. In this case, we will be setting both motors to true to be consistent with how we assembled the robot earlier.

Creating a Variable

In Microsoft MakeCode, you need to be able to create variables to store information for your robot to compare against, or to just remember. You can use the built-in variables under the Variables drawer as shown below.

variable drawer

But, you can also make your own custom variables. To do this click on the Variables drawer and select Make New Variable. You can then name it and use it in your program. In this case, we are going to create two new variables. One to have the micro:bit remember what our black line looks like (i.e. black_line) and another for the current sensor reading (current_surface_reading).

naming variable

Set To

To store a value or piece of information in a variable you use the set &lowbar;&lowbar;&lowbar;&lowbar;&lowbar;&lowbar;&lowbar; to block. This allows you to select a variable and set it to a value or block of your choice. In this case, the line following sensor value connected to pin P1. We do this once in the on start block to get a base reading from the sensor so that our micro:bit remembers the value of the black line. This calibrates the sensor for the micro:bot. Pressing button A while the program is running will also save the line sensor reading again.

Analog Read Pin

To get that base reading from the line sensor we use the analog read pin &lowbar;&lowbar; block to get an analog value (0 - 1023) from the line sensor.1023 is totally black and 0 is totally saturated white. Your surface will be something probably in between.

If Condition Statements

To compare the current reading of the line sensor to its known baseline value that was captured and stored in the on start block, we use an if statement block. The if block accepts a logical statement. If that statement (current_surface_reading &geq; black_line - 100) is true, then the if block runs then "then" section of code. If that statement is false, then the "else" section of the block is run.

You may be asking yourself why subtract 100 from the surface value. Well, that number is a sensitivity value. The sensor reading fluctuates as the robot moves around and when the motors are running. By subtracting 100 from the original surface variable, we give the change in lighting a "wiggle room" or tolerance of 100. If you want your sensor to be more sensitive, you would make the number smaller. If you need it less sensitive, make it bigger.

To debug, we'll send serial to the USB before the condition statement and animate the LEDs of the micro:bit within each condition statement show icon &lowbar;&lowbar;&lowbar;&lowbar;&lowbar; (or show leds &lowbar;&lowbar;&lowbar;&lowbar;&lowbar;) block to help visualize when the micro:bot moves forward, back, or to the left.

What You Should See

Serial Output

For the scope of this tutorial, we'll use the MakeCode console to output the serial output. If you have paired the micro:bit to your computer and used the one-click download feature for MakeCode, a "Show console Device" button should appear in MakeCode. Click on the button to view the serial output. A graph and serial monitor will appear over the MakeCode code editor. You may notice that there is no data graphed and a number on the bottom left. The serial monitor will also display a number with a counter. The counter indicates how many times our output the same value. This is due to the graph automatically resizing. Try moving the line following sensor around the surface of a table. Keep in mind that the micro:bit in the simulator does not reflect the LEDs on the physical micro:bit in real-time.

MakeCode Serial Console

You will notice that the data will start jumping around as the line following sensor on P1 reads the surface. Below is a snapshot of the line following sensor on a white table. The surface that the sensor was reading was not perfectly white and caused the sensor readings to jump around ~693 to ~721. You may see a different output depending on the line following sensor, surface, and distance between the sensor and surface.

Output on a White Table

To better understand what is going on when the line following sensor sees a dark black line, we'll place different surfaces under the sensor. We'll use the following three surfaces to illustrate what is happening in the graph:

  • white table
  • brown cardboard
  • black electrical tape
White Table under P1Brown Cardboard under P1Black Electrical Tape under P1
White Table under P1Brown Cardboard under P1Black Electrical Tape under P1

The MakeCode serial plotter automatically zooms in/out so it may be hard to view the data at first. Placing a different surface under the sensor with the micro:bot staying still makes it easy to see the output once the console zooms out. Here's the raw output after placing the table, cardboard, and electrical tape under the sensor for a few seconds.

Output on a White Table, Brown Cardboard, and Black Electrical Tape

Let's look at the same graph but highlighted for the different surfaces. The output highlighted in blue was the surface that we initially read (which was ~693 to ~721). The small changes in the readings seem insignificant when comparing the output to other surfaces. Placing a small piece of brown cardboard under the sensor will cause the sensor readings to drop a certain range. The surface of the cardboard was a bit higher than the surface of the table. In this case, it was about ~82 to ~85 as highlighted in green. Moving the sensor over a dark black line will cause the sensor readings to jump to a certain range again. In this case, the values were around ~943 to ~983 as highlighted in red. Feel free to take some notes down on paper to remember what your range is for different surfaces.

Output Highlighted on a White Table, Brown Cardboard, and Black Electrical Tape

If you turn on the motor and have the micro:bot take a few steps across each surface, you'll notice that the output starts becoming noisy instead of being a steady output. This is due to the small differences across the surface and the IR light being reflected back while the micro:bot is moving. There also might be some noise coming from the batteries whenever the motors pull power and sunlight coming from the windows.

Output on a White Table, Brown Cardboard, and Black Electrical with the Motor Turned On Tape

If we inspect the output when the sensor is over the white table (highlighted in blue), the readings jump around ~632 to ~813. This is a bit bigger than what we initially read. If we inspect the output when the sensor is over the brown cardboard surface (highlighted in green), the readings jump around between ~60 to ~650. This is bigger than what we initially read. One reason for this is that the brown cardboard is not uniform throughout the material. Additionally, the distance between the line following sensor and cardboard became the same as when it was driving over the white table. If we inspect the output when the sensor is over black electrical tape (highlighted in red), the readings jump around ~932 to ~988. This is a bit bigger than what we initially read with the white table but not as big as the brown cardboard surface.

Output Highlighted on a White Table, Brown Cardboard, and Black Electrical Tape with the Motor Turned On

Now that we understand the output, we can head back into the code to adjust it as necessary where it says black_line - 100 to distinguish a light surface (white table or brown cardboard) from a dark surface (i.e. black electrical tape). Since we know that the values for a dark black line will be anything above ~932, we take that baseline value connected to P1 and subtract it by 100. Subtracting it by a value of 100 gives the line following sensor some tolerances in case there is an error in reading a black line. As a result, anything above ~832 will be recognized as a black line. The image below highlights the area in red where it is black_line - 100. If the current reading is above the boundary (indicated by the red line), the micro:bot will recognize it as the black electrical tape. Keep in mind that the analog sensor is not able to go higher than 1023, so anything between ~823 to ~1023 will be recognized as a dark line and does not need to be included in the code. Depending on your surfaces, you may need to adjust the value as necessary to change the sensitivity.

Boundary where it is probably a Black Line

Roaming micro:bot

Once your code is loaded find a light surface, preferably white and add a line of black electrical tape to the surface. For simplicity, let's make the width of the line between 1.5 inches and 2.0 inches. Continue adding black electrical tape until you make a square. In fact, if you have a large enough space you can create a 3 foot square you will be perfect! Place the center line following sensor connected to P1 on the black line. Then press the RESET button on your micro:bit. The micro:bot will remember what a black line looks like. Make sure to change the motor switch from "STOP MOTORS" to "RUN MOTORS." If you ever need to re-calibrate the sensor while the code is running, simply place the line following sensor connected to P1 over the dark black line and press the A button.

Stop Motors
Switch Flipped to STOP MOTORSSwitch Flipped to RUN MOTORS

The micro:bot will try to move away from the black line by backing up and turn to the left a bit. Your robot will attempt to drive forward until the black tape is directly under the center line sensors. When that happens your robot will stop, reverse, pivot to the left a bit, and try to drive forward again before hitting a line once more. If it works correctly and your robot is within the black square line, your robot should stay inside of the box forever!

Go Further: So, you have built a robot corral! There is a lot of resources being used causing the micro:bot to drive slow. Try removing the serial output, removing the show LEDs code blocks, adjusting the speed of the motors, and tweaking the pause blocks to see if you can get the micro:bot to move faster in the square. Or maybe try to use what you now know to build a maze for your robot to solve on its own! Better yet, try adjusting the logic used in the if statements to have the micro:bot driving on a black surface and contained within a white line.

Troubleshooting

  • Moto:Bit blocks not showing up - Make sure you have a network connection and you have added the package to your makeCode environment.

  • Micro:Bit Not Showing Up On My Machine - Try unplugging the USB cable and plugging it back in. Also, be sure that you have the cable inserted all the way into your micro:bit

  • Robot Not Moving - Make sure your motors are hooked up correctly in the motor ports and your motor power switch is set to “RUN Motors”, the battery pack is plugged in, and you have fresh batteries.

  • Robot Not Driving Forward - If your motors are hooked up correctly and we have inverted both motors in the code, try hitting the reset button on the micro:bit. This can happen after uploading when initially powering the micro:bit up.

  • Moving in Reverse?! - There are two options if you notice the micro:bot moving in the wrong direction. As explained above, you can flip the wiring of your motors or use the set &lowbar;&lowbar;&lowbar;&lowbar; motor invert to &lowbar;&lowbar;&lowbar;&lowbar; block in your on start block to change what is forward vs. reverse.

  • Robot Drives Over the Black Line - Your motors may still be running as the micro:bit is updating the LEDs pausing, or sending serial data to the USB. Make sure to have the micro:bot drive forward slowly (but not to slow where the motors will not move) before taking an additional sensor reading. You can also try to adjust the values or remove the blocks of code used for debugging. If the micro:bot drives to fast, it will not be able to see the width of the black line. The width of the line may be too small or the material for the black line might not be dark enough for the micro:bot to see. Try increasing the width of the black line or changing the material (i.e. besides black electrical tape, try using a darker paint, marker, pencil, etc.) used for the black line.

  • Robot Doesn't Detect Line - If changing the width of your line doesn't help, remember line sensor calibration settings can be very sensitive depending on your environment. Press the A button to calibrate when the robot is on the black_line or change the value being subtracted from the black_line.

Experiment 3: Following a Line

Introduction

OK, you have your robot staying inside of box drawn on the floor, but that still seems a little odd and random. You want your robot to go somewhere, do something and then keep going! In this experiment, you will elaborate what you learned from Experiment 2 to get your robot to follow a line.

Parts Needed

You will need the following parts:

  • 1x micro:bit board (Not Included with Kit)
  • 1x Micro-B USB cable (Not Included with Kit)
  • 1x moto:bit Carrier Board
  • 2x Wheels
  • 1x Assembled Shadow Chassis
  • 2x Hobby Gear Motors
  • 1x 4xAA Battery Holder
  • 4x AA Batteries (Not Included with Kit)
  • 3x Analog Line Following Sensors
  • 3x 3-Pin Jumper Wires

Didn’t get the kit? Have no fear! Here are the parts you will need to complete this experiment. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Hobby Gearmotor - 140 RPM (Pair)

Hobby Gearmotor - 140 RPM (Pair)

ROB-13302
$4.95$4.11
2
USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13
SparkFun moto:bit

SparkFun moto:bit

DEV-14213
$15.95
3
micro:bit Board

micro:bit Board

DEV-14208
$14.95
7
Wheel - 65mm (Rubber Tire, Pair)

Wheel - 65mm (Rubber Tire, Pair)

ROB-13259
$2.95
2
SparkFun RedBot Sensor - Line Follower

SparkFun RedBot Sensor - Line Follower

SEN-11769
$2.95
7
Battery Holder - 4xAA to Barrel Jack Connector

Battery Holder - 4xAA to Barrel Jack Connector

PRT-09835
$2.49
Shadow Chassis

Shadow Chassis

ROB-13301
$12.95
7
Jumper Wire - 0.1", 3-pin, 6"

Jumper Wire - 0.1", 3-pin, 6"

PRT-10368
$1.50
Panasonic Alkaline Battery - AA

Panasonic Alkaline Battery - AA

PRT-15201
$0.50

Suggested Reading

Getting Started with the micro:bit

The BBC micro:bit is a compact, powerful programming tool that requires no software installation. Read on to learn how to use it YOUR way!

Introduction to Using Multiple Line Sensors

In the previous experiment, you used a single line sensor (the middle sensor) to detect the line on the floor. That is great for staying inside of a line, but now, you need to follow a line. That is where the other two line sensors come in.

Multiple Lines Sensors

Essentially, you want the center sensor to detect the line, but not the other two, meaning that the robot is centered on the line. If one of the side sensors detect a line it means that you are veering to one side or another and your robot should correct itself. We will use the information from multiple sensors combined with an if/else statement block to build a decision tree for your robot to follow. For simplicity, we will start with using just two of the line sensors (the left and right sensors) to follow a dark black line. As you add more line following sensors to a robot, the code can get complex. However, the robot will able to follow a line better.

Line Follower Robot with Two Line Following Sensors

P0 and P2 Reading a Black Line

Hardware Hookup

Note: If you already hooked up your sensors in Experiment 2, please skip this section.

Like the motors, you should have already hooked up the line sensors during the assembly portion of this guide. You can go there now for the full assembly instructions. Double check to make sure that the wires are hooked up to your line sensors correctly!

Hooking Up Line Sensors

Line Sensor Connections to Wire

The line sensors hookup to your moto:bit via female / female jumper wires that snake through the chassis of your robot up to the moto:bit. The sensors hookup to the moto:bit in the following order:

  • LEFT =>PO
  • CENTER =>P1
  • RIGHT =>P2

Double check to make sure they are hooked up correctly and in the proper orientation

Line Sensor Connections to moto:bit

Experiment 3a -- Simple IR Sensor Reading

Let's break up this experiment into two parts. First, we will have the micro:bot follow a straight dark, black line. Then we will have a slightly more complex path to try to have the micro:bot drive around a path with a zigzagged pattern.

Running Your Script

Be sure to add the moto:bit package as instructed in the Installing the moto:bit Package in MakeCode section of this tutorial.

Now, you can either download the following example script below and drag and drop it onto your micro:bit, or use it as an example and build it from scratch in MakeCode.

Calibration is very important with the line sensors to work accurately. Your environment will greatly affect the P0 and P2 analog readings and thresholds for the surface values so you might have to customize these numbers to suit your application.

Code to Note

Let’s take a look at the code and what to expect.

Experiment 3a Screenshot Code

Click on image for a closer view

black_Line_L and black_Line_R

Like in the previous experiment, you need to set a baseline value for the surface that your robot is driving on. This is actually called a calibration value. We need to do this for two sensors now; left and right. We go through the same routine we did for the single sensor previously, but for the left and right sensors.

Comma Delimiter

For debugging, we set up the serial again. However, we will use the join block with a comma delimiter. This is useful for graphing more than one sensor readings.

On Button Press

As in the first experiment, we use the On Button Press block to start the program. Since we are using button A again to recalibrate the line following sensors whenever we need, we'll be using button B to start the program. This is so you can get a good base reading to calibrate your sensors without having to wrestle with a robot that is trying to move around. To remind us to press button B, the on start block displays a short animation once to point at button B. If the motor switch is flipped to the RUN MOTORS side, pressing button B will cause the micro:bot to start following a line.

While

The While block is a logic block that is similar to the loop block, but a bit smarter. The While block accepts a TRUE/FALSE statement, if that statement is true the block will loop whatever code is placed inside of it. If that value is false, the While block is simply skipped over. We hardcode a true value into the While block so that it constantly loops when the B button is pressed. That way we have the benefits of both the event block and the loop block without needing complicated programming.

If Condition Statements

We'll use if/else statements once again to check the sensor readings and move the micro:bot:

  • Case 1:
    • If both are reading the same, move forward.

Case 1 Moving Forward
  • Case 2:
    • If the left sensor sees a dark black line but the other does not, move forward and a little to the left toward the dark black line closer to the left side of the micro:bot.

Case 2 Move Forward and a Little to the Left
  • Case 3:
    • If the right sensor sees a dark black line but the other does not, move forward and a little to the right toward the dark black line closer to the right side of the micro:bot. There are slight differences in the motors and wheels so we tweak the left motor strength a bit so that the micro:bot actually turns toward the right (50 + 5).

Case 3 Move Forward and a Little to the Right
  • Case 4:
    • If we do not see a dark black line, stop.

Case 4: Stop

What You Should See

Serial Output

We'll use the MakeCode console to output the serial output again. If you have paired the micro:bit to your computer and used the one-click download feature for MakeCode, a "Show console Device" button should appear in MakeCode. Click on the button to view the serial output.

You will notice that the data will start jumping around as the line following sensors on P0 and P2 read the surface. Below is a snapshot of the line following sensors on a light surface. Notice that the output of both sensors were not the same. This is due to the slight differences in the line following sensors. You may see a different output with your sensors.

Serial Output White Table

Moving the micro:bot over a piece of brown cardboard and black electrical tape, you will notice that the sensor readings move at the same time when the graph zooms out.

White Table under P0 and P2Brown Cardboard under P0 and P2Black Electrical Tape under P0 and P2
White Table under P0 and P2Brown Cardboard under P0 and P2Black Electrical Tape under P0 and P2

For this reading, we moved the micro:bot further into the cardboard so that the distance between the line following sensors and cardboard box were the same.

Serial Output Three Different Surfaces with Two Line Following Sensors

Let's look at the same graph but highlighted for the different surfaces. Overall, the output is similar to what we saw in experiment 2 when the motors are turned off.

Serial Output Highlighted Three Different Surfaces with Two Line Following Sensors

The image below highlights the area where it is above black_line_L - 100 and black_line_R - 100. Note that we need to do this for the left and right line following sensor due to the slight differences. As a result, anything above ~875 for the left line following sensor (as indicated by the red line) is probably a dark surface. Additionally, anything above ~892 for the right line following sensor (as indicated by the black line) is probably a dark surface.

Boundaries where it is probably a Black Line

As we turn on the motors for the micro:bot and view the data, the output will become noisy instead of being a steady output. You'll also see the output become slightly bigger when ever the motors are turned on whenever it tries to follow a dark black line. The image below highlights the area when both sensors see a dark black line. When this happens, the micro:bot will drive forward.

Line Following Sensors Both Seeing a Dark Line while Driving Forward

The image below shows when the left line following sensor (when it is above black_line_L - 100) sees a dark black line. The motors turn on and tries to move toward the line on the left. Note that the right line following sensor stays around the same value but becomes noisy.

Left Line Following Sensor Seeing a Dark Line while Driving Toward the Left

The image below shows when the right line following sensor (when it is above black_line_R - 100) sees a dark black line. The motors turn on and tries to move toward the line on the right. Note that the left line following sensor stays around the same value but becomes noisy.

Right Line Following Sensor Seeing a Dark Line while Driving Toward the Right

Straight Line Following micro:bot

Once you have loaded your script, place your robot on a dark black line on a light / white background. Make sure you have it centered with the line just underneath the center line sensor. Make sure the motor switch is changed from "STOP MOTORS" to "RUN MOTORS" and press the B button to start.

Stop MotorsRun Motors
Stop MotorsRun Motors

Pressing Button B

Your robot should drive forward until one of the side line sensors detects the dark black line and then it will turn in that direction to correct itself. Depending on your line shape and thickness your robot may "waddle" more or less. If you have the motors running too fast, it will continue moving until it sees a light surface. Make sure to have the robot slowly move forward or it may fall of the edge of a table!


Experiment 3b -- Following a Course with a Zigzags

Now that the micro:bot can follow a straight line, let's try to have the micro:bot follow simple polygon with zigzags.

Simple Polygon Course

Running Your Script

Be sure to add the moto:bit package as instructed in the Installing the moto:bit Package in MakeCode section of this tutorial.

Now, you can either download the following example script below and drag and drop it onto your micro:bit, or use it as an example and build it from scratch in MakeCode.

Calibration is very important with the line sensors to work accurately. Your environment will greatly affect the P0 and P2 analog readings and thresholds for the surface values so you might have to customize these numbers to suit your application.

Code to Note

Let’s take a look at the code and what to expect.

Experiment 3b Screenshot Code

Click on image for a closer view

Modified If Condition Statement

Most of the code used for experiment 3B is pretty much the same when following a black line. You should see the same condition statements for case 1 through case 3 when using P0 and P2 as the micro:bot attempts to follow a dark black line.

Case 1 Moving ForwardCase 2 Move Forward and a Little to the LeftCase 3 Move Forward and a Little to the Right
Case 1 - Moving ForwardCase 2 - Moving Forward and LeftCase 3 - Moving Forward and Right

However, case 4 will be adjusted to keep searching for a path. If we do not see a dark black line, we will take a step back and search three times to the left. The variable move_left will keep track of how many times we have looked to the left. Each time we search to the left, we will increase the power of the motor so that we do not get stuck in the same spot. After the 3rd time, we will try looking to the right before starting all over again.

Case 4 Correction

We will only want to use the move_left variable in case 4. We'll reset the variable whenever we go into the other cases.

What You Should See

The serial output will be the same if you open the MakeCode console. If you need, you can open it back up to view the output. If you have not already, make a track on a flat surface with varying edges. Make sure that there is enough of material adjacent to the track. If the wheels or nub caster run off the track, it may have problems trying to get back on the surface. We used a cardboard surface with black electrical tape for this experiment. Additional cardboard was attached to prevent the micro:bot from getting stuck.

Simple Polygon Course on Cardboard

This example works well to follow small changes in the line for turns but will also adjust for sharp turns. You'll follow the same steps to get the robot to start following a line. The only difference is that the robot will follow a zigzagged course in this example. By default, the micro:bot will attempt to correct itself to eventually follow a track in a counter-clockwise motion. Keep in mind that there are limitations in following a dark black line when only using only two line following sensors. Additionally, the surface was not completely flat. As you can see from the GIF below that the floor was rocking as the micro:bot was following the line. Adding more line following sensors can help the micro:bot follow a line better and keep it from driving off the track.

Line Following Robot with Sharp Turns

Go Further: Your robot can go where you tell it by following a line. We've just scratched the surface for line following problems. Here are some more challenges to explore and experiment:

  • Try adding more code to utilize the center line following sensor.
  • Instead of having the robot follow a counter-clockwise motion, try have the robot move in a clockwise motion.
  • Adjust the code to follow a dark black line for a complex maze
  • Adjust the motor speed and remove the LED array to see how fast your line following robot can move along the line without veering off the course.
  • Use the built-in accelerometer to increase the motor speed whenever the micro:bot is on a slanted surface so that the robot can navigate rough terrain.
  • Add an additional mode to invert the condition statements to follow a light white line against a dark surface instead of a dark black line against a light surface.
  • Try adjusting the width of your track to see if the robot can follow a more narrow line.

Troubleshooting

  • Robot Drives In a Circle - Double check your wiring and your code, your robot is not seeing the line. Also, double check that there isn't something like dust blocking your sensor.

  • Robot Isn't Moving - Pesky motor switch! Make sure that is set to "run" and you have fresh batteries.

  • Robot Not Driving Forward - If your motors are hooked up correctly and we have inverted both motors in the code, try hitting the reset button on the micro:bit. This can happen after uploading when initially powering the micro:bit up.

  • Moving in Reverse?! - There are two options if you notice the micro:bot moving in the wrong direction. As explained above, you can flip the wiring of your motors or use the set &lowbar;&lowbar;&lowbar;&lowbar; motor invert to &lowbar;&lowbar;&lowbar;&lowbar; block in your on start block to change what is forward vs. reverse.

  • Robot Waddles a Lot! - Change the width of your line.

  • Robot Doesn't Detect Line - If changing the width of your line doesn't help, remember line sensor calibration settings can be very sensitive depending on your environment. Also, the code calibrates when the micro:bot starts up. Make sure to have the sensors over a black line.

Experiment 4: Using the Accelerometer

Introduction

Now, what happens when something bumps into your robot? It just stays there and take it from this bully? No! It should move out of the way, or do something. In this experiment you will use the accelerometer on the micro:bit to trigger the robot to move out of the way. If you flip the robot on its back or stand it on end it will stop driving (play dead)!

Parts Needed

You will need the following parts:

  • 1x micro:bit board (Not Included with Kit)
  • 1x Micro-B USB Cable (Not Included with Kit)
  • 1x moto:bit carrier board
  • 2x Wheels
  • 1x Assembled Shadow Chassis
  • 2x Hobby Gear Motors
  • 1x 4xAA Battery Holder
  • 4x AA Batteries (Not Included with Kit)

Didn’t get the kit? Have no fear! Here are the parts you will need to complete this experiment. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Hobby Gearmotor - 140 RPM (Pair)

Hobby Gearmotor - 140 RPM (Pair)

ROB-13302
$4.95$4.11
2
USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13
SparkFun moto:bit

SparkFun moto:bit

DEV-14213
$15.95
3
micro:bit Board

micro:bit Board

DEV-14208
$14.95
7
Wheel - 65mm (Rubber Tire, Pair)

Wheel - 65mm (Rubber Tire, Pair)

ROB-13259
$2.95
2
Battery Holder - 4xAA to Barrel Jack Connector

Battery Holder - 4xAA to Barrel Jack Connector

PRT-09835
$2.49
Shadow Chassis

Shadow Chassis

ROB-13301
$12.95
7
Panasonic Alkaline Battery - AA

Panasonic Alkaline Battery - AA

PRT-15201
$0.50

Suggested Reading

What is Electricity?

We can see electricity in action on our computers, lighting our houses, as lightning strikes in thunderstorms, but what is it? This is not an easy question, but this tutorial will shed some light on it!

Accelerometer Basics

A quick introduction to accelerometers, how they work, and why they're used.

Getting Started with the micro:bit

The BBC micro:bit is a compact, powerful programming tool that requires no software installation. Read on to learn how to use it YOUR way!

Introduction to the Accelerometer

On the back of the micro:bit you can see a number of small chips. One of them is the accelerometer. The micro:bit has an onboard accelerometer that measures gravitational force. Depending on the version that you have, the accelerometer and compass can be on separate ICs or combined into a single IC.

v1.0 w/ Accelerometer on Separate ICv1.5 w/ Combined Accelerometer and Magnetometer
v1.0 w/ Accelerometer on Separate ICv1.5 w/ Combined Accelerometer and Magnetometer

An accelerometer is a sensor that measures the gravitational forces pulling on it in all three dimensions of the chip's X, Y and Z axes.

Triple Axis Accelerometer Visualization

Visualization of a Common Accelerometer (ADXL345) with Three Axes

Accelerometers are devices that measure acceleration, which is the rate of change of the velocity of an object. They measure in meters per second squared (m/s2) or in G-forces (g). A single G-force for us here on planet Earth is equivalent to 9.8 m/s2, but this does vary slightly with elevation (and will be a different value on different planets due to variations in gravitational pull). Accelerometers are useful for sensing vibrations in systems or for orientation applications. Vibration is what we are looking for!

Hardware Hookup

You have had the hardware hooked up the whole time! It is on the micro:bit! Feel free to move on.

Running Your Script

Be sure to add the moto:bit package as instructed in the Installing the moto:bit Package in MakeCode section of this tutorial.

Now, you can either download the following example script below and drag and drop it onto your micro:bit, or use it as an example and build it from scratch in MakeCode.

Code to Note

Let’s take a look at the code and what to expect.

Code to Note

On [Accelerometer]

The micro:bit has a built in accelerometer that measures the gravitational forces that are acting upon it. With other microcontrollers this is sometimes hard to use and make sense of the data you receive from the sensor. But, MakeCode has simplified that for you in an event block under the Input drawer (you will see it as On Shake) that allows you to pick a number of different force levels, orientations and even patterns (like shaking it). We use this to detect a number of orientations that you can put your robot in. For example the motors will only be ON in the screen up orientation.

If you tap the robot hard enough it will run / drive away from you. If you flip it over the motors will turn off. Same thing holds true if you place it on its tail with the micro:bit pointing up.

Try playing around with the different events that you can trigger with the accelerometer. Can you get it to detect bumping into an object like the wall and have it respond???

What You Should See

Once your code is loaded to your micro:bit and your motor switch is set to "RUN MOTORS." Your robot should not do anything at first. Give it a good tap / smack on top of the micro:bit. If you apply enough force to it your robot should run away. To stop your robot either flip the robot over to its back the motors should stop, or pick it up and set the robot on end with it sitting on its tail with the micro:bit logo pointing up. To run the program again, return the robot to its wheels right side up and smack it again.

Go Further: You can use the idea of detecting a bump in different ways. Try to write a program that giving your robot a nudge or tap starts it to drive forward for a bit, then you need to nudge it again a bit.

Troubleshooting

  • Robot Doesn't Move - Double check to make sure you have uploaded the new code to your board. Also, make sure your motor switch is set to the "RUN MOTORS" position.

  • Moving in Reverse?! - There are two options if you notice the micro:bot moving in the wrong direction. As explained above, you can flip the wiring of your motors or use the set &lowbar;&lowbar;&lowbar;&lowbar; motor invert to &lowbar;&lowbar;&lowbar;&lowbar; block in your on start block to change what is forward vs. reverse.

Experiment 5: Controlling a Servo - Battle Bot

Introduction

Your robot should do something more than just drive around! Maybe control a small robotic arm, a gripper or even a weapon of some kind. In this experiment you will integrate servo motors with your robot to build a Battle Bot with Jousting Lances. This experiment combines all the elements you've learned so far in this tutorial.

Parts Needed

You will need the following parts:

  • 1x micro:bit board (Not Included with Kit)
  • 1x Micro-B USB Cable (Not Included with Kit)
  • 1x moto:bit Carrier Board
  • 2x Wheels
  • 1x Assembled Shadow Chassis
  • 2x Hobby Gear Motors
  • 1x 4xAA Battery Holder
  • 4x AA Batteries (Not Included with Kit)
  • 3x Analog Line Following Sensors
  • 3x 3-Pin Jumper Wires
  • 2x Hobby Servos

Didn't get the kit? Have no fear! Here are the parts you will need to complete this experiment...

Servo - Generic (Sub-Micro Size)

Servo - Generic (Sub-Micro Size)

ROB-09065
$8.95
11
Hobby Gearmotor - 140 RPM (Pair)

Hobby Gearmotor - 140 RPM (Pair)

ROB-13302
$4.95$4.11
2
SparkFun moto:bit

SparkFun moto:bit

DEV-14213
$15.95
3
micro:bit Board

micro:bit Board

DEV-14208
$14.95
7
Wheel - 65mm (Rubber Tire, Pair)

Wheel - 65mm (Rubber Tire, Pair)

ROB-13259
$2.95
2
SparkFun RedBot Sensor - Line Follower

SparkFun RedBot Sensor - Line Follower

SEN-11769
$2.95
7
Battery Holder - 4xAA to Barrel Jack Connector

Battery Holder - 4xAA to Barrel Jack Connector

PRT-09835
$2.49
Shadow Chassis

Shadow Chassis

ROB-13301
$12.95
7
Jumper Wire - 0.1", 3-pin, 6"

Jumper Wire - 0.1", 3-pin, 6"

PRT-10368
$1.50
Panasonic Alkaline Battery - AA

Panasonic Alkaline Battery - AA

PRT-15201
$0.50

You Will Also Need

To complete this experiment, we are going to also need a few more components.

  • 2x Skewers (Not Included with Kit)
  • 2x Ping Pong Balls (Optional, Not Included with Kit)
  • Hot Glue or Tape (Not Included with Kit)

Suggested Reading

Hobby Servo Tutorial

Servos are motors that allow you to accurately control the rotation of the output shaft, opening up all kinds of possibilities for robotics and other projects.

Getting Started with the micro:bit

The BBC micro:bit is a compact, powerful programming tool that requires no software installation. Read on to learn how to use it YOUR way!

Introduction to the Servo Motor

Unlike the action of most motors that continuously rotate, a servo motor can rotate to and hold a specific angle until it is told to rotate to a different angle. You can control the angle of the servo by sending it a Pulse Width Modulation (PWM) pulse train (turning a pin on and off really fast at different intervals); the PWM signal is mapped to a specific angle from 0 to 180 degrees in the servo block with MakeCode.

Generic Micro Servo Motor

Inside of the servo there is a gearbox connected to a motor that drives the shaft. There is also a potentiometer that gives feedback on the rotational position of the servo, which is then compared to the incoming PWM signal. The servo adjusts accordingly to match the two signals.

Hardware Hookup

In this experiment, you will actually be using two different servo motors to create a Battle Bot! One will be used as a "left" jousting lance and the other as the "right". If you look at the servos, you will notice that they have three wires have different colors; red, black and white. Red is the supply voltage, black is ground and white is the signal. Hook the two servos up to the moto:bit at the two labeled servo ports. Make sure you line up ground to ground.

Male Servo Pins

The "left" is connected to pin P15 while the "right" servo is connected to pin P16. Using a bit of hot glue or tape, you can attach the servos to each side of the robot chassis.

Next, you can build the jousting lances by utilizing some grilling skewers! You will only need two that can be cut down to the needed size. You can either glue or tape each skewer to the servo to the supplied attachments. Each servo set comes with a small bag of attachments as seen below. In this experiment, we utilized the double arm micro horn, but any of them will work.

Servo Attachment Package

Don't have any skewers laying around? Be creative here!

Bot Assembled with Servos

This Battle Bot utilized electrical tape to mount the jousting lances to the servo motors, and it ended up looking something like this...

Battle Bot

Now, set your contraption aside until you have uploaded your code.

Running Your Script

Be sure to add the moto:bit package as instructed in the Installing the moto:bit Package in MakeCode section of this tutorial.

Now, you can either download the following example script below and drag and drop it onto your micro:bit, or use it as an example and build it from scratch in MakeCode.

Code to Note

Don't be overwhelmed by everything this code has to offer! I know it looks rather menacing, but the truth is that you've already done all of this code in previous experiments.

Experiment 5 Screenshot Code

Having a hard time seeing the code? Open the MakeCode in a separate window to edit or click on the image for a closer look.

Servo Write Pin to

The Servo Write Pin to block is found under the Pins drawer and it accepts a pin number that you have a servos signal wire attached to as well as an angle that you want it to rotate to. That's the basics for controlling a servo motor with Microsoft MakeCode!

On Button A, On Button B and On Button A+B

In this example we use the On Button event blocks a lot. They allow us to break out different functions we want without messy if statements.

In this program the On Button A event block resets the calibration value for the table surface for the robot to use as a comparison value and also sets the servo positions to 90 degrees.

Press Button A

The On Button B block is used to set servo position to 45 degrees.

Press Button B

Finally the On Button A+B event block is used to run the program.

If / Then Statements

You may notice that there is a few if / then blocks inside of the if statement in the forever block. This will aid your Battle Bot in making decisions and knowing what it has to do next.

What You Should See

Before running the program, make a thick line (about 12" wide x 6" long) using black electrical tape. This is where your robot will meet with an opposing robot.

When the code initializes, the servo "arms" will move into a starting position and take initial readings for your line sensors to establish a comparison point to the ground environment. Make sure to calibrate it with a black line before starting. Then place each robot at an equal distance away from the line.

Initially, the Battle Bot will not move. Press on buttons A and B at the same time to run the program. The robot will move forward if none of the line sensors detect the black line. If the center line sensor detects a black line, the Battle Bot will immediately start both servos and move backwards. If the left or right line sensors detect a dark surface, the side that detected it will have the corresponding jousting lance start to move while turning away from it. So your Battle Bot is prepared to defend itself from any oncoming situation!

Go Further: Design two parallel tracks using a black surface. Separate the tracks with a center "wall". Adjust the servos and extend the length of the skewers so that the robots can joust the other robot across the wall. Design and program the robot to follow their respective paths without turning back using the line following sensors. See who can disarm the other robot first.

Or figure out a creative way for it to know when to drop something at a specific location. Could you also program it to pick something up?

Troubleshooting

  • Robot Not Moving - Make sure your motors are hooked up correctly in the motor ports and your motor power switch is set to "RUN Motors", the battery pack is plugged in, and you have fresh batteries.

  • Moving in Reverse?! - There are two options if you notice the micro:bot moving in the wrong direction. As explained above, you can flip the wiring of your motors or use the set &lowbar;&lowbar;&lowbar;&lowbar; motor invert to &lowbar;&lowbar;&lowbar;&lowbar; block in your on start block to change what is forward vs. reverse.

  • Servo Moves in the Wrong Direction - Flip your servos, or change your code so that it rotates the correct direction.

  • Servo Doesn't Move at All! - Double check your connections of the servos to the moto:bit to make sure that they are hooked up correctly.

Bonus Experiments!

Go further by pairing the micro:bot kit with parts from the micro:arcade kit!

Wireless Remote Control with micro:bit

January 21, 2019

In this tutorial, we will utilize the MakeCode radio blocks to have the one micro:bit transmit a signal to a receiving micro:bit on the same channel. Eventually, we will control a micro:bot wirelessly using parts from the arcade:kit!

Resources and Going Further

For more information about the moto:bit, check out the resources below:

We produce a number of other kits and carrier boards that you can hook up to your micro:bit to help take your projects to the next level. Here is some further reading that may help you along in learning more about the world of electronics.

For more information on our micro:bit ecosystem, check out these tutorials:

Getting Started with the micro:bit

The BBC micro:bit is a compact, powerful programming tool that requires no software installation. Read on to learn how to use it YOUR way!

micro:climate Kit Experiment Guide

A weather station kit that is built on top of the inexpensive, easy-to-use micro:bit and Microsoft MakeCode.

SparkFun gator:particle Hookup Guide

The gator:particle is an I2C heart-rate monitor and pulse oximeter that can be used as a particle sensor. This tutorial will get you started using the gator:particle with the micro:bit platform.

For more robot fun, check out our these other tutorials outside of the micro:bit ecosystem.

Easy Driver Hook-up Guide

Get started using the SparkFun Easy Driver for those project that need a little motion.

Experiment Guide for RedBot with Shadow Chassis

This Experiment Guide offers nine experiments to get you started with the SparkFun RedBot. This guide is designed for those who are familiar with our SparkFun Inventor's Kit and want to take their robotics knowledge to the next level.

Getting Started with the AutoDriver - v13

SparkFun's AutoDriver is a powerful tool for controlling stepper motors. Here's how to use it.

Getting Started with the Autonomous Kit for the Sphero RVR

Want to get started in robotics? Look no further than the SparkFun autonomous kit for the Sphero RVR! Whether you purchased the Basic or Advanced kit, this tutorial will get you rolling...

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

SparkFun Clock Generator 5P49V60 (Qwiic) Hookup Guide

$
0
0

SparkFun Clock Generator 5P49V60 (Qwiic) Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1133

Introduction

The SparkFun Clock Generator 5P49V60 breakout board offers a wide range of customizable frequencies in a wide range of different signal types using a single reference clock. Four (single output) clock outputs can generate frequencies from 1MHz-200MHz and eight (differential output) clock outputs can generate frequencies from 1MHz-350MHz. The frequency's many properties can be manipulated in code via I2C using the SparkFun Arduino Library. The SparkFun Clock Generator also has four banks of programmable memory for the time when it's ready to sit on its' own within the project without a microcontroller. This hookup guide will go over all of the many available functions of the SparkFun Clock Generator and gives the hardware rundown on what exactly is on this board.

SparkFun Clock Generator Breakout - 5P49V60 (Qwiic)

SparkFun Clock Generator Breakout - 5P49V60 (Qwiic)

BOB-15734
$29.95

Required Materials

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. For example, I chose the RedBoard Qwiic as a simple demo, but you could use any microcontroller. Add it to your cart, read through the guide, and adjust the cart as necessary.

SparkFun RedBoard Qwiic

SparkFun RedBoard Qwiic

DEV-15123
$19.95
5
USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13
Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
Female Headers

Female Headers

PRT-00115
$1.50
7
Resistor 100 Ohm 1/4 Watt PTH - 20 pack (Thick Leads)

Resistor 100 Ohm 1/4 Watt PTH - 20 pack (Thick Leads)

PRT-14493
$1.20

Required Tools

An oscilloscope is highly recommended to verify that the programmed clock signal is correct as its the only way to verify the output accurately. SparkFun only has a few oscilloscopes in its' catalog, but if it's time to add this essential Electrical Engineering tool to your work bench, then check out SparkFun's offerings below.

DSO Nano V3 - Pocket-Sized Digital Oscilloscope

DSO Nano V3 - Pocket-Sized Digital Oscilloscope

TOL-11702
$127.50
1
Digital Storage Oscilloscope - 100MHz (TBS2104)

Digital Storage Oscilloscope - 100MHz (TBS2104)

TOL-14925
$2,454.95

Suggested Reading

If you aren't familiar with the Qwiic system, we recommend reading here for an overview.

Qwiic Connect System
Qwiic Connect System

We would also recommend taking a look at the following tutorials if you aren't familiar with them. In particular the tutorial on how to use an oscilloscopes might be very helpful depending on your experience.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

How to Use an Oscilloscope

How to work the dials and buttons on an oscilloscope, and a glossary of the o-scope lexicon.

How to Work with Jumper Pads and PCB Traces

Handling PCB jumper pads and traces is an essential skill. Learn how to cut a PCB trace, add a solder jumper between pads to reroute connections, and repair a trace with the green wire method if a trace is damaged.

Hardware Overview

Power

Power can be supplied through the header along the top side of the board labeled 3.3V and GND. Alternatively, power can be supplied through the Qwiic connectors on either side of the board.

Top View of Input PowerBottom View of Qwiic Connectors

Qwiic Connectors

There are two Qwiic connectors on either end of the SparkFun Clock Generator to provide power and I2C connectivity simultaneously. The Qwiic ecosystem is made for fast prototyping by removing the need for soldering I2C data lines. However, in this case soldering is required to connect to the clock outputs.

Bottom View w/ Qwiic Connectors

LED

There's a single red power LED, labeled PWR, on the bottom side of the board which indicates power is being supplied to the board.

Bottom View with Power LED

Jumpers

There are three jumpers on the SparkFun Clock Generator.

Top View of Jumpers

LED

Let's start with the jumpers on the right side of the board. The jumpers labeled LED can be cut to disconnect the red power LED so that it doesn't come on when power is supplied to the board.

SEL

The second jumper labeled SEL enables the ability to load settings from the SparkFun's Clock Generators' One Time Programming memory banks. This disables the I2C data communication, turning those lines into selection pins. More information can be found down further under One Time Programming.

I2C

Finally, the jumpers labeled as I2C can be cut to disable the pull-up resistors on the I2C bus. In general, you shouldn’t need to mess with this jumper. But if you have many devices on your I2C bus, you may want to remove these resistors by cutting the two small traces between the solder pads. Not sure how to cut a jumper? Read here!

Headers

There are two rows of headers on the SparkFun Clock Generator: one set contains all of the clock outputs while the other has I2C and a Shutdown/Output Enable Pin. There are also two pins just off-center of the board where a clock signal can be supplied to the board in place of the SparkFun Clock Generator's crystal.

Clock Output

The clock output header is located at the bottom of the board. There are four possible clock signals with four complementary signals for differential clock transmission. Each set of outputs, 1-4B, has it's own frequency output divider that allows for customizable outputs. Below are example sketches for SparkFun's Arduino Library that demonstrates how to easily set these frequencies.

Top View of Clock OutputBottom View of Clock Output

I2C

On the opposite edge from the clock output header is header for I2C and a pin labeled SD/OE. The software configurable pin labeled SD/OE stands for "Shutdown/Output Enable" and serves a dual purpose of shutting down the IC or turning on and off the clock outputs. By default this pin acts as an output enable, disabling the clocks when held low. In the SparkFun Arduino Library, you can use the function: sdInputPinControl(byte control) to enable shutdown instead.

Top View of I2C and Shutdown/Output Enable PinsBottom View of I2C and Shutdown/Output Enable Pins

Alternate Clock Input Header

Just to the right of the SparkFun Clock Generator's Crystal - the little silver box just above the main IC, are two small holes labeled CLKIN and CLKINB. Using this small header it's possible to feed the SparkFun Clock Generator an external reference clock in place of the on-board crystal. There are two pins, but CLKIN can be used exclusively for single ended clock input. There is an Arduino example below that demonstrates how to enable this feature in code but more information on the hardware connectivity can be found on page 20 of the datasheet.

Top View w/ Clock Input HeaderBottom View w/ Clock Input Header

Board Dimensions

The overall board size is 1.10"x1.00". There are two mounting holes available on the board.

Board Dimension

Clock Output Frequency

The SparkFun Clock Generator generates frequencies by using the small onboard crystal just above the IC in the center, as a reference clock. The diagram shown below from the datasheet displays how this works internally.

alt text

The reference clock (upper left two topmost pins) is manipulated internally in a phase lock loop (PLL center) to generate a frequency for the output dividers (FOD 1-4). These output dividers then set the frequencies for their respective clock outputs. These outputs are capable of frequencies between 1MHz-200MHz for single ended output or 1MHz-350MHz for differential signal output (see table in next section for specifics). It is possible to get even lower frequencies by feeding the output of one clock to the output divider of another clock in software. This is demonstrated in Arduino Example 6 - Multiplex Clock Output below.

Each output divider for each clock is synchronized to maintain a low skew rate (phase of each clock) which can be programatically manipulated. In addition, the slew rate (rise and fall times) for each clock can also be set with one of four settings (see table below). Finally, a spread spectrum can be applied to the clock to reduce it's EMI or to increase it's robustness.

For each clock signal a corresponding signal type must be selected and proper hardware terminations must be applied accordingly. This is explained with some detail in the next section.

Slew rate

Below is the possible slew rate settings for the output frequencies at 3.3V.

Slew Rates - 3.3V
Library Constant Minimum Typical Units
SLOWEST 1.0 2.2 V/ns
SLOW 1.2 2.3 V/ns
FAST 1.3 2.4 V/ns
FASTEST 1.7 2.7 V/ns

Signal Types and Termination

The SparkFun Clock Generator outputs different types of clock signals that each require their own specific hardware terminations. The following transmission outputs are available:

Single Ended Output Differential Signal Output
Frequency Range 1MHz - 200MHz 1MHz - 350MHz
CMOS LVPECL
CMOS2 LVDS
CMOSD HCSL33

In addition, transmission of these signals require ~50&ohm; trace impedance to avoid attenuation and distortion of the clock signal. Towards this goal, the board has been designed with 60&ohm; trace impedance with the shortest length possible between the header and the IC. The difference between the ideal trace and the Sparkfun Clock Generator's impedance can be remedied with series resistors or proper terminations and may not even be an issue depending on the selected frequency.

The selected signal type will require a different hardware termination. Below are the hardware terminations found in the 5P49V60 Clock Generator's datasheet.

Signal Type Hardware Termination
LVCMOS
LVPECL
LVDS
HCSL33 Driver
HCSL33 Source

One Time Programming (OTP)

The SparkFun Clock Generator can save all of the programmed settings to any of its four programmable banks of RAM. However, keep in mind that this RAM can only be programmed once (One Time Programmable)! After programming any of the banks of memory, it's possible to select which bank is loaded (0-3) when the SparkFun Clock Generator powers up. This is done by closing the SEL jumper and using the pin labeled SCL as "select zero" and SDA as "select one". Using these pins like two bits will select the corresponding bank, see table below.

Select 0 (SCL) Select 1 (SDA) Bank
0 0 0
0 1 1
1 0 2
1 1 3

A detailed list of steps on how to accomplish programming these banks can be found on page 5 of the programming guide.

Hardware Hookup

The Qwiic connector system makes it easy to connect to the clock generator to the RedBoard Qwiic, but to see the output on our SparkFun Clock Generator it will need to be hooked up to an oscilloscope. To do that, we'll first solder solder female header pins. Should you decide to use the board without a microcontroller, you will need solder pins ore wires to GND and 3V3 pins.

This image shows two Clock Generators side by side. On the left one, female headers have been soldered to the double row of PTH headers - the clock outputs.

We'll be using LVPECL mode as our output type. Under the Hardware Overview it's mentioned that properly terminating your output depends on its OUTPUT mode and so to terminate this properly we'll use two sets of 100Ohm resistors. Placing each set in parallel will result in 50 Ohm termination to ground.

This image shows two sets of 100 Ohm resistors. Each resistor pair is twisted together in parallel and then the two pairs are attached end to end.
These have been twisted together and then soldered for extra strength

Next, that will be plugged into the Clock One Output as shown below.

This image show the resistor pairs plugged into the Clock Output labled "1" on the Clock Generator.

Next, the SparkFun Clock Generator is plugged into the Redboard Qwiic via the Qwiic cable.

This image shows the SparkFun Clock Generator plugged into the Redboard Qwiic using a Qwiic cable.

Now the Oscilloscope is attached to the terminations as shown below:

This image shows the Oscilloscope attached to teh resistors that are plugged into Clock Output one of the Clock Generator.

Now if you load up Example 1: Generate a Clock Signal you'll see 16MHz output on the Oscilloscope's screen.

This image shows the Oscilloscope showing the clock signal generated by the SparkFun Clock Generator across its' screen.

You may notice a bit of over shooting in the picture above and a bit of ringing in the signal and that's for a number of reasons. I'm terminating my signal on a 1MOhm Oscilloscope probe, when I should be using a 50 Ohm instead. I also have an extended ground cable on the probe, which should be shortened for better signal capture. None the less, I hope that this is still demonstrative of the SparkFun Clock Generator capabilities.

SparkFun Clock Generator 5P49V60 Arduino Library

Note: This examples below assume you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

If you're using the RedBoard Qwiic and have never connected a CH340 device to your computer before, you may need to install drivers for the USB-to-serial converter. Check out our section on How to Install CH340 Drivers for help with the installation

We've written an Arduino library to make it even easier to get started with the SparkFun Clock Generator 5P49V60. The library will give you its' full functionality and provides example code for 90% of the SparkFun Clock Generator's capabilites. You can obtain the library through the Arduino Library Manager by searching SparkFun Clock Generator or you can download the ZIP file below from its GitHub repository to manually install it.

Example 1: Generate a Clock Signal

The first example demonstrates the very basics of the SparkFun Clock Generator: how to generate a clock signal. At the top the correct library is imported and the microcontroller connects to the SparkFun Clock Generator over the default I2C address: 0x6A.

language:c
#include <Wire.h>
#include "SparkFun_5P49V60.h"

// Uses default address at 0x6A, alternate available at 0x68
SparkFun_5P49V60 clockGen;

void setup(){

  Wire.begin();
  Serial.begin(115200);

  if (clockGen.begin() == true){
    Serial.println("Clock Generator Ready.");
  }
  else {
    Serial.println("Could not communicate with the SparkFun Clock Generator.");
    while(1);
  }

After connecting to the SparkFun Clock Generator, the internal clock frequency of the voltage controlled oscillator is set to 1600MHz (1.6GHz). This frequency can then be fed to the frequency output dividers of the clock outputs. This is done with clockGen.muxPlltoFodOne() which tells the IC to send the VCO frequency to the frequency output divider of clock one. Next the output mode is set to LVPECL_MODE (low voltage positive emitter coupled logic) with clockGen.clockOneConfigMode(LVPECL_MODE).

language:c    
  // Fist, Setting the internal oscillator to a known value.
  Serial.println("Setting Internal Clock Frequency to 1600MHz.");
  clockGen.setVcoFrequency(1600.0); // Give float value in MHz.

  // Clock One -----------------------------------------------------
  // Use internal phase lock loop for clock output calculation.
  clockGen.muxPllToFodOne();
  Serial.println("Setting Output Mode to LVPECL.");
  // There are many OUTPUT modes available for each clock - this example uses
  // LVPECL (Low voltage Positive Emitter Coupled Logic) mode.
  clockGen.clockOneConfigMode(LVPECL_MODE);

Finally the frequency is set to 16MHz by giving a float value of 16.0 to the clockGen.setClockOneFreq() function.

  language:c
  Serial.println("Setting Clock One Frequency to 16MHz.");
  clockGen.setClockOneFreq(16.0); // Give float value in MHz, 16.0 = 16000000Hz or 16MHz
  // --------------------------------------------------------------

}

void loop(){

  delay(1000);

}

Example 2: Generate Multiple Clocks

This example does exactly what the first example does but demonstrates how to also turn on other clock outputs. This example reinforces how the voltage controlled oscillator frequency is piped to each of the frequency output dividers of the clocks. This doesn't always have to be the case, you can pipe the output of the frequency output divider of one clock to a different output divider to get lower frequencies! Remember that 1MHz is the lowest possible output (clock output frequencies) of any of the frequency output dividers, unless you use this method. Check out example 6 below for more information!

language:c
#include <Wire.h>
#include "SparkFun_5P49V60.h"

// Uses default address at 0x6A, alternate available at 0x68
SparkFun_5P49V60 clockGen;

void setup(){

  Wire.begin();
  Serial.begin(115200);

  if (clockGen.begin() == true){
    Serial.println("Clock Generator Ready.");
  }
  else {
    Serial.println("Could not communicate with the SparkFun Clock Generator.");
    while(1);
  }

  // Fist, Setting the internal oscillator to a known value. 
  Serial.println("Setting Internal Clock Frequency to 1600MHz.");
  clockGen.setVcoFrequency(1600.0); // Give float value in MHz 

After connecting to the SparkFun Clock Generator, the internal clock frequency of the voltage controlled oscillator is set to 1600MHz (1.6GHz). This frequency can then be fed to the frequency output dividers of the clock outputs. This is done with clockGen.muxPlltoFodOne() and clockGen.muxPlltoFodTwo() which tells the IC to send the VCO frequency to the frequency output divider of clock one and two respectively. Next the output mode is set to LVPECL_MODE (low voltage positive emitter coupled logic) with clockGen.clockOneConfigMode(LVPECL_MODE) and clockGen.clockTwoConfigMode(LVPECL_MODE).

language:c
  // Clock One----------------------------------------------------
  // Use internal phase lock loop for clock output calculation.
  clockGen.muxPllToFodOne();
  Serial.println("Setting Output Mode for Clock One to LVPECL.");
  // There are many OUTPUT modes available for each clock - this example uses
  // LVPECL (Low voltage Positive Emitter Coupled Logic) mode.
  clockGen.clockOneConfigMode(LVPECL_MODE);
  Serial.println("Setting Clock One Frequency to 8MHz.");
  clockGen.setClockOneFreq(8.0); // Give float value in MHz, 8.0 = 8000000Hz or 8MHz
  // --------------------------------------------------------------

  // Clock Two--------------------------------------------------
  // Use internal phase lock loop for clock output calculation.
  clockGen.muxPllToFodOne();
  Serial.println("Setting Output Mode for Clock Two to LVPECL.");
  clockGen.clockTwoConfigMode(LVPECL_MODE);
  Serial.println("Setting Clock Two Frequency to 16MHz.");
  clockGen.setClockOneFreq(16.0); // Give float value in MHz, 16.0 = 16000000Hz or 16MHz
  // -----------------------------------------------------------

}

void loop(){
  delay(1000); 
}

Finally clock one has its frequency set to 8 MHz and clock two to 16MHz.

Example 3: Integer and Fractional Divider Calculation

In this example, the division of the reference clock and the division for the frequency output dividers of each clock are set manually. It's especially beneficial to do this manually when applying fractional values to the frequency dividers. These values often have remainders that must be rounded and thus become the round-off error of your clock output in parts per million. Knowing this error value could be important to your application. To determine the division values requires some simple math. First, as in the first two examples the correct libraries are imported and the microcontroller connects to the SparkFun Clock Generator using its' default address: 0x6A.

language:c
void setup(){

  Wire.begin();
  Serial.begin(115200);

  if (clockGen.begin() == true){
    Serial.println("Clock Generator Ready.");
  }
  else {
    Serial.println("Could not communicate with the SparkFun Clock Generator.");
    while(1);
  }

As in the previous sections the voltage controlled oscillator is set to to 1600MHz (1.6GHz). However the register value must be calculated with some simple math. Our desired input (1600MHz) divided by the frequency of the reference clock (16MHz) equals the divider value 100. *Easy Peezy Lemon Squeezy... *

language:c
1600/16 = 100

Now we set the register values in code.

language:c  
  // Fist, Setting the internal oscillator to a known value that makes for easy
  // division: 1600MHz. 1600MHz/16MHz = 100
  Serial.println("Setting Integer Divider.");
  clockGen.setPllFeedbackIntDiv(100);
  Serial.print("Integer Divider set to: ");
  uint16_t fbVal = clockGen.readPllFeedBackIntDiv();
  Serial.println(fbVal);

The formla for this calculation is in the example sketch's comments. Next the divider values for a frequency of 22MHz is calculated with a similar equation. Divide the voltage controlled oscillator's frequency from above (1600MHz) by two, then divide that value by the desired clock output (22MHz) to get the the clock's frequency output divider's value.

language:c
(1600/2)/22 = 36.3636

This divider value has a decimal and consequently will have two separate values to write to the SparkFun Clock Generator's registers. The first value is the integer portion (36) and the second value is the fractional portion (.36). The integer value can be set as is, but the fractional value first needs additional calculations to translate it into a value the SparkFun Clock Generator expects. To do that we multiply the fractional value by 224 and round that value to the closest integer. The decimal value is the clock output's rounding error in parts per million.

language:c
2^24 * .36 = 6039796.76
.76 = rounding error 
76/ppm

Now we write these two values to their registers.

language:c
  // Clock One -----------------------------------------------------
  // To get 16MHz Output = (1600MHz/2)/22MHz = 36.3636
  // Integer portion = 36
  // Fractional portion = .36 -> Need to convert to a HEX value
  // 2^24 * .36 = 6039796.76
  // Round the value to closest integer = 6039797
  clockGen.setIntDivOutOne(36);
  clockGen.setFractDivFodOne(6039797);
  Serial.print("FOD One Integer Divider: ");
  Serial.println(clockGen.readIntDivOutOne());
  Serial.print("FOD One Fractional Divider: ");
  Serial.println(clockGen.readFractDivFodOne());
  clockGen.muxPllToFodOne();
  // There are many OUTPUT modes available for each clock - this example uses
  // LVPECL (Low voltage Positive Emitter Coupled Logic) mode and terminates 
  // the clock with a 100Ohm resistance to GND.
  clockGen.clockOneConfigMode(LVPECL_MODE);
  clockGen.clockOneControl(ENABLE);
  // --------------------------------------------------------------

}

void loop(){
  delay(1000); 
}

The integer portion is set with clockGen.setIntiDivOutOne(36) and the fractional portion is set with clockGen.setFractDivOut(6039796). These two values are then read back with their respective "read" functions: clockGen.readIntDivOutOne() and clockGen.readFractDivFodOne(). Next we pipe (multiplex) the VCO frequency to the frequency output divider we just set, set the signal type, and enable the clock. In the previous examples all of the math was done behind the scenes but here doing the math may prove beneficial when needing to know the rounding error.

Example 4 and 5: Change Slew and Skew Clock Signals

The next two examples deal with manipulating the frequencies of the clock outputs. The body of the examples have been reduced to the relevant code blocks in this hookup guide, because the first three examples establish the steps to setup the basics of your SparkFun Clock Generator.

First, the slew rate is modified below by setting it to FAST with the function clockGen.clockOneSlew(FAST). This is one of four settings: SLOWEST, SLOW, FAST, and FASTEST that range from 2.2-2.7 V/ns; see the table above in the Hardware Overview under Clock Output Frequency, for possible settings. After setting the slew rate, the SparkFun Clock Generator is reset with clockGen.globalReset() because changing a clock output's slew rate results in a desychronization of the clock outputs. Global reset is a handy function to keep in your back pocket in case of undesired results.

language:c
// Slew rate for clock one.  
Serial.println("Setting Slew Rate.");
clockGen.clockOneSlew(FAST);
Serial.print("Slew rate set, resetting clock signals.");
clockGen.globalReset();

Secondly, the skew rate is set in the following code block. Each clock output is synchronized with each other to maintain a minimal skew rate between them by default. This however, is changed for clock one by calling clockGen.skewClockOne(). In the following code block clock one is skewed by 10 nano-seconds relative to clock two.

language:c 
// Clock One Skew------------------------------------------------
// Clocks are syncronized on every pulse - this skew will ofset clock one by
// 10ns relative to clock two. 
clockGen.skewClockOne(10); // Give values in nano seconds. 
//---------------------------------------------------------------

Example 6: Multiplex Clock Output

Finally in this last example, the many ways that a clock frequency can be multiplexed through software is demonstrated. If, for example, you wanted a lower frequency than the lowest possible frequency output of the frequency output dividers (1MHz), then you can pipe an already low frequency to another divider to get even lower frequencies. Or, if you've set one divider and want that frequency piped out of each output rather than setting each divider, this can also be done. Let's look at the code below.

This example has been reduced to the relevant code block. The first two examples have already demonstrated how to import the correct libraries and connect to the microcontroller to the SparkFun Clock Generator over its default address 0x6A. After setting the internal VCO to 1600MHz, its' frequency is piped to the output divider of clock one with clockGen.muxPllToFodOne(). What's important to note is that these values are set manually as in Example 3 because using the more abstract function of clockGen.setClockOne() assumes your piping the VCO frequency to a frequency output divider and NOT, as in this example, piping the output to another frequency output divider.

  clockGen.setVcoFrequency(1600.0); // Give float value in MHz.
  language:c
  // Clock One -----------------------------------------------------
  // To get 16MHz Output = (1600MHz/2)/16MHz = 50
  clockGen.setIntDivOutOne(50);
  Serial.print("FOD One Integer Divider: ");
  Serial.println(clockGen.readIntDivOutOne());
  clockGen.muxPllToFodOne();
  // There are many OUTPUT modes available for each clock - this example uses
  // LVPECL (Low voltage Positive Emitter Coupled Logic) mode and terminates 
  // the clock with a 100Ohm resistance to GND.
  clockGen.clockOneConfigMode(LVPECL_MODE);
  clockGen.clockOneControl(ENABLE);
  // --------------------------------------------------------------

With clock two we see something different. The function clockGen.muxFodOneToFodTwo() takes the output of the frequency output divider for clock one and pipes it to the frequency output divider of clock two. Now this demonstrates its function but doesn't actually divide it a second time.

  language:c
  // Clock Two -----------------------------------------------------
  // This function call multiplexes the settings from Clock One's Output
  // Divider to the Output Divider of Clock Two. In this way you can divide a
  // low frequency to get even lower frequencies. The settings for the Clock Two are
  // set to zero so will output a 16MHz frequency.  
  clockGen.muxFodOneToFodTwo();
  clockGen.clockTwoConfigMode(LVPECL_MODE);
  clockGen.clockTwoControl(ENABLE);
  // --------------------------------------------------------------

Finally, with clock three the output of clock two is piped to clock three's output, resulting in a round about way of getting three clock outputs to 16MHz. It would have been easier to use the relevant functions to pipe the first output to the next three outputs.

  // Clock Three -----------------------------------------------------
  // This function call multiplexes the output from clock two to the output of
  // clock three. If you want to duplicate a signal this may be the best
  // option. Notice that you don't need to enable clock three to see an output
  // on this line. 
  clockGen.muxOutTwoToOutThree();
  clockGen.clockThrConfigMode(LVPECL_MODE);
  // --------------------------------------------------------------

}

void loop(){
  delay(1000); 
}

To summarize there are three avenues that you can multiplex frequencies with the SparkFun Clock Generator. The first is to take the VCO frequency and pipe that to the any of the frequency output dividers. Secondly you can take the output of the frequency output dividers and pipe them to a the next sequential frequency output divider: FOD1->FOD2->FOD3->FOD4. Finally you can pipe the output of a frequency output divider to any of the next sequential clock outputs: Clock 1 -> Clock 2 -> Clock 3 -> Clock 4.

Resources and Going Further

That SparkFun Clock Generator 5P49V60 is a wildly versatile breakout board. There are still functions of the clock generator for the small sliver of advanced users that were not demonstrated in this hookup guide. Specifically spread spectrum manipulation and one time programming were not explicitly covered but for more information on these topics, check out the resources below:

Need some inspiration for your next project? Check out some of these related tutorials:

MiniGen Hookup Guide

Using the MiniGen, SparkFun's Arduino Pro Mini signal generator shield

Real Time Clock Module Hookup Guide

A quick introduction to the DS1307 RTC module and a hookup guide for the SparkFun Breakout.

DeadOn RTC Breakout Hookup Guide

An introduction to the DS3234 real-time clock (RTC), example wiring diagrams, and an Arduino library!

Qwiic Real Time Clock Module (RV-1805) Hookup Guide

Find out what time it is, even after the power's been out on your project for a while with the Qwiic Real Time Clock (RTC) module.

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Basic Servo Control for Beginners

$
0
0

Basic Servo Control for Beginners a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1109

Introduction

From simply sweeping an object back and forth to adding steering to your robot or R/C car, hobby servos are a great way to add some motion to your next project. Servos allow you to easily control the speed, direction and position [1] of the output shaft with just three wires!

Short video Demo of Servo Control

This tutorial covers a few different ways to control servos along with a project demonstrating how to control a servo from an external input. We will cover some basics of controlling servos with one example that requires no programming at all. Then we will control the servos with code using the Arduino IDE and Python. Feel free to jump to the example you would like to work with depending on the parts and code environment you prefer.

Recommended Reading

Before going through this tutorial, you may want to check out these related guides to get familiar with the concepts and parts used in the examples:

Pulse Width Modulation

An introduction to the concept of Pulse Width Modulation.

Motors and Selecting the Right One

Learn all about different kinds of motors and how they operate.

Hobby Servo Tutorial

Servos are motors that allow you to accurately control the rotation of the output shaft, opening up all kinds of possibilities for robotics and other projects.
Note: Output shaft positional feedback is only available on standard (closed-loop) servos. We cover that in more detail in the next section.

Servo Motor Basics

Before we get to the examples in this tutorial, we'll want to review a few basics about servo motors. For a detailed rundown of servos, their background, and how they work, take a look at our Hobby Servo Tutorial.

Standard vs Continuous Servos

SparkFun carries two types of hobby servo motors: standard and continuous rotation. There are several differences between the two types but for the purpose of this tutorial we'll only review the primary distinctions between Standard and Continuous Rotation servos.

A standard servo moves on a rotation arc (usually 0-90° or 0-180°) and provides positional feedback to the controller. This lets you move it to a specific point on the rotation arc and the servo reports its position back to the controller. Standard servos work great for things like steering control in R/C applications, controlling a robotic gripper or controlling a pan/tilt bracket like we cover later in this tutorial.

Standard Servo Graphic

A continuous rotation servo (sometimes referred to as a full rotation or just 360° servo) behaves more like a standard DC motor. Instead of controlling the position of the servo, the controller sets the speed and direction of the motor. Continuous rotation servos work well as drive motors or other applications where you need to control the speed and direction of a motor with just a few wires.

Continuous Rotation Graphic

Each type has their benefits and drawbacks so you will want to consider whichever type works best for your servo project.

Connector Pinout

One of the most important things to make note of with any servo is the pinout of the connector in order to prevent wiring things up incorrectly.

Most servos follow a specific color-code for Power (VCC), Ground (GND) and Control Signal. The table below lists the color-coding for three commonly used servo connector types. The pin numbering is almost universally the same but manufacturers may use different colors for the wires. If your servo does not match or you are not certain, it is always best to double-check the documentation for your servo.


Pin Number & Name Color Scheme - Hitec Color Scheme - Futaba Color Scheme - JR
1. Ground (-)BlackBlackBrown
2. Power Supply (+)RedRedRed
3. Control SignalYellow or WhiteWhiteOrange

Table for common servo pinouts.

Voltage Range and Power Supply

Next, you need to select a power supply for your servo project. Make sure the voltage provided by your power supply falls into the voltage range for your servo (commonly 4.8-6V but check the datasheet for your servo to be sure). Also, ensure your power supply can supply enough current to drive the servo. Again, the datasheet for your servo will have some helpful information to figure out the max current your servo may draw from your power supply. Usually, you can look at the stall current (if listed) in your servo's datasheet to determine the max current draw of your servo motor.

Control Signal Range

The last concept we want to revisit is a servo's control signal range. We're only going to cover the control signal range for this tutorial. For a more thorough explanation of a how a servo control signal works, check out this section of our Hobby Servo tutorial.

The primary thing to remember here is your servo's control signal pulse duration/width range. This is usually between 1 and 2 ms but can vary between manufacturers and servo types. Be sure to check your servo's specifications for the pulse range to avoid damaging the motor and gearbox. This is particularly important when you are sending PWM values from a microcontroller or single board computer like we demonstrate in the Arduino and Python sections.

Servo Control with the SparkFun Servo Trigger

Our first example demonstrates how to move a servo motor using the SparkFun Servo Trigger. This example requires no coding or computer connection but assembling it as recommended involves some through-hole soldering. If you are not familiar with soldering through-hole components, take a look at our How to Solder: Through-Hole Soldering tutorial to get started.

The Servo Trigger works by using pre-loaded firmware on the board to interpret the position of the three potentiometers on the board. The potentiometers determine the start and stop positions of the servo (labeled "A" and "B") as well as how long it takes for the servo to travel from the start and stop positions (labeled "T"). The movement sequence is initiated by connecting the IN and GND pins together. In this example, we are going to use this Concave Button to create that connection.

This is just a brief overview of how the SparkFun Servo Trigger works. For a full overview of the board and how to use it, take a look at our Hookup Guide for it.

Servo Trigger Hookup Guide

March 26, 2015

How to use the SparkFun Servo Trigger to control a vast array of Servo Motors, without any programming!

Required Materials

To follow along with this example, you will need the materials in the Wishlist below. Feel free to add or remove items to your cart depending on what parts you already have or which servo you would like to use.

Required Tools

Along with the parts listed above, we recommend the following tools and materials to assemble your circuit:

Wire Strippers - 22-30AWG

Wire Strippers - 22-30AWG

TOL-14762
$12.95
Soldering Iron - 30W (US, 110V)

Soldering Iron - 30W (US, 110V)

TOL-09507
$9.95
7
Solder Lead Free - 15-gram Tube

Solder Lead Free - 15-gram Tube

TOL-09163
$3.50
2
Solder Wick #2 5ft. - Generic

Solder Wick #2 5ft. - Generic

TOL-09327
$2.49
4

Hardware Hookup

Once you have all of your materials and tools together it's time to start assembling your circuit. We will start by soldering to the servo pins on the Servo Trigger. Clip off three pins from your chosen breakaway header and solder it to the row of 3 pins for the servo labeled SIG, VCC and GND. Using a male header lets us easily connect and disconnect our servo motor from the trigger board. If your wire harness for your servo is too short you can lengthen it with this servo extension cable.

Servo Trigger with 3-pin header soldered to Servo control pins

Next up is the connections to our button. Take your two spade connectors and solder the bare wire end to the IN and GND pins on the opposite side of the Servo Trigger from your servo connection. You can substitute other materials here to connect your control input (ie pushbutton) like hook-up wire if you want to use a different button that does not have a microswitch. Once that is soldered into place, connect the spade connector end of that wire soldered to IN to the connector labeled NO and the other spade connector soldered to GND to the COM connector on your button's microswitch.

Photo of Servo Trigger with button connections

The last part of assembling our circuit is making the connections for the power supply. You can solder headers into place and use jumper wires to make the connections to your power supply similar to the servo connection but since this is connected directly to our power supply, we're going to solder wire directly to the VCC and GND pins on the side of the Servo Trigger for a secure connection.

We want two lengths of wire for the Power and Ground inputs from our power supply. Strip one end of each wire and solder it to the VCC and GND pins on the side of the Servo Trigger as the photo below demonstrates.

Photo showing wire soldered to the VCC and GND pins on Servo Trigger and connected to DC Barrel Jack Adapter

Now, when using the DC Barrel Jack Adapter, strip away a some of the insulation on the other end of your wires now soldered to the Servo Trigger, insert them into the screw terminal on the end of the adapter and secure them into place using a screwdriver. Make sure to match the wire soldered to the VCC pin with the terminal labeled "+ and the other wire soldered to GND with the one labeled "-".

⚡ Heads up! Make sure to connect VCC and GND to their respective connections on the DC Barrel Jack Adapter (labeled "+" and "-"). Wiring them in reverse can short out your circuit and damage the Servo Trigger, Servo and your power supply!

With everything soldered to your Servo Trigger and your button and servo connected (assuming you have not done so already), connect your power supply and press the button. You should see your servo sweep from one side to the other. Try adjusting the three potentiometers on your Servo Trigger to switch the direction, movement arc and movement time for your servo.

Photo showing everything wired up to the Servo Trigger and powered on

Troubleshooting Tips

Servo Not Moving or Powering On

The most common source of any problems with the servo not moving or not reacting to the button press will be a bad solder joint. If your servo is not powering up or is not moving when you press your button, check that your solder connections are completely connecting the pin or wire to the solder pad and the wires or solder joints are not touching each other. Also, make sure your power supply is plugged in fully to the DC Barrel Jack Adapter and your wall socket and is providing enough voltage to power the servo and the Servo Trigger. For tips on reworking bad solder joints, take a look at our Troubleshooting Tips Guide.

Erratic Movement

This may be caused by the potentiometers set beyond the servo's pulse range or possibly by having the button wired backward. Try adjusting the "A" and "B" potentiometers to fix erratic movement. If your servo is moving immediately when power is applied and then reacting unexpectedly to your button press, you may have one of your wires for the button connected incorrectly. Check to make sure you have the IN pin tied to the NO connector and the GND pin tied to the COM connector on your button.

Controlling a Servo with Arduino and Servo Library

Our second example circuit requires much less assembly and no soldering but it involves uploading and using code with the Arduino IDE. If you are not familiar with Arduino or do not have it installed on your computer, take a look through the guides below to install the IDE and get started with Arduino.

What is an Arduino?

February 26, 2013

What is this 'Arduino' thing anyway?

Installing Arduino IDE

March 26, 2013

A step-by-step guide to installing and testing the Arduino software on Windows, Mac, and Linux.

The SparkFun RedBoard Qwiic will act as our servo motor driver and controller using Pulse-Width Modulation (PWM).

Required Materials

To follow along with this example, you will need the materials listed below. Depending on what parts you already have or if you would like to use another development board or servo, you may want to adjust the items in your cart.

Hardware Assembly

All we need to do for this circuit is connect our Servo Motor to our RedBoard like the diagram below demonstrates:



Servo Circuit Diagram

Though setting this circuit up is very simple since we are just using three pins on our RedBoard Qwiic, note that the Servo's power pin is connected to VIN and not 5V. The 5V pin can only source up to 250mA which is not enough to drive most servos so we use the VIN pin instead.

Heads up! Powering the servo from VIN works well for this example so long as you are powering the RedBoard Qwiic via USB from your computer but the VIN pin is tied directly to your power supply so if you end up powering the RedBoard via the Barrel Jack connector or other method, make sure it is within the voltage range of your servo.

Arduino Code

Once you have your circuit wired up, it's time to upload some code! Connect your RedBoard (or other development board) to your computer with a USB cable and take note of the Port it shows up on. Now, open the Arduino IDE, copy the code below and paste it into a new sketch (making sure to delete the default code template).

Next, we need to select the board type (in this case Arduino/Genuino Uno) and COM port that the board enumerated to in the Tools menu. Then click the "Upload" button. If there were no errors during compilation and uploading, you should now see your servo moving back and forth.

language:c
/******************************************************************************
servo-sketch.ino
Example sketch for connecting a servo to a SparkFun RedBoard
  Servo Motor: (https://www.sparkfun.com/products/11965)
  SparkFun RedBoard: (https://www.sparkfun.com/products/13975)
Byron Jacquot@ SparkFun Electronics
May 17, 2016

**SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).**

Development environment specifics:
Arduino 1.6.5
******************************************************************************/

#include <Servo.h>

Servo servo;

uint32_t next;

void setup()
{
  // the 1000 & 2000 set the pulse width 
  // mix & max limits, in microseconds.
  // Be careful with shorter or longer pulses.
  servo.attach(9, 1000, 2000);

  next = millis() + 500;
}

void loop()
{
  static bool rising = true;

  if(millis() > next)
  {
    if(rising)
    {
      servo.write(180);
      rising = false;
    }
    else
    {
      servo.write(0);
      rising = true;
    }

    // repeat again in 3 seconds.
    next += 3000;
  }

}

Tips and Troubleshooting

Compilation/Upload Errors

If you run into any compilation or upload errors, the most common pitfall is the wrong Port was selected. Double check which port your RedBoard is on and retry. If you have multiple ports showing up in the "Port" menu, take note of which ports are available before plugging in your RedBoard and then select the new port that shows up in that menu after connecting it.

Another potential issue is if your code was not copied properly. The usual culprit for this is the code template was not entirely deleted/overwritten by the example. Take a quick look at your code and make sure you do not have any duplicated void loop();'s or void setup();'s or other rogue bits of code left over from the default template. The error printout at the bottom of the screen will give more thorough information on what the error is and can point you to any compiler errors in your code.

Servo Movement Problems

If your servo is not moving at all, you probably have a wire misplaced. Try rewiring the connections to ensure that your wiring has the servo connected to the correct pins on your RedBoard.

If your servo is jittery or seems like it is locking up, you may be driving it beyond the servo's pulse range. Check your servo's datasheet and adjust the second and third values in the servo.attach(9, 1000, 2000); function in the setup.

Controlling a Servo with Python and Pi Servo pHAT

Our third example demonstrates how to drive a servo using a Raspberry Pi and the SparkFun Servo pHAT for Raspberry Pi with the SparkFun PiServoHAT Python Module. The Servo pHAT can control up to 16 PWM devices so it is a great choice for projects using multiple servos along with other PWM devices like LEDs. The Raspberry Pi also has much more processing power than a development board like the RedBoard we used in the previous example so you can run all sorts of processes in the background for a complex project.

If you have never used a Raspberry Pi or the Servo pHAT before, we highly recommend reading through these tutorials before proceeding. The Getting Started with the Raspberry Pi tutorial is the most important in order to set up your Raspberry Pi as you cannot continue with this example without first configuring your Pi.

Python Programming Tutorial: Getting Started with the Raspberry Pi

June 27, 2018

This guide will show you how to write programs on your Raspberry Pi using Python to control hardware.

Pi Servo pHAT (v2) Hookup Guide

July 11, 2019

This hookup guide will get you started with connecting and using the Pi Servo pHAT on a Raspberry Pi.

Required Materials

To follow along with this example, you will need the following materials. Depending on what parts you already have, or if you would like to use a different Raspberry Pi or servo, you can adjust your cart accordingly.

Along with these parts, you will want a keyboard, mouse and monitor to connect to your Raspberry Pi to configure and interact with it. Alternatively, you can use another computer to do a headless setup for your Raspberry Pi. Also, if you already have a suitable SD card you would like to use, you can download and install the Raspbian OS for the Pi from the Raspberry Pi Foundation following the instructions from their Setting up your Raspberry Pi guide.

Hardware Hookup

Hooking everything up with the Servo pHAT is pretty straightforward but there are a few things to note. With everything powered off, plug the pHAT on to the Pi's 2x20 GPIO Header, taking care to align it properly so it looks like the photos below.


Pi Servo pHAT on Raspberry Pi 3
Pi Servo pHAT on Raspberry Pi ZeroW

Pi Servo pHAT properly connected to a Raspberry Pi 3 (left) and Raspberry Pi Zero W (right). Click image to enlarge.


Next, connect your servo to one of the 3-pin channel headers taking care to match the pins on the servo with the silkscreen labels on the Servo pHAT. The example we are using defaults to Channel 0 so, if you use a different channel, make sure to adjust the code accordingly. Do not connect servos to the Pi while it is powered on as the resulting current spike can cause the Raspberry Pi to reset.

Now, go ahead and plug in your Pi. Then turn it on and we're ready to move on to programming. The photos below show two options for powering the Raspberry Pi and Pi Servo pHAT.

Power from Pi
Power from USB-C

Examples of two of the various power supply options.

Python Package

With all of the hardware assembled and your Pi configured and ready to go, it is time to install the Python module and run one of the examples. For this particular experiment, we'll use Example 2 - Full Sweep with 180 deg. Servo.

First, we need to install the package to our Pi. For the sake of keeping this tutorial short we'll only cover how to install the entire SparkFun Qwiic Python package. If you would like to install individual parts of the package or install them manually, please head on over to this section of our Hookup Guide for the Servo pHAT for detailed instructions.

The SparkFun Qwiic Python Package installs all the available Python packages for our Qwiic products and includes the required I2C driver package. On systems that support PyPi via pip3 (use pip for Python 2), installation is simple using the following commands:

For all users (note the user must have sudo privileges) enter the following command from your command prompt:

language:bash
sudo pip3 install sparkfun-qwiic

If you just want to install the package for the current user enter this command in your command prompt:

language:bash
pip install sparkfun-qwiic

With the SparkFun Qwiic package installed it is time to create and run our code. You can either download or copy the code below into a file. Then open/save the file and execute the code in your preferred Python IDE. For example, to run the example in the default development environment on Raspbian, IDLE, click Run>Run Module or use the F5 key. To stop the example, use the Ctrl + C key combination.

While the example is running, you should see your servo moving back and forth over a 180 degree arc.

language:python
#-----------------------------------------------------------------------
# Pi Servo Hat - Example 2
#-----------------------------------------------------------------------
#
# Written by  SparkFun Electronics, June 2019
# Author: Wes Furuya
#
# Compatibility:
#     * Original: https://www.sparkfun.com/products/14328
#     * v2: https://www.sparkfun.com/products/15316
# 
# Do you like this library? Help support SparkFun. Buy a board!
# For more information on Pi Servo Hat, check out the product page
# linked above.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http:www.gnu.org/licenses/>.
#
#=======================================================================
# Copyright (c) 2019 SparkFun Electronics
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#=======================================================================

"""
This example should be used with a 180 degree (range of rotation) servo
on channel 0 of the Pi Servo Hat.

The extended code (commented out), at the end of the example could be
used to test the full range of the servo motion. However, users should
be wary as they can damage their servo by giving it a position outside
the standard range of motion.
"""

import pi_servo_hat
import time

# Initialize Constructor
test = pi_servo_hat.PiServoHat()

# Restart Servo Hat (in case Hat is frozen/locked)
test.restart()

# Test Run
#########################################
# Moves servo position to 0 degrees (1ms), Channel 0
test.move_servo_position(0, 0, 180)

# Pause 1 sec
time.sleep(1)

# Moves servo position to 180 degrees (2ms), Channel 0
test.move_servo_position(0, 180, 180)

# Pause 1 sec
time.sleep(1)

# Sweep
#########################################
while True:
    for i in range(0, 180):
        print(i)
        test.move_servo_position(0, i, 180)
        time.sleep(.001)
    for i in range(180, 0, -1):
        print(i)
        test.move_servo_position(0, i, 180)
        time.sleep(.001)

#########################################
# Code below may damage servo, use with caution
# Test sweep for full range of servo (outside 0 to 180 degrees).
# while True:
#     for i in range(-45, 200):
#         print(i)
#         test.move_servo_position(0, i, 180)
#         time.sleep(.001)
#     for i in range(200, -45, -1):
#         print(i)
#         test.move_servo_position(0, i, 180)
#         time.sleep(.001)

Troubleshooting Tips

If you are having any difficulty getting your servo to move or recognize the Servo pHAT on your Pi, here are a few tips to help troubleshoot.

No Available Devices

If you see this error readout: OSError: [Errno 121] Remote I/O error, double check your connections to the GPIO header.

Also make sure that the I2C hardware is enabled on your Raspberry Pi. If it is not enabled, you will probably see this error readout: Failed to connect to I2C bus 1.. If you need help enabling I2C on your Pi, take a look at this section of our Raspberry Pi: SPI and I2C Tutorial.

Check your I2C Connection

A simple method to check if your Raspberry Pi can communicate with the Servo pHAT over I2C is to ping the I2C bus. On the latest releases of Raspbian Stretch, the i2ctools package should come pre-installed. If it isn't run the following command in the terminal:

language:bash
sudo apt-get install i2ctools

With the i2ctools package is installed, you can ping the I2C bus with the following command in the terminal:

language:bash
i2cdetect -y 1

You should see a table printed out in the terminal. If the Servo pHAT is connected and working properly you should see the address space for 0x40 marked with 40.

Current Draw Problems

If your servos are drawing more current that your power supply can handle, your Servo pHAT will not operate correctly and the Raspberry Pi may reboot or brown out intermittently.

If you have a particularly large servo, or many servos driving a heavy load, you might notice the Pi rebooting or browning out when using the USB port on the Pi to power both the Pi and the Servo pHAT. You can try switching to powering the Pi and Servo pHAT directly through the USB-C connector on the pHAT, but a better solution is to sever the Power Isolation jumper and power each device individually. We cover where to locate that jumper and how to modify it in the "Jumpers" subsection of the Hardware Overview section of the Servo pHAT Hookup Guide.

Direct Servo Control with the Qwiic Joystick

Controlling servos in loops can be good for projects where you just want something moving while powered but what if you want more of a direct ability to control your servo? This project looks to demonstrate how to do just that!

For this project, we'll use the Qwiic Joystick as our input to control two servos on a pan/tilt bracket attached to a RedBoard Qwiic. Make sure to check out the Qwiic Joystick Hookup Guide for more information about the Qwiic Joystick:

Qwiic Joystick Hookup Guide

February 21, 2019

Looking for an easy way to implement a joystick to your next Arduino or Raspberry Pi project? This hookup guide will walk you through using the Qwiic Joystick with the Arduino IDE on a RedBoard Qwiic and in Python on a Raspberry Pi.

Required Materials

To follow along with this example project you will need the following materials. Depending on what parts you already have, you may want to update your cart accordingly.

Hardware Hookup

The first thing we want to assemble for this project is our pan/tilt bracket with the two sub-micro servos. The assembly guide below gives some basic instructions on how to build the pan/tilt bracket with your servos.

Pan/Tilt Bracket Assembly Guide

Pan/Tilt Bracket Assembly Guide
Assembly Tips:
Take care to align the servos properly so you can take advantage of the full range of motion and avoid having to re-seat the servos once everything is wired up.

Depending on the fit, you may need to use three washers for spacing instead of 2 like the guide suggests.

With the pan/tilt bracket assembled, connect the signal wires of the servos to the assigned I/O pins on your RedBoard and connect the Qwiic Joystick to the RedBoard with a Qwiic Cable. The example code uses D9 for the horizontal servo and D10 for the vertical servo by default but you can connect them to other pins if needed by modifying the servoH.attach(9); and servoV.attach(10); functions.

Finally, we need to connect the power supply pins for our servos. Just like with the Arduino Servo Library example from earlier, we are going to use the VIN pin on our RedBoard since the 5V pin can only source up to 250mA and our pan/tilt servos can pull in excess of 350mA with nothing attached to the bracket.

Since we have two servos for our pan/tilt bracket, we will use a breadboard to net the power pins for the servos together.

Note: If you have never used a breadboard before, we recommend taking a look at our How to Use a Breadboard tutorial.

Connect the power and ground pins of each servo to the "+" and "-' rails of your breadboard and then, with the RedBoard unpowered, connect the VIN and GND pins on your RedBoard to the respective rails on the breadboard as well. Once you have all of the power and ground pins tied together properly, plug in your RedBoard via USB.

Heads up! Just like with the simple Arduino example, the VIN pin works just fine to drive our servos when connected to a USB port since it outputs 5V but if you use another power source for your circuit, make sure to power the servos within their voltage range. For the servos used in this project (and most other hobby servos), that is 4.8-6V.

Photo of full circuit with Qwiic Joystick, RedBoard Qwiic and Pan/Tilt Bracket
Having trouble seeing the circuit? Click the photo for a larger view.

Arduino Code

With everything wired up, it is time to upload our code. First, we need to install the Qwiic Joystick Library if it is not installed already. You can manually install it by downloading it from the link above but we recommend installing the library through the Library Manager tool. Simply open that up and search for "SparkFun Qwiic Joystick" and click install. If you've never installed an Arduino library before, our Installing an Arduino Library Tutorial covers the entire process.

Now that the library is installed, go ahead and copy the code below and paste it into a new sketch. Select "Arduino/Genuino Uno" as your board (or if you are using another development board, select that) as well as the "Port" your board is on and upload the code.

language:c
/*
 Example code to control two servos using the SparkFun Qwiic Joystick.
 Code takes the readings of the Vertical (Y) and Horizontal (X) axes of the joystick
 and maps them to values between 0 and 180 degrees.

 Based off of the Arduino "Knob" example:

 Controlling a servo position using a potentiometer (variable resistor)
 by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>

 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>
#include "SparkFun_Qwiic_Joystick_Arduino_Library.h"

JOYSTICK joystick; // create joystick object to send position values


Servo servoH;  // create servo object to control a servo
Servo servoV;

int h;    // variable to read the horizontal values from the Qwiic Joystick
int v;    // variable to read the vertical values from the Qwiic Joystick

void setup() {
  servoH.attach(9); // attaches servo1 on pin 9 to the servo object
  servoV.attach(10);  // attaches servo2 on pin 10 to the servo object
  Serial.begin(9600);
  Serial.println("Qwiic Joystick Servo Control");

  if(joystick.begin() == false)
  {
    Serial.println("Joystick not connected. Check wiring. Freezing...");
    while(1);
  }
}

void loop() {
  h = joystick.getHorizontal();   // reads the value of the Qwiic Joystick's horizontal axis (between 0 & 1023)
  h = map(h, 0, 1023, 0, 160);     // scale it to use it with the servo (value between 0 and 180)
  servoH.write(h);                  // sets the horizontal servo position according to the scaled value
  v = joystick.getVertical(); // reads the value of the Qwiic Joystick's vertical axis (between 0 & 1023)
  v = map(v, 0, 1023, 0, 165);
  servoV.write(v);
  delay(15);    // waits for the servo to get there
  /*Serial.print("X: ");  //uncomment these lines to view the serial print of the x and y axes of the Qwiic Joystick 
  Serial.print(joystick.getHorizontal());   //these can be helpful for debugging or identifying any drift on your joystick
  Serial.print("Y: ");
  Serial.print(joystick.getVertical());
  Serial.println();*/
}

Once the code finishes uploading try moving the joystick around. You should see the servo connected to pin 9 react to movements on the horizontal axis and the servo on pin 10 will react to movements on the vertical axis just like the GIF below.

GIF of the pan/tilt bracket moving

Troubleshooting Tips

Here are some tips if you run into some common pitfalls with this example.

Compilation and Upload Errors

If you end up getting any compilation errors such as avrdude stk500_recv() programmer is not responding or something similar regarding the target device (aka our RedBoard), make sure you have selected the correct Port for your RedBoard as well as the correct board type.

If you see errors similar to SparkFun_Qwiic_Joystick_Arduino_Library.h: No such file or directory, the Qwiic Joystick library was not installed properly. Check to make sure the library is installed and is the latest version using the Arduino Library Manager tool.

Power Issues

Since we are using a breadboard for this example, a common cause of any power issues (e.g. the entire circuit is not turning on when plugged into USB) is a misplaced wire. Check that you have all of your power and ground wires properly connected on your breadboard. A common error is one or more of the wires is backward (i.e. power to ground or vice versa). Verify those are plugged into the right rail on your breadboard and are making a good connection to both the servo and your RedBoard.

Resources and Going Further

Now that you have a solid base understanding of how to control servos in a variety of ways, it's time to think about how you can integrate them into some projects! You can add all sorts of different things to the pan/tilt bracket like a camera or LED array. You can swap the Qwiic Joystick from the last project for another sensor like an IMU or you could even send the joystick data over a wireless connection and be on your way to creating your own R/C car or robot!

For some inspiration on ways to integrate servos into projects, take a look at the tutorials below using servos.

Building a Safe Cracking Robot

How to crack an unknown safe in under an hour.

Setting Up the Pi Zero Wireless Pan-Tilt Camera

This tutorial will show you how to assemble, program, and access the Raspberry Pi Zero as a headless wireless pan-tilt camera.

SparkFun ESP32 DMX to LED Shield

Learn how to utilize your DMX to LED Shield in a variety of different ways.

LED Gumball Machine

Hacking gumball machines to make the world a happier, blinkier place.

Or check out these blog posts for inspiration for your own servo project:


learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

SparkFun Qwiic Thermocouple Hookup Guide

$
0
0

SparkFun Qwiic Thermocouple Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1110

Introduction

How many times have you asked yourself, "Self? How can I measure both the ambient temperature as well as that thing over there, AND set temperature limits to trigger interrupts so I don't have to constantly poll over I2C? And how can I make it as easy as possible?" Well, we've got your answer. SparkFun has 2 new thermocouple amplifier boards - the SparkFun Qwiic Thermocouple - PCC and the SparkFun Qwiic Thermocouple - Screw Terminals; both of which do all of the above with a resolution of 0.0625°C, and an accuracy of ±1.5°C (worst-case). The boards come ready to accept a K-type thermocouple, which gives a temperature range of -200°C to 1350°C. Additionally, the MCP9600 has four onboard temperature alerts for those interrupt triggers as well as the ability to enter alternate operation modes in order to save power.

Let's dig in and see how all this works!

SparkFun Qwiic Thermocouple Amplifier - MCP9600 (PCC Connector)

SparkFun Qwiic Thermocouple Amplifier - MCP9600 (PCC Connector)

SEN-16294
$24.95
SparkFun Qwiic Thermocouple Amplifier - MCP9600 (Screw Terminals)

SparkFun Qwiic Thermocouple Amplifier - MCP9600 (Screw Terminals)

SEN-16295
$19.95

Required Materials

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Suggested Reading

If you aren’t familiar with the following concepts, we recommend checking out these tutorials before continuing. If you aren't familiar with the Qwiic system, we recommend reading here for an overview.

Qwiic Connect System
Qwiic Connect System

Serial Terminal Basics

This tutorial will show you how to communicate with your serial devices using a variety of terminal emulator applications.

Processor Interrupts with Arduino

What is an interrupt? In a nutshell, there is a method by which a processor can execute its normal program while continuously monitoring for some kind of event, or interrupt. There are two types of interrupts: hardware and software interrupts. For the purposes of this tutorial, we will focus on hardware interrupts.

A Brief Theory of Operation

Thermocouples are fairly ubiquitous, being used in everything from industrial kilns and diesel engines to pilot light sensors and thermostats in your home or office. Let's take a brief moment to go over how they work.

Roughly a couple hundred years ago, a man named Thomas Seebeck discovered the principal that thermocouples use. He noticed that if you take two wires made of dissimilar metals, connect them at the two ends, and make a temperature gradient between one end and the other, a voltage potential formed and current flowed. One junction is held in the environment where the temperature of interest exists. This is known as the hot junction. The other junction is referred to as the cold junction.

thermocouple schematic

K-type thermocouple with cold junction spread for voltage measurement

There are many types of thermocouples, which mainly differ by the types of metals used in the two wires. The most common general purpose thermocouple is type K. They are made out of chromel and alumel. These two alloys produce a potential of approximately 41.276 µV/°C, and voltage out can be calculated using the equation below.

k-type linear approximation of voltage

K-type thermocouples can read between from −200 °C to +1350 °C (−330 °F to +2460 °F) and are fairly stable.

Hardware Overview

MCP9600

At the heart of this board is the MicroChip Technology Inc MCP9600 Thermocouple EMF to Temperature Converter. Inside this chip are two temperature sensors, one for the thermocouple itself (the hot junction) and one for the chip itself (the cold junction). In addition, the MCP9600 has four onboard temperature alerts that allow you to set a temperature limit to trigger an interrupt when the temperature reaches a certain value. This frees up your microcontroller and your I2C bus. The MCP9600 can also be put into alternate operation modes in order to save power. The sensor supports a burst mode, where it will take a specifiable number of samples, return the results, and then go to sleep. More information can be found in the MCP9600 Datasheet (PDF).

MCP9600 HighlightBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

Power

Ideally, power will be supplied via the Qwiic connectors on either side of the board. Alternatively, power can be supplied through the header along the bottom side of the board labeled 3V3 and GND. The input voltage range should be between 2.7-5.5V.

Top View of Input PowerBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

Qwiic Connectors

There are two Qwiic connectors on either end of the SparkFun Qwiic Thermocouple boards to provide power and I2C connectivity simultaneously. The I2C address of the board is 0x60 by default , but has 7 other address the board can be configured to use.

I2C Input HighlightBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

I2C Pins

The I2C pins break out the functionality of the Qwiic connectors. Depending on your application, you can connect to these pins via the plated through holes for SDA and SCL.

I2C Input HighlightBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

Jumpers

I2C Jumper

These boards are both equipped with pull-up resistors. If you are daisy-chaining multiple Qwiic devices, you will want to cut this jumper; if multiple sensors are connected to the bus with the pull-up resistors enabled, the parallel equivalent resistance will create too strong of a pull-up for the bus to operate correctly. As a general rule of thumb, disable all but one pair of pull-up resistors if multiple devices are connected to the bus. To disable the pull up resistors, use an X-acto knife to cut the joint between the two jumper pads highlighted below.

I2C Input HighlightBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

ADDR Jumper

The MCP9600 uses an analog voltage to set the I2C address. By default, the ADDR jumper pulls the address pin low, which gives the board a default address of 0x60. Cutting the jumper pulls the address pin high through a 10K resistor, which will change the address to 0x67.

I2C Input HighlightBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

For addresses other than 0x67, a resistor will need to be soldered. Refer to the table below for the resistor value and corresponding address.

AddressResistor (kΩ)
0x600
0x612.2
0x624.3
0x637.5
0x6413
0x6522
0x6643
0x67N/A



Resistor location on each board:

I2C Input HighlightBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

LED Jumper

Wanna turn off that pesky power LED? Cut this jumper.

I2C Input HighlightBottom View of Qwiic Connectors
PCC ConnectorScrew Terminal

Board Dimensions

Feel free to click on either of the images below for a closer look!


Qwiic Thermocouple Amplifier PCCQwiic Thermocouple Amplifier Screw Terminals

Hardware Hookup

For this tutorial, we'll use the Amplifier board with the PCC connector. Grab your Qwiic cable and plug one end into the RedBoard Qwiic and the other end into the Thermocouple Amplifier.

image of redboard with qwiic cable plugged into thermocouple qwiic connector

Then you can connect the K-type Thermocouple into the PCC connector as so:

plugging in the thermocouple to the amplifier board

Click for a closer view.

Plug in the RedBoard Qwiic When you are all set up, you should have something that looks like this:

Picture of board, plugged into a redboard, plugged into a K-type thermocouple

Click for a closer view.

Software Setup and Programming

Note: This code/library has been written and tested on Arduino IDE version 1.8.10. Otherwise, make sure you are using the latest stable version of the Arduino IDE on your desktop.

If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

SparkFun has written a library to work with the Qwiic Thermocouple. You can obtain this library through the Arduino Library Manager by searching for MCP9600. Find the one written by SparkFun Electronics and install the latest version. If you prefer downloading libraries manually, you can grab them from the GitHub Repository.

Example Code

Once you've installed the library, you should be able to find the examples in Arduino under File>Examples>SparkFun MCP9600 Thermocouple Library.

MCP9600 Arduino Examples

Example 1: Basic Readings

While all of the examples are well commented, let's quickly run through example 1 just to get your feet wet. The best part? It's pretty much plug and play. So go ahead and open up Example 1, or alternatively, copy and paste the code below into an Arduino window:

language:c
/*
  Temperature Measurements with the MCP9600 Thermocouple Amplifier
  By: Fischer Moseley
  SparkFun Electronics
  Date: July 8, 2019
  License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware License).

  This example outputs the ambient and thermocouple temperatures from the MCP9600 sensor.

  Hardware Connections:
  Attach the Qwiic Shield to your Arduino/Photon/ESP32 or other
  Plug the sensor onto the shield
  Serial.print it out at 115200 baud to serial monitor.
*/

#include <SparkFun_MCP9600.h>
MCP9600 tempSensor;

void setup(){
    Serial.begin(115200);
    Wire.begin();
    Wire.setClock(100000);
    tempSensor.begin();         // Uses the default address 0x60 for SparkFun
    //tempSensor.begin(0x66);   // Default address for SparkX 

    //check if the sensor is connected
    if(tempSensor.isConnected()){
        Serial.println("Device will acknowledge!");
    }
    else {
        Serial.println("Device did not acknowledge! Freezing.");
        while(1); //hang forever
    }

    //check if the Device ID is correct
    if(tempSensor.checkDeviceID()){
        Serial.println("Device ID is correct!");        
    }
    else {
        Serial.println("Device ID is not correct! Freezing.");
        while(1);
    }
}

void loop(){ //print the thermocouple, ambient and delta temperatures every 200ms if available
    if(tempSensor.available()){
        Serial.print("Thermocouple: ");
        Serial.print(tempSensor.getThermocoupleTemp());
        Serial.print("°C   Ambient: ");
        Serial.print(tempSensor.getAmbientTemp());
        Serial.print("°C   Temperature Delta: ");
        Serial.print(tempSensor.getTempDelta());
        Serial.print("°C");
        Serial.println();
    }
    delay(20); //don't hammer too hard on the I2C bus
}

What You Should See

Open up the Serial Monitor and make sure your baud rate is 115200. You should see something like the image below. If you move the hot junction (ie, the thermocouple wand) closer to a heat source, you should see the Thermocouple temperature go up.

Serial Monitor Output for Example 1

Troubleshooting

Resources and Going Further

Want more information on the Qwiic Thermocouple? Check out the links here:

Qwiic Thermocouple Amplifier PCC:

Qwiic Thermocouple Amplifier Screw Terminals:

Hardware and Library:

Need inspiration for more projects? We have loads of great Qwiic tutorials! Check 'em out!

RedBoard Edge Hookup Guide

The RedBoard Edge is a RedBoard that's been rebuilt around the idea that projects are eventually put into an enclosure to help clean up their look.

IoT Power Relay

Using the ESP32 to make a web-configured timed relay.

TFMini - Micro LiDAR Module (Qwiic) Hookup Guide

The TFMini is a ToF (Time of Flight) LiDAR sensor capable of measuring the distance to an object as close as 30 cm and as far as 12 meters! The TFMini allows you to easily integrate LiDAR into applications traditionally reserved for smaller sensors such as the SHARP GP-series infrared rangefinders. With the added Qwiic feature, you can quickly connect to the sensor via I2C!

Displaying Your Coordinates with a GPS Module

This Arduino tutorial will teach you how to pinpoint and display your GPS coordinates with a press of a button using hardware from our Qwiic Connect System (I2C).

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado


Raspberry Pi 4 Kit Hookup Guide

$
0
0

Raspberry Pi 4 Kit Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1131

Introduction

The improved Raspberry Pi 4 Model B [ 2GB and 4GB ] is another upgrade in the line of Raspberry Pi single board computers, what's new? This hookup guide goes through the same process of getting going that worked with the previous Raspberry Pi Models.

Raspberry Pi 4 Model B (2 GB)

Raspberry Pi 4 Model B (2 GB)

DEV-15446
$39.95
1
Raspberry Pi 4 Model B (4 GB)

Raspberry Pi 4 Model B (4 GB)

DEV-15447
$59.95
3

There are a few kits available depending on your project. Depending on the version that you order, you can have one that includes the 2GB or 4GB RAM.

Basic Kit Version

Materials Required

You'll need a mouse, keyboard, monitor, wall adapter with minimum power requirements, and cables to begin. Once configured, the Pi can be operated from its own peripherals or another computer connected over the Internet.

Kit Versions

Each version includes a Raspberry Pi 4 with a different size RAM. Check out below for the different kit versions available!

  • Basic

Basic Kit Version

The basic kit offers the bare bones of what you need to get up and running. This is assuming that you have a monitor, keyboard, mouse, and card reader [1] on hand.

SparkFun Raspberry Pi 4 Basic Kit - 2GB

SparkFun Raspberry Pi 4 Basic Kit - 2GB

KIT-16383
$74.95
SparkFun Raspberry Pi 4 Basic Kit - 4GB

SparkFun Raspberry Pi 4 Basic Kit - 4GB

KIT-16384
$89.95

The connectors are different on the Pi 4 so you will need the appropriate cable adapters to power the Pi and display to a monitor.

Getting an OS

The microSD card included in the kit does not have an image flashed. You'll need to flash a microSD card if a Raspberry Pi image to the card or if it becomes corrupt. There are a few Linux-based images available depending on your application. For beginners, we recommend getting NOOBS. Otherwise, the Raspbian with the PIXEL desktop would be the best.

  • NOOBS (i.e. New Out-Of-the Box Software) - Contains Raspbian and LibreELEC. Other images can also be downloaded from the internet and installed.
  • Raspbian - Official Raspberry Pi Debian-based computer operating system. There are three downloads. We recommend the desktop version with recommended software. The other downloads are the same but with less software. For advanced users, Raspbian Lite is the minimal text-only version and requires users to navigate using the command line interface (CLI).
  • Other 3rd Party OS Images - There are other distributions available from third-party. If you are feeling adventurous, check out the other images available!

For the scope of this tutorial, we will summarize two of the images from the Pi foundation.

Flashing the Image NOOBS

If you decide to use NOOBS, you will need to:

  • Insert the microSD card into a card reader
  • Download the ZIP file for NOOBS


  • Extract the ZIP file
  • Format your Raspberry Pi's microSD card if needed
  • Copy all the contents from the unzipped folder into the microSD card
  • Eject the microSD card from your computer

Flashing the Image Raspbian and 3rd Party OS Images

Then follow the steps below to flash an image using the Raspberry Pi Imager.

  • Insert the microSD card and card reader into your computer's port.
  • Open the software imaging tool[2] of your choice (in this case, we'll use the Raspberry Pi Imager for your OS but you can use other images as well).


  • Press CHOOSE OS to select the Operating System from the list (in this case, we'll use one of the Raspbian images but you could use any of the 3rd party images ).
  • Press CHOOSE SD CARD to select mounted microSD Card.
  • Press Write (it will take a while depending on the image and microSD card so just do a little dance as you wait).
  • Eject the microSD card when finished.

Assembly

The Pi is straight-forward and easy to put together, but in the event that something doesn't seem right, this section will give you an idea of what it is supposed to look like.

Pi 4 Basic Kit in Parts

Unbox and gather these components before beginning the assembly

Attaching Peripherals

Attach desired consumer computer equipment. At a minimum to get up and running or navigate through the Pi, we recommend connecting:

  • monitor w/ HDMI port [3]
  • mini-HDMI to HDMI cable
  • keyboard & mouse
  • power supply [4]

Connecting Hardware

Need easy access to the GPIO pins on the board? If you ordered a Qwiic cable, Qwiic enabled device, and the basic kit version, take a look at the Qwiic SHIM to quickly access the I2C pins. Or if you included the Pi Wedge with prototyping parts in your order, check out the associated tutorial for the Pi Wedge to easily access the GPIO pins on a breadboard.

Qwiic SHIM for Raspberry Pi Hookup Guide

December 5, 2019

Ever wanted to prototype I2C components on a Pi? Now you can!

Preassembled 40-pin Pi Wedge Hookup Guide

October 29, 2015

Using the Preassembled Pi Wedge to prototype with the Raspberry Pi B+.

Methods of Working with the Pi

Once the Pi is configured, there are a few methods of using it depending on if you want to use it like a desktop or manage it remotely.

This section covers using the Pi in the following ways

  • Using HDMI-out with Monitor -- Operate your Pi like a desktop computer.
  • Headless without a Monitor
    • Using the serial terminal -- Some functionality.
    • Using SSH -- Operate through a network linked to another computer.
    • Using VNC -- Control the Pi's graphical desktop remotely over the Internet using a computer. This is useful if you decide to remotely connect to a Pi that may or may not be connected to a monitor.

Using HDMI-out with a Monitor

If this is the first time you are booting NOOBS, you'll need to connect your Raspberry Pi to a monitor and follow the installer. In the window, select Raspbian Full [RECOMMENDED] and click on the button to Install. You'll need to be patient as the software installs the OS to the microSD card. Once finished, click on OK. This will restart the Pi.

PIXEL Desktop (GUI)

By selecting NOOBS with Raspbian, it automatically logs in and starts a graphical user interface.

Once the desktop installs, follow the wizard to configure your Raspberry Pi!

Command Line Interface (CLI)

If configured to boot to shell, log in with the following credentials:

     username: pi
     password: raspberry

Then, enter startx in the command line to enter a graphical environment where you are presented with a desktop-type menu-driven operating system.

If you need to get back to text land, you can either

  • Log off through the Task Bar Menu
    • drops back to the shell, closing down the X window system
  • Open xterm from the Task Bar
    • opens a shell in a graphical window
  • Use CTRL+ALT+1 through CTRL+ALT+8
    • gives you a number of shells, with 7 being the graphic environment (if loaded).

Remember, shutdown with the menu item or enter the following command from a shell, and wait for the system to halt before removing power.

language:bash
sudo shutdown -h now

Headless without a Monitor

As an alternative, you can also log into the Pi as a "headless" computer. This is basically a Raspberry Pi without a monitor, keyboard, or mouse. You can decide to connect to the Pi using a serial UART or SSH. For advanced users, you will need to turn on the interfaces before you can take advantage of these setups.

Headless Raspberry Pi Setup

April 23, 2018

Configure a Raspberry Pi without a keyboard, mouse, or monitor.

How to Use Remote Desktop on the Raspberry Pi with VNC

July 9, 2018

Use RealVNC to connect to your Raspberry Pi to control the graphical desktop remotely across the network.

Configuring the Pi

This section goes over configuring the keyboard, wired, and wireless internet.

Configuring the Keyboard Layout raspi-config

The Raspbian distribution comes defaulted to European hardware. With US keyboards, the " (quotation mark) symbol is replaced by @ (commercial at) and our number sign # is replaced by the European pound sign £. This can make it aggravating when trying to #define things. Invoke the config tool with the following command in the command line:

language:bash
sudo raspi-config

Then take the following actions:

  • Set the default locale for the system

    • Select "Internationalisation Options"
    • Select "Change Locale"
    • Deselect en_GB.UTF-8 UTF-8
    • Select en_US.UTF-8 UTF-8, (Ok)
    • Set default to en_US.UTF-8, (Ok)
  • Change the keyboard layout -- from the Internationalisation Options menu,

    • Change Keyboard Layout
    • Leave set as: Generic 105-key (Intl) PC (Ok)
    • Select Other (Ok)
    • Select English (US) (Ok)
    • Select English (US) (Ok)
    • Select default (Ok)
    • Select No compose key (Ok)
    • Set Ctrl+Alt+Bksp function (Ok)
  • Finish with the dialog and get back to the shell

    • Try the " and # keys at the prompt. It may be necessary to restart the pi at this point.

Configuring the Internet Interfaces

Automatic Configuration

Raspbian does a good job of configuring wireless networks automatically. By default, DHCP is configured so that the Pi will receive an IP address when a network cable is plugged it to the Ethernet port or when a wireless network is connected.

To use the graphical network tool, right click on the icon on the right side of the task bar, and click "WiFi Networks (dhcpcdui) Settings". Then, select the interface desired (wlan0 or eth0) to disable the DHCP and set your own IP, if necessary.

To connect to a wireless network, click on the icon, select the desired network, and enter the password.

Hovering over the icon will bring up a status of wlan0 and eth0 that also shows the IP address.

Manual (text-based) Configuration

At this time, the network configuration works out of the box so there's really nothing to configure, but in case something goes awry, here's the basics of what can be played with and a known-working configuration to compare with.

A configuration file, interfaces, configures both wired and wireless devices. Enter the following command into a terminal to edit the interfaces file.

language:bash
sudo nano /etc/network/interfaces

Replace "nano" with "leafpad" if you prefer graphics. Here's what our Pi 3 is using:

language:bash
# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

iface eth0 inet manual

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

By default, this file is set up to get its configuration from /etc/wpa_supplicant/wpa_supplicant.conf, which is really the proper place for wifi information. Here are the contents:

language:bash
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
        ssid="myNetworkSSID"
        psk="mySuperSecurePassword"
        key_mgmt=WPA-PSK
}
A note on network configuration: Try the gui tool first, and only modify the files as a last resort. If you find the tool doesn't work, save your configuration files as a backup, and don't be afraid to try your hand at a manual configuration.

Applying the Changes

Sometimes the link should be cycled for a new configuration to take. Rather than shutting down the pi and restarting, use ifdown and ifup to bring the link down and back up.

For wireless connections, use

language:bash
sudo ifdown wlan

and

language:bash
sudo ifup wlan0

For wired connections, use

language:bash
sudo ifdown eth0

and

language:bash
sudo ifup eth0

Troubleshooting

Having issues getting the Raspberry Pi to work? Check out this sticky note from the Raspberry Pi Foundation's forum for basic troubleshooting.

Having problems with a piece of SparkFun hardware designed for the Raspberry Pi and interfacing it? Try checking out the SparkFun forums to see if we can assist.

Resources and Going Further

Raspberry Pi Accessories

If you are looking to add additional features, check out the accessories to power your Raspberry Pi remotely, build a homemade motion-activated security system, or go retro by building your own arcade controller to emulate classic video games!

PiJuice HAT - Raspberry Pi Portable Power Platform

PiJuice HAT - Raspberry Pi Portable Power Platform

PRT-14803
4
Raspberry Pi LCD - 7" Touchscreen

Raspberry Pi LCD - 7" Touchscreen

LCD-13733
$64.95$62.95
39
Raspberry Pi Camera Module V2

Raspberry Pi Camera Module V2

DEV-14028
$29.95$28.95
10
SparkFun PiRetrocade

SparkFun PiRetrocade

KIT-14007
$39.95
7


Here are some links to our other Pi resources.

Need some inspiration? Check out these tutorials and projects.

SD Cards and Writing Images

How to upload images to an SD card for Raspberry Pi, PCDuino, or your favorite SBC.

Headless Raspberry Pi Setup

Configure a Raspberry Pi without a keyboard, mouse, or monitor.

Qwiic pHAT for Raspberry Pi Hookup Guide

Get started interfacing your Qwiic enabled boards with your Raspberry Pi. The Qwiic pHAT connects the I2C bus (GND, 3.3V, SDA, and SCL) on your Raspberry Pi to an array of Qwiic connectors.

Qwiic SHIM for Raspberry Pi Hookup Guide

Ever wanted to prototype I2C components on a Pi? Now you can!

Or check out some of these blog posts for ideas.


learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Temperature Sensor Comparison

$
0
0

Temperature Sensor Comparison a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1164

Introduction

It all started when I wanted to measure the temperature of a room at SparkFun. But what is the best? Well, it depends on what you are looking for in your project. There are a lot of temperatures available. This article will compare a few of the more popular ones we carry.

Comparing Three Temperature Sensors

Required Materials

To follow along with this comparison guide, you will need the following parts at a minimum to connect to the sensors. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

SparkFun RedBoard Qwiic

SparkFun RedBoard Qwiic

DEV-15123
$19.95
5
Break Away Headers - Straight

Break Away Headers - Straight

PRT-00116
$1.50
20
USB micro-B Cable - 6 Foot

USB micro-B Cable - 6 Foot

CAB-10215
$4.95
13
Qwiic Cable - Breadboard Jumper (4-pin)

Qwiic Cable - Breadboard Jumper (4-pin)

PRT-14425
$1.50
Qwiic Cable - 50mm

Qwiic Cable - 50mm

PRT-14426
$0.95
Breadboard - Mini Modular (Blue)

Breadboard - Mini Modular (Blue)

PRT-12045
$3.95

Tools

Depending on your project, you may need a soldering iron, solder, and general soldering accessories.

Soldering Iron - 60W (Adjustable Temperature)

Soldering Iron - 60W (Adjustable Temperature)

TOL-14456
$14.95
8
Solder Lead Free - 15-gram Tube

Solder Lead Free - 15-gram Tube

TOL-09163
$3.50
2

Suggested Reading

If you aren’t familiar with the following concepts below or linked throughout the comparison guide, we recommend checking out these tutorials before continuing if you decide to recreate these tests.

How to Solder: Through-Hole Soldering

This tutorial covers everything you need to know about through-hole soldering.

Analog to Digital Conversion

The world is analog. Use analog to digital conversion to help digital devices interpret the world.

Analog vs. Digital

This tutorial covers the concept of analog and digital signals, as they relate to electronics.

Analog vs Digital Sensor

Before we compare temperature sensors, it would be good to know differences between an analog and digital sensor.

Analog Sensor

An analog sensor takes a reading and outputs a smooth, continuous signal.

example analog signal that is smoooth

Example of a smooth, continuous analog signal.

These are usually low cost and easy to use, which is great for beginners. However, they do require an analog-to-digital converter (ADC) to read the output. Microcontrollers (like an Arduino Uno/RedBoard Qwiic) have this built in (I've yet to come across one without an analog input). Single board computers (like the Raspberry Pi) on the other hand, do not have a hardware ADC and requires a dedicated chip to read the sensor.

Depending on the sensor, you may need to build an additional circuit to read or filter the signal. Sensor readings are more susceptible to noise from power supplies and other components in the circuit. The wire length may also affect the readings over long distances.

Digital Sensor

A digital sensor outputs a signal with discrete steps.

example digital signal that is discrete

Example of a discrete digital signal.

These can cost more. However, they are easier to include in a design since they require a serial protocol to the output. Microcontrollers and single board computers should have the basic serial protocols (I2C, UART, SPI) built in. You'll just need to make sure there is a library for the architecture and your preferred programming language.

Digital sensors may include additional features. No additional circuitry needs to be built if the chip is on a breakout board. These sensors are not as likely to be affected by the power supply and other components in the circuit. While serial protocols have limitations in the overall length, the sensor readings are not affect by the wire length like an analog sensor.

Round 1: TMP117 vs TMP102 vs TMP36

For simplicity, let's compare three temperature sensors from the SparkFun catalog in this round! We'll be measuring the ambient temperature of the air using these sensors.

Temperature Sensor - TMP36

Temperature Sensor - TMP36

SEN-10988
$1.50
16
SparkFun Digital Temperature Sensor Breakout - TMP102

SparkFun Digital Temperature Sensor Breakout - TMP102

SEN-13314
$5.95
4
SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SEN-15805
$13.95
1

TMP36

We'll connect the TMP36 using the circuit from the SIK.

Fritzing Circuit DiagramRedBoard Qwiic and TMP36 Connected
Fritzing Circuit DiagramRedBoard Qwiic and TMP36 Connected

Below is the modified example code from the SIK to output to the serial monitor. Grab the code and upload to your Arduino if you are trying to follow along!

language:c
/******************************************************************************
  TMP36.ino
  Written by Ho Yun "Bobby" Chan
  @ SparkFun Electronics
  Date: Nov 4, 2019
  https://gist.github.com/bboyho/c30b70fc308f41b92a6f1b07e5a54838

  Description: This sketch configures temperature sensor and prints the
  temperature in degrees celsius and fahrenheit. Simply adjust the `output_select`
  to view the °C, °F, or both. Open the Serial Monitor or Plotter at 115200 baud 
  to view the data.

  Development Environment Specifics:
  Arduino 1.8.9+

  License:
  This code is released under the MIT License (http://opensource.org/licenses/MIT)
  Distributed as-is; no warranty is given.

******************************************************************************/

//variables for TMP36
float tmp36_voltage = 0;                      //the voltage measured from the TMP36
float tmp36_degC = 0;                         //the temperature in Celsius, calculated from the voltage
float tmp36_degF = 0;                         //the temperature in Fahrenheit, calculated from the voltage

//0 = output degrees °C
//1 = output degrees °F
//any other number = output degrees °C and °F
int output_select = 1; //select output

void setup() {
  Serial.begin(115200);    // Start serial communication at 115200 baud
  if (output_select == 0 ) {
    Serial.println("TMP36[°C]");
  }
  else if (output_select == 1) {
    Serial.println("TMP36[°F]");
  }
  else {
    Serial.print("TMP36[°C]");
    Serial.print(",");
    Serial.println("TMP36[°F]");
  }
}// end setup

void loop() {
  //get TMP36 readings and calculate
  tmp36_voltage = analogRead(A0) * 0.004882814;   //convert the analog reading, which varies from 0 to 1023, back to a voltage value from 0-5 volts
  tmp36_degC = (tmp36_voltage - 0.5) * 100.0;     //convert the voltage to a temperature in degrees Celsius
  tmp36_degF = tmp36_degC * (9.0 / 5.0) + 32.0;   //convert the voltage to a temperature in degrees Fahrenheit

  if (output_select == 0 ) {
    // Print temperature in °C
    //Serial.print("Temperature in Celsius: ");
    Serial.println(tmp36_degC);//TMP36 temperature
  }
  else if (output_select == 1) {
    // Print temperature in °F
    //Serial.print("Temperature in Fahrenheit: ");
    Serial.println(tmp36_degF);

  }
  else {
    Serial.print(tmp36_degC);       //TMP36 temperature
    Serial.print(",");              //seperator
    Serial.println(tmp36_degF);
  }

  delay(5); // Delay added for easier readings

}//end loop

Let's observe the output that was taken at that moment to measure the ambient temperature of the room. The temperature reading seems to jump around between 75.5°F and 76.5°F. Other times, the output would spike. (This was probably due to the TMP36 being built on a breadboard or noise from the power supply). Adding a decoupling capacitor between Vcc and GND helped smooth the signal but I would still get small spikes in the readings.

TMP36 Output on the Arduino Serial Plotter

Click image for a closer view.

TMP102 vs TMP36

Can we get a more precise reading? Why yes we can! Let's try using a digital temperature sensor to compare. I soldered headers to the TMP102 and included it on the breadboard based off the TMP102 hookup guide. Using the Qwiic cable to breadboard adapter made it quick to connect the sensor to the RedBoard.

Fritzing Circuit DiagramRedBoard Qwiic, TMP36, and TMP102 Connected
Fritzing Circuit DiagramRedBoard Qwiic, TMP36, and TMP102 Connected

The code was adjusted to output both the TMP36 and TMP102 in the serial monitor for comparison. Additionally, address of the TMP102 was adjusted to 0x49 to compare with the TMP117. Grab the code and upload it to your Arduino if you are trying to follow along!

language:c
/******************************************************************************
  TMP102vsTMP36.ino
  Written by: Ho Yun "Bobby" Chan
  @ SparkFun Electronics
  Date: Nov 4, 2019

  Description: This sketch configures temperature sensors and prints the
  temperature in degrees celsius and fahrenheit. For comparison, the
  TMP102 and TMP36 temperature sensor is also printed to compare the output
  in degrees celsius and fahrenheit. Simply adjust the `output_select`
  to view the °C, °F, or both. Open the Serial Monitor or Plotter at 115200 baud 
  to view the data.

  Resources/Libraries:
  Wire.h (included with Arduino IDE)
  SparkFunTMP102.h (included in the src folder) https://github.com/sparkfun/SparkFun_TMP102_Arduino_Library

  Development Environment Specifics:
  Arduino 1.8.9+

  License:
  This code is released under the MIT License (http://opensource.org/licenses/MIT)
  Distributed as-is; no warranty is given.

******************************************************************************/

#include <Wire.h>            // Used to establish serial communication on the I2C bus
#include "SparkFunTMP102.h" // Used to send and recieve specific information from our sensor

// The default address of the device is 0x48 = (GND) like the TMP117
// but it's already being used so we use a different address
TMP102 sensor0(0x49); //initialize sensor

//variables for TMP36
float tmp36_voltage = 0;                          //the voltage measured from the TMP36
float tmp36_degC = 0;                         //the temperature in Celsius, calculated from the voltage
float tmp36_degF = 0;                         //the temperature in Fahrenheit, calculated from the voltage


//0 = output degrees °C
//1 = output degrees °F
//any other number = output degrees °C and °F
int output_select = 1; //select output

void setup()
{
  //Wire.begin();
  sensor0.begin();
  Serial.begin(115200);    // Start serial communication at 115200 baud
  Wire.setClock(400000);   // Set clock speed to be the fastest for better communication (fast mode)


  sensor0.wakeup();//turn on TMP102

  if (output_select == 0 ) {
    Serial.println("TMP102[°C]");
    Serial.print(",");
    Serial.println("TMP36[°C]");

  }
  else if (output_select == 1) {
    Serial.print("TMP102[°F]");
    Serial.print(",");
    Serial.println("TMP36[°F]");
  }
  else {
    Serial.println("TMP102[°C]");
    Serial.print(",");
    Serial.print("TMP36[°C]");
    Serial.print(",");
    Serial.print("TMP102[°F]");
    Serial.print(",");
    Serial.println("TMP36[°F]");
  }
}

void loop()
{

  //get TMP102 sensor readings
  float tmp102_tempC = sensor0.readTempC();
  float tmp102_tempF = sensor0.readTempF();

  //get TMP36 readings and calculate
  tmp36_voltage = analogRead(A0) * 0.004882814;   //convert the analog reading, which varies from 0 to 1023, back to a voltage value from 0-5 volts
  tmp36_degC = (tmp36_voltage - 0.5) * 100.0;       //convert the voltage to a temperature in degrees Celsius
  tmp36_degF = tmp36_degC * (9.0 / 5.0) + 32.0; //convert the voltage to a temperature in degrees Fahrenheit


  if (output_select == 0 ) {
    // Print temperature in °C
    //Serial.print("Temperature in Celsius: ");
    Serial.println(tmp102_tempC);  //TMP102 temperature
    Serial.print(",");  //seperator
    Serial.println(tmp36_degC);//TMP36 temperature
  }
  else if (output_select == 1) {
    // Print temperature in °F
    //Serial.print("Temperature in Fahrenheit: ");
    Serial.print(tmp102_tempF);  //TMP102 temperature
    Serial.print(",");  //seperator
    Serial.println(tmp36_degF);

  }
  else {
    Serial.print(tmp102_tempC);//TMP102 temperature
    Serial.print(",");  //seperator
    Serial.print(tmp36_degC);//TMP36 temperature
    Serial.print(",");  //seperator
    Serial.print(tmp102_tempF);
    Serial.print(",");              //seperator
    Serial.println(tmp36_degF);
  }

  delay(50); // Delay added for easier readings
}

After taking a set of datapoints at a different moment to measure the ambient temperature of the room, the TMP102 performed better. The temperature readings remained stable and was not as noisy. It is a bit difficult to see in the graph but by opening the serial monitor, the temperature readings only jump around 76.52°F and 76.64°F.

TMP36 and TMP102 Output on the Arduino Serial Plotter

Click image for a closer view.

TMP117 vs TMP102 vs TMP36

Not bad but can we get an even better temperature reading? Why yes we can! Connecting the TMP117 was easier since all that was needed for the circuit was to add a Qwiic cable between the RedBoard Qwiic and the TMP117.

Fritzing Circuit DiagramRedBoard Qwiic, TMP36, TMP102, and TMP117 Connected
Fritzing Circuit DiagramRedBoard Qwiic, TMP36, TMP102, and TMP117 Connected

The code was adjusted once again to compare the TMP117 against the other sensors. Grab the code and upload it to your Arduino if you are trying to follow along!

language:c
/******************************************************************************
  TMP117vsTMP102vsTMP36.ino
  Written by: Ho Yun "Bobby" Chan
  @ SparkFun Electronics
  Date: Nov 4, 2019

  Description: This sketch configures temperature sensors and prints the
  temperature in degrees celsius and fahrenheit. For comparison, the
  TMP117, TMP102, and TMP36 temperature sensor is also printed to compare the output
  in degrees celsius and fahrenheit. Simply adjust the `output_select`
  to view the °C, °F, or both. Open the Serial Monitor or Plotter at 115200 baud 
  to view the data.

  Resources/Libraries:
  Wire.h (included with Arduino IDE)
  SparkFunTMP117.h (included in the src folder) http://librarymanager/All#SparkFun_TMP117
  SparkFunTMP102.h (included in the src folder) https://github.com/sparkfun/SparkFun_TMP102_Arduino_Library

  Development Environment Specifics:
  Arduino 1.8.9+

  License:
  This code is released under the MIT License (http://opensource.org/licenses/MIT)
  Distributed as-is; no warranty is given.

******************************************************************************/

/*
  NOTE: For the most accurate readings using the TMP117:
  - Avoid heavy bypass traffic on the I2C bus
  - Use the highest available communication speeds
  - Use the minimal supply voltage acceptable for the system
  - Place device horizontally and out of any airflow when storing
  For more information on reaching the most accurate readings from the sensor,
  reference the "Precise Temperature Measurements with TMP116" datasheet that is
  linked on Page 35 of the TMP117's datasheet
*/

#include <Wire.h>            // Used to establish serial communication on the I2C bus
#include <SparkFun_TMP117.h> // Used to send and recieve specific information from our sensor
#include "SparkFunTMP102.h" // Used to send and recieve specific information from our sensor

// The default address of the device is 0x48 = (GND)
TMP117 sensor; // Initalize sensor

// The default address of the device is 0x48 = (GND) as well
// but it's already being used so we use a different address
TMP102 sensor0(0x49); //initialize sensor

//variables for TMP36
float tmp36_voltage = 0;                          //the voltage measured from the TMP36
float tmp36_degC = 0;                         //the temperature in Celsius, calculated from the voltage
float tmp36_degF = 0;                         //the temperature in Fahrenheit, calculated from the voltage


//0 = output degrees °C
//1 = output degrees °F
//any other number = output degrees °C and °F
int output_select = 1; //select output

void setup()
{
  //Wire.begin();
  sensor0.begin();
  Serial.begin(115200);    // Start serial communication at 115200 baud
  Wire.setClock(400000);   // Set clock speed to be the fastest for better communication (fast mode)

  //Serial.println("TMP117 Example 1: Basic Readings");
  if (sensor.begin() == true ) // Function to check if the sensor will correctly self-identify with the proper Device ID/Address
  {
    //Serial.println("Begin");

    sensor0.wakeup();//turn on TMP102

    if (output_select == 0 ) {
      Serial.print("TMP117[°C]");
      Serial.print(",");
      Serial.println("TMP102[°C]");
      Serial.print(",");
      Serial.println("TMP36[°C]");

    }
    else if (output_select == 1) {
      Serial.print("TMP117[°F]");
      Serial.print(",");
      Serial.print("TMP102[°F]");
      Serial.print(",");
      Serial.println("TMP36[°F]");
    }
    else {
      Serial.print("TMP117[°C]");
      Serial.print(",");
      Serial.println("TMP102[°C]");
      Serial.print(",");
      Serial.print("TMP36[°C]");
      Serial.print(",");
      Serial.print("TMP117[°F]");
      Serial.print(",");
      Serial.print("TMP102[°F]");
      Serial.print(",");
      Serial.println("TMP36[°F]");
    }
  }
  else
  {
    Serial.println("Device failed to setup- Freezing code.");
    while (1); // Runs forever
  }
}

void loop()
{
  // Data Ready is a flag for the conversion modes - in continous conversion the dataReady flag should always be high
  if (sensor.dataReady() == true) // Function to make sure that there is data ready to be printed, only prints temperature values when data is ready
  {
    //get TMP117 sensor readings
    float tempC = sensor.readTempC();
    float tempF = sensor.readTempF();

    //get TMP102 sensor readings
    float tmp102_tempC = sensor0.readTempC();
    float tmp102_tempF = sensor0.readTempF();

    //get TMP36 readings and calculate
    tmp36_voltage = analogRead(A0) * 0.004882814;   //convert the analog reading, which varies from 0 to 1023, back to a voltage value from 0-5 volts
    tmp36_degC = (tmp36_voltage - 0.5) * 100.0;       //convert the voltage to a temperature in degrees Celsius
    tmp36_degF = tmp36_degC * (9.0 / 5.0) + 32.0; //convert the voltage to a temperature in degrees Fahrenheit


    if (output_select == 0 ) {
      // Print temperature in °C
      //Serial.print("Temperature in Celsius: ");
      Serial.print(tempC);//TMP117 temperature
      Serial.print(",");  //seperator
      Serial.println(tmp102_tempC);  //TMP102 temperature
      Serial.print(",");  //seperator
      Serial.println(tmp36_degC);//TMP36 temperature
    }
    else if (output_select == 1) {
      // Print temperature in °F
      //Serial.print("Temperature in Fahrenheit: ");
      Serial.print(tempF);
      Serial.print(",");              //seperator
      Serial.print(tmp102_tempF);  //TMP102 temperature
      Serial.print(",");  //seperator
      Serial.println(tmp36_degF);

    }
    else {
      Serial.print(tempC);//TMP117 temperature
      Serial.print(",");  //seperator
      Serial.print(tmp102_tempF);  //TMP102 temperature
      Serial.print(",");  //seperator
      Serial.print(tmp36_degC);//TMP36 temperature
      Serial.print(",");  //seperator
      Serial.print(tempF);
      Serial.print(",");  //seperator
      Serial.print(tmp102_tempF);  //TMP102 temperature
      Serial.print(",");              //seperator
      Serial.println(tmp36_degF);
    }

    //delay(5); // Delay added for easier readings
  }
}

After taking another set of datapoints at a different time, the TMP117 performed better than the TMP102 and TMP36. The datapoints were more smooth and less prone to noise. Looking closer at the values via the serial monitor, the temperature readings would jump between 75.99°F and 76.02°F with the TMP117. In one instance, the TMP36's output started spiking just was we saw in the initial tests using a TMP36.

TMP36, TMP102, TMP117 Output on the Arduino Serial PlotterTMP36, TMP102, TMP117 Output with Spikes in Readings on the Arduino Serial Plotter
Click image for a closer view.

Good, Better, Best? Which is the Best?

So, you might ask, which of the three temperature sensors is the best? Well, that really depends on how you plan to use it. In my opinion, the Qwiic TMP117 is a winner in my eyes for this round. It is able to measure the temperature of a room without a lot of jitter and it was easy to connect with the Qwiic system. The sensors performed as expected when looking at the datasheet. The board did not require any soldering. There was no additional circuitry that needed to build or code needed to average the temperature sensor readings. The power supply did not cause as much of a fluctuation with the digital temperature sensors like the analog temperature sensor.

The TMP102 could work as well if I was not looking for such precise temperature reading of the room. While it is not as expensive as the TMP117, it does require some soldering for this version of the TMP102 board. The TMP36 is good but it would require a bit more effort to filter out the errors.

Other Considerations

For simplicity, three sensors were used as a comparison out of the box to measure the ambient temperature of the air. This did not take into account other factors such as:

  • offset temperature of each sensor
  • other microcontrollers with higher ADC to compare the analog sensor
  • range (e.g. are you measuring the temperature of an object at room temperature or in an oven)
  • medium (e.g. are you measuring the temperature of an object in air or submerged in water)
  • current consumption
  • temperature sensors that have the ability to also measure the humidity, barometric pressure, and altitude

Improving TMP36 Readings

There are also techniques to improve on the TMP36 temperature readings that were:

Resources and Going Further

Looking for more temperature related fun? Check out these other related tutorials from SparkFun.

MAX31855K Thermocouple Breakout Hookup Guide

Learn how to take readings with a k-type thermocouple using the MAX31855K cold-junction-compensated k-type thermocouple-to-digital converter.

HIH-4030 Humidity Sensor Hookup Guide

Measure relative humidity with SparkFun's HIH-4030 Humidity Sensor Breakout.

RHT03 (DHT22) Humidity and Temperature Sensor Hookup Guide

Measure relative humidity and temperature or your environment with the RHT03 (a.k.a DHT22) low cost sensor on a single wire digital interface connected to an Arduino!

Qwiic Atmospheric Sensor (BME280) Hookup Guide

Measure temperature, humidity, barometric pressure with the SparkFun Atmospheric Sensor Breakout BME280 (Qwiic).

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

SparkFun Qwiic Shield for Thing Plus Hookup Guide

$
0
0

SparkFun Qwiic Shield for Thing Plus Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1107

Introduction

The SparkFun Qwiic Shield for Thing Plus provides an easy-to-assemble way to add the SparkFun Qwiic ecosystem to any development board with the Thing Plus Footprint. This shield is also compatible with the Feather Footprint so you can add Qwiic functionality to any development board that uses the Thing Plus or Feather Footprints! It connects the I2C bus (GND, 3.3V, SDA, and SCL) on your Thing Plus to four SparkFun Qwiic connectors. The Qwiic ecosystem allows for easy daisy chaining so, as long as your devices are on different addresses, you can connect as many Qwiic devices as you'd like.

SparkFun Qwiic Shield for Thing Plus

SparkFun Qwiic Shield for Thing Plus

DEV-16138
$3.50

Required Materials

To follow along with this tutorial, you will need an Arduino development board with the Thing Plus footprint. This includes the all variants of the SparkFun Thing Plus boards and many other Thing Plus-compatible boards! Here are a few of the compatible boards:

SparkFun Thing Plus - ESP32 WROOM

SparkFun Thing Plus - ESP32 WROOM

WRL-15663
$20.95
1
SparkFun Thing Plus - Artemis

SparkFun Thing Plus - Artemis

WRL-15574
$20.95
SparkFun Thing Plus - SAMD51

SparkFun Thing Plus - SAMD51

DEV-14713
$19.95
1

You will also need some headers to solder to both your Thing Plus and Qwiic Shield:

Break Away Headers - Straight

Break Away Headers - Straight

PRT-00116
$1.50
20
Female Headers

Female Headers

PRT-00115
$1.50
7
Break Away Headers - Long

Break Away Headers - Long

PRT-10158
$2.95
3
Feather Stackable Header Kit

Feather Stackable Header Kit

PRT-15187
$1.50

Now you probably would not want the Qwiic Shield for Thing Plus if you didn't have any Qwiic products to use with it, right? Well, if you don't have any Qwiic products, the following might not be a bad place to start:

SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic)

SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic)

GPS-15712
$64.95
2
SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SparkFun High Precision Temperature Sensor - TMP117 (Qwiic)

SEN-15805
$13.95
1
SparkFun Qwiic Motor Driver

SparkFun Qwiic Motor Driver

ROB-15451
$14.95
1
SparkFun Proximity Sensor Breakout - 20cm, VCNL4040 (Qwiic)

SparkFun Proximity Sensor Breakout - 20cm, VCNL4040 (Qwiic)

SEN-15177
$6.95

You will need some of our Qwiic cables to connect your devices to the shield. Below are a few options:

Qwiic Cable - 100mm

Qwiic Cable - 100mm

PRT-14427
$1.50
Qwiic Cable - 200mm

Qwiic Cable - 200mm

PRT-14428
$1.50
Qwiic Cable - 50mm

Qwiic Cable - 50mm

PRT-14426
$0.95
Qwiic Cable - 500mm

Qwiic Cable - 500mm

PRT-14429
$1.95

Lastly, if you want to use a non-Qwiic I2C device, these adapters help to convert it to a Qwiic connector:

Qwiic Cable - Breadboard Jumper (4-pin)

Qwiic Cable - Breadboard Jumper (4-pin)

PRT-14425
$1.50
SparkFun Qwiic Adapter

SparkFun Qwiic Adapter

DEV-14495
$1.50
Qwiic Cable - Female Jumper (4-pin)

Qwiic Cable - Female Jumper (4-pin)

CAB-14988
$1.50

Required Tools

You will need a soldering iron, solder, and general soldering accessories to solder the header pins to the Qwiic shields:

Soldering Iron - 30W (US, 110V)

Soldering Iron - 30W (US, 110V)

TOL-09507
$9.95
7
Solder Lead Free - 15-gram Tube

Solder Lead Free - 15-gram Tube

TOL-09163
$3.50
2

Suggested Reading

If you aren't familiar with the Qwiic system, we recommend reading here for an overview:

Qwiic Connect System
Qwiic Connect System

We would also recommend taking a look at the following tutorials if you aren't familiar with them:

How to Solder: Through-Hole Soldering

This tutorial covers everything you need to know about through-hole soldering.

Arduino Shields

All things Arduino Shields. What they are and how to assemble them.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

Hardware Overview

Qwiic Connectors

The Qwiic Shield for Thing Plus has four Qwiic connectors on it. The two on the edges are the standard horizontal connectors and the two in the middle are vertical connectors.

Image highlighting Qwiic Connectors

I2C Jumper

This jumper is a little different than our normal I2C pull up jumpers as it is open by default. The jumper only needs to be closed if your slave device does not have pull up resistors. Essentially all SparkFun I2C breakouts come with pull up resistors on them so if you are using a Qwiic I2C device or another SparkFun I2C device, you can most likely leave it open. When closed, the SDA and SCL lines are pulled to 3.3V by 4.7K resistors. If you have never worked with solder jumpers before, check out this tutorial for some tips and tricks for working with them.

Image higlighting I2C Jumper

Board Dimensions

The shield measures 2.00in x 0.90in (50.8mm x 22.86mm) and has four mounting holes that fit a 4-40 screw.

Dimensional Drawing for Qwiic Shield for Thing Plus

Hardware Assembly

All you need to get started using the Qwiic Shield for Thing Plus is to solder whichever headers you choose to the shield and, if necessary, to your Thing Plus (or compatible board). If you have never worked with an Arduino Shield before or need some tips, our Arduino Shields Tutorial provides detailed instructions on how to assemble and use them.

Once you have soldered headers to your shield and connected it to your Thing Plus, it's time to start connecting Qwiic devices! Below you can see the Qwiic Shield connected to a SparkFun Thing Plus - SAMD51 using the Feather Stackable Header Kit along with a couple of Qwiic Devices chained to it.

Qwiic Shield connected to a Thing Plus board with two Qwiic devices.

Resources and Going Further

For more information, take a look at the resources below.

If you are having trouble getting your Qwiic devices to connect using your newly assembled Qwiic Shield, you may want to take a look at these tutorials for help troubleshooting and reworking your shield.

Now that you have your Qwiic Shield ready to go, it's time to check out some Qwiic-enabled products. Below are a few to get started.

SparkFun Spectral Sensor Breakout - AS7263 NIR (Qwiic)

SparkFun Spectral Sensor Breakout - AS7263 NIR (Qwiic)

SEN-14351
$25.95
2
SparkFun Distance Sensor Breakout - 4 Meter, VL53L1X (Qwiic)

SparkFun Distance Sensor Breakout - 4 Meter, VL53L1X (Qwiic)

SEN-14722
$21.95
8
SparkFun Pro nRF52840 Mini - Bluetooth Development Board

SparkFun Pro nRF52840 Mini - Bluetooth Development Board

DEV-15025
$29.95
SparkFun Advanced Autonomous Kit for Sphero RVR

SparkFun Advanced Autonomous Kit for Sphero RVR

KIT-15303
$164.95

Before you go, here are some other tutorials using the Qwiic Connect System you may want to look through:

Three Quick Tips About Using U.FL

Quick tips regarding how to connect, protect, and disconnect U.FL connectors.

Hookup Guide for the SparkFun RedBoard Artemis

Get started with the RedBoard Artemis - all the functionality of the SparkFun Artemis module wrapped in the familiar Uno footprint

Qwiic Atmospheric Sensor (BME280) Hookup Guide

Measure temperature, humidity, barometric pressure with the SparkFun Atmospheric Sensor Breakout BME280 (Qwiic).
New!

Temperature Sensor Comparison

A comparison of analog and digital temperature sensors. Which is better?

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

SparkFun Qwiic Digital Temperature Sensor - TMP102 Hookup Guide

$
0
0

SparkFun Qwiic Digital Temperature Sensor - TMP102 Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1002

Introduction

We all like to know the temperature, right? Well, with the SparkFun Digital Temperature Sensor - TMP102 (Qwiic) we've made this just about as easy as it gets. Based off of the original Digital Temperature Sensor Breakout - TMP102, we've added Qwiic connectors to bring this bad boy into our plug-and-play Qwiic Ecosystem, made the board just a bit bigger at 1" x1", and added an address jumper instead of breaking out the address pin. Let's dive in and have some fun!

SparkFun Digital Temperature Sensor - TMP102 (Qwiic)

SparkFun Digital Temperature Sensor - TMP102 (Qwiic)

SEN-16304
$5.95

Required Materials

To follow along with this tutorial, you will need the following materials. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

Suggested Reading

If you aren't familiar with the Qwiic system, we recommend reading here for an overview.

Qwiic Connect System
Qwiic Connect System

We would also recommend taking a look at the following tutorials if you aren't familiar with them.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

Analog vs. Digital

This tutorial covers the concept of analog and digital signals, as they relate to electronics.

Serial Terminal Basics

This tutorial will show you how to communicate with your serial devices using a variety of terminal emulator applications.
New!

Temperature Sensor Comparison

A comparison of analog and digital temperature sensors. Which is better?

Hardware Overview

TMP102

Have you heard the phrase "Good things come in small packages"? Well, here's is a prime example! This board centers around Texas Instruments' TMP102 Low-Power Digital Temperature Sensor. This tiny little chip measures 1.6-mm × 1.6-mm and packs quite a nice punch. Here are some of the highlights, but feel free to check out the Datasheet for more information.

Highlights:

  • Uses the I2C interface
  • 12-bit, 0.0625°C resolution
  • Typical temperature accuracy of ±0.5°C
  • Supports up to four TMP102 sensors on the I2C bus at a time

TMP102 Highlight

Power

Ideally, power will be supplied via the Qwiic connectors on either side of the board. Alternatively, power can be supplied through the header along the bottom side of the board labeled 3V3 and GND. The input voltage range should be between 1.4-3.6V.

Power Options Highlighted

Qwiic Connectors

Our Qwiic Ecosystem makes sensors pretty much plug and play. There are two Qwiic connectors on either side of the Qwiic Temperature Sensor - TMP102 board to provide power and I2C connectivity simultaneously.

The I2C address of the board is 0x48 by default , but has 3 other addresses the board can be configured to use.

QWiic connectors highlighted

I2C Pins

The I2C pins break out the functionality of the Qwiic connectors. Depending on your application, you can connect to these pins via the plated through holes for SDA and SCL.

I2C PTH highlighted

Alert Pin

The alert pin is an over temperature alert, which has an open-drain and is pulled up through a 10kΩ resistor. The alert can also be read over I2C as shown in the example in the Software Setup and Programming section.

Alert Pin Highlighted

Jumpers

I2C Jumpers

Like most (if not all) of our Qwiic boards, the TMP102 Temperature Sensor comes equipped with a pull-up resistor. If you are daisy-chaining multiple Qwiic devices, you will want to cut this jumper; if multiple sensors are connected to the bus with the pull-up resistors enabled, the parallel equivalent resistance will create too strong of a pull-up for the bus to operate correctly. As a general rule of thumb, disable all but one pair of pull-up resistors if multiple devices are connected to the bus. To disable the pull up resistors, use an X-acto knife to cut the joint between the two jumper pads highlighted below.

I2C Jumper location highlighted

ADDR Jumpers

The default I2C address of the board is 0x48. To change the address, cut the jumper connecting the two pads closest to the 0x48 label. Soldering one of the center pads to one of the outer most pads will change the boards address to the matching label. The TMP102's address is determined by connecting the address pin directly to one of the following:

ADDRAddress
GND0x48
3V30x49
SDA0x4A
SCL0x4B



ADDR Jumper location highlighted

LED Jumpers

Cutting this jumper will disable the Power LED on the front of the board.

LED Jumper location highlighted

Board Dimensions

Image showing the board's dimensions from Eagle

Click on the image for a closer view

Hardware Assembly

With the Qwiic ecosystem, getting up and running is easy! Just plug one end of your Qwiic cable into your TMP102 sensor and the other into the Qwiic port on your RedBoard Qwiic. Voila! You're ready to sense some temperatures!

Hooking up TMP102 via qwiic connectors to redboard qwiic

Click the image for a closer view.

Software Setup and Programming

Note: This code/library has been written and tested on Arduino IDE version 1.8.10. Otherwise, make sure you are using the latest stable version of the Arduino IDE on your desktop.

If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

The Qwiic version of this board uses the same Arduino library as the original board. You can obtain this library through the Arduino Library Manager by searching for SparkFun TMP102. If you prefer downloading libraries manually, you can grab it from the GitHub Repository.

Once the library is installed, open Arduino, and expand the examples menu. You should see the TMP102 example.

Example from Library

TMP102 Library Overview

Main functions

These are functions used to read settings and temperatures from the sensor.

  • bool begin( uint8_t deviceAddress, TwoWire &wirePort ) - Takes the device address and I2C bus as optional inputs. If left blank, this function uses the default address 0x48, and uses the Wire bus.

  • float readTempC( void ) - Returns the current temperature in Celsius.

  • float readTempF( void ) - Returns the current temperature in Fahrenheit.

  • float readLowTempC( void ) - Reads T_LOW register in Celsius.

  • float readHighTempC( void ) - Reads T_HIGH register in Celsius.

  • float readLowTempF( void ) - Reads T_LOW register in Fahrenheit.

  • float readHighTempC( void ) - Reads T_HIGH register in Fahrenheit.

  • void sleep( void ) - Put TMP102 in low power mode (<0.5 uA).

  • void wakeup( void ) - Return to normal power mode (~10 uA). When the sensor powers up, it is automatically running in normal power mode, and only needs to be used after * sleep() is used.

  • bool alert( void ) - Returns the state of the Alert register. The state of the register is the same as the alert pin.

  • void setLowTempC(float temperature) - Sets T_LOW (in Celsius) alert threshold.

  • void setHighTempC(float temperature) - Sets T_HIGH (in Celsius) alert threshold.

  • void setLowTempF(float temperature) - Sets T_LOW (in Fahrenheit) alert threshold.

  • void setHighTempF(float temperature) - Sets T_HIGH (in Fahrenheit) alert threshold.

  • void setConversionRate(uint8_t rate) - Sets the temperature reading conversion rate. 0: 0.25Hz, 1: 1Hz, 2: 4Hz (default), 3: 8Hz.

  • void setExtendedMode(bool mode) - Enable or disable extended mode. 0: disabled (-55C to +128C), 1: enabled (-55C to +150C).

  • void setAlertPolarity(bool polarity) - Sets the polarity of the alert. 0: active LOW, 1: active HIGH

  • void setFault(uint8_t faultSetting) - Sets the number of consecutive faults before triggering alert. 0: 1 fault, 1: 2 faults, 2: 4 faults, 3: 6 faults.

  • void setAlertMode(bool mode) - Sets the type of alert. 0: Comparator Mode (Active from when temperature > T_HIGH until temperature < T_LOW), 1: Thermostat mode (Active from when temperature > T_HIGH until any read operation occurs.

Example Code

Once the library is installed, open the example code to get started! Make sure to select your board and COM port before hitting upload to begin experimenting with the temperature sensor.

language:c
/******************************************************************************
TMP102_example.ino
Example for the TMP102 I2C Temperature Sensor
Alex Wende @ SparkFun Electronics
April 29th 2016
~

This sketch configures the TMP102 temperature sensor and prints the
temperature and alert state (both from the physical pin, as well as by
reading from the configuration register.

Resources:
Wire.h (included with Arduino IDE)
SparkFunTMP102.h

Development environment specifics:
Arduino 1.0+

This code is beerware; if you see me (or any other SparkFun employee) at
the local, and you've found our code helpful, please buy us a round!

Distributed as-is; no warranty is given.   
******************************************************************************/

// Include the SparkFun TMP102 library.
// Click here to get the library: http://librarymanager/All#SparkFun_TMP102

#include <Wire.h> // Used to establied serial communication on the I2C bus
#include <SparkFunTMP102.h> // Used to send and recieve specific information from our sensor

// Connections
// VCC = 3.3V
// GND = GND
// SDA = A4
// SCL = A5
const int ALERT_PIN = A3;

TMP102 sensor0;

void setup() {
  Serial.begin(115200);
  Wire.begin(); //Join I2C Bus

  pinMode(ALERT_PIN,INPUT);  // Declare alertPin as an input

  /* The TMP102 uses the default settings with the address 0x48 using Wire.

     Optionally, if the address jumpers are modified, or using a different I2C bus,
     these parameters can be changed here. E.g. sensor0.begin(0x49,Wire1)

     It will return true on success or false on failure to communicate. */
  if(!sensor0.begin())
  {
    Serial.println("Cannot connect to TMP102.");
    Serial.println("Is the board connected? Is the device ID correct?");
    while(1);
  }

  Serial.println("Connected to TMP102!");
  delay(100);

  // Initialize sensor0 settings
  // These settings are saved in the sensor, even if it loses power

  // set the number of consecutive faults before triggering alarm.
  // 0-3: 0:1 fault, 1:2 faults, 2:4 faults, 3:6 faults.
  sensor0.setFault(0);  // Trigger alarm immediately

  // set the polarity of the Alarm. (0:Active LOW, 1:Active HIGH).
  sensor0.setAlertPolarity(1); // Active HIGH

  // set the sensor in Comparator Mode (0) or Interrupt Mode (1).
  sensor0.setAlertMode(0); // Comparator Mode.

  // set the Conversion Rate (how quickly the sensor gets a new reading)
  //0-3: 0:0.25Hz, 1:1Hz, 2:4Hz, 3:8Hz
  sensor0.setConversionRate(2);

  //set Extended Mode.
  //0:12-bit Temperature(-55C to +128C) 1:13-bit Temperature(-55C to +150C)
  sensor0.setExtendedMode(0);

  //set T_HIGH, the upper limit to trigger the alert on
  sensor0.setHighTempF(82.0);  // set T_HIGH in F
  //sensor0.setHighTempC(29.4); // set T_HIGH in C

  //set T_LOW, the lower limit to shut turn off the alert
  sensor0.setLowTempF(81.0);  // set T_LOW in F
  //sensor0.setLowTempC(26.67); // set T_LOW in C
}

void loop()
{
  float temperature;
  boolean alertPinState, alertRegisterState;

  // Turn sensor on to start temperature measurement.
  // Current consumtion typically ~10uA.
  sensor0.wakeup();

  // read temperature data
  temperature = sensor0.readTempF();
  //temperature = sensor0.readTempC();

  // Check for Alert
  alertPinState = digitalRead(ALERT_PIN); // read the Alert from pin
  alertRegisterState = sensor0.alert();   // read the Alert from register

  // Place sensor in sleep mode to save power.
  // Current consumtion typically <0.5uA.
  sensor0.sleep();

  // Print temperature and alarm state
  Serial.print("Temperature: ");
  Serial.print(temperature);

  Serial.print("\tAlert Pin: ");
  Serial.print(alertPinState);

  Serial.print("\tAlert Register: ");
  Serial.println(alertRegisterState);

  delay(1000);  // Wait 1000ms
}

Troubleshooting

Resources and Going Further

Want more information on the Qwiic TMP102? Check out these links!

Need more inspiration? Check out our Qwiic line of products:

RedBoard Qwiic Hookup Guide

This tutorial covers the basic functionality of the RedBoard Qwiic. This tutorial also covers how to get started blinking an LED and using the Qwiic system.

SparkFun GPS Breakout (ZOE-M8Q and SAM-M8Q) Hookup Guide

The SparkFun ZOE-M8Q and SAM-M8Q are two similarly powerful GPS units but with different project applications. We'll compare both chips before getting each up and running.

Hookup Guide for the BlackBoard Artemis ATP

Get started with the BlackBoard Artemis ATP - all the functionality of the SparkFun Artemis module wrapped in the Mega Arduino Footprint

Power Delivery Board - USB-C (Qwiic) Hookup Guide

This guide will go over how to use the USB Type-C Power Delivery Board.

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Assembly Guide for SparkFun JetBot AI Kit V2.0

$
0
0

Assembly Guide for SparkFun JetBot AI Kit V2.0 a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t1165

Introduction

SparkFun’s version of the JetBot merges the industry leading machine learning capabilities of the NVIDIA Jetson Nano with the vast SparkFun ecosystem of sensors and accessories. Packaged as a ready-to-assemble robotics platform, the SparkFun JetBot AI Kit v2.0 requires no additional components or 3D printing to get started - just assemble the robot, boot up the Jetson Nano, connect to WiFi and start using the JetBot immediately. This combination of advanced technologies in a ready-to-assemble package makes the SparkFun JetBot Kit a standout, delivering one of the strongest robotics platforms on the market. This guide serves as hardware assembly instructions for the JetBot AI Kit v2.0. The SparkFun JetBot comes with a pre-flashed micro SD card image that includes the Nvidia JetBot base image with additional installations of the SparkFun Qwiic Python library, Edimax WiFi driver, AWS RoboMaker ready with AWS IoT Greengrass, and of course the JetBot ROS. Users only need to plug in the SD card and set up the WiFi connection to get started.

Completed JetBot Kit
Note: We recommend that you read all of the directions first, before building your JetBot. However, we empathize if you are just here for the pictures & a general feel for the SparkFun JetBot. We are also those people who on occasion void warranties & recycle unopened instructions manuals but please note, SparkFun can only provide support for the instructions laid out in the following pages.

Attention: The SD card in this kit comes pre-flashed to work with our hardware and has the all the modules installed (including the sample machine learning models needed for the collision avoidance and object following examples). The only software procedures needed to get your JetBot running are steps 2-4 from the Nvidia instructions (i.e. setup the WiFi connection and then connect to the JetBot using a browser). Please DO NOT format or flash a new image on the SD card; otherwise, you will need to flash our image back onto the card.

If you accidentally make this mistake, don't worry. You can find instructions for re-flashing our image back onto the SD card in the Software Setup section of this guide

The Jetson Nano Developer Kit offers extensibility through an industry standard GPIO header and associated programming capabilities like the Jetson GPIO Python library. Building off this capability, the SparkFun kit includes the SparkFun Qwiic pHAT for Raspberry Pi, enabling immediate access to the extensive SparkFun Qwiic ecosystem from within the Jetson Nano environment, which makes it easy to integrate more than 30 sensors (no soldering and daisy-chainable).


The SparkFun Qwiic Connect System is an ecosystem of I2C sensors, actuators, shields and cables that make prototyping faster and less prone to error. All Qwiic-enabled boards use a common 1mm pitch, 4-pin JST connector. This reduces the amount of required PCB space, and polarized connections mean you can’t hook it up wrong.

Qwiic Connect System

Materials

PartQty
JetBot Chassis Kit1
Hobby Gearmotor (pair) included as part of JetBot Chassis Kit1
Camera mount included as part of JetBot Chassis Kit1
Wheels & Tires - included as part of JetBot Chassis Kit2
Lithium Ion Battery Pack - 10Ah (3A/1A USB Ports)1
Edimax 2-in-1 WiFi and Bluetooth 4.0 Adapter1
Jetson Dev Kit v3 *only included in specified Kits*1
SparkFun JetBot image (Pre Flashed)1
Leopard Imaging 145 FOV Camera1
SparkFun Micro OLED Breakout (Qwiic)1
SparkFun Qwiic Motor Driver1
SparkFun Qwiic pHAT v2.0 for Raspberry Pi1
Qwiic Cable - 100mm1
Qwiic Cable - 200mm1
Jumper Wires Premium 6" M/M (10-pack)1
USB Micro-B Cable - 6"1
Dual Lock Velcro1
PartQty
Standoff - Nylon (4-40; 3/8in.)10
1/4" Phillips Screw with 4-40 Thread20
Machine Screw Nut - 4-4010
M2 Nylon hex nut4
M2 Nylon screw slotted drive4
JetBot Chassis Hardware *included as part of JetBot Chassis Kit1

Recommended Tools

We did not include any tools in this kit because if you are like us you are looking for an excuse to use the tools you have more than needing new tools to work on your projects. That said, the following tools will be required to assemble your SparkFun JetBot.

  • Small phillips & small flat head head screwdriver will be needed for chassis assembly & to tighten the screw terminal connections for each motor. We reccomend the Pocket Screwdriver Set; TOL-12268.
  • Pair of scissors will be needed to cut the adhesive Dual Lock Velcro strap to desired size; recommended, but not essential..
  • Optional- adjustable wrench or pliers to hold small components (nuts & standoffs) in place while tightening screws; your finger grip is usually enough to hold these in place while tightening screws & helps to ensure nothing is over tightened.

A Note About Directions

When we talk about the "Front," or "Forward" of the JetBot, we are referring to direction the camera is pointed when the JetBot is fully assembled. "Left" and "Right" will be from the perspective of the SparkFun JetBot (i.e. what the JetBot camera sees).

Front of Jetbot

1. Robotics Chassis Kit Initial Assembly

Begin by with one of the two bare base plates included with the JetBot Chassis Kit. It does not matter which one, they are identical.

Jetbot Base Plate

Push two of the included motor mounts through the designated holes in the base plate as shown below. Two more motor mounts will be attached on the outside of the base plate after the motor is installed.

Motor Mount attached to base plate

Your JetBot Chassis Kit includes a pair of hobby motors & wheel assemblies.

Motor & Wheel

Attach the pair of motors using the long threaded machine screws & nuts included with the JetBot Chassis Kit. The motor will be sandwiched between an internal & external motor mount. Tighten the screws until they are snug.

Motors attached to base plate
Note: Install the motors so the "DAGU robot" sticker is facing out. This will ensure that your JetBot drives forward when following the hookup of the Qwiic Motor driver.

Once both motors are attached, flip the base plate over as pictured & thread the motor terminal leads through the baseplate as shown.

Additionally, attach the four longer brass standoffs at each corner of the base plate using the threaded screws included with the JetBot Chassis Kit. Refer to the photograph of the caster ball assembly to make sure you are using the correctly sized brass standoffs.

Base plate with motors & standoffs attached

Having trouble seeing the image? Click on it for a larger view.

Build the ball caster assembly using the two shorter brass standoffs.

Caster ball assembly

Install the caster ball assembly as shown in the assembled photo below. Additionally, attach the wheels to the hobby motor axles.

caster placement

2. Camera Assembly & Installation

Next, locate the camera mount assembly in the JetBot Chassis Kit. The unassembled view of the parts is laid out in the proper orientation for assembly.

Note: This orientation is necessary to ensure the camera mount fits on the top plate of the chassis.

alt text

Unpackage the Leopard Imaging camera and assemble the camera mount as shown in the following photograph.

alt text

Having trouble seeing the image? Click on it for a larger view.

Please reference the note about the "Front" of the JetBot in the end of the Introduction to ensure that you mount the camera on the correct side of the camera mount. Align the four holes in the camera mounting plate with those on the camera. Place all four nylon flathead screws through the camera & camera mounting plate prior to fully tightening the nylon nuts. This will ensure equal alignment across all four screws. While holding the nuts in place with a finger, tighten the screws in a rotating criss cross pattern; similar to how you tighten lug nuts on a car rim.

Note: Make sure to orient the camera so the ribbon cable is extending over the "top" of the camera mount as shown below.

camera to mount

Attach the camera mount & camera to the JetBot Chassis Kit top plate (the unused base plate) using two sets of screws and nuts included in the chassis kit.

camera mount attached to top plate

3. Accessory Installation to Main Chassis

Cut the strip of dual lock Velcro into two roughly equal sized strips. Take one side of the dual lock Velcro and attach to the back of the battery pack as shown.

battery pack

Place the corresponding pieces of dual lock Velcro on the initial chassis assembly as pictured.

chassis and battery

Press firmly on the battery pack to attach the dual lock Velcro interface between the chassis and battery. Route the motor terminal wires as shown.

Install the included nylon standoffs using the included 4-40 screws (10 packs) on the top mounting plate (the one we just finished attaching our camera and mount to). Pictured below are the standoffs for the Jetson Nano Dev Kit & the SparkFun Qwiic Motor Driver. Be sure to keep the standoffs on the right side somewhat loose. The mounting holes in the top plate are oblong to compensate for manufacturing tolerances & ensure a secure fit to the Jetson Nano Dev Kit.

The last four screws included with the JetBot Chassis Kit (shown on the right of the photo below) will be used to attach the top plate to the brass standoffs on each corner of the base plate.

final chassis assembly

Once the chassis is fully assembled, attach the SparkFun Qwiic Motor Driver as shown using the mounting hole on the board to the right of the 4x motor screw terminal. Attach the motor leads as pictured; see below for more details.

Qwiic Motor Driver mounted and connected to both motors
Having trouble seeing the connections to the Qwiic Motor Driver? Click on the image for a larger view.

Connect the motor leads according to the table below; remember the "Right"& "Left" designations from the Introduction. They should match the image above. The right motor is on the right side of this photo.

A1A2B1B2
Left Motor Ground (-)Left Motor Power (+)Right Motor Ground (-)Right Motor Power (+)

Image of the bottom of the Qwiic Motor Driver

Install the Micro SD card with the SparkFun JetBot Image (pre flashed) into the Micro SD card slot on the Jetson Nano. It is easier to do this prior to installing the Jetson Nano Dev Kit onto the chassis. This image is from the original JetBot Assembly guide.

Placing the microSD card into the SD card slot on the Jetson Nano

Attach the Jetson Nano Dev Kit using four 4-40 screws to the previously installed Nylon standoffs. Remember we left the right side standoffs loose so align them with the mounting holes on the Jetson Nano Dev Kit & tighten until sung.

Additionally, install the Edimax 2in1 USB WiFi & Bluetooth adaptor into any of the USB ports on the Jetson Nano Dev Kit.

JetBot with the Edimax wireless adapter plugged in.
Having trouble seeing the Edimax 2in1 USB WiFi & Bluetooth adapter in the image? Click on it for a larger view.

Attach the 100mm Qwiic cable to the underside of the SparkFun Qwiic Micro OLED as shown below.

Qwiic Micro OLED with Qwiic cable connected

Attach the SparkFun Qwiic Micro OLED to the JetBot Chassis using another Nylon Standoff & 4-40 screw. Attach the 100mm Qwiic cable to the SparkFun Qwiic Motor Driver. Secure the Qwiic Micro OLED by tightening the screw until sung.

Connect the qwiic pHAT on the Jetson Nano Dev Kit's 2x20 GPIO headers taking care to align it as the photo below shows.

Attach the Leopard Imaging camera ribbon cable to the Jetson Nano Dev Kit's front-most camera connector.

JetBot Kit with accessory boards mounted and Qwiic pHAT connected to the Jetson Nano GPIO header. Camera cable is also connected to the Jetson Nano
Having trouble seeing everything in the image? Click on it for a larger view.

Connect the SparkFun Qwiic Micro OLED display to the Qwiic pHAT using the 200mm Qwiic cable.

Image highlighting Qwiic Micro OLED connected to the Qwiic pHAT with a 200mm cable
Having trouble seeing the image? Click on it for a larger view.

Finally attach the Qwiic Motor Driver's motor power screw terminals to the 2 pin screw terminal for 5V and Ground on the Qwiic pHAT using the included 6 inch M/M jumper wires. We recommend using one black wire (ground) & one red wire (power), but you can use any included color your head desires.

The Qwiic Motor Driver's motor power screw terminals connected to the screw terminals on the Qwiic pHAT
Having trouble seeing the wires and detail the image? Click on it for a larger view.

Use the included 6 inch USB Micro-B Cable to connect the Jetson Nano Dev Kit to the battery pack.

Fully assembled JetBot v2.0 Kit
Having trouble seeing everything the image? Click on it for a larger view.
Note: Make sure the USB cable is plugged into the orange USB port on the battery pack. This will provide the required 3.1A @ 5V required by the Jetson Nano Dev Kit.

Allow the JetBot a few minutes to power up. When the JetBot is ready the Micro OLED will display the SparkFun flame logo, followed by the available disk image space & IP address once connected to a WiFi network.

4. Software Setup Guide from NVIDIA

Attention: The SD card in this kit comes pre-flashed to work with our hardware and has the all the modules installed (including the sample machine learning models needed for the collision avoidance and object following examples). The only software procedures needed to get your JetBot running are steps 2-4 from the Nvidia instructions (i.e. setup the WiFi connection and then connect to the JetBot using a browser). Please DO NOT format or flash a new image on the SD card; otherwise, you will need to flash our image back onto the card (instructions below).

Your SparkFun JetBot comes with a Pre-Flashed micro SD card. Users only need to plug in the SD card and set up the WiFi connection to get started.

  • The default password on everything (i.e. login/user, jupyter notebook, and superuser) is "jetbot".
  • We recommend that users change their passwords after initial setup. These are typically covered on the first boot of your Jetson Nano as detailed in the NVIDIA Getting Started with Jetson Nano walkthrough

Software Setup

The only step needed to get your JetBot kit up and running is to log into the JetBot and setup your WiFi connection. Once that is done, you are now ready to connect to the JetBot wirelessly. If you need instructions for doing so, you can use the link below.

However, please take note of our instructions below. You will want to skip steps 1 and 5 to avoid erasing the image on the card or undoing the hardware configuration.

Instructions

  1. Skip step 1 of Nvidia's instructions: It references how to flash your SD card, so feel free to skip to Step 2 - Boot Jetson Nano.
Note: Following Step 1 will erase the pre-flashed image and make a lot of extra work for yourself.
  1. Skip step 5 of Nvidia's instructions: This step should already be setup on the pre-flashed SD card.
    • If in the future, you need to update your notebooks, you can follow Step 5 - Install latest software (optional) to download the repository (don't download it into the home directory and skip the last command line instruction of the forth step).

Get and install the latest JetBot repository from GitHub by entering the following commands

git clone https://github.com/NVIDIA-AI-IOT/jetbot
cd jetbot
sudo python3 setup.py install
Note: Running sudo python3 setup.py install in the command line will overwrite the software modifications for SparkFun's hardware in the kit.

Troubleshooting

In the event that you accidentally missed the instructions above, here are instructions to get back on track.

Re-Flashing the SD card

If you need to re-flash your SD card, follow the instructions from Step 1 Nvidia's guide. However, download and use our image instead (click link below).

Note: Don't forget to uncompress (i.e. unzip, extract, or expand) the file from the .zip file/folder first. You should be pointing the "flashing" software to a ~62GB .img file to flash the image (sparkfun_jetbot_v01-00.img) onto the SD card. Not every unzip utility can handle this large of a file! The Windows 10 'Extract All' command has been found you work as well as 7Zip and Winzip.

Alternatively, there are other options for flashing images onto an SD card. If you have a preferred method, feel free to use the option you are most comfortable with.

Re-Applying the Software Modifications

If you have accidentally overwritten the software modifications for the hardware included in your kit, you will need to repeat Step 5 from Nvidia's guide from the desktop interface (if you are comfortable performing the following steps from the command line, feel free to do so).

Skip steps 1 and 2: Plug in a keyboard, mouse, and monitor. Then log in to the desktop interface (if you haven't changed your password, the default password is: jetbot).

Follow step 3: Launch the terminal. There is an icon on sidebar on the left hand side. Otherwise, you can use the keyboard short cut (Ctrl + Alt + T).

Follow step 4: However, before you execute sudo python3 setup.py install you will want to copy in our file modifications to the jetbot directory you are in.

  1. Begin by downloading our files (click link below).
  1. Next, extract the file.

  2. Next, replace the files in the jetbot folder. The file paths must be the same, so make sure to overwrite files exactly.

Click on the icon that looks like a filing cabinet on the left hand side of the GUI. This is your Home directory. From here, you will need to proceed into the jetbot folder. There you will find a jetbot folder with similar files to the ones you just extracted. Delete the folder and copy in our files (you can also just overwrite the files as well).

  1. Now, you can execute sudo python3 setup.py install in the terminal.

Follow step 5: Finish up by following step 5. Now you are back on track to getting your JetBot running again!

Note: If you need to install the Python packages for the Qwiic devices (i.e. the OLED and SCMD motor driver), use the following command in the terminal: sudo pip3 install sparkfun-qwiic.

5. Examples

The "object following" jupyter notebook example won't work due to the required dependencies that had not been released by NVIDIA prior to the creation of the SparkFun JetBot image. These updates can be manually installed on your Jetson Nano with the JetPack 4.2.1 release.

Update: The engine generated for the example utilized a previous version of TensorRT and is therefore, not compatible with the latest release. For more details on this issue, check out the following GitHub issue.

Resources and Going Further

Now that you've successfully got your JetBot AI up and running, it's time to incorporate it into your own project!

For more information, check out the resources below:

Need some inspiration for your next project? Check out some of these related tutorials:

LIDAR-Lite v3 Hookup Guide

A tutorial for connecting the Garmin LIDAR-Lite v3 or the LIDAR-Lite v3HP to an Arduino to measure distance.

Clap On Lamp

Modify a simple desk lamp to respond to a double clap (or other sharp noise) using parts from the SparkFun Inventor's Kit v4.0.

WiFi Controlled Robot

This tutorial will show you how to make a robot that streams a webcam to a custom website that can be remotely controlled.

Basic Autonomous Kit for Sphero RVR Assembly Guide

Get your Basic Autonomous Kit for Sphero RVR all hooked up with this guide!

learn.sparkfun.com | CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Viewing all 1123 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>