Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Firmata.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
// extended command set using sysex (0-127/0x00-0x7F)
/* 0x00-0x0F reserved for user-defined commands */
#define ENCODER_DATA 0x61 // reply with encoders current positions
#define LED_STRIP_DATA 0x62 // control neo pixels
#define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq
#define STRING_DATA 0x71 // a string message with 14-bits per char
#define STEPPER_DATA 0x72 // control a stepper motor
Expand Down Expand Up @@ -80,8 +81,9 @@
#define ONEWIRE 0x07 // pin configured for 1-wire
#define STEPPER 0x08 // pin configured for stepper motor
#define ENCODER 0x09 // pin configured for encoders
#define LED_STRIP 0x0A // pin configured for led strips
#define IGNORE 0x7F // pin configured to be ignored by digitalWrite and capabilityResponse
#define TOTAL_PIN_MODES 11
#define TOTAL_PIN_MODES 12

extern "C" {
// callback function types
Expand Down
56 changes: 56 additions & 0 deletions test/neopixel_test/neopixel_test.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <Firmata.h>
#include <Ethernet.h>
#include <Wire.h>
#include <Servo.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>

#include <utility/FirmataExt.h>
FirmataExt firmataExt;

#include "utility/neopixelFirmata.h"
NeopixelFirmata* neopixelFirmata = neopixelFirmataFactory();

/*==============================================================================
* FUNCTIONS
*============================================================================*/

void systemResetCallback()
{
// initialize a defalt state

// pins with analog capability default to analog input
// otherwise, pins default to digital output
for (byte i=0; i < TOTAL_PINS; i++) {
}

firmataExt.reset();
}

/*==============================================================================
* SETUP()
*============================================================================*/

void setup()
{
Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);
firmataExt.addFeature(*neopixelFirmata);
Firmata.attach(SYSTEM_RESET, systemResetCallback);

// start up the default Firmata using Serial interface:
Firmata.begin(57600);
systemResetCallback(); // reset to default config
}

/*==============================================================================
* LOOP()
*============================================================================*/
void loop()
{

while(Firmata.available()) {
Firmata.processInput();
}

}

75 changes: 75 additions & 0 deletions utility/LedStripFirmata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "LedStripFirmata.h"
// Choose one pixel subtype to include
#include "NeopixelFirmata.h"
// #include "Ws2801PixelFirmata.h" // Not completed yet

void LedStripFirmata::handleCapability(byte pin)
{
if (IS_PIN_DIGITAL(pin))
{
Firmata.write(LED_STRIP);
Firmata.write(1); // Not sure if this is necessary
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary per the protocol, but has no meaning for this particular device. For something like analog input or pwm it specifies the resolution in number of bits.

}
}

boolean LedStripFirmata::handlePinMode(byte pin, int mode)
{
if (mode == LED_STRIP && IS_PIN_DIGITAL(pin))
{
return true;
}
return false;
}

void LedStripFirmata::reportDone()
{
Firmata.write(START_SYSEX);
Firmata.write(LED_STRIP_DATA);
Firmata.write(LED_STRIP_CMD_DONE);
Firmata.write(END_SYSEX);
}

void LedStripFirmata::reportType()
{
Firmata.write(START_SYSEX);
Firmata.write(LED_STRIP_DATA);
Firmata.write(LED_STRIP_CMD_QUERY);
Firmata.write(ledType());
Firmata.write(END_SYSEX);
}


boolean LedStripFirmata::handleSysex(byte command, byte argc, byte* argv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhere in this function you need to set the pin mode or the pin mode of LED_STRIP will not be set properly for the device. See the these lines in EncoderFirmatahttps://github.com/firmata/arduino/blob/configurable_dev/utility/EncoderFirmata.cpp#L50-L51 for an example. You also need to be sure to respect IGNORE pins. See an example here. In most cases there will not be a collision with IGNORE. The reason it was introduced is if a SPI device such as an ethernet or wi-fi controller are used, you can have conflicts with other Firmata features that may try to use one of the pins needed by the SPI interface.

{
if (command != LED_STRIP_DATA)
{
return false;
}

byte npCommand = argv[0];
if (!initialized && npCommand != LED_STRIP_CMD_INIT && npCommand != LED_STRIP_CMD_QUERY)
{
// Firmata.sendString("Led Strip Not Initialized: Not Initialized");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string is too long. Strings are extremely expensive in microcontrollers with limited SRAM such as the ATMega328p (Arduino Uno). For now, either leave this commented out as you have or shorten it to as few characters as possible. I had proposed a couple of new ways to handle errors a while back but was not able to get consensus around a solution. I need to reopen that discussion.

return false;
}

switch(npCommand) {
case LED_STRIP_CMD_QUERY:
reportType();
return true;

default:
return handleStripCommand(npCommand, argc, argv);
}

return true;

}


LedStripFirmata* ledStripFirmataFactory()
{
#ifdef NeopixelFirmata_H
return new NeopixelFirmataImpl();
#endif
}
50 changes: 50 additions & 0 deletions utility/LedStripFirmata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#ifndef LedStripFirmata_H
#define LedStripFirmata_H

#include <Firmata.h>
#include "FirmataExt.h"

#define LED_STRIP_CMD_QUERY 0x00
#define LED_STRIP_CMD_INIT 0x01
#define LED_STRIP_CMD_PIXEL 0x02
#define LED_STRIP_CMD_CLEAR 0x04
#define LED_STRIP_CMD_SHOW 0x05
#define LED_STRIP_CMD_BRIGHTNESS 0x06
#define LED_STRIP_CMD_DONE 0x07 // Response

#define LED_STRIP_INIT_PARAM_PIN 0x01
#define LED_STRIP_INIT_PARAM_COUNT 0x02
#define LED_STRIP_INIT_PARAM_ORDER 0x04
#define LED_STRIP_INIT_PARAM_SPEED 0x05

#define LED_STRIP_PIXEL_PARAM_LOCATION 0x01
#define LED_STRIP_PIXEL_PARAM_RED 0x03
#define LED_STRIP_PIXEL_PARAM_GREEN 0x05
#define LED_STRIP_PIXEL_PARAM_BLUE 0x07

#define LED_STRIP_BRIGHTNESS_PARAM_VALUE 0x01

#define LED_STRIP_TYPE_NEOPIXEL 0x00
#define LED_STRIP_TYPE_WS2801 0x01

class LedStripFirmata : public FirmataFeature
{
public:
LedStripFirmata() {}
void handleCapability(byte pin);
boolean handlePinMode(byte pin, int mode);
boolean handleSysex(byte command, byte argc, byte* argv);
virtual void reset() = 0;

protected:
virtual boolean handleStripCommand(byte command, byte argc, byte* argv) = 0;
void reportDone();
void reportType();
virtual byte ledType() = 0;

boolean initialized = false;
};

LedStripFirmata* ledStripFirmataFactory();

#endif // LedStripFirmata_H
108 changes: 108 additions & 0 deletions utility/NeopixelFirmata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include "LedStripFirmata.h"
#include "NeopixelFirmata.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try moving NeopixelFirmata.cpp and NeopixelFirmata.h to /utility/devices/ and compiling under both the latest version of Arduino 1.5.x and 1.0.x. Arduino keeps changing the way they compile files within subdirectories you may run into an issue here (with /devices/). I would prefer to keep device-specific code under a /devices/ subdirectory if possible.

#include <Adafruit_NeoPixel.h>

#define TOBYTE(loc) ((argv[loc] + (argv[loc+1] << 7))&0xFF)

NeopixelFirmataImpl::NeopixelFirmataImpl()
{
pixels = NULL;
}

boolean NeopixelFirmataImpl::handleStripCommand(byte npCommand, byte argc, byte* argv)
{
byte tmp;

switch(npCommand) {

case LED_STRIP_CMD_INIT:
initialize(
argv[LED_STRIP_INIT_PARAM_PIN],
TOBYTE(LED_STRIP_INIT_PARAM_COUNT),
argv[LED_STRIP_INIT_PARAM_ORDER],
argv[LED_STRIP_INIT_PARAM_SPEED]
);
break;

case LED_STRIP_CMD_CLEAR:
pixels->clear();
break;

case LED_STRIP_CMD_SHOW:
pixels->show();
break;

case LED_STRIP_CMD_BRIGHTNESS:
if (argc>2) {
pixels->setBrightness(TOBYTE(LED_STRIP_BRIGHTNESS_PARAM_VALUE));
} else {
reportBrightness();
}
break;

case LED_STRIP_CMD_PIXEL:
tmp = TOBYTE(LED_STRIP_PIXEL_PARAM_LOCATION);

if(tmp > pixels->numPixels())
{
// Firmata.sendString("NeoPixel: Location out of range");
return false;
}

setPixel(
tmp,
TOBYTE(LED_STRIP_PIXEL_PARAM_RED),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Encoder7Bit instead of the TOBYTE macro. You can refer to OneWireFirmata for examples of use.

TOBYTE(LED_STRIP_PIXEL_PARAM_GREEN),
TOBYTE(LED_STRIP_PIXEL_PARAM_BLUE)
);
break;

default:
// Firmata.sendString("NeoPixel: Unknown Command");
return false;
}

return true;

}

void NeopixelFirmataImpl::reset()
{
if (pixels != NULL)
{
delete pixels;
pixels = NULL;
}
}

void NeopixelFirmataImpl::initialize(byte pin, byte count, byte order, byte speed)
{
reset();

pixels = new Adafruit_NeoPixel(count, pin, order + speed);
pixels->begin();
for(int i=0; i<count; i++) {
pixels->setPixelColor(i, 0, 0, 255);
pixels->show();
delay(50);
}
pixels->clear();
pixels->show();
reportDone();
}

void NeopixelFirmataImpl::reportBrightness()
{
byte brightness = pixels->getBrightness();
Firmata.write(START_SYSEX);
Firmata.write(LED_STRIP_DATA);
Firmata.write(LED_STRIP_CMD_BRIGHTNESS);
Firmata.write(brightness & 0x7F);
Firmata.write((brightness >> 7) & 0x7F);
Firmata.write(END_SYSEX);
}

void NeopixelFirmataImpl::setPixel(byte location, byte red, byte green, byte blue)
{
pixels->setPixelColor(location, red, green, blue);
}
26 changes: 26 additions & 0 deletions utility/NeopixelFirmata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef NeopixelFirmata_H
#define NeopixelFirmata_H

#include "LedStripFirmata.h"
#include "Adafruit_Neopixel.h"

class NeopixelFirmataImpl : public LedStripFirmata
{
public:
NeopixelFirmataImpl();
virtual void reset();

protected:
byte ledType() { return LED_STRIP_TYPE_NEOPIXEL; }
virtual boolean handleStripCommand(byte command, byte argc, byte* argv);
bool initialized;

private:
Adafruit_NeoPixel* pixels;
void initialize(byte pin, byte count, byte order, byte speed);
void reportBrightness();
void setPixel(byte position, byte red, byte green, byte blue);
};

#endif // NeopixelFirmata_H