summaryrefslogtreecommitdiff
path: root/blog/wifi-led-driver/index.html
blob: ed5667b037851bcee7bdff406a007fd8b00fc753 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<!DOCTYPE html>
<html><head>
    <meta charset="utf-8">
    <title>Wifi Led Driver | Home</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="color-scheme" content="dark light">
    <link rel="stylesheet" href="/style.css">
</head>
<body><nav>
    <div class="internal">
        
        <a href="/" title="Home">Home</a>
        <a href="/blog/" title="Blog">Blog</a>
        <a href="/projects/" title="Projects">Projects</a>
        <a href="/about/" title="About">About</a>
    </div>
    <div class="search">
        <div id="search"></div>
    </div>
    <div class="external">
        <a href="https://git.jaseg.de/" title="cgit">cgit</a>
        <a href="https://github.com/jaseg" title="Github">Github</a>
        <a href="https://gitlab.com/neinseg" title="Gitlab">Gitlab</a>
        <a href="https://chaos.social/@jaseg" title="Mastodon">Mastodon</a>
    </span>
</nav>

    <header>
        <h1>Wifi Led Driver</h1>
<ul class="breadcrumbs">
    <li><a href="/">jaseg.de</a></li>
    <li><a href="/blog/">Blog</a></li><li><a href="/blog/wifi-led-driver/">Wifi Led Driver</a></li>
</ul>
 <strong>2018-05-02</strong>
    </header>
    <main data-pagefind-body>
        <div class="document">


<div class="section" id="project-motivation">
<h2>Project motivation</h2>
<!-- FIXME finished project picture with LED tape -->
<figure data-pagefind-ignore>
    <img src="images/board_in_case.small.jpg">
    <figcaption>The completed driver board installed in the 3D-printed case. This device can now be connected to
    12V and two segments of LED tape that can then be controlled trough Wifi. The ESP8266 module goes on the pin
    header on the left and was removed for this picture.
    </figcaption>
</figure><p>After the <a class="reference external" href="http://jaseg.de/blog/multichannel-led-driver/">multichannel LED driver</a> was completed, I was just getting used to controlling LEDs at 14-bit resolution.
I liked the board we designed in this project, but at 32 channels it was a bit large for most use cases. Sometimes I
just want to pop a piece of LED tape or two somewhere, but I don't need a full 32 channels of control. I ended up
thinking that a smaller version of the 32-channel driver that didn't require a separate control computer would be
handy. So I sat down and designed a variant of the design with only 8 channels instead of 32 and an on-board <a class="reference external" href="https://en.wikipedia.org/wiki/ESP8266">ESP8266</a>
module instead of the <a class="reference external" href="https://en.wikipedia.org/wiki/RS-485">RS485</a> transceiver for WiFi connectivity.</p>
</div>
<div class="section" id="the-electronics">
<h2>The Electronics</h2>
<p>The schematic was mostly copy-pasted from the 32-channel design. The PCB was designed from scratch. This time, I went
for a 5x7cm form factor to allow for enough room for all connectors and to give the <a class="reference external" href="https://en.wikipedia.org/wiki/ESP8266">ESP8266</a>'s WiFi antenna enough
space. The board has two 5-pin <a class="reference external" href="https://www.phoenixcontact.com/online/portal/de?uri=pxc-oc-itemdetail:pid=1757019&amp;library=dede&amp;tab=1">Phoenix-style</a> for two RGB-White (RGBW) tapes and one 2-pin <a class="reference external" href="https://www.phoenixcontact.com/online/portal/de?uri=pxc-oc-itemdetail:pid=1757019&amp;library=dede&amp;tab=1">Phoenix-style</a> connector for
12V power input. The control circuitry and the serial protocol are unchanged, but the <a class="reference external" href="http://www.st.com/resource/en/datasheet/stm32f030f4.pdf">STM32</a> now talks to an <a class="reference external" href="http://www.watterott.com/de/ESP8266-WiFi-Serial-Transceiver-Modul">ESP-01</a>
module running custom firmware.</p>
<p>The LEDs are driven using a <a class="reference external" href="http://www.ti.com/lit/ds/symlink/sn74hc595.pdf">74HC595</a> shift register controlling a bunch of <a class="reference external" href="http://aosmd.com/pdfs/datasheet/AO3400.pdf">AO3400</a> <a class="reference external" href="https://en.wikipedia.org/wiki/MOSFET">MOSFETs</a>, with resistors in front of
the <a class="reference external" href="https://en.wikipedia.org/wiki/MOSFET">MOSFETs</a>' gates to slow down the transitions a bit to reduce brighntess nonlinearities and <a class="reference external" href="https://en.wikipedia.org/wiki/Electromagnetic_interference">EMI</a> resulting from
ringing of the LED tape's wiring inductance.</p>
<p>The board has two spots for either <a class="reference external" href="https://en.wikipedia.org/wiki/Resettable_fuse">self-resettable fuses (polyfuses)</a> or regular melting-wire <a class="reference external" href="https://en.wikipedia.org/wiki/Fuse_(electrical)">fuses</a> in
a small <a class="reference external" href="https://en.wikipedia.org/wiki/Surface-mount_technology">SMD</a> package, one for each RGBW output. For low currents the self-resettable fuses should be okay but at higher
currents their <a class="reference external" href="http://m.littelfuse.com/~/media/electronics/datasheets/resettable_ptcs/littelfuse_ptc_16r_datasheet.pdf.pdf">trip times get long enough that they become unlikely to trip in time to save anything</a>, so plain old non-resettable fuses would be the way to go there.</p>
<!-- FIXME finished board photos -->
<!-- FIXME board with test tape picture -->
<div class="subfigure" data-pagefind-ignore>
    <figure>
        <img src="images/schematic.png">
        <figcaption>
        The schematic of the driver board, with the ESP8266 on the top left, the STM32 microcontroller for LED
        modulation below, the shift register in the middle and the LED drivers and outputs on the right.
        <a href="resource/schematic_and_pcb.pdf">Download PDF</a>
        </figcaption>
    </figure>
    <figure>
        <img src="images/layout.png">
        <figcaption>
        The board layout with the top side being visible. The top side contains the footprint for the ESP8266, the
        microcontroller, fuses, filter cap, connectors and the shift register. The LEDs are connected on the left,
        with one connector per LED tape segment. The power input connector is on the bottom right. The LED driver
        MOSFETs are in small SOT-23 packages on the back of the board. Since this board is not intended for
        super-high currents, the MOSFETs are adequately cooled just through the board's copper planes.
        <a href="resource/schematic_and_pcb.pdf">Download PDF</a>
        </figcaption>
    </figure>
</div><figure data-pagefind-ignore>
    <img src="images/boards.small.jpg">
    <figcaption>The completed PCBs of this project (front) and the `multichannel LED driver`_ project the driver
    circuitry was derived from (back).
    </figcaption>
</figure></div>
<div class="section" id="the-firmware">
<h2>The Firmware</h2>
<p>The <a class="reference external" href="http://www.st.com/resource/en/datasheet/stm32f030f4.pdf">STM32</a> firmware only had to be slightly modified to accomodate the reduced channel count since the protocol remains
unchanged. The ESP firmware is based on <a class="reference external" href="https://github.com/Spritetm/esphttpd">esphttpd</a> by <a class="reference external" href="http://spritesmods.com/">Spritetm</a>. The modifications to the webserver firmware are pretty
basic. First, the UART console has been disabled since I use the UART to talk to the STM32. The few bootloader messages
popping out the UART on boot are not an issue, since they're unlikely to contain the fixed 32-bit address prefix the
serial protocol requires for the <a class="reference external" href="http://www.st.com/resource/en/datasheet/stm32f030f4.pdf">STM32</a> to do anything.</p>
<p>Second, I added LED control by adding drivers for the serial protocol and a bunch of colorspace conversion functions.
When I first tested the prototype software, I noticed that color reproduction was extremely poor. When I just sent a
<a class="reference external" href="https://en.wikipedia.org/wiki/HSL_and_HSV">HSV</a> rainbow fade from a python command line, the result looked totally wrong. The fade did not seem to go at a constant
speed and some colors, in particular yellow, orange and greens, were not visible at all. The problem turned out to be a
stark mismatch of the red, green and blue channels of the LED tape and less-than-optimal color reproduction of the pure
colors. I decided to properly measure the LED tape's color reproduction so I could compensate for it in software. This
turned out to be an extremely interesting project, the details of which you can read in my <a class="reference external" href="http://jaseg.de/blog/led-characterization/">LED characterization</a>
article.</p>
<p>Third, I updated the built-in websites with some ad-hoc documentation on how to use the thing and a basic interface for
LED control.</p>
<!-- FIXME screenshot of firmware website -->
</div>
<div class="section" id="making-an-enclosure">
<h2>Making an enclosure</h2>
<p>To be actually useful, the driver needed a robust enclosure. Bare PCBs are nice for prototyping, but for actually
putting the thing anywhere it needs a case to protect it against random destruction.</p>
<p>The board has four mounting holes with comfortable spacing in its corners to allow easy mounting inside a 3D-printed
case. The case itself is described in an <a class="reference external" href="http://www.openscad.org/">OpenSCAD</a> script. To make it look a little nicer, a little 3D relief is laid
into the lid. The 3D relief is generated with a bit of blender magic. The source <a class="reference external" href="https://en.wikipedia.org/wiki/STL_(file_format)">STL</a> model is loaded into blender, then
blender's amazingly flexible rendering system is used to export a depth map of a projection of the model as a <a class="reference external" href="https://en.wikipedia.org/wiki/Portable_Network_Graphics">PNG</a> file.
This depth map is then imported as a triangle mesh into <a class="reference external" href="http://www.openscad.org/">OpenSCAD</a>.</p>
<p>For the relief to look good, I chose a rather high resolution for the depth map. This unfortunately leads to extreme
memory use and processing time on the part of <a class="reference external" href="http://www.openscad.org/">OpenSCAD</a>, but since I have access to a sufficiently fast machine that is
not a problem. Just be careful if you try opening the <a class="reference external" href="http://www.openscad.org/">OpenSCAD</a> file on your machine, <a class="reference external" href="http://www.openscad.org/">OpenSCAD</a> will probably crash
unless you're on a beefy machine or interrupt it when it starts auto-rendering the file.</p>
<p>The board is mounted into the enclosure using knurled insert nuts that are pressed into a 3D-printed hole using a bit of
violence.</p>
</div>
</div>
    </main><footer>
    Copyright © 2023 Jan Sebastian Götte
    / <a href="/about/">About</a>
    / <a href="/imprint/">Imprint</a>
</footer>
<script src="/pagefind/pagefind-ui.js"></script>
        <script>
            if(navigator.getEnvironmentIntegrity!==undefined)document.querySelector('body').innerHTML=`<h1>Your browser
            contains Google DRM</h1>"Web Environment Integrity" is a Google euphemism for a DRM that is designed to
            prevent ad-blocking, and which Google has forced into their browsers against widespread public opposition.
                In support of an open web, this website does not function with this DRM. Please install a browser such
            as <a href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a> that respects your freedom and supports
            ad blockers.`;

            window.addEventListener('DOMContentLoaded', (event) => {
                new PagefindUI({element: "#search", showSubResults: true});
            });
        </script>
    </body>
</html>