Having trouble with Weasley clock code


#1

I am quite new to this, my apologies but I am having trouble deciphering some code. The original code I was able to find from a project someone else posted:

Weasley Clock project

His light string has 50 LED’s and he has 6 people. My string only has 25 LED’s and I have 4 people. I have changed the PIXEL COUNT to 25 and changed the People and Color sections to 4 people/initials.

I have uploaded the code and installed IFTTT on my Android phone. If I add Activities for myself the rule says that it has fired, but the LED’s don’t always turn on. The LED for “Home” works fine, along with one I defined for “Work”. The problem is that the four other rules for me do not turn on the LED’s after the rule fires. I have also noticed that all of the LED’s don’t “swirl” when the unit first turns on. Only the first 6 - 8 LED’s turn on.

I have been able to verify the LED’s all work by uploading a “Rainbow” code that turns all of my LED’s on and cycles through different colors of the rainbow. That works fine.

It therefore appears that the code I am trying to use for the Weasley clock needs to be modified due to my LED and people counts. I assume that is what has been causing the issues.

Any suggestions would be appreciated…thanks!


#2

Having some code to look at would be helpful :wink:


#3
#include "neopixel/neopixel.h"
#include <stdio.h>
#include <string.h>
#include <math.h>

#define PIXEL_COUNT 25


Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, D3, WS2812B);
int brite = 3;

struct entry {
    String str;
    int n;
};

struct entry places[] = { //After the first letter and a space, write this word in IFTTT
    "home", 1,
    "work", 2,
    "prison", 3,
    "cottage", 4,
	"mortal", 5,
	"transit", 6,
    0,0
};

struct entry people[] = { //This letter should be first character in IFTTT
    "C", 1,
    "S", 2,
    "A", 3,
    "R", 4,
    0,0
};

struct entry colors[] = { //Defines the color for each name.
    "C", 0x00ff00,
    "S", 0xff0000,
    "A", 0xffff00,
    "R", 0x00ff80,
    0,0
};

//name=people=capitalized letters

int updateClock(String command) {
  int commaIndex = command.indexOf(' '); //locate the space
  int secondCommaIndex = command.indexOf(' ', commaIndex+1); //locate the second space, starting one character after the first space
  String name = command.substring(0, commaIndex); //name's value is the string starting at the beginning and ending before the space
  String loc = command.substring(commaIndex+1, secondCommaIndex); //loc's value is the string starting after the space and ending before the second space
  int person = number_for_key(name, people); //check for match between the string, name, and people then record the number of the person
  if(person != 0){
	  flashB(number_for_key(name, colors)); //send color code to flash B for name
	  int place = number_for_key(loc, places);
	  if(place != 0){
	      
		  allMineOff(person);
		    int personcolor = number_for_key(name, colors);
		  	int red = floor(personcolor / (256*256));
            int green = (int)floor(personcolor / 256) % 256;
            int blue = personcolor % 256;
		  strip.setPixelColor(7+person+6*place, strip.Color(green, red, blue));
		  strip.show();
	  }
  }
  return 1;
}

void setup() {
    Particle.function("updateClock", updateClock);
    //pinMode(buttonPin, INPUT);
	strip.begin();
    strip.show();
	startupSwirl();
	strip.setBrightness(80);
	allOff();
	for(int j=1; j<=6; j++) { // set everyone to home
	    strip.setPixelColor(7+j+6*4, strip.Color(255, 255, 255));
	}
}

void loop() {
    strip.show();
    strip.setBrightness(50);
}

int number_for_key(String key, struct entry dict[]){ //checks the given name with the list of names allowed, returns number of match
    for(int j=0; j<6; j++) {
        String name = dict[j].str;
        if (strcmp(name, key) == 0)
            return dict[j].n;
    }
    return 0;
}

//This swirl is just for flashiness, only occurs on start up.
void startupSwirl() { // outer hands counterclockwise, inner hands clockwise
	int swirldelay = 50;
	for(int j=0; j<2; j++) {
    	for(int i=14; i<25; i+=3) {
    		allOff();
    		strip.setPixelColor(i, strip.Color(255, 255, 255));
    		strip.setPixelColor(62-i, strip.Color(255, 255, 255));
    		strip.show();
    		delay(swirldelay);
    		
    		allOff();
    		strip.setPixelColor(i+2, strip.Color(255, 255, 255));
    		strip.setPixelColor(62-i, strip.Color(255, 255, 255));
    		strip.show();
    		delay(swirldelay);
    	}
	}
}


void flashB(int hexValue){
	int red = floor(hexValue / (256*256));
    int green = (int)floor(hexValue / 256) % 256;
    int blue = hexValue % 256;
	for(int j=0; j<5; j++) {
		for(int i=0; i<14; i++) {
			strip.setPixelColor(i, strip.Color(green, red, blue));
		}
		strip.show();
		delay(300);
		for(int i=0; i<14; i++) {
			strip.setPixelColor(i, strip.Color(0,0,0));
		}
		strip.show();
		delay(300);
	}
}

void allMineOff(int n) {
	for(int i=7+n; i<PIXEL_COUNT; i+=6) {
		strip.setPixelColor(i, strip.Color(0, 0, 0));
	}
	strip.show();
}

void allOff() {
	for(int i=0; i<PIXEL_COUNT; i++) {
		strip.setPixelColor(i, strip.Color(0, 0, 0));
	}
	strip.show();
}

void debug(String message, int value) {
    char msg [50];
    sprintf(msg, message.c_str(), value);
    Spark.publish("DEBUG", msg);
}

#4

First time posting, wasn’t sure whether to copy and paste the entire code, or put a link to it from someone else. Anyways, the code I just posted is what I’m using. It loads fine but doesn’t seem to turn all the LED’s on.


#5

I just realized that people had been updating the code within the window of what I posted…thanks!

I am able to upload the code to my Photon but the rules that were working seem to have stopped. After further investigation the IFTTT app is showing the “Call A Function” area with “Options Unavailable” for my device. It definitely showed my code previously, not sure why it doesn’t now.

The Particle is online and I can upload and flash it with different code from the Particle code builder site. It seems to be an issue linking my IFTTT account and my Particle. Any suggestions?


#6

OK, had to reboot the item a couple of times, but seems to be connected to my IFTTT account again.

So…some testing completed on the code I have loaded, some interesting findings.

It appears only the “home” and “work” options actually turn an LED on the strip. This occurs for all users.

C home = LED 15
S home = LED 16
A home = LED 17
R home = LED 18
C work = LED 21
S work = LED 22
A work = LED 23
R work = LED 24

For all of the other options (prison, cottage, mortal, transit) the IFTTT application fires, the first 14 LED’s on the string blink on, but no individual bulb turns on.

I find it interesting that LED’s 19 and 20 aren’t being used, along with LED 25. I don’t 100% understand what the various counters in the code do (j and i) and am wondering if I am having difficulty due to the difference in LED totals between the source code and what I am using.

Anyone willing to share some thoughts on this?


#7

Hi guys, just wondered if anyone had some thoughts on this issue. Only two functions seem to work for all 4 people if I use the code listed above. Not sure why the other LED’s don’t turn on when the triggers fire.


#8

Your assumption is right; the problem is due to the number of LEDs you’re using based on this line in updateClockString,

strip.setPixelColor(7+person+6*place, strip.Color(green, red, blue));

With home (place = 1), the calculation in that function call gives you 14, 15, 16, 17 (corresponding to pixels 15-18)
With work (place = 2), the calculation gives you 20, 21, 22, 23 (corresponding to pixels 21-24)

With any of the other places the calculation gives you numbers higher than 25, the number of your pixel count.

I’m not sure what you’re saying about the swirl. It looks like from the code, that pixels 15,18, 21, and 24 should light up followed by 17, 20, and 23. I don’t understand how “only the first 6 - 8 LED’s turn on” since nothing lower than index 14 is passed to the setPixelColor function.

So, the values in the loops do need to be adjusted, but how depends on what you want to see, and I’m not sure what that is. It would help to know which pixels are where on your clock.


#9

Thanks so much for the assistance Ric. That makes more sense now.

I believe I can change the code to the following and it will make better use of the LED’s

	  strip.setPixelColor(person-4+4*place, strip.Color(green, red, blue));

I’ve done some preliminary testing and it seems to do what I want it to. I will complete some more testing and validate all options work, with no overlap.


#10

I have updated the code for my project and can get the lights to turn on for each person, as desired. The problem I am now encountering is when it updates a user, it turns off the LED for every other user. I assume it has something to do with the AllMineOff routine, but I have made the changes I believe should work and it still doesn’t seem to take effect. Some feedback would be appreciated. I will upload the updated code below this post


#11
#include "neopixel/neopixel.h"
#include <stdio.h>
#include <string.h>
#include <math.h>

#define PIXEL_COUNT 25


Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, D3, WS2812B);
int brite = 3;

struct entry {
    String str;
    int n;
};

struct entry places[] = { //After the first letter and a space, write this word in IFTTT
    "home", 1,
    "work", 2,
    "prison", 3,
    "cottage", 4,
	"mortal", 5,
	"transit", 6,
    0,0
};

struct entry people[] = { //This letter should be first character in IFTTT
    "C", 1,
    "S", 2,
    "A", 3,
    "R", 4,
    0,0
};

struct entry colors[] = { //Defines the color for each name.
    "C", 0xffff00,
    "S", 0xff0000,
    "A", 0x00ff00,
    "R", 0x00ff80,
    0,0
};

//name=people=capitalized letters

int updateClock(String command) {
  int commaIndex = command.indexOf(' '); //locate the space
  int secondCommaIndex = command.indexOf(' ', commaIndex+1); //locate the second space, starting one character after the first space
  String name = command.substring(0, commaIndex); //name's value is the string starting at the beginning and ending before the space
  String loc = command.substring(commaIndex+1, secondCommaIndex); //loc's value is the string starting after the space and ending before the second space
  int person = number_for_key(name, people); //check for match between the string, name, and people then record the number of the person
  if(person != 0){
	  flashB(number_for_key(name, colors)); //send color code to flash B for name
	  int place = number_for_key(loc, places);
	  if(place != 0){
	      
		  allMineOff(person);
		    int personcolor = number_for_key(name, colors);
		  	int red = floor(personcolor / (256*256));
            int green = (int)floor(personcolor / 256) % 256;
            int blue = personcolor % 256;
		  strip.setPixelColor(person-4+4*place, strip.Color(green, red, blue));
		  strip.show();
	  }
  }
  return 1;
}

void setup() {
    Particle.function("updateClock", updateClock);
    //pinMode(buttonPin, INPUT);
	strip.begin();
    strip.show();
	startupSwirl();
	strip.setBrightness(80);
	allOff();
	for(int j=1; j<=4; j++) { // set everyone to home
	   // strip.setPixelColor(7+j+6*4, strip.Color(255, 255, 255));
	   strip.setPixelColor(j, strip.Color(255, 255, 255));
	}
}

void loop() {
    strip.show();
    strip.setBrightness(50);
}

int number_for_key(String key, struct entry dict[]){ //checks the given name with the list of names allowed, returns number of match
    for(int j=0; j<4; j++) {
        String name = dict[j].str;
        if (strcmp(name, key) == 0)
            return dict[j].n;
    }
    return 0;
}

//This swirl is just for flashiness, only occurs on start up.
void startupSwirl() { // outer hands counterclockwise, inner hands clockwise
	int swirldelay = 50;
	for(int j=0; j<2; j++) {
        for(int i=1; i<25; i+=3) {
    		allOff();
    		strip.setPixelColor(i, strip.Color(255, 255, 255));
    		strip.setPixelColor(25-i, strip.Color(255, 255, 255));
    		strip.show();
    		delay(swirldelay);
    		
    		allOff();
    		strip.setPixelColor(i+2, strip.Color(255, 255, 255));
    		strip.setPixelColor(25-i, strip.Color(255, 255, 255));
    		strip.show();
    		delay(swirldelay);
    	}
	}
}


void flashB(int hexValue){
	int red = floor(hexValue / (256*256));
    int green = (int)floor(hexValue / 256) % 256;
    int blue = hexValue % 256;
	for(int j=0; j<5; j++) {
		for(int i=0; i<14; i++) {
			strip.setPixelColor(i, strip.Color(green, red, blue));
		}
		strip.show();
		delay(300);
		for(int i=0; i<14; i++) {
			strip.setPixelColor(i, strip.Color(0,0,0));
		}
		strip.show();
		delay(300);
	}
}

void allMineOff(int n) {
	for(int i=n+1; i<PIXEL_COUNT; i+=4) {
		strip.setPixelColor(i, strip.Color(0, 0, 0));
	}
	strip.show();
}

void allOff() {
	for(int i=0; i<PIXEL_COUNT; i++) {
		strip.setPixelColor(i, strip.Color(0, 0, 0));
	}
	strip.show();
}

#12

No, it actually doesn’t have to do with that (though there is a problem in that function; the for statement should start with int i=n, not int i=n+1). It has to do with the flashB function. That flashes then turns off all the first 14 LED’s, so when you update the person, anything that was in those first 14 is overwritten with zero’s for the color (turning them off).

The original Weasley clock project had more LED’s, and the ones used for the flashB (the first 14) were not the same ones used for the people (they started at 15). You need to rethink your strategy.

BTW, there’s another problem in your code in the number_for_key function. You need to go to j<6 to accommodate your 6 places, not j<4.