0:23
everyone welcome to controllers tech
0:27
today in this video we will see how to
0:30
interface addressable leds with the
0:34
i am going to use ws2812 leds for
0:40
this video is divided into two halves
0:44
in the first half i will show how to use
0:46
pulse width modulation using the dma
0:50
and in the second half we will use that
0:52
idea to interface the led
0:55
the first part of the video is
0:57
configuration and it is common to both
1:01
let's start with the configuration then
1:04
i am using f446re controller
1:09
give some name to this project and click
1:14
here is our cube mx first of all i am
1:18
setting the external crystal for the
1:22
before going any forward let's set up
1:26
i have 8 megahertz external crystal
1:30
i am using the 72 megahertz clock
1:33
this is to make sure the blue pill users
1:36
can use the same configuration
1:38
too you can use any other clock too
1:41
just pay attention to the configuration
1:44
note here the apd1 timer clock is
1:47
running at 72 megahertz
1:49
and so is the apb 2 clock
1:52
this means that all the timers are also
1:55
going to be running at this
1:56
frequency since all of them are
1:58
connected to either of these buses
2:01
now i am going to use the timer one for
2:05
select the pwm output mode
2:09
you can see the pin got selected here
2:12
now comes the very important part
2:15
but before that let's take a look at the
2:24
this is the data sheet of ws21812
2:29
and i also have here for ws2812b
2:42
as you can see the led data is 24 bit
2:47
the higher eight bits are the green
2:49
color their next eight bits for the red
2:51
and then the blue we must send the bits
2:57
we will talk about this in the second
3:01
this is the important part right now
3:04
here is how we send a zero
3:08
t zero high is the time for which the
3:12
so basically to send a zero we must keep
3:15
the pulse high for 0.35 microseconds
3:19
and then keep it low for 0.8
3:26
it could be plus minus 150 nanoseconds
3:30
the total period for the pulse should be
3:44
if we see the frequency for this signal
3:49
so we need 800 kilohertz timer frequency
3:57
if you remember all the timers are
3:59
running at 72 megahertz
4:01
anyway i am using timer 1 which is
4:05
and its frequency is 72.
4:08
now we need to bring this frequency to
4:13
we can do this by using a prescaler of 9
4:16
and then using an auto reload value of
4:24
or we could keep the prescaler 1 and use
4:34
i am gonna go with the second option
4:37
you will see in a minute why
4:44
by the way the same setup is also valid
5:04
you can see a little difference in the
5:06
high time or low time
5:08
but that does not matter that much we
5:11
already have uncertainty of 150
5:14
nanoseconds to take into account
5:29
so let's keep the prescaler 1 and set
5:31
the auto reload register to 90.
5:38
the reason is simple this auto reload
5:42
value corresponds to 100
5:44
of the duty cycle that means
5:48
if we set the value 90 to the capture
5:51
we will get pwm signal with 100
5:54
duty now it's easier to calculate the
5:59
compared to 9 right this is the reason i
6:03
choose to keep it 90.
6:05
if you can keep it 100 it will be the
6:08
because it will be easier to calculate
6:10
the duty percentage then
6:13
so let's see what percentage of duty
6:18
as you know to send a zero we must keep
6:21
the signal high for 0.4 microseconds
6:25
out of 1.25 this comes around 32
6:30
this is our duty cycle to send a zero 32
6:38
and to send a one the duty cycle is 68
6:46
let's see this again to send a zero
6:49
we have to keep the signal 32 percent
6:53
and 68 percent low whereas to send a 1
6:57
it should be 68 high and 32
7:01
low so basically to send a zero
7:04
one third of the signal is high and two
7:14
to send a one two-third of the signal is
7:22
since our 100 duty is 90 we have to
7:26
calculate the one-third
7:27
and two-third from this 90.
7:30
we will do that later in the code
7:38
select the timer channel we are sending
7:41
the data from memory to the
7:43
so select the option keep the dma to
7:48
it will be easier to stop it i am
7:51
keeping the data width to 16 bits
7:56
click save to generate the project now
8:06
here is our main file let's create a
8:09
function to send the data to the dma it
8:12
will take the value of green
8:14
red and blue as the arguments
8:17
you know the color codes first we will
8:20
create a 32-bit variable
8:23
which will store the 24-bit data for the
8:27
green should be the msb the red and at
8:32
now we will check the individual bits of
8:36
i am starting the check from the msb
8:44
if the bit is 1 we will store 60 in that
8:57
remember the data sheet to send a one
9:00
two third of the signal must be high
9:05
since our reload value is 90 the two
9:09
which will represent the 68 duty cycle
9:17
else if the bit is zero we will store 30
9:23
guys i am storing the msb to the last so
9:26
that the it will be easier for me to
9:28
represent this data on the scope
9:31
when we will see the actual led code the
9:35
first now we will start the pwm with dma
9:40
and send our buffer in the main function
9:44
call the send i am just using some
10:08
and this should be a pointer to 32-bit
10:17
okay let's run it now
10:25
i am going to connect my analyzer now
10:31
start the recording here run the code
10:40
and that should be enough
10:49
this is a bit messy here you see
10:52
dma is keep sending the data it doesn't
10:57
so we need to stop it
11:03
let's look for the callback function
11:08
when the data transmission is finished
11:12
callback will be called
11:19
inside this callback function we will
11:43
okay this time it's definitely stopped
11:50
here we have the pulse
11:54
seems like we got the 24 bit data
11:58
you can see the pulse width is 1.25
12:03
also some pulse are 833 nanoseconds wide
12:07
which is basically a one and some are
12:11
413 nanoseconds wide
12:14
which represents the zero
12:20
i have divided this data into three
12:24
now remember here that i stored the msb
12:27
data into msb position
12:29
so the lsb data is sent first
12:32
that means the first eight bits on the
12:34
analyzer are for the blue color
12:37
these eight bits are for blue if i
12:40
divide it into two parts
12:42
you can convert them to hexadecimal now
12:45
we have zero cross six five which is one
12:48
hundred and one in decimal
12:50
this whole inverted situation is there
12:53
because i send the lsb first
12:55
but we will not do that during the
12:58
anyway then we have zero cross ff that
13:06
and at last we have zero cross zero five
13:08
which is basically five
13:11
those last four zeros you see they are
13:15
it took some time for the interrupt to
13:17
process and the dma to stop
13:19
and within that time dma transmitted
13:23
okay this is it about using dma with pwm
13:28
you saw how can we use dma to change the
13:30
duty cycle of the signal at really high
13:34
we can't so that using the simple pwm
13:37
because of the time required for the
13:39
instructions to process
13:42
it will mess up our data that is being
13:44
transferred to the device
13:47
now we will start the second half
13:50
here we will interface the ws2812 led
13:55
obviously i am going to use the pwmdma
13:59
lets start by defining the maximum leds
14:02
that you have in cascade
14:05
if you want to control brightness set
14:12
now led data is a matrix of four columns
14:16
and the number of rows will be same as
14:18
the number of leds you have
14:20
this will store the values for the color
14:23
for the individual led
14:25
led mod is another matrix but it will
14:29
that are modified as per the brightness
14:33
now i am defining a data sent flag here
14:37
once the dma has been stopped this will
14:40
make sure that dma does not send another
14:44
while the first data is still being
14:51
this function will be used to set color
14:54
led here first parameter is the led
14:58
to which we want to set the color then
15:00
the values of the colors
15:03
i am keeping the red first because
15:05
that's how you find the color codes in
15:09
here first column will store the led
15:12
second column will store the value for
15:16
and last column for blue note that we
15:19
are storing the green value
15:21
first as the device require us to send
15:23
the green value first
15:26
now this is the function to set the
15:28
brightness for the leds
15:30
you can input the brightness from 0 to
15:35
brightness is nothing special you just
15:37
have to scale the actual values by some
15:40
factor for example 255 is the brightest
15:45
so 127 will be 50 bright
15:48
and around 63 will be 25 brightness
15:53
the problem that i faced here was the
15:55
linearity in the brightness values
15:59
what i mean is you just can't increment
16:02
which will scale the brightness linearly
16:06
so i came up with this solution
16:09
i am dividing by the tangent of the
16:11
angle which varies between 45 to 90
16:16
this way the scale is not perfectly
16:18
linear but it remains
16:19
somewhat linear here we don't change the
16:23
value in the first column
16:24
since this is the led number and for the
16:29
we will divide the led data by this
16:33
and store it in the led mod this entire
16:36
process will only take place
16:38
if you have defined the use of
16:53
this is the function that we will use to
16:55
send the values to the pwm dma here i am
16:58
defining a 32-bit variable
17:01
that can store the 24-bit color data
17:05
we have to perform this operation for
17:07
each led individually
17:10
remember we store the green code in the
17:14
red in the third and blue in the fourth
17:17
we will shift the green code by 16 place
17:20
red by 8 and no shift for blue
17:24
now we will check individual bit in the
17:28
starting from the msb if the bit is 1
17:32
we will store the value 60 in the lsb
17:36
note here guys the msb is needed to be
17:39
and that's why we are storing the msb
17:42
to the lsb and the pwm data
17:46
i have already explained you the
17:48
significance of this 60.
17:50
it's two-third of the reload value
17:54
and if the bit is zero we will write 30
18:04
once all the led values are stored note
18:08
i am continuing storing another 50 zeros
18:11
this is explained in the data sheet
18:25
as you can see after sending one set of
18:28
data for all the leds
18:30
we need to keep the line low for more
18:32
than 50 microseconds
18:34
since our pwm width is 1.25 microseconds
18:38
we can just send 50 zeros to the pwm
18:43
this will correspond to more than 50
18:45
microseconds delay for the driver
18:48
and by the way you can see here the data
18:51
for all the leds must be sent
18:53
together the driver will use the first
18:56
24 bits for the first led and
18:59
automatically shifts the rest of it to
19:03
which will be further shifted to third
19:06
and so on so that's why
19:09
after sending the data for all the leds
19:12
we must send a low for 50 microseconds
19:15
to indicate that there is another set of
19:24
and after all the storing is finished we
19:26
will send the data to the dma
19:29
i haven't changed the variable here yet
19:33
pwm data can store 24 times the leds
19:45
that extra 50 is used to store this
19:50
now after sending the data we will wait
19:52
for this flag to set
19:54
this will indicate that dma has been
19:57
and you can send another set of data now
20:01
these are all the functions needed
20:04
now let's send some color data
20:13
here i will set the led 0 first
20:17
red is 255 and others are zero
20:22
so this will be purely red then set the
20:25
green to the first led
20:27
and blue to the second led
20:30
and now we will call the ws2812
20:34
send to send this data to the respective
20:38
let's build it okay we have got some
20:43
i have defined it wrong here this
20:46
seems all right now we have to define
20:51
for the tangent function
21:09
okay didn't work i forgot to include the
21:15
let's keep it full bright that is 45
21:28
great you can see the three leds light
21:32
the first one is red second is green
21:35
and the third is blue you might not be
21:38
able to see the difference in second and
21:42
this is just due to camera quality
21:45
trust me the second is green and the
21:50
let me just comment out the blue color
21:52
and run this code again
22:06
now you can see the first is red and
22:11
so this part worked pretty good
22:16
i will add some more random colors now
22:20
but before that let's see what happens
22:22
when we set the brightness to zero
22:34
as expected the leds are completely off
22:38
good then i will continue adding more
22:43
i don't exactly know what these colors
22:47
now all the leds are set in the while
22:51
i will increase the brightness up to 45
22:54
and then decrease it down to zero
22:57
and let's add 50 milliseconds delay
23:26
you can see we have got ourselves a very
23:38
so we can just take some random color
23:44
and set the values in the led
23:48
i will comment out other leds
23:54
set the brightness to 20 which is
23:56
approximately 50 percent
24:03
and you can see we got the color we
24:06
the code works pretty straightforward
24:10
set the color set the brightness and
24:14
this part here i have shot after
24:16
shooting the original video
24:18
so you might feel the cut this is the
24:21
code to generate the rainbow effect
24:24
obviously i haven't written it look at
24:28
so i will explain you how i got it
24:32
you have to go to this link here first
24:36
you need to add the led strip click on
24:40
and select the number of leds you have
24:44
now click add effect we can easily get
24:47
other effects with our regular program
24:51
so here i am using the rainbow effect
24:55
click on animation and then control the
25:13
once you got what you need click
25:15
generate arduino code
25:18
now let's copy this code in our notepad
25:24
out of this entire code we are only
25:27
interested in this part
25:29
so i will copy this and paste it in my
25:37
let's rename it to the rainbow effect
25:48
this function set pixel color we will
25:51
replace it with the set led
25:55
and after setting the led we will send
26:11
let's build if once to check where the
26:17
we don't need this line here we will add
26:26
this variable here we will define it
26:34
if you check the code we copied this is
26:36
unsigned 16-bit variable
26:43
so let's define it now correct it
27:03
resetting the strip is just like setting
27:06
the variable to zero
27:50
so this is it now let's call this
27:54
function in the while loop
27:56
and add 30 milliseconds delay
28:13
you can see the nice rainbow effect
28:20
you can play with some more patterns
28:23
just follow what i did
28:26
this is it for this video i hope things
28:31
the video got very long but i needed to
28:34
explain the basics behind pwm dma we can
28:37
use the same logic in some other devices
28:41
i guess i will try with dht temperature
28:44
and see if it works with pwm
28:48
anyway you can download the code from
28:50
the link in the description
28:53
keep watching and have a nice day ahead