- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I want to Drive RGB LED strip using PSoC 4100S Plus family member CY8C4146.
So my questions are,
1. How can I drive the RGB LED strip like WB2812?
2. Is UDBs are required to drive the RGB LED strip?
Because there is no UDB in PSoC 4100S Plus.
Thanks in Advance.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
At first this sounded an easy sample,
but this ended up my first fight in the ns range time adjustment.
For those advanced PSoC experts, this could be done by using UDB or DMA & PWM.
But unfortunately I am not that advanced.
According to the data sheet you linked the timing requirements are
When I tried with CY8CKIT-149 running at 24MHz,
only rising and falling gpio using DOUT_Write() took around 1 us.
This meant we had no margin to adjust.
So I changed the clock to 48MHz.
Now flipping GPIO took only 500ns (0.5us)
I ran a simple test
=================
#define INC_DELAY i++
#define code_0() DOUT_Write(1);DOUT_Write(0);INC_DELAY;
#define code_1() DOUT_Write(1);INC_DELAY;DOUT_Write(0);
void min_test(void)
{
volatile int i = 0 ;
// TrigOut_Write(1) ;
code_0() ;
code_1() ;
code_0() ;
code_1() ;
// TrigOut_Write(0) ;
}
===================
And it gave me
T0H: 480ns T0L: 760ns, T1H: 740ns , T1L: 550ns
So all values were withing the required range.
Then I modified the code for 24bit loop.
But the loop made the later half of the signal (low level) much longer.
So it was a time for hacking.
I noticed that calling DOUT_Write() costs a function calling time,
so I dragged out the contents of DOUT_Write() from the generated DOUT.c
And also the "value" variable was replaced with a constant of 0 or 1.
Now DOUT_Write(1) ended up
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(1 << DOUT_SHIFT) & DOUT_MASK));
After all my send_data() function looks like
====================
void send_value(uint8_t r, uint8_t g, uint8_t b)
{
volatile int i = 0 ;
uint8_t int_status ;
uint8 drVal ;
uint32_t composit_value = 0 ;
uint32_t mask ;
mask = 0x01 << 23 ;
composit_value = (g << 16) | (r << 😎 | b ;
int_status = CyEnterCriticalSection() ;
do {
if (composit_value & mask) {
// code_1
// DOUT_Write(1) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(1 << DOUT_SHIFT) & DOUT_MASK));
INC_DELAY ; INC_DELAY ; INC_DELAY ; INC_DELAY ;
// DOUT_Write(0) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(0 << DOUT_SHIFT) & DOUT_MASK));
} else {
// code_0
// DOUT_Write(1) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(1 << DOUT_SHIFT) & DOUT_MASK));
INC_DELAY ; INC_DELAY ;
// DOUT_Write(0) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(0 << DOUT_SHIFT) & DOUT_MASK));
INC_DELAY ; INC_DELAY ; INC_DELAY ;
}
} while( mask >>= 1 ) ;
CyExitCriticalSection(int_status) ;
}
====================
As far as I tested with values of 0, 255, 170
the wave form seemed to be within the range.
So I will not be surprised if this works.
but also not will I if it does not.
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
How much current do you think the LED will draw?
I think that general MCU does not have enough current to drive the LEDs like WB2812.
The current that can be applied to a single GPIO is about several mA. If you need more current, bundle some GPIO pins or add an external LED driver device. LED can be controlled programmatically without UDB.
Regards,
Kenshow
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you Kenshow for response.
The strip consist of 6 RGB LED which can be individually controlled.
For Current requirement I am using external power source.
The strip has three pins
5V
GND
Data In (single wire communication)
The Data In is used to control the LEDs
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can find an implementation on PSoC 4200 using UDB in following page.
https://www.element14.com/community/thread/27131/
PSoC 4 Pioneer Kit Community Project#100 – PSoC 4 Times Square LED Billboard
I don't know if this can be implemented in PSoC 4100S without UDB.
Regards,
Noriaki
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
The WB2812 can be connected sequentially, so you can control only one data line. I think that it can be achieved by setting GPIO and combining it with CyDelay(), or by using a serial interface such as SPI instead.
Regards,
Kenshow
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
At first this sounded an easy sample,
but this ended up my first fight in the ns range time adjustment.
For those advanced PSoC experts, this could be done by using UDB or DMA & PWM.
But unfortunately I am not that advanced.
According to the data sheet you linked the timing requirements are
When I tried with CY8CKIT-149 running at 24MHz,
only rising and falling gpio using DOUT_Write() took around 1 us.
This meant we had no margin to adjust.
So I changed the clock to 48MHz.
Now flipping GPIO took only 500ns (0.5us)
I ran a simple test
=================
#define INC_DELAY i++
#define code_0() DOUT_Write(1);DOUT_Write(0);INC_DELAY;
#define code_1() DOUT_Write(1);INC_DELAY;DOUT_Write(0);
void min_test(void)
{
volatile int i = 0 ;
// TrigOut_Write(1) ;
code_0() ;
code_1() ;
code_0() ;
code_1() ;
// TrigOut_Write(0) ;
}
===================
And it gave me
T0H: 480ns T0L: 760ns, T1H: 740ns , T1L: 550ns
So all values were withing the required range.
Then I modified the code for 24bit loop.
But the loop made the later half of the signal (low level) much longer.
So it was a time for hacking.
I noticed that calling DOUT_Write() costs a function calling time,
so I dragged out the contents of DOUT_Write() from the generated DOUT.c
And also the "value" variable was replaced with a constant of 0 or 1.
Now DOUT_Write(1) ended up
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(1 << DOUT_SHIFT) & DOUT_MASK));
After all my send_data() function looks like
====================
void send_value(uint8_t r, uint8_t g, uint8_t b)
{
volatile int i = 0 ;
uint8_t int_status ;
uint8 drVal ;
uint32_t composit_value = 0 ;
uint32_t mask ;
mask = 0x01 << 23 ;
composit_value = (g << 16) | (r << 😎 | b ;
int_status = CyEnterCriticalSection() ;
do {
if (composit_value & mask) {
// code_1
// DOUT_Write(1) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(1 << DOUT_SHIFT) & DOUT_MASK));
INC_DELAY ; INC_DELAY ; INC_DELAY ; INC_DELAY ;
// DOUT_Write(0) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(0 << DOUT_SHIFT) & DOUT_MASK));
} else {
// code_0
// DOUT_Write(1) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(1 << DOUT_SHIFT) & DOUT_MASK));
INC_DELAY ; INC_DELAY ;
// DOUT_Write(0) ;
drVal = (uint8)(DOUT_DR & (uint8)(~DOUT_MASK));
DOUT_DR = (drVal | ((uint8)(0 << DOUT_SHIFT) & DOUT_MASK));
INC_DELAY ; INC_DELAY ; INC_DELAY ;
}
} while( mask >>= 1 ) ;
CyExitCriticalSection(int_status) ;
}
====================
As far as I tested with values of 0, 255, 170
the wave form seemed to be within the range.
So I will not be surprised if this works.
but also not will I if it does not.
moto