I am currently working on a ESP8266 driven 4x4x4 RGB LED cube. It works with two TLC5947 led drivers in series and quick cycling through all 4 planes to get a static image.
It works fine so far but the image seems to flicker every ~0.75 seconds or so. I tried disabling every other component in my sketch but the problem persists. I tried disabling Wifi with
WiFi.mode(WIFI_OFF);
I feel like the ESP8266 SDK does something in the background that I am not aware of. I heard that the SDK handles some Wifi functions in the background that might stop my timer from firing exactly every 1500µs. I will just post the relevant part of the code here.
xyz current_led = xyz { 0, 1, 0 };
rgb rgb_data[4][4][4];
os_timer_t tlcTimer;
void tlc_init()
{
SPI.begin();
SPI.setFrequency(1000000);
pinMode(PLANE_1_PIN, OUTPUT);
pinMode(PLANE_2_PIN, OUTPUT);
pinMode(PLANE_3_PIN, OUTPUT);
pinMode(PLANE_4_PIN, OUTPUT);
pinMode(BLANK_AND_LATCH_PIN, OUTPUT);
start_tlc_timer();
}
void start_tlc_timer()
{
// initialize transmitter timer
system_timer_reinit();
// set callback function
os_timer_setfn(&tlcTimer, transmit, NULL);
// enable timer (fourth argument: 0=us, 1=ms)
ets_timer_arm_new(&tlcTimer, 1500, true, 0);
}
void reinit_timer(uint16_t timeout)
{
ets_timer_disarm(&tlcTimer);
ets_timer_arm_new(&tlcTimer, timeout, true, 0);
}
void transmit(void *pArg)
{
// Write SPI data
uint8_t data_array[72];
for(uint8_t i = 0; i < 8; i++)
{
data_array[i * 9 + 0] = rgb_data[current_led.x][current_led.y][current_led.z].blue;
data_array[i * 9 + 1] = rgb_data[current_led.x][current_led.y][current_led.z].green >> 4;
data_array[i * 9 + 2] = rgb_data[current_led.x][current_led.y][current_led.z].green << 4;
data_array[i * 9 + 3] = rgb_data[current_led.x][current_led.y][current_led.z].red;
select_next_led();
data_array[i * 9 + 4] = rgb_data[current_led.x][current_led.y][current_led.z].blue >> 4;
data_array[i * 9 + 5] = rgb_data[current_led.x][current_led.y][current_led.z].blue << 4;
data_array[i * 9 + 6] = rgb_data[current_led.x][current_led.y][current_led.z].green;
data_array[i * 9 + 7] = rgb_data[current_led.x][current_led.y][current_led.z].red >> 4;
data_array[i * 9 + 8] = rgb_data[current_led.x][current_led.y][current_led.z].red << 4;
select_next_led();
}
SPI.writeBytes(data_array, 72);
// Reset enable pins
digitalWrite(PLANE_1_PIN, 0);
digitalWrite(PLANE_2_PIN, 0);
digitalWrite(PLANE_3_PIN, 0);
digitalWrite(PLANE_4_PIN, 0);
// Latch
digitalWrite(BLANK_AND_LATCH_PIN, 1);
digitalWrite(BLANK_AND_LATCH_PIN, 0);
// Set enable pin
switch(current_led.z)
{
case 2:
digitalWrite(PLANE_1_PIN, 1);
current_led.z = 3;
break;
case 3:
digitalWrite(PLANE_2_PIN, 1);
current_led.z = 0;
break;
case 0:
digitalWrite(PLANE_3_PIN, 1);
current_led.z = 1;
break;
case 1:
digitalWrite(PLANE_4_PIN, 1);
current_led.z = 2;
break;
}
}
void select_next_led()
{
switch(current_led.y)
{
case 0:
current_led.x--;
if(current_led.x < 0)
{
current_led.x = 0;
current_led.y = 3;
}
break;
case 1:
current_led.x++;
if(current_led.x > 3)
{
current_led.x = 3;
current_led.y = 0;
}
break;
case 2:
current_led.x--;
if(current_led.x < 0)
{
current_led.x = 0;
current_led.y = 1;
}
break;
case 3:
current_led.x++;
if(current_led.x > 3)
{
current_led.x = 3;
current_led.y = 2;
}
break;
}
}
As you can see the timer should fire every 1500µs:
ets_timer_arm_new(&tlcTimer, 1500, true, 0);
Does anybody know why I get that flickering/inaccurate timing? My loop function is empty while the setup function just calls the tlc_init function and populates the rgb_data array with an example image.
Thanks for reading!
Edit:
I just tested the timing with the system_get_time() function like this inside the transmit function:
this_time = system_get_time();
difference = this_time - last_time;
if(difference > 1500+200 || difference < 1500-200)
Serial.println(difference);
last_time = this_time;
The Serial output matched the flicker frequency I can see with my eyes. It was always inaccurate by about +/-270µs. Now my question is: How can I make the timer more accurate?