Thread: Simple Structure And Array Issue

  1. #1
    Registered User
    Join Date
    May 2015
    Posts
    18

    Simple Structure And Array Issue

    I am working on a project to control 22 TLC5971 LED drivers. I have written the code for testing one and it is working. I tried to modify the code to control all the 22 LED drivers TLC5971 but it is not working.


    I have attached here the working code for one of the LED drivers. May be you have some idea.

    Please i would appreciate if someone can assist me
    Code:
    struct TLC5971 {	uint16_t GS[4][3]; // 4 -> number of channels; 3 -> Different colours. Takes values from 0 - 65535
    	uint8_t BCB:7;
    	uint8_t BCG:7;
    	uint8_t BCR:7;
    	uint8_t BLANK:1;
    	uint8_t DSPRPT:1;
    	uint8_t TMGRST:1;
    	uint8_t EXTGCK:1;
    	uint8_t OUTTMG:1;
    	uint8_t cmd:6;
    } tlc5971;
    
    
    
    
    
    
    void sendBits(void)
    {
    	uint8_t n, *p = (uint8_t*)&tlc5971;
    	
    	for (n = 28; n-- > 0; )
    	{
    		usartSPI_transfer(p[n]);
    	}
    	
    }
    
    
    
    
    int main(void)
    {
    	//tlc5971_init();
    	tlc5971.cmd = 0x25;
    	tlc5971.TMGRST = 1;
    	tlc5971.DSPRPT = 1;
    	tlc5971.BCB = 10;
    	tlc5971.BCG = 10;
    	tlc5971.BCR = 10;
    	tlc5971.GS[2][BLUE] =  0x6000;			// OUTB0 = 16384
    	tlc5971.GS[2][GREEN] = 0x2000;			// OUTG0 = 8192
    	tlc5971.GS[2][RED] = 0x4000;			// OUTR0 = 24576
    	
    	usartSPI_init();
    	
    	while(1)
    	{
    		CS_lo();
    		sendBits();
    		CS_hi();
    		_delay_us(5);		// Atleast: 8*Period T + 1.34us 
    	}
    
    }

  2. #2
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Please note that helping with microcontroller code can be difficult, as it might require knowledge of a specific device, and certainly requires knowledge of the hardware you're interfacing with.

    I tried to modify the code to control all the 22 LED drivers TLC5971 but it is not working.
    You should show your attempt, and explain exactly how it's not working.

    According to the data sheet:

    When units of the TLC5971 are cascaded (as shown in Figure 32), N × 224 bits must be written from the
    controller into the first device to control all devices.
    The number of cascaded devices is not limited as long as the
    proper voltage is supplied to the device at VCC. The packets for all devices must be written again whenever the
    data in one packet is changed.
    If your current code works with a single TLC5971, then it appears you should be able to create an array of struct (with 22 elements). Then you simply send all bits for each struct in the array.

  3. #3
    Registered User
    Join Date
    May 2015
    Posts
    18
    This is what I have done so far but it is not working. I am sure the code is not correct. Please I would appreciate if someone can check the code and repair it for me.

    Code:
    #include "usartSPI.h"#include "tlc5971_poecie.h"
    #include <avr/io.h>
    
    // this struct is implementation dependent on packing and endian.
    
    
    struct TLC5971 {
    	
    	uint16_t GS[4][3];
    	uint8_t BCB:7;
    	uint8_t BCG:7;
    	uint8_t BCR:7;
    	uint8_t BLANK:1;
    	uint8_t DSPRPT:1;
    	uint8_t TMGRST:1;
    	uint8_t EXTGCK:1;
    	uint8_t OUTTMG:1;
    	uint8_t cmd:6;
    } tlc5971;
    
    
    
    void tlc5971_init()
    {
        tlc5971.BLANK = 1;
        //tlc5971.DSPRPT = 1;
        //tlc5971.TMGRST = 1;
        //tlc5971.EXTGCK = 1;
        //tlc5971.OUTTMG = 1;
        //tlc5971.BCR = 127;
        //tlc5971.BCG = 127;
        //tlc5971.BCB = 127;
        
    }
    
    
    // The sendBits() is amended to use the address of the particular struct 
    
    
    void sendBits(struct TLC5971 *ptlc)
    {
        uint8_t n, *p = (uint8_t*)ptlc;
        
        for (n = 28; n-- > 0; )
        {
            usartSPI_transfer(p[n]);
        }
        
    }
    
    
    struct TLC5971 tlcarray[tlcN];        // Array of structure variables
    
    
    int main(void)
    {
        usartSPI_init();
        struct TLC5971 *ptlc;   // pointer of structure type
        ptlc = &tlcarray[21];
        ptlc->BCR = 64;            // Accessing Structure Member BCR
        ptlc->BCG = 64;            // Accessing Structure Member BCG
        ptlc->BCB = 64;            // Accessing Structure Member BCB
        ptlc->TMGRST = 1;        // Accessing Structure Member TMGRST
        ptlc->EXTGCK = 1;
        ptlc->cmd = 0x25;
        ptlc->GS[0][BLUE] = 3;
        ptlc->GS[0][GREEN] = 3;
        ptlc->GS[0][RED] = 3;
        
        
        while (1) {
            CS_lo();
            sendBits(&tlcarray[0]);
            sendBits(&tlcarray[1]);
            sendBits(&tlcarray[2]);
            sendBits(&tlcarray[3]);
            sendBits(&tlcarray[4]);
            sendBits(&tlcarray[5]);
            sendBits(&tlcarray[6]);
            sendBits(&tlcarray[7]);
            sendBits(&tlcarray[8]);
            sendBits(&tlcarray[9]);
            sendBits(&tlcarray[10]);
            sendBits(&tlcarray[11]);
            sendBits(&tlcarray[12]);
            sendBits(&tlcarray[13]);
            sendBits(&tlcarray[14]);
            sendBits(&tlcarray[15]);
            sendBits(&tlcarray[16]);
            sendBits(&tlcarray[17]);
            sendBits(&tlcarray[18]);
            sendBits(&tlcarray[19]);
            sendBits(&tlcarray[20]);
            sendBits(&tlcarray[21]);
            CS_hi();
            _delay_us(5);
        }
    }
    /*
    
    
    int main(void)
    {
        usartSPI_init();
        //tlc5971_init();
        struct TLC5971 *ptlc;
        struct TLC5971 tlcarray[22];
        ptlc = &tlcarray[21];
        ptlc->BCR = 10;
        ptlc->BCG = 10;
        ptlc->BCB = 10;
        ptlc->TMGRST = 1;
        ptlc->EXTGCK = 1;
        ptlc->cmd = 0x25;
        ptlc->GS[0][BLUE] = 3;
        ptlc->GS[0][GREEN] = 3;
        ptlc->GS[0][RED] = 3;
        
        while (1) 
        {
            CS_lo();
            for(uint8_t i= 0; i <= tlcN-1; i++ )
            {
                sendBits(&tlcarray[i]);
            }
            CS_hi();
        }
    }
    */
    Last edited by ssquared; 05-27-2015 at 03:08 PM.

  4. #4
    Registered User
    Join Date
    May 2015
    Posts
    18
    Please I am still waiting for some advice on how to do the task

  5. #5
    Registered User
    Join Date
    Feb 2012
    Posts
    347
    You can try the following

    Code:
    while (1) {
            CS_lo();
            sendBits(&tlcarray[0]);
           CS_hi();
           _delay_us(5);
           CS_lo();
            sendBits(&tlcarray[1]);
           CS_hi();
           _delay_us(5);
           CS_lo();
            sendBits(&tlcarray[2]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[3]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[4]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[5]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[6]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[7]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[8]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[9]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[10]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[11]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[12]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[13]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[14]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[15]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[16]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[17]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[18]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[19]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[20]);
           CS_hi();
           _delay_us(5);
          CS_lo();
            sendBits(&tlcarray[21]);
           CS_hi();
           _delay_us(5);
    
        }
    please remember i am making only a guess.

  6. #6
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    You need to loop through the array and initialize the struct members for each element in the array.

    Quote Originally Posted by Satya View Post
    You can try the following
    You bring up an interesting point. "CS" usually stands for "Chip Select", but the device does not have such an input ... but it does have an SCK (serial clock) input, which I don't see represented in the code. Furthermore, the SCK must be pulsed for each bit transmitted to the device. So unless the SCK is being pulsed where we can't see it (e.g. in the "usartSPI_transfer()" function), then the OP is not correctly controlling the device.

    @OP: Unfortunately, I do not have the time or desire to learn how to operate the TLC5971. You need to study the sequence/timing diagrams on the data sheet, and ensure your code is following the required sequence/timing specs.

  7. #7

  8. #8
    Registered User
    Join Date
    May 2015
    Posts
    18
    The TLC5971 chip has no chip select pin. It relies on a timed gap in the SCK signal for synchronisation. The time gap should not be less than 8*Period of SCKI + 1.34us. That is why I am using 5us.

  9. #9
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Also at AVRFreaks. ssquared seems to be using an ATmega1284p.

    Keeping the SCK low for 8 to 16384 cycles after a set of 224 bits causes all the chained TLC5971s to latch the data they have in their shift registers. This means that you only keep SCK low after sending 22×224 bits = 4928 bits. Normally, the data only goes through the shift register, a bit at a time, without affecting the TLC5971 operation in any way.

    If EXTGCK=0, the TLC5971 need at least 1.34µs (27 clock cycles at 20MHz) to update to the new state, before they are ready for a new data stream.

    If EXTGCK=1, you need to wait for 1.34µs or more (27 clock cycles at 20MHz), keeping both data and SCK low. Then, you need to basically send zeroes, to provide a valid clock on the SCK line while keeping data low, since SCK (your usart SPI clock signal!) is used as the PWM clock source for the LEDs. Leading zeroes are ignored by the TLC5971s, so you can just keep sending zero bytes until you want to start a new update (you don't need to send a multiple of 224 zero bits). During the update, the data shifts through the TLC5971 chips, but the PWM settings are kept unchanged (unlatched), until the SCK delay occurs, causing the new data to be latched to all the TLC5971 chips simultaneously.

    I'd personally use a 616-byte buffer with a 2-byte state variable (618 extra bytes of SRAM used) and the SPI interrupt to keep the SPI running whenever the device is enabled. A separate array, perhaps uint16_t led[88][3];, would be calculated/modified by the program itself (say, as an 8x11 RGB display), and a separate function used to (make sure the previous state has been completely sent, and then) copy the new LED states to the new array, and telling the interrupt handler (via the state variable) that a new state should be sent. Total SRAM use would then be 1146 bytes (882 bytes if using uint8_t led[88][3];) -- but as mentioned, the ATmega1284p has 16k of SRAM, so that should not be a problem -- and you could "draw" to the led array like it was a display, except that visual changes only occur after you call the update function. Best fit for a small game or gadget, in my opinion.

  10. #10
    Registered User
    Join Date
    May 2015
    Posts
    18
    Thanks for your reply. I am using Atmega1284p with a Frequency of 12.5MHz and baud rate of 921600 for the USART in MSPIM. I have attached here the working code. But the LEDs don't turn on in the pattern set in the code
    Code:
    #include "usartSPI.h"#include "tlc5971_poecie.h"
    #include <avr/io.h>
    
    
    
    
    
    
    void tlc5971_init()
    {
        tlc5971.BLANK = 1;
        tlc5971.DSPRPT = 0;
        tlc5971.TMGRST = 1;
        tlc5971.EXTGCK = 1;
        tlc5971.OUTTMG = 0;
        
    }
    
    
    
    
    void sendBits(void)
    {
        uint8_t n, *p = (uint8_t*)&tlc5971;
        
        for (n = 28; n-- > 0; )
        {
            usartSPI_transfer(p[n]);
        }
        //_delay_us(5);        // Atleast: 8*Period T + 1.34us
    }
    
    
    
    
    void testPattern(void)
    {
        
        tlc5971.BLANK = 0;
        for(uint8_t i=0; i<4 ; i++)
        {
            
            for (uint8_t j=0; j<3; j++)
            {
                tlc5971.GS[i][j] = 0x6000;            // OUTB0 = 16384
                tlc5971.GS[i][j] = 0x2000;            // OUTG0 = 8192
                tlc5971.GS[i][j] = 0x4000;            // OUTR0 = 24576
            }
            while(1)
            {
                //CS_lo();
                sendBits();
                //CS_hi();
                _delay_us(5);        // Atleast: 8*Period T + 1.34us
                break ;
            }
            
            _delay_ms(500);    
            tlc5971.BLANK = 1;
        }
        
    }
    
    
    int main(void)
    {
        //tlc5971_init();
        tlc5971.cmd = 0x25;
        tlc5971.TMGRST = 1;
        tlc5971.DSPRPT = 1;
        
        tlc5971.BCB = 3;
        tlc5971.BCG = 3;
        tlc5971.BCR = 3;
        
        usartSPI_init();
        //testPattern();
        
        while(1)
        {    
            //CS_lo();
            testPattern();
            sendBits();
            //CS_hi();
            _delay_us(5);        // Atleast: 8*Period T + 1.34us
            
        }
            
    }
    Last edited by ssquared; 05-30-2015 at 02:45 PM.

  11. #11
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by ssquared View Post
    the LEDs don't turn on in the pattern set in the code
    There is no pattern in your code. It sets all LEDs to 25% red, 25% green, 25% blue.

    I am not convinced your claim "one is working".

    To start with, you should use only one TLC5971, and make its four leds something like 25% red, 75% green, 25% blue; 50% red, 0% green, 0% blue; 0% red, 0% green, 50% blue; 0% red, 50% green, 0% blue. After you get that working, change the color values, and verify the changes match exactly.

    After you get that working, create a fader where each component of the four LEDs fade at different rates. Verify that the color components fade correctly (both "in" and "out"), and otherwise also as expected.

    Only after you get those working, continue with chaining. Not before. If you bulldoze ahead with chaining the TLC5971, while still possibly having serious issues with your code, you're building on quicksand. Not useful.

    In general, when working with new hardware, you really need to advance carefully. Make sure you get each step right, before advancing to the next step, or you end up having your base crumble out from beneath you. Verify each step carefully. When you encounter issues like you have now, you should have first backed down to a single TLC5971, and verified your control over the four LEDs it supports is complete. You claimed in your first post you have one TLC5971 under control, but you really do not, you're just stuffing more code on top of other code, and seeing what sticks. I don't like such an approach.

  12. #12
    Registered User
    Join Date
    May 2015
    Posts
    18
    Thanks for your reply and guidance. This is the code I used for the test using one LED driver.

    I tested the four different conditions separately and the LEDs turned on as expected. For example, in test 1 , I expected all the LEDs attached to the R0, G0 and B0 output to turn On and that is what I got. I did same for test 2, test 3 and test 4 and they were all correct.
    Code:
    void tlc5971_init(){
    	tlc5971.BLANK = 1;
    	tlc5971.DSPRPT = 0;
    	tlc5971.TMGRST = 1;
    	tlc5971.EXTGCK = 1;
    	tlc5971.OUTTMG = 0;
    	tlc5971.BCR = 50;
    	tlc5971.BCG = 50;
    	tlc5971.BCB = 50;
    }
    
    
    
    
    void sendBits(void)
    {
    	uint8_t n, *p = (uint8_t*)&tlc5971;
    	
    	for (n = 28; n-- > 0; )
    	{
    		usartSPI_transfer(p[n]);
    	}
    	
    }
    
    
    
    
    int main(void)
    {
    	//tlc5971_init();
    	tlc5971.cmd = 0x25;
    	tlc5971.TMGRST = 1;
    	tlc5971.DSPRPT = 1;
    	tlc5971.BCB = 3;
    	tlc5971.BCG = 3;
    	tlc5971.BCR = 3;
    	
    	
    	// Test 1
    	tlc5971.GS[0][0] =  0x6000;			// OUTB0 = 16384
    	tlc5971.GS[0][1] = 0x2000;			// OUTG0 = 8192
    	tlc5971.GS[0][2] = 0x4000;			// OUTR0 = 24576
    	
    	// Test 3
    	tlc5971.GS[1][0] =  0x6000;			// OUTB1 = 16384
    	tlc5971.GS[1][1] = 0x2000;			// OUTG1 = 8192
    	tlc5971.GS[1][2] = 0x4000;			// OUTR1 = 24576
    	
    	// Test 4
    	tlc5971.GS[2][0] =  0x6000;			// OUTB2 = 16384
    	tlc5971.GS[2][1] = 0x2000;			// OUTG2 = 8192
    	tlc5971.GS[2][2] = 0x4000;			// OUTR2 = 24576
    	
    	// Test 2
    	tlc5971.GS[3][0] =  0x6000;			// OUTB3 = 16384
    	tlc5971.GS[3][1] = 0x2000;			// OUTG3 = 8192
    	tlc5971.GS[3][2] = 0x4000;			// OUTR3 = 24576
    	
    	
    	
    			
    	usartSPI_init();
    	
    	while(1)
    	{
    		
    		CS_lo();
    		sendBits();
    		CS_hi();
    		_delay_us(5);		// Atleast: 8*Period T + 1.34us
    	}
    }

  13. #13
    Registered User
    Join Date
    May 2015
    Posts
    18

    Code for fader

    I have just written the code for the Fader. Please check if it is correct.
    Code:
    void testFader(void){
    	for(int fadeValue = 0 ; fadeValue <= 127; fadeValue +=5) {
    		// sets the value (range from 0 to 127):
    		tlc5971.BCB = fadeValue + 3;
    		tlc5971.BCG = fadeValue + 25;
    		tlc5971.BCR = fadeValue + 64;
    		// wait for 30 milliseconds to see the dimming effect
    		_delay_ms(30);
    	}
    
    
    	// fade out from max to min in increments of 5 points:
    	for(int fadeValue = 127 ; fadeValue >= 0; fadeValue -=5) {
    		// sets the value (range from 0 to 127):
    		tlc5971.BCB = fadeValue + 3;
    		tlc5971.BCG = fadeValue + 25;
    		tlc5971.BCR = fadeValue + 64;
    		// wait for 30 milliseconds to see the dimming effect
    		_delay_ms(30);
    	}
    }

  14. #14
    Registered User
    Join Date
    May 2015
    Posts
    18
    One problem is that all the LED in the matrix are white, so I can really check how the colours are changing.

    Quote Originally Posted by Nominal Animal View Post
    There is no pattern in your code. It sets all LEDs to 25% red, 25% green, 25% blue.

    I am not convinced your claim "one is working".

    To start with, you should use only one TLC5971, and make its four leds something like 25% red, 75% green, 25% blue; 50% red, 0% green, 0% blue; 0% red, 0% green, 50% blue; 0% red, 50% green, 0% blue. After you get that working, change the color values, and verify the changes match exactly.

    After you get that working, create a fader where each component of the four LEDs fade at different rates. Verify that the color components fade correctly (both "in" and "out"), and otherwise also as expected.

    Only after you get those working, continue with chaining. Not before. If you bulldoze ahead with chaining the TLC5971, while still possibly having serious issues with your code, you're building on quicksand. Not useful.

    In general, when working with new hardware, you really need to advance carefully. Make sure you get each step right, before advancing to the next step, or you end up having your base crumble out from beneath you. Verify each step carefully. When you encounter issues like you have now, you should have first backed down to a single TLC5971, and verified your control over the four LEDs it supports is complete. You claimed in your first post you have one TLC5971 under control, but you really do not, you're just stuffing more code on top of other code, and seeing what sticks. I don't like such an approach.

  15. #15
    Registered User
    Join Date
    May 2015
    Posts
    18

    Sending 616 Bytes

    Please I wish to send 616 Bytes using SPI. I have written this code. Please I would appreciate if i can get some feedback

    Code:
    void sendBits(void){
    	uint16_t n; 
    	uint8_t *p = (uint8_t*)&tlc5971;
    	
    	for (n = 616; n-- > 0; )
    	{
    		usartSPI_transfer(p[n]>>8);  	// Sending the MSB
    		usartSPI_transfer(p[n]&FF);		// Sending the LSB
    	}
    	//_delay_us(5);		// Atleast: 8*Period T + 1.34us
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A simple Array issue
    By TastySauceCode in forum C++ Programming
    Replies: 11
    Last Post: 09-22-2011, 06:02 AM
  2. 2nd array simple issue (IMPORTANT!)
    By Kadmany in forum C Programming
    Replies: 1
    Last Post: 04-23-2011, 06:46 AM
  3. Strange structure array issue...
    By IndioDoido in forum C Programming
    Replies: 9
    Last Post: 03-23-2008, 06:29 AM
  4. Structure Issue
    By fkheng in forum C Programming
    Replies: 2
    Last Post: 06-09-2003, 12:15 AM
  5. (structure+array+pointer)to make a simple database
    By frankie in forum C Programming
    Replies: 5
    Last Post: 04-26-2002, 05:14 PM

Tags for this Thread