In this section we'll set up a dashboard on Adadfruit IO to control a servo and neopixels on the Feather/Crickit.
Setting up Adafruit IO
Let's start by connecting the servo and NeoPixels to Adafruit IO. If you aren't familiar with feeds, we have a guide for that.
We start by creating a new feed group called crickit
(Feeds -> Actions -> Create New Group). We'll use that to contain the feeds for this guide. Now we can add the feeds: neopixel-control
and servo1-control
via Feeds -> Actions -> Create a new Feed. When you create each, you have the option of adding them to a group. Do so, adding them to the crickit
group.
Arduino Code
The first program is called dashboard_control.ino. This program will allow you to control a servo and NeoPixels connected on an Adafruit Crickit Featherwing via Adafruit IO.
The key parts of the code are setting up the feeds and handling events from them.
Code Highlights
Setting up the feeds is split into two parts: declaring them, and initializing them. The declarations are simple: make variables that are pointers to AdafruitIO_Feed
instances.
AdafruitIO_Feed *servo1_control; AdafruitIO_Feed *neopixel_control;
There's a function to allocate/initialize the feeds. It's called near the start of the setup()
function.
void setup_feeds() { servo1_control = io.feed("crickit.servo1-control"); neopixel_control = io.feed("crickit.neopixel-control"); }
Notice that the feed names have a crickit.
prefix. That's because they are in the crickit
feed group. Now the connection to Adafruit IO can be started.
In config.h the AdafruitIO
interface object is created, in our case using WiFi:
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
Once the feeds have been created, the Adafruit IO interface object can be initialized. This will make the connection to Adafruit IO and get it running.
io.connect(); while(io.status() < AIO_CONNECTED) { Serial.print("."); delay(500); }
Setting up the hardware
Now that Adafruit IO is set up, we can turn to the Crickit and it's connected hardware.
Adafruit_Crickit crickit; seesaw_Servo servo_1(&crickit); seesaw_NeoPixel strip = seesaw_NeoPixel(NEOPIX_NUMBER_OF_PIXELS, NEOPIX_PIN, NEO_GRB + NEO_KHZ800);
And we initialize them at the end of setup():
void setup() { ... servo1_control->get(); servo_1.attach(CRICKIT_SERVO1, 600, 2400); }
The attach function literally attaches the servo object to a specific servo port on the Crickit, servo 1, in this case.
The attach function 'attaches' the servo object to a specific servo port on the Crickit. servo 1
, in this case.
Be sure to plug in your servo into the right slot, and with the white/yellow wire next to the 1 symbol
Loop()
In this sketch, the loop()
function is does the bare minimum: it keeps the connection to Adafruit IO alive and well and routes any incoming events to the associated handler function.
void loop() { // io.run(); is required for all sketches. // it should always be present at the top of your loop // function. it keeps the client connected to // io.adafruit.com, and processes any incoming data. io.run(); }
Event handlers
Back in setup()
, after the connection to Adafruit IO and the feeds are in place the event handlers can be set.
servo1_control->onMessage(handle_servo_message); neopixel_control->onMessage(handle_neopixel_message);
This attaches an event handler function to each of the Adafruit IO feeds that we want to respond to: handle_servo_message
handles servo angle events, and handle_neopixel_message
handles NeoPixel color changes.
void handle_servo_message(AdafruitIO_Data *data) { Serial.print("received servo control <- "); Serial.println(data->value()); int angle = data->toInt(); if(angle < 0) { angle = 0; } else if(angle > 180) { angle = 180; } servo_1.write(angle); } void handle_neopixel_message(AdafruitIO_Data *data) { Serial.print("received neopixel control <- "); Serial.println(data->value()); long color = data->toNeoPixel(); for (int pixel = 0; pixel < NEOPIX_NUMBER_OF_PIXELS; pixel++) { strip.setPixelColor(pixel, color); } strip.show(); }
That's it: set everything up and attach even handlers. This sketch is completely reactive, responding to events by making changes to the hardware.
Generating events
Now that the Feather and Crickit are set up and the sketch in place, we need to send it events to handle. We'll make an Adafruit IO dashboard for this. If you haven't worked with dashboards, there's a guide to get you started.
We'll want a number slider block connected to the servo1-control
feed that has a value range of 0 to 180. For neopixel-control
we need to make a color picker block.
If everything worked, you should be able to power up the Feather/Crickit and change the dashboard controls to see the servo rotate and the NeoPixels change color.
You can use the Arduino serial monitor to monitor the status messages from the sketch, just in case the board does not make a connection first to the WiFi network and then to Adafruit IO.
The complete sketch is below:
// SPDX-FileCopyrightText: 2018 Dave Astels for Adafruit Industries // // SPDX-License-Identifier: MIT // Crickit + Adafruit IO Subscribe Example // // Adafruit invests time and resources providing this open source code. // Please support Adafruit and open source hardware by purchasing // products from Adafruit! // // Written by Dave Astels for Adafruit Industries // Copyright (c) 2018 Adafruit Industries // Licensed under the MIT license. // // All text above must be included in any redistribution. /************************** Configuration ***********************************/ // edit the config.h tab and enter your Adafruit IO credentials // and any additional configuration needed for WiFi, cellular, // or ethernet clients. #include "config.h" #include <Adafruit_Crickit.h> #include <seesaw_servo.h> #include <seesaw_neopixel.h> #define NEOPIX_PIN (20) /* Neopixel pin */ #define NEOPIX_NUMBER_OF_PIXELS (7) // set up the feeds AdafruitIO_Feed *servo1_control; AdafruitIO_Feed *neopixel_control; // set up the Crickit Adafruit_Crickit crickit; seesaw_Servo servo_1(&crickit); // create servo object to control a servo // Parameter 1 = number of pixels in strip // Parameter 2 = Arduino pin number (most are valid) // Parameter 3 = pixel type flags, add together as needed: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) seesaw_NeoPixel strip = seesaw_NeoPixel(NEOPIX_NUMBER_OF_PIXELS, NEOPIX_PIN, NEO_GRB + NEO_KHZ800); void setup_feeds() { servo1_control = io.feed("crickit.servo1-control"); neopixel_control = io.feed("crickit.neopixel-control"); } void setup() { // start the serial connection Serial.begin(115200); // wait for serial monitor to open while(! Serial); setup_feeds(); Serial.println("Feeds set up"); Serial.println("Connecting to Adafruit IO"); // connect to io.adafruit.com io.connect(); // set up message handlers for the servo and neopixel feeds. // the handle_*_message functions (defined below) // will be called whenever a message is // received from adafruit io. servo1_control->onMessage(handle_servo_message); neopixel_control->onMessage(handle_neopixel_message); // wait for a connection while(io.status() < AIO_CONNECTED) { Serial.print("."); // Serial.println(io.statusText()); delay(500); } // we are connected Serial.println(); Serial.println(io.statusText()); if (!crickit.begin()) { Serial.println("Error starting Crickit!"); while(1); } else { Serial.println("Crickit started"); } if(!strip.begin()){ Serial.println("Error starting Neopixels!"); while(1); } else { Serial.println("Neopixels started"); } servo1_control->get(); servo_1.attach(CRICKIT_SERVO1); Serial.println("setup complete"); } void loop() { // io.run(); is required for all sketches. // it should always be present at the top of your loop // function. it keeps the client connected to // io.adafruit.com, and processes any incoming data. io.run(); } void handle_servo_message(AdafruitIO_Data *data) { Serial.print("received servo control <- "); Serial.println(data->value()); int angle = data->toInt(); if(angle < 0) { angle = 0; } else if(angle > 180) { angle = 180; } servo_1.write(angle); } void handle_neopixel_message(AdafruitIO_Data *data) { Serial.print("received neopixel control <- "); Serial.println(data->value()); long color = data->toNeoPixel(); for (int pixel = 0; pixel < NEOPIX_NUMBER_OF_PIXELS; pixel++) { strip.setPixelColor(pixel, color); } strip.show(); }
Text editor powered by tinymce.