Skip to content

Commit

Permalink
Added _P070_NeoPixel_Clock.ino (letscontrolit#489)
Browse files Browse the repository at this point in the history
* NeoPixel ring clock

A clock that uses a ring of 60 NeoPixel LEDs as display for a classic
clock.
The hours are RED, the minutes are GREEN, the seconds are BLUE and the
hour marks are WHITE.
The brightness of the clock hands and the hour marks can be set in the
device page, or can be set by HTTP  or Rules commands. The format is as
follows:
Clock,1,128,32 → 1=enable display, 128=hand brightness, 32=mark
brightness
Clock,0,, → 0=disable display, without changing the saved values of the
brightness
Clock,,65, → change only the brightness of the clock hands
Clock,,,10  → change only the brightness of the hour marks

* - The plugin declaration was cleaned up
- The commands are working
- Correction of offset

* Update _P070_NeoPixel_Clock.ino

* Fix

* Update _P070_NeoPixel_Clock.ino

* Changed the name of the plugin

Changed the name of the plugin to "Output - NeoPixel Ring Clock [TESTING]"

* GlobalSyncOption not needed

GlobalSyncOption not needed, therefore set to false.
  • Loading branch information
ovywan authored and psy0rz committed Sep 14, 2017
1 parent 4917dab commit 2d8e14e
Showing 1 changed file with 280 additions and 0 deletions.
280 changes: 280 additions & 0 deletions src/_P070_NeoPixel_Clock.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
//#######################################################################################################
//#################################### Plugin 070: NeoPixel ring clock #######################################
//#######################################################################################################

//A clock that uses a strip/ring of 60 WS2812 NeoPixel LEDs as display for a classic clock.
//The hours are RED, the minutes are GREEN, the seconds are BLUE and the hour marks are WHITE.
//The brightness of the clock hands and the hour marks can be set in the device page,
//or can be set by commands. The format is as follows:
// Clock,<Enabled 1/0>,<Hand brightness 0-255>,<Mark brightness 0-255>

#ifdef PLUGIN_BUILD_TESTING

#ifndef CONFIG
#define CONFIG(n) (Settings.TaskDevicePluginConfig[event->TaskIndex][n])
#endif

#include <Adafruit_NeoPixel.h>

#define NUMBER_LEDS 60 //number of LED in the strip

boolean Plugin_070_enabled; //used to enable/disable the display.
byte Plugin_070_brightness; //brightness of the clock "hands"
byte Plugin_070_marks; //brightness of the hour marks
byte Plugin_070_offset; //position of the 12 o'clock LED on the strip
boolean thick_12_mark;
byte marks[14];

Adafruit_NeoPixel * Plugin_070_pixels;

#define PLUGIN_070
#define PLUGIN_ID_070 70
#define PLUGIN_NAME_070 "Output - NeoPixel Ring Clock [TESTING]"
#define PLUGIN_VALUENAME1_070 "Enabled"
#define PLUGIN_VALUENAME2_070 "Brightness"
#define PLUGIN_VALUENAME3_070 "Marks"
boolean Plugin_070(byte function, struct EventStruct *event, String& string)
{
boolean success = false;

switch (function)
{

case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_070;
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
Device[deviceCount].VType = SENSOR_TYPE_TRIPLE;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = false;
Device[deviceCount].ValueCount = 3;
Device[deviceCount].SendDataOption = false;
Device[deviceCount].TimerOption = false;
Device[deviceCount].GlobalSyncOption = false;
break;
}

case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_070);
break;
}

case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_070));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_070));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_070));
break;
}

case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = F("GPIO &rarr; LED");
break;
}

case PLUGIN_WEBFORM_LOAD:
{
addFormSubHeader(string, F("Clock configuration"));
addFormNumericBox(string, F("12 o'clock LED position"), F("offset"), CONFIG(3), 0, 59);
addFormNote(string, F("Position of the 12 o'clock LED in the strip"));
addFormCheckBox(string, F("Thick 12 o'clock mark"), F("thick_12_mark"), CONFIG(4));
addFormNote(string, F("Check to have 3 LEDs marking the 12 o'clock position"));
addFormCheckBox(string, F("Clock display enabled"), F("enabled"), CONFIG(0));
addFormNote(string, F("LED activation"));
addFormNumericBox(string, F("LED brightness"), F("brightness"), CONFIG(1), 0, 255);
addFormNote(string, F("Brightness level of the H/M/S hands (0-255)"));
addFormNumericBox(string, F("Hour mark brightness"), F("marks"), CONFIG(2), 0, 255);
addFormNote(string, F("Brightness level of the hour marks (0-255)"));

success = true;
break;
}

case PLUGIN_WEBFORM_SAVE:
{
CONFIG(0) = isFormItemChecked(F("enabled"));
CONFIG(1) = getFormItemInt(F("brightness"));
CONFIG(2) = getFormItemInt(F("marks"));
CONFIG(3) = getFormItemInt(F("offset"));
CONFIG(4) = isFormItemChecked(F("thick_12_mark"));

Plugin_070_enabled = CONFIG(0);
Plugin_070_brightness = CONFIG(1);
Plugin_070_marks = CONFIG(2);
Plugin_070_offset = CONFIG(3);
thick_12_mark = CONFIG(4);

calculateMarks();

success = true;
break;
}

case PLUGIN_INIT:
{
if (!Plugin_070_pixels)
{
Plugin_070_pixels = new Adafruit_NeoPixel(NUMBER_LEDS, Settings.TaskDevicePin1[event->TaskIndex], NEO_GRB + NEO_KHZ800);
Plugin_070_pixels->begin(); // This initializes the NeoPixel library.
}
Plugin_070_enabled = CONFIG(0);
Plugin_070_brightness = CONFIG(1);
Plugin_070_marks = CONFIG(2);
Plugin_070_offset = CONFIG(3);
thick_12_mark = CONFIG(4);

calculateMarks();

success = true;
break;
}

case PLUGIN_ONCE_A_SECOND:
{
Clock_update();
success = true;
break;
}

case PLUGIN_WRITE:
{
string.toLowerCase();
String command = parseString(string, 1);
String param1 = parseString(string, 2);
String param2 = parseString(string, 3);
String param3 = parseString(string, 4);

if (command == F("clock")) {
if (param1 != "") {
int val_Mode = param1.toInt();
if (val_Mode > -1 && val_Mode < 2) {
Plugin_070_enabled = val_Mode;
CONFIG(0) = Plugin_070_enabled;
}
}
if (param2 != "") {
int val_Bright = param2.toInt();
if (val_Bright > -1 && val_Bright < 256) {
Plugin_070_brightness = val_Bright;
CONFIG(1) = Plugin_070_brightness;
}
}
if (param3 != "") {
int val_Marks = param3.toInt();
if (val_Marks > -1 && val_Marks < 256) {
Plugin_070_marks = val_Marks;
CONFIG(2) = Plugin_070_marks;
}
}
/* //Command debuging routine
String log = F("Clock: ");
addLog(LOG_LEVEL_INFO,log);
log = F(" Enabled = ");
log += param1;
addLog(LOG_LEVEL_INFO,log);
log = F(" Brightness = ");
log += param2;
addLog(LOG_LEVEL_INFO,log);
log = F(" Marks = ");
log += param3;
addLog(LOG_LEVEL_INFO,log);
*/
success = true;
}
break;
}

case PLUGIN_READ:
{
UserVar[event->BaseVarIndex] = Plugin_070_enabled;
UserVar[event->BaseVarIndex + 1] = Plugin_070_brightness;
UserVar[event->BaseVarIndex + 2] = Plugin_070_marks;

success = true;
}

}
return success;
}

void Clock_update()
{
clearClock(); //turn off the LEDs
if (Plugin_070_enabled > 0) { //if the display is enabled, calculate the LEDs to turn on
int Hours = hour();
int Minutes = minute();
int Seconds = second();
timeToStrip(Hours, Minutes, Seconds);
}
Plugin_070_pixels->show(); // This sends the updated pixel color to the hardware.
}

void calculateMarks()
{ //generate a list of the LEDs that have hour marks
for (int i = 0; i < 12; i++) {
marks[i] = 5 * i + (Plugin_070_offset % 5);
}
if (thick_12_mark) {
if (Plugin_070_offset == 0) {
marks[12] = 1;
marks[13] = 59;
}
else if (Plugin_070_offset == 59) {
marks[12] = 0;
marks[13] = 58;
}
else {
marks[12] = Plugin_070_offset + 1;
marks[13] = Plugin_070_offset - 1;
}
}
else {
marks[12] = 255;
marks[13] = 255;
}
}

void clearClock() {
for (int i = 0; i < NUMBER_LEDS; i++) {
Plugin_070_pixels->setPixelColor(i, Plugin_070_pixels->Color(0, 0, 0));
}
}

void timeToStrip(int hours, int minutes, int seconds) {
if (hours > 11) hours = hours - 12;
hours = (hours * 5) + (minutes / 12) + Plugin_070_offset; //make the hour hand move each 12 minutes and apply the offset
if (hours > 59) hours = hours - 60;
minutes = minutes + Plugin_070_offset; //apply offset to minutes
if (minutes > 59) minutes = minutes - 60;
seconds = seconds + Plugin_070_offset; //apply offset to seconds
if (seconds > 59) seconds = seconds - 60;
for (int i = 0 ; i < 14; i ++) { //set the hour marks as white;
if ((marks[i] != hours) && (marks[i] != minutes) && (marks[i] != seconds) && (marks[i] != 255)) { //do not draw a mark there is a clock hand in that position
Plugin_070_pixels->setPixelColor(marks[i], Plugin_070_pixels->Color(Plugin_070_marks, Plugin_070_marks, Plugin_070_marks));
}
}
uint32_t currentColor;
uint8_t r_val, g_val, b_val;
for (int i = 0; i < NUMBER_LEDS; i++) { //draw the clock hands, adding the colors together
if (i == hours) { //hours hand is RED
Plugin_070_pixels->setPixelColor(i, Plugin_070_pixels->Color(Plugin_070_brightness, 0, 0));
}
if (i == minutes) { //minutes hand is GREEN
currentColor = Plugin_070_pixels->getPixelColor(i);
r_val = (uint8_t)(currentColor >> 16);
Plugin_070_pixels->setPixelColor(i, Plugin_070_pixels->Color(r_val, Plugin_070_brightness, 0));
}
if (i == seconds) { //seconds hand is BLUE
currentColor = Plugin_070_pixels->getPixelColor(i);
r_val = (uint8_t)(currentColor >> 16);
g_val = (uint8_t)(currentColor >> 8);
Plugin_070_pixels->setPixelColor(i, Plugin_070_pixels->Color(r_val, g_val, Plugin_070_brightness));
}
}
}

#endif

0 comments on commit 2d8e14e

Please sign in to comment.