Last active
January 5, 2020 20:10
-
-
Save tvdzwan/9008833 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Arduino serial-interface for controlling the ws2812 leds. The serial interface is based on the | |
// Adalight protocol. The protocol is as follows: | |
// [prefix][led count][checksum][red, green, blue]* | |
// prefix := 'Ada' | |
// led count := number of leds - 1 (uint16_t big endian) | |
// checksum := led count high bit XOR led count low bit XOR 0x55 (uint8_t) | |
// red, green, blue := channel intensity [0-255] (uint8_t) | |
// | |
/// Definition of the maximum number of possible leds (depends on the available memory) | |
/// NOTE: The actual number of used leds is determined runtime in the adalight protocol | |
/// This number does not need to be modified to match the number of leds (as long as there | |
/// are less leds then the maximum allowed number) | |
#define MAX_LED_COUNT 512 | |
/// Definition of the GPIO pin | |
#define BOOTSEQUENCE_IN_PIN 7 | |
#define BOOTSEQUENCE_OUT_PIN 8 | |
#define ARDUINO_LED_PIN 13 | |
#define WS2812_PIN 2 | |
/// Definition of the serial-baudrate | |
/// NOTE: 500kHz seemed to be the maximum (test at 1MHz failed) | |
#define serialRate 500000 | |
/// FastSPI_LED2 includes | |
#include<FastLED.h> | |
/// The prefix for start sending led-data | |
static const uint8_t prefix[] = {'A', 'd', 'a'}; | |
/// Array with led data to write | |
static CRGB _leds[MAX_LED_COUNT]; | |
/// The controller for controlling the WS2812B strip on the configured PIN (default is GRB) | |
static WS2811Controller800Khz<WS2812_PIN, GRB> _controller; | |
/// | |
/// Checks if BOOTSEQUENCE_IN_PIN is connected to BOOTSEQUENCE_OUT_PIN by making the OUT_PIN first | |
/// high and then low and checking if the IN_PIN follows these levels | |
/// | |
/// @return True if the bootsequence is enabled by connecting IN_PIN and OUT_PIN | |
/// | |
bool checkForBootSequence(); | |
/// | |
/// Runs a simple test sequence on the connected leds. This method can be used to check that the | |
/// leds are properly connected to the arduino. | |
/// | |
void runTestSequence(); | |
void setup() | |
{ | |
// Set all the led values to zero | |
memset(_leds, 0, MAX_LED_COUNT * sizeof(CRGB)); | |
// Initialise the LED controller | |
_controller.init(); | |
// Run the optional boot sequence | |
if (checkForBootSequence()) | |
{ | |
runTestSequence(); | |
} | |
// Switch all leds off (write black) | |
_controller.showColor(CRGB(0, 0, 0), MAX_LED_COUNT); | |
// Open the serial-connection | |
Serial.begin(serialRate); | |
// Send 'Ada' string to host | |
Serial.print("Ada\n"); | |
} | |
void loop() | |
{ | |
// Wait for first byte of 'Ada' | |
for(int i = 0; i < sizeof(prefix); ++i) | |
{ | |
while (!Serial.available()); | |
// Check next byte in Magic Word | |
if(prefix[i] != Serial.read()) | |
return; | |
} | |
// Wait for highByte, lowByte, Checksum to be available | |
while(Serial.available() < 3); | |
// Read high and low byte and the checksum | |
int highByte = Serial.read(); | |
int lowByte = Serial.read(); | |
int checksum = Serial.read(); | |
if (checksum != (highByte ^ lowByte ^ 0x55)) | |
{ | |
// Checksum check failed | |
return; | |
} | |
uint16_t ledCount = ((highByte & 0x00FF) << 8 | (lowByte & 0x00FF) ) + 1; | |
if (ledCount > MAX_LED_COUNT) | |
{ | |
// Make sure that we do not read more data dan available in the buffer | |
ledCount = MAX_LED_COUNT; | |
} | |
// read the transmission data and set LED values | |
for (int i = 0; i < ledCount; i++) | |
{ | |
// Wait for the next color spec to be available | |
while(Serial.available() < 3); | |
// Read the color spec | |
_leds[i].r = Serial.read(); | |
_leds[i].g = Serial.read(); | |
_leds[i].b = Serial.read(); | |
} | |
// shows new values | |
_controller.show(_leds, ledCount); | |
} | |
bool checkForBootSequence() | |
{ | |
// Configure the BOOTSEQUENCE pin as in- and out-put | |
pinMode(BOOTSEQUENCE_IN_PIN, INPUT); | |
pinMode(BOOTSEQUENCE_OUT_PIN, OUTPUT); | |
// Set the bootsequence out pin high | |
digitalWrite(BOOTSEQUENCE_OUT_PIN, HIGH); | |
// Read the value of the input pin (should be high) | |
int highValue = digitalRead(BOOTSEQUENCE_IN_PIN); | |
// Set the bootsequence out pin high | |
digitalWrite(BOOTSEQUENCE_OUT_PIN, LOW); | |
// Read the value of the input pin again (should be low) | |
int lowValue = digitalRead(BOOTSEQUENCE_IN_PIN); | |
// BOOTSEQUENCE_IN_PIN is only connected to BOOTSEQUENCE_OUT_PIN if the read values match the written values | |
return (highValue == HIGH && lowValue == LOW); | |
} | |
void runTestSequence() | |
{ | |
// Switch the onboard led on | |
pinMode(BOOTSEQUENCE_OUT_PIN, OUTPUT); | |
digitalWrite(ARDUINO_LED_PIN, HIGH); | |
// Simple boot-sequence to check the arduino setup | |
_controller.showColor(CRGB::DarkRed, MAX_LED_COUNT); | |
delay(500); | |
_controller.showColor(CRGB::DarkGreen, MAX_LED_COUNT); | |
delay(500); | |
_controller.showColor(CRGB::DarkBlue, MAX_LED_COUNT); | |
delay(500); | |
// Switch the onboard led off | |
digitalWrite(ARDUINO_LED_PIN, LOW); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An arduino sketch for controlling a WS2812B led string connected to an Arduino nano, using the AdaLight serial protocol.
The code contains an extra test hook, which can be enabled by connecting pin 7 and 8. In this case the arduino will run a short color sequence across the led string when booting.
The code has been developed as part of the Hyperion project (https://github.com/tvdzwan/hyperion).
The source is released under MIT-License (see http://opensource.org/licenses/MIT).