# Driving me NUTS

This has been driving me mad and I’ve only just found the answer – thanks to some clues people have given me – but as many of the responses were wrong – you might well find this interesting.

I have a an array of 180 bytes – for 60 serial LEDs – 3 bytes each for red, green and blue respectively.

So this routine calls back every second – and updates the 60 LEDs which are in a circle. The hour indicator is formed of 7 LEDs, bright in the centre, dimmer to the edges, the minutes indicator is 3 LEDs – again bright in the middle. The seconds are shown as 1 LED.

And it was working a treat – except at midnight where it bombed with all LEDs on – and for the LIFE of me I could not see why..

Ignore the bits in RED….

LOCAL void ICACHE_FLASH_ATTR clock_cb(void *arg)
{
if (sysCfg.clock!=255) // fancy clock on a port
{

int hour12=(tm.Hour%12)*5;
for (int a=0;a<180;a+=3)
{
rgb.buffer[a]=0;
rgb.buffer[a+1]=0;
rgb.buffer[a+2]=0;
}
rgb.buffer[(tm.Second*3+2)%180]=255; // seconds hand blue

rgb.buffer[(tm.Minute*3-3)%180]=8; // minutes green
rgb.buffer[(tm.Minute*3)%180]=255; // minutes green
rgb.buffer[(tm.Minute*3+3)%180]=8; // minutes green

int x=((hour12)+(tm.Minute/12))*3;

rgb.buffer[(x-8)%180]=5;
rgb.buffer[(x-5)%180]=16;
rgb.buffer[(x-2)%180]=80;
rgb.buffer[(x+1)%180]=255;
rgb.buffer[(x+4)%180]=80;
rgb.buffer[(x+7)%180]=16;
rgb.buffer[(x+10)%180]=5;

WS2812OutBuffer(rgb.buffer, 180,1); // 60 LEDs
}
}

So here’s the thing – all these years I’ve been thinking % was a MOD operator – it’s NOT – it’s a simple remainder..

In order words..

(-3 % 180) which I had COMPLETELY expected to be returning 177 – was in fact returning –3  !!!!!

That explains a LOT. The solution – a simple MOD function.

LOCAL int ICACHE_FLASH_ATTR mod(int a, int b)
{
int ret = a % b;
if(ret < 0)
ret+=b;
return ret;
}

Hence mod(-3,180) returns the right answer. Here’s the final clock once-a-second callback routine for a 60-LED array.

LOCAL void ICACHE_FLASH_ATTR clock_cb(void *arg)
{
if (sysCfg.clock!=255) // fancy clock on a port
{
int hour12=(tm.Hour%12)*5;

int a;
for (a=0;a<178;a+=3)
{
rgb.buffer[a]=0;
rgb.buffer[a+1]=0;
rgb.buffer[a+2]=0;
}

rgb.buffer[mod(tm.Second*3+2,180)]=255; // seconds hand blue
rgb.buffer[mod(tm.Minute*3-3,180)]=8; // minutes green
rgb.buffer[mod(tm.Minute*3,180)]=255; // minutes green
rgb.buffer[mod(tm.Minute*3+3,180)]=8; // minutes green

int x=((hour12)+(tm.Minute/12))*3;

rgb.buffer[mod(x-8,180)]=5;
rgb.buffer[mod(x-5,180)]=16;
rgb.buffer[mod(x-2,180)]=80;
rgb.buffer[mod(x+1,180)]=255;
rgb.buffer[mod(x+4,180)]=80;
rgb.buffer[mod(x+7,180)]=16;
rgb.buffer[mod(x+10,180)]=5;

WS2812OutBuffer(rgb.buffer, 180,1); // 60 LEDs
}
}