diff --git a/config.toml b/config.toml index 3145c44..10ba64a 100644 --- a/config.toml +++ b/config.toml @@ -1,5 +1,4 @@ -baseURL = "https://jaseg.net/" +baseURL = "https://jaseg.github.io/_testrepo/" languageCode = "en-us" title = "jaseg.net" theme = "hugo-classic" -publishDir = "docs" diff --git a/content/posts/led-characterization/images/photodiode_sensitivity.svg b/content/posts/led-characterization/images/photodiode_sensitivity.svg new file mode 100644 index 0000000..e845444 --- /dev/null +++ b/content/posts/led-characterization/images/photodiode_sensitivity.svg @@ -0,0 +1,874 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/led-characterization/index.rst b/content/posts/led-characterization/index.rst index 0f6e32b..ebcc16c 100644 --- a/content/posts/led-characterization/index.rst +++ b/content/posts/led-characterization/index.rst @@ -103,14 +103,13 @@ over the problem, there are several sources for imperfections:
Strong ringing on the LED voltage waveform edge at about
             100% overshoot during about 70% of the cycle time. -
The shift register logic output of the multichannel LED driver directly driving a small mosfet's - gate through an inch or so of PCB trace caused extremely bad ringing at high driving - frequencies.
+
The LED strip being at the end of a couple meters of wire caused extremely bad ringing at high + driving frequencies.
Weak ringing on the LED voltage waveform edge at about 30%
             overshoot during about 20% of the cycle time. -
Adding a resistor dampened the ringing somewhat, but ultimately it cannot be eliminated - entirely.
+
Adding a resistor in front of the MOSFET gate to slow the transition dampened the ringing + somewhat, but ultimately it cannot be eliminated entirely.
@@ -371,6 +370,17 @@ The photodiode's response is strongly wavelength-dependent. In particular in the gets very poor down to about 20% at the edge to ultraviolet. This effect is strong enough to move the apparent location of the blue peak towards red. +.. raw:: html + +
+ A plot of photodiode sensitivity against wavelength relative
+        to peak sensitivity at 820nm.  The sensitivity rises from 20% at 380nm approximately linearly to 80% at 620nm,
+        then the rise rolls off. +
A plot of the photodiode's relative sensitivity in the visible spectrum. The sensitivity is + normalized against its peak at 820nm. +
+
+ The problem is that in order to remove this non-linearity, we would already have to know the wavelength of the measured light. Since I don't, I settled for a two-step process. First, a coarse wavelength calibration is done relative to the red peak and the short-wavelength edge of the blue peak. The photodiode measurements are then sensitivity-corrected @@ -390,7 +400,6 @@ wavelength in nanometers. - .. FIXME re-do these measurements, avoiding clipping .. FIXME re-do calibration using CCFL .. FIXME calibration for brightness imbalance due to wedge-shaped projection of spectrum diff --git a/content/posts/multichannel-led-driver/images/asymmetric_iled.svg b/content/posts/multichannel-led-driver/images/asymmetric_iled.svg new file mode 100644 index 0000000..c18d5de --- /dev/null +++ b/content/posts/multichannel-led-driver/images/asymmetric_iled.svg @@ -0,0 +1,2222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/multichannel-led-driver/images/asymmetric_vgate.svg b/content/posts/multichannel-led-driver/images/asymmetric_vgate.svg new file mode 100644 index 0000000..473f494 --- /dev/null +++ b/content/posts/multichannel-led-driver/images/asymmetric_vgate.svg @@ -0,0 +1,1933 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/multichannel-led-driver/images/bcm_schema.jpg b/content/posts/multichannel-led-driver/images/bcm_schema.jpg new file mode 100644 index 0000000..5d3ef08 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/bcm_schema.jpg differ diff --git a/content/posts/multichannel-led-driver/images/corrected_brightness_sim.svg b/content/posts/multichannel-led-driver/images/corrected_brightness_sim.svg new file mode 100644 index 0000000..2b9cf16 --- /dev/null +++ b/content/posts/multichannel-led-driver/images/corrected_brightness_sim.svg @@ -0,0 +1,765 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/multichannel-led-driver/images/driver_linearity_raw.svg b/content/posts/multichannel-led-driver/images/driver_linearity_raw.svg new file mode 100644 index 0000000..58aa43f --- /dev/null +++ b/content/posts/multichannel-led-driver/images/driver_linearity_raw.svg @@ -0,0 +1,937 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/multichannel-led-driver/images/driver_output_ltspice_schematic.jpg b/content/posts/multichannel-led-driver/images/driver_output_ltspice_schematic.jpg new file mode 100644 index 0000000..52000a8 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/driver_output_ltspice_schematic.jpg differ diff --git a/content/posts/multichannel-led-driver/images/driver_pcb_built.jpg b/content/posts/multichannel-led-driver/images/driver_pcb_built.jpg new file mode 100644 index 0000000..f5da956 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/driver_pcb_built.jpg differ diff --git a/docs/images/driver_ringing_strong.jpg b/content/posts/multichannel-led-driver/images/driver_ringing_strong.jpg similarity index 100% rename from docs/images/driver_ringing_strong.jpg rename to content/posts/multichannel-led-driver/images/driver_ringing_strong.jpg diff --git a/docs/images/driver_ringing_weak.jpg b/content/posts/multichannel-led-driver/images/driver_ringing_weak.jpg similarity index 100% rename from docs/images/driver_ringing_weak.jpg rename to content/posts/multichannel-led-driver/images/driver_ringing_weak.jpg diff --git a/content/posts/multichannel-led-driver/images/led_strip_alight.jpg b/content/posts/multichannel-led-driver/images/led_strip_alight.jpg new file mode 100644 index 0000000..b001395 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/led_strip_alight.jpg differ diff --git a/content/posts/multichannel-led-driver/images/linearization_setup.jpg b/content/posts/multichannel-led-driver/images/linearization_setup.jpg new file mode 100644 index 0000000..faafc92 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/linearization_setup.jpg differ diff --git a/content/posts/multichannel-led-driver/images/olsndot_output_schematic.jpg b/content/posts/multichannel-led-driver/images/olsndot_output_schematic.jpg new file mode 100644 index 0000000..90941df Binary files /dev/null and b/content/posts/multichannel-led-driver/images/olsndot_output_schematic.jpg differ diff --git a/content/posts/multichannel-led-driver/images/olsndot_pcb.png b/content/posts/multichannel-led-driver/images/olsndot_pcb.png new file mode 100644 index 0000000..87b10f8 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/olsndot_pcb.png differ diff --git a/content/posts/multichannel-led-driver/images/olsndot_schematic.png b/content/posts/multichannel-led-driver/images/olsndot_schematic.png new file mode 100644 index 0000000..69906e5 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/olsndot_schematic.png differ diff --git a/content/posts/multichannel-led-driver/images/overshoot_sim_r0.svg b/content/posts/multichannel-led-driver/images/overshoot_sim_r0.svg new file mode 100644 index 0000000..004872b --- /dev/null +++ b/content/posts/multichannel-led-driver/images/overshoot_sim_r0.svg @@ -0,0 +1,1885 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/multichannel-led-driver/images/overshoot_sim_r100.svg b/content/posts/multichannel-led-driver/images/overshoot_sim_r100.svg new file mode 100644 index 0000000..c8efd61 --- /dev/null +++ b/content/posts/multichannel-led-driver/images/overshoot_sim_r100.svg @@ -0,0 +1,1788 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/multichannel-led-driver/images/pwm_schema.jpg b/content/posts/multichannel-led-driver/images/pwm_schema.jpg new file mode 100644 index 0000000..0265665 Binary files /dev/null and b/content/posts/multichannel-led-driver/images/pwm_schema.jpg differ diff --git a/content/posts/multichannel-led-driver/images/uncorrected_brightness_sim.svg b/content/posts/multichannel-led-driver/images/uncorrected_brightness_sim.svg new file mode 100644 index 0000000..28cb4be --- /dev/null +++ b/content/posts/multichannel-led-driver/images/uncorrected_brightness_sim.svg @@ -0,0 +1,727 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/posts/multichannel-led-driver/index.rst b/content/posts/multichannel-led-driver/index.rst index ff8930e..8d5ad42 100644 --- a/content/posts/multichannel-led-driver/index.rst +++ b/content/posts/multichannel-led-driver/index.rst @@ -1,5 +1,457 @@ --- -title: "Multichannel Led Driver" +title: "32-Channel LED tape driver" date: 2018-05-02T11:31:14+02:00 +draft: true --- +Theoretical basics +================== + +Together, a friend and I outfitted the small staircase at Berlin's Chaos Computer Club with nice, shiny RGB-WW LED tape +for ambient lighting. This tape is like regular RGB tape but with an additional warm white channel, which makes for much +more natural pastels and whites. There are several variants of RGBW tape. Cheap ones have separate RGB and white LEDs, +which is fine for indirect lighting but does not work for direct lighting. Since we wanted to mount our tape in channels +at the front of the steps, we had to use the slightly more expensive variant with integrated RGBW LEDs. These are LEDs +in the 5050 (5.0mm by 5.0mm) form factor common with RGB LEDs that have a small section divided off for the white +channel. The red, green and blue LED chips sit together in the larger section covered with clear epoxy and the white +channel is made up from the usual blue LED inside a yellow phosphor in the smaller section. + +Since we wanted to light up all of 15 steps, and for greatest visual effect we would have liked to be able to control +each step individually we had to find a way to control 60 channels of LED tape with a reasonable amount of hardware. + +LED tape has integrated series resistors and runs off a fixed 12V or 24V constant-voltage supply. This means you don't +need a complex constant-current driver as you'd need with high-power LEDs. You can just hook up a section of LED tape +to a beefy MOSFET to control it. Traditionally, you would do *Pulse Width Modulation* (PWM) on the MOSFET's input to +control the LED tape's brightness. + +Pulse Width Modulation +---------------------- + +`Pulse Width Modulation`_ is a technique of controlling the brightness of a load such as an LED with a digital signal. +The basic idea is that if you turn the LED on and off much too fast for anyone to notice, you can control its power by +changing how long you turn it on versus how long you leave it off. + +PWM divides each second into a large number of periods. At the beginning of each period, you turn the LED on. After +that, you wait a certain time until you turn it off. Then, you wait for the next period to begin. The periods are always +the same length but you can set when you turn off the LED. If you turn it off right away, it's off almost all the time +and it looks like it's off to your eye. If you turn it off right at the end, it's on almost all the time and it looks +super bright to your eye. Now, if you turn it off halfway into the cycle, it's on half the time and it will look to your +eye as half as bright as before. This means that you can control the LED's brightness with only a digital signal and +good timing. + +.. raw:: html + +
+ A visualization of PWM at different duty cycles. +
Waveforms of two PWM cycles at different duty cycles.
+
+ +PWM works great if you have a dedicated PWM output on your microcontroller. It's extremely simple in both hardware and +software. Unfortunately for us, controlling 32 channels with PWM is not that easy. Cheap microcontrollers only have `a +handful of hardware PWM outputs`_, so we'd either have to do everything in software, bit-banging our LED modulation, or +we'd have to use a dedicated chip. + +Doing PWM in software is both error-prone and slow. Since the maximum dynamic range of a PWM signal is limited by the +shortest duty cycle it can do, software PWM being slow means it has poor PWM resolution at maybe 8 bits at most. Poor +color resolution is not a problem if all you're doing is to fade around the `HSV rainbow`_, but for ambient lighting +where you *really* want to control the brightness down to a faint shimmer you need all the color resolution you can get. + +If you rule out software PWM, what remains are dedicated `hardware PWM controllers`_. Most of these have either of three +issues: + +* They're expensive +* They don't have generous PWM resolution either (12 bits if you're lucky) +* They're meant to drive small LEDs such as a 7-segment display directly and you can't just hook up a MOSFET to their + output + +This means we're stuck in a dilemma between two poor solutions if we'd want to do PWM. Luckily for us, PWM is not the +only modulation in town. + +.. _`Pulse Width Modulation`: https://en.wikipedia.org/wiki/Pulse-width_modulation +.. _`a handful of hardware PWM outputs`: https://www.nxp.com/parametricSearch#/&c=c731_c380_c173_c161_c163&page=1 +.. _`HSV rainbow`: https://en.wikipedia.org/wiki/HSL_and_HSV +.. _`hardware PWM controllers`: http://www.ti.com/lit/ds/symlink/tlc5940.pdf + +Binary Code Modulation +---------------------- + +PWM is the bread-and-butter of the maker crowd. Everyone and their cat is doing it and it works really well most of the +time. Unbeknownst to most of the maker crowd, there is however another popular modulation method that's mostly used in +professional LED systems: Enter `*Binary Code Modulation* (BCM) `_. + +BCM is to PWM sort of what barcodes are to handwriting. While PWM is easy to understand and simple to implement if all +you have is a counter and an IO pin, BCM is more complicated. On the other hand, computers can do complicated and BCM +really shines in multi-channel applications. + +Similar to PWM, BCM works by turning on and off the LED in short periods fast enough to make your eye perceive it as +partially on all the time. In PWM the channel's brightness is linearly dependent on its duty cycle, i.e. the percentage +it is turned on. In PWM the duty cycle D is the total period T divided by the on period T_on. The issue with doing PWM +on many channels at once is that you have to turn off each channel at the exact time to match its duty cycle. +Controlling many IO pins at once with precise timing is really hard to do in software. + +BCM avoids this by further dividing each period into smaller periods which we'll call *bit periods* and splitting each +channel's duty cycle into chunks the size of these bit periods. The amazingly elegant thing in BCM now is that as you +can guess from the name these bit periods are weighted in powers of two. Say the shortest bit period lasts 1 +microsecond. Then the second-shortest bit period is 2 microseconds and the third is 4, the fifth 8, the sixth 16 and so +on. + +.. raw:: html + +
+ A visualization of BCM at different duty cycles. +
Waveforms of a single 4-bit BCM cycle at different duty cycles. This BCM can produce 16 different + levels.
+
+ +Staggered like this, you turn on the LED for integer value of microseconds by turning it on in the bit periods +corresponding to the binary bits of that value. If I want my LED to light for 19 microseconds every period, I turn it on +in the 16 microsecond bit period, the 2 microsecond bit period and the 1 microsecond bit period and leave it off for the +4 and 8 mircosecond bit periods. + +Now, how this is better instead of just more complicated than plain old PWM might not be clear yet. But consider this: +Turning on and off a large number of channels, each at its own arbitrary time is hard because doing the timing in +software is hard. We can't use hardware timers since we only have two or three of those, and we have 32 channels. +However, we can use one hardware timer to trigger a really cheap external latch to turn on or off the 32 channels all at +once. With this setup, we can only controll all channels at once, but we can do so with very precise timing. + +All we need to do is to set our timer to the durations of the BCM bit periods, and we can get the same result as we'd +get with PWM with only one hardware timer and a bit of code that is not timing-critical anymore. + +Applications of Binary Code Modulation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +BCM is a truly wondrous technique, and outside of hobbyist circles it is in fact very widely known. Though we're using +it to control just 32 channels here, you can do much more channels without any problems. The most common application +where BCM is invariably used is *any* kind of LED screen. Controlling the thousands and thousands of LEDs in an LED +screen with PWM with a dedicated timer for each LED would not be feasible. With BCM, all you need to dedicate to a +single LED is a flipflop (or part of one if you're multiplexing). In fact, there is a whole range of `ICs with no other +purpose than to enable BCM on large LED matrices `_. Basically, these are a +high-speed shift register with latched outputs much like the venerable 74HC595_, only their outputs are constant-current +sinks made so that you can directly connect an LED to them. + +.. _74HC595: http://www.ti.com/lit/ds/symlink/sn74hc595.pdf + +Running BCM on LED tape +~~~~~~~~~~~~~~~~~~~~~~~ + +In our case, we don't need any special driver chips to control our LED tape. We just connect the outputs of a 74HC595_ +shift register to one MOSFET_ each, and then we directly connect the LED tape to these MOSFETs. The MOSFETs allow us to +drive a couple of amps into the LED tape from the weak outputs of the shift register. + +The BCM timing is done by hooking up two timer channels of our microcontroller to the shift registers *strobe* and +*reset* inputs. We set the timer to PWM mode so we can generate pulses with precise timing. At the beginning of each +bit period, a pulse will strobe the data for this bit period that we shifted in previously. At the end of the bit +period, one pulse will reset the shift register and one will strobe the freshly-reset zeros into the outputs. + +.. raw:: html + +
+ From left to right, we see the STM32, one of the shift
+        registers, and the LEDs and MOSFETs. The LED tape is driven to ground by the MOSFETs, which are in turn directly
+        driven from the shift register outputs. The shift register is wired up to the STM32 with its clock and data
+        inputs on SCK and MOSI and its RESET and STROBE inputs on channel 2 and 3 of timer 1. +
+ The schematic of a single output of this LED driver. Multiple shift register stages can be cascaded. +
+
+ + +Our implementation of this system runs on an STM32F030F4P6_, the smallest, cheapest ARM microcontroller you can get from +ST. This microcontroller has only 16kB of flash and 1kB of RAM, but that's plenty for our use. We use its SPI controller +to feed the modulation data to the shift registers really fast, and we use two timer channels to control the shift +registers' reset and strobe. + +We can easily cascade shift registers without any ill side-effects, and even hundreds of channels should be no problem +for this setup. The only reason we chose to stick to a 32-channel board is the mechanics of it. We thought it would be +easier to have several small boards instead of having one huge board with loads of connectors and cables coming off it. + +The BOM cost per channel for our system is 3ct for a reasonable MOSFET, about 1ct for one eighth of a shift register +plus less than a cent for one resistor between shift register and MOSFET. In the end, the connectors are more expensive +than the driving circuitry. + +.. _MOSFET: https://en.wikipedia.org/wiki/MOSFET +.. _STM32F030F4P6: http://www.st.com/resource/en/datasheet/stm32f030f4.pdf + +Hardware design +=============== + +From this starting point, we made a very prototype-y hardware design for a 32-channel 12V LED tape driver. The design is +based on the STM32F030F4P6_ driving the shift registers as explained above. The system is controlled through an RS485_ +bus that is connected up to the microcontroller's UART using an MAX485_-compatible RS485 transceiver. The LED tape is +connected using 9-pin SUB-D_ connectors since they are cheap and good enough for the small current of our short segments +of LED tape. The MOSFETs we use are small SOT-23_ logic-level MOSFETs. In various prototypes we used both International +Rectifier's IRLML6244_ as well as Alpha & Omega Semiconductor's AO3400_. Both are good up to about 30V/5A. Since we're +only driving about 2m of LED tape per channel we're not going above about 0.5A and the MOSFETs don't even get warm. + +.. _RS485: https://en.wikipedia.org/wiki/RS-485 +.. _MAX485: https://datasheets.maximintegrated.com/en/ds/MAX1487-MAX491.pdf +.. _IRLML6244: https://www.infineon.com/dgdl/?fileId=5546d462533600a4015356686fed261f +.. _AO3400: http://aosmd.com/pdfs/datasheet/AO3400.pdf +.. _SUB-D: https://en.wikipedia.org/wiki/D-subminiature +.. _SOT-23: http://www.nxp.com/documents/outline_drawing/SOT23.pdf + +Switching nonlinearities +------------------------ +During testing of our initial prototype, we noticed that the brightness seemed to jump around when fading to very low +values. It turned out that our extremely simple LED driving circuit consisting of only the shift register directly +driving a MOSFET, which in turn directly drives the LED tape was maybe a little bit too simple. After some measurements +it turned out that we were looking at about 6Vpp of ringing on the driver's output voltage. The picture below is the +voltrage we saw on our oscilloscope on the LED tape. + +.. raw:: html + +
+ Strong ringing on the LED voltage waveform edge at about
+            100% overshoot during about 70% of the cycle time. +
Bad ringing on the LED output voltage caused by wiring inductance. Note that the effect on the + actual LED current is less bad than this looks since the LED's V/I curve is nonlinear.
+
+ + +Dynamic switching behavior: Cause and Effect +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A bit of LTSpice_ action later we found that the inductance of the few metres of cable leading to the LED tape is the +likely culprit. The figure below is the schematic used for the simulations. + +.. raw:: html + +
+ The LTSpice schematic of one output of the driver,
+        taking into account the shift register's output ESR and the wiring ESL. +
The schematic of the simulation in LTSpice
+
+ +As tested, the driver does not include any per-output smoothing so the ~.5A transient on each BCM cycle hits the cable +in full. Combined with the cable inductance, this works out to a considerable lag of the rising edge of the LED +current, and bad ringing on its falling edge. Below is the voltage on the LED output from an LTSpice simulation of our +driver. + +.. raw:: html + +
+ The result of the LTSpice simulation of our driver output. The LED
+        current shows similar ringing to what we measured using the oscilloscope. Interestingly, the gate voltage shows
+        strong ringing, too. +
The result of our LTSpice simulation. This simulation assumes 1µH of wiring inductance and 50Ω of + output impedance on the part of the shift register. The ringing at the gate visible in the gate voltage graph is + due to feed-through of the ringing at the output through the MOSFET's parasitic Cgd.
+
+ +We were able to reduce the rining and limit the effect somewhat by +putting a 220Ω series resistor in between the shift register output and the MOSFET gate. This resistor forms an RC +circuit with the MOSFET's nanofarad or two of gate capacitance. The result of this is that the LED current passing the +wire's ESL rises slightly more slowly and thus the series inductance gets excited slightly less, and the overshoot +decreases. Below is a picture of the waveform with the dampening resistor in place and a picture of our measurement for +comparison. The resistor values don't agree perfectly since the estimated ESL and stray capacitance of the wiring is +probably way off. + +.. raw:: html + +
+ Weak ringing on the LED voltage waveform edge at about 30%
+        overshoot during about 20% of the cycle time. +
Adding a resistor in front of the MOSFET gate to slow the transition dampened the ringing somewhat, + but ultimately it cannot be eliminated entirely. Note how you can actually see the miller plateau on the + trailing edge of this signal. +
+
+ +.. raw:: html + +
+ The result of the LTSpice simulation of our driver output with an
+        extra 100 Ohms between shift register output and MOSFET gate. Similar to the oscilloscope measurement the
+        ringing is much reduced in its amplitude. +
The LTSpice simulation result with the same parameters as above but with an extra 100Ω between the + shfit register's output and the MOSFET's gate.
+
+ +A side effect of this fix is that now the effective on-time of the LED tape is much longer than the duty cycle at the +shift register's output at very small duty cycles (1µs or less). This is caused by the MOSFET's `miller +plateau`_. For illustration, below is a graph of both the excitation waveform (the boxy line) and the resulting LED +current (the other ones) both without dampening (top) and with 220Ω dampening (bottom). As you can see the effective +duty cycle of the LED current is not at all equal to the 50% duty cycle of the excitation square wave. + +.. raw:: html + +
+ The result of an LTSpice simulation of the LED duty cycle without and
+        with dampening. Dampening widens the LED current waveform from 50% duty cycle with sharp edges to about 80% duty
+        cycle with soft edges. +
Simulated LED duty cycle with and without dampening. The dampening resistance used in this + simulation was 220Ω.
+
+ +.. raw:: html + +
+ The gate voltages in the spice simulation above. The undampened
+        response shows sharp edges with the miller plateau being a barely noticeable step, but with strong ringing on
+        the trailing edge. The dampened response shows RC-like slow-edges, but has wide miller plateaus on both edges
+        adding up to about 50% of the pulse width. +
The MOSFET gate voltage from the simulation in the figure above. You can clearly see how the miller + plateau (the horizontal part of the trace at about 1V) is getting much wider with added dampening, and how the + resulting gate charge/discharge curve is not at all that of a capacitor anymore.
+
+ + + +In conclusion, we have three major causes for our calculated LED brightness not matching reality: + +* Ringing of the equivalent series inductance of the wiring leading up to the LED tape +* Miller plateau lag +* The dampening resistor and the MOSFET gate forming an RC filter that helps with wire ESL ringing but worsens the + miller plateau issue and deforms the LED current edges. + +Added up, these three effects yield a picture that agrees well with our simulations and measurements. The overall effect +is neglegible at long period durations (>10µs), but gets really bad at short period durations (<1µs). The effect is +non-linear, so correcting for it is not as simple as adding an offset. + +.. _LTSpice: http://www.analog.com/en/design-center/design-tools-and-calculators/ltspice-simulator.html +.. _`miller plateau`: https://www.vishay.com/docs/68214/turnonprocess.pdf + +Measuring LED tape brightness +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order to correct for the nonlinearities mentioned above, we decided to implement a lookup table mapping BCM period to +actual timer setting. That is, each row of the table contains the actual period length we need to set the +microcontroller's timer to in order to get our intended brightness steps. + +To calibrate our driver, we needed a setup for reproducible measurement of the relative brightness of our LED tape at +different settings. Absolute brightness is not of interest to us as the eye can't perceive it. To perform the +calibration, the LED driver is set to enable each single BCM period in turn, i.e. brightness values 1, 2, 4, 8, 16 etc. + +The setup we used to measure the LED tape's brightness consists of a bunch of LED tape stuck into a tin can for +shielding against both stray light and electromagnetic interference and a photodiode looking at the LED tape. We used +the venerable BPW34_ photodiode in our setup as I had a bunch leftover from another project and because they are quite +sensitive owing to their physically large die area. + +.. raw:: html + +
+ The led measurement setup consists of several PCBs and a
+        breadboard linked with a bunch of wires and a big tin can to shield the LEDs and the photodiode. A large sub-D
+        connector is put into the top of the tin can as a feed-through for the LED tape's control signals and the
+        photodiode signal. In the background the control laptop is visible. +
The LED brighness measurement setup. The big tin can contains a bunch of LED tape and the + photodiode. The breadboard on the right is used for the photodiode preamplifier and for jumpering around the LED + tape's channels. The red board next to it is the buspirate used as ADC. The board on the bottom left is a + TTL-to-RS485 converter and the board in the middle is the unit under test.
+
+ +The photodiode's photocurrent is converted into a voltage using a very simple transimpedance amplifier based around a +MCP6002_ opamp that was dampened into oblivion with a couple nanofarads of capacitance in its feedback loop. The +MCP6002_ is a fine choice here since I had a bunch and because it is a CMOS opamp, meaning it has low bias current that +would mess up our measurements. For many applications, opamp bias current is not a big issue but when using the opamp to +directly measure very small currents at its input it quickly swamps out the signal for most BJT-input types. + +The transimpedance amplifier's output is read from the computer using the ADC input of a buspirate USB thinggamajob. In +general I would not recommend the buspirate as a tool for this job since it's ADC is not particularly good and it's +programming interface is positively atrocious, but it was what I had and it beat first wiring up one of the dedicated +ADC chips I had in my parts bin. + +The computer runs a small python script cycling the LED tape through all its BCM period settings and taking a brightness +measurement at each step. Later on, these measurements can be plotted to visualize the resulting slope's linearity, and +we can even do a simulation of the resulting brightness for all possible control values by just adding the measured +photocurrents for a certain BCM setpoint just as our retinas would do. + +.. raw:: html + +
+ +
+ A plot of the measured brightness of our LED tape for each BCM period. The brightness values are normalized + to the value measured at the LSB setpoint (brightness=1/65535). Ideally, this plot would show a straight + line with slope 1. Obviously, it doesn't. The bend in the curve is caused by the above-mentioned duty cycle + offset adding an offset to all brightness values. Shown is both the raw data (light), which has essentially zero + measurement error and a linear fit (dark). + + The plot is in log-log to approximate how the human eye would perceive brightness, i.e. highly sensitive at + low values but not very sensitive at all at large values. +
+
+ +While it would be possible to fully automate the optimization of BCM driver lookup tables, we needed only one and in the +end I just sat down and manually tweaked the ideal values we initially calculated until I liked the result. You can see +the resulting brightness curve below. + +.. raw:: html + +
+
+ +
+ Calculated brightness curve for the uncorrected BCM setup. As you can see, at low setpoints the result + is about as smooth as sandpaper, which is well in line with our observations. At high setpoints the + offset gets swamped out and the nonlinearity in the low bits is not visible anymore. +
+
+ +
+ Brightness curve for the corrected BCM setup extrapolated using actual measurements. Looks as buttery + smooth in real life as it does in this plot. +
+ +
+
+ +.. _BPW34: http://www.vishay.com/docs/81521/bpw34.pdf +.. _MCP6002: http://ww1.microchip.com/downloads/en/DeviceDoc/21733j.pdf + +Controlling the driver +---------------------- + +Now that our driver was behaving linear enough that you couldn't see it actually wasn't we needed a nice way to control +it from a computer of our choice. In the ultimate application (our staircase) we'll use a raspberry pi for this. Since +we already settled on an RS485_ bus for its robustness and simplicity, we had to device a protocol to control the driver +over this bus. Here, we settled on a simple, COBS_-based protocol for the reasons I wrote about in `How to talk to your +microcontroller over serial `_. + +To address our driver nodes, we modified the Makefile to build a random 32-bit MAC into each firmware image. The +protocol has only five message types: + +1. A 0-byte *ping* packet, to which each node would reply with its own address in the + first 100ms after boot. This can be used to initially discover the addresses of all nodes connected to the bus. You'd + spam the bus with *ping* packets, and then hit reset on each node in turn. The control computer would then receive + each device's MAC address as you hit reset. +2. A 4-byte *address* packet that says which device that the following packet is for. This way of us using the packet + length instead of a packet type field is not particularly elegant, but our system is simple enough and it was easy to + implement. +3. A 64-byte *frame buffer* packet that contains 16 bits of left-aligned brightness data for every channel +4. A one-byte *get status* packet that tells the device to respond with... +5. ...a 27-byte status packet containing a brief description of the firmware (version number, channel count, bit depth + etc.) as well as the device's current life stats (VCC, temperature, uptime, UART frame errors etc.). + +Wrapped up in a nice python interface we can now easily enumerate any drivers we connect to a bus, query their status +and control their outputs. + +.. _COBS: https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing + +Conclusion +---------- + +.. raw:: html + +
+
+ + A picture of the LED driver schematic + +
The LED driver schematic
+
+ + A picture of the LED driver PCB layout + +
The LED driver PCB layout
+
+
+ +Putting some thought into the control circuitry and software, you can easily control large numbers of channels of LEDs +using extremely inexpensive driving hardware without any compromises on dynamic range. The design we settled on can +drive 32 channels of LED tape with a dynamic range of 14bit at a BOM cost of below 10€. All it really takes is a couple +of shift registers and a mildly bored STM32 microcontroller. + +Get a PDF file of the schematic and PCB layout `here `_ or download the CAD files +and the firmware sources `from github `_. + diff --git a/content/posts/multichannel-led-driver/olsndot_v02_schematics_and_pcb.pdf b/content/posts/multichannel-led-driver/olsndot_v02_schematics_and_pcb.pdf new file mode 100644 index 0000000..2a4e037 Binary files /dev/null and b/content/posts/multichannel-led-driver/olsndot_v02_schematics_and_pcb.pdf differ diff --git a/content/posts/serial-protocols/index.rst b/content/posts/serial-protocols/index.rst new file mode 100644 index 0000000..a5db824 --- /dev/null +++ b/content/posts/serial-protocols/index.rst @@ -0,0 +1,8 @@ +--- +title: "How to talk to your microcontroller over serial" +date: 2018-05-19T08:09:46+02:00 +draft: true +--- + + + diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index bb77343..0000000 --- a/docs/404.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - 404 Page not found | jaseg.net - - - -
- - - - - - -
- - - - -
- - -404 NOT FOUND - -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/categories/index.html b/docs/categories/index.html deleted file mode 100644 index 4509997..0000000 --- a/docs/categories/index.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - Categories | jaseg.net - - - -
- - - - - - -
- - - - -
- - -

Categories

- -
    - -
- -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/categories/index.xml b/docs/categories/index.xml deleted file mode 100644 index 485ed46..0000000 --- a/docs/categories/index.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - Categories on jaseg.net - https://jaseg.net/categories/ - Recent content in Categories on jaseg.net - Hugo -- gohugo.io - en-us - - - - - - \ No newline at end of file diff --git a/docs/css/fonts.css b/docs/css/fonts.css deleted file mode 100644 index c851143..0000000 --- a/docs/css/fonts.css +++ /dev/null @@ -1,7 +0,0 @@ -body { - font-family: -apple-system, BlinkMacSystemFont, 'Avenir Next', Avenir, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -} -code { - font-family: "Lucida Console", Monaco, monospace; - font-size: 85%; -} diff --git a/docs/css/style.css b/docs/css/style.css deleted file mode 100644 index 07b1293..0000000 --- a/docs/css/style.css +++ /dev/null @@ -1,211 +0,0 @@ -/* @import url('https://fonts.googleapis.com/css?family=Roboto+Slab:400,700|Source+Serif+Pro'); */ -/* @import url('https://fonts.googleapis.com/css?family=Fredoka+One|Source+Serif+Pro'); */ -@import url('https://fonts.googleapis.com/css?family=Baloo|Source+Serif+Pro'); - -body { - max-width: 800px; - margin: auto; - padding: .2em; - line-height: 20pt; - font-size: 12pt; -} - -/* Table of Contents, if wanted - -Add to yaml: - -output: -blogdown::html_page: -toc: true - - */ - -#TableOfContents, #TOC { - border: 1px solid #eee; -} - -/* Header and Footer */ -.menu li { display: inline-block; } -.article-meta, .menu a { - text-decoration: none; - background: #ff99cc; - color: #FFF; - padding: 5px; - text-shadow: 0px 1px 1px #fe3ea0; -} - - -.article-meta h1, .article-meta h2 { - margin-top: 1em; - color: white; -} - - -.terms { font-size: .9em; } -.menu, .article-meta, footer { text-align: center; } -.title { font-size: 1.1em; } -footer a { text-decoration: none; } - -.pull-left { - float: left -} -.pull-right { - float: right -} - -a { - color: #ff6bb6; - text-decoration: none; -} - -a:hover { - background: #83cbe3; - color: white; -} - -/* Adjust background at your leisure! */ -header { - position: relative; - width: 100%; - height: 1.75rem; - font-size: .875rem; - background: #83cbe3; - font-family: 'Baloo', sans-serif; -} - -h1, h2, h3, h4, h5, h6 { - margin-top: 2em; - font-family: 'Baloo', sans-serif; - /* color: #ff99cc; */ - color: #ff6bb6; -} - -li { - padding-bottom: 1em; -} - -header ul, -header ol { - margin: 0; - padding: 0; - list-style: none -} -header nav { - padding: 0 0.5rem -} - -header a { - color: #fff; - line-height: 1.75rem; - padding: 0 0.5rem -} -header a:hover, -header .current a { - color: #fff -} - -/* Code Boxes */ -pre { - border: 1px solid #ddd; - box-shadow: 5px 5px 5px #eee; - background: #f8f8f8; - padding: 1em; - overflow-x: auto; -} -code { background: #f9f9f9; } -pre code { background: none; } - -/* Images, tables, misc. */ -img, iframe, video { max-width: 100%; } -main { - text-align: justify; - word-wrap: break-word; - font-family: "Source Serif Pro", "Times New Roman", serif; - color: #555; - hyphens: auto; -} - -/* Caution! duplicate this rule below. */ -::selection { - background: #83cbe3; - color: white; -} - -::-moz-selection { - background: #83cbe3; - color: white; -} - -/* Caution! duplicate this rule below. */ -a::-moz-selection { - background: #ff99cc; - color: white; -} - -a::selection { - background: #ff99cc; - color: white; -} - -blockquote { - background: #f9f9f9; - border-left: 5px solid #ccc; - padding: 3px 1em 3px; -} - -table { - margin: auto; - border-top: 1px solid #666; - border-bottom: 1px solid #666; -} -table thead th { border-bottom: 1px solid #ddd; } -th, td { padding: 5px; } -tr:nth-child(even) { background: #eee } - -figure.side-by-side { - width: 20em; - display: inline-block; - margin: 16px 16px 16px 16px; - vertical-align: top; -} - -figure img, figure video { - display: block; - margin-left: auto; - margin-right: auto; - width: 100%; -} - -figcaption a { - background: white; - color: #83cbe3; -} - -figcaption a:hover { - background: #ff6bb6; -} - -figcaption { - display: block; - line-height: 16pt; - background: #83cbe3; - color: white; - font-family: 'Baloo', sans-serif; - padding: 1em; - border-radius: 0 0 0.5em 0.5em; -} - -figure { - margin-top: 3em; - margin-bottom: 3em; -} - -#license-info img { - vertical-align: middle; -} - -#license-info { - color: #aaa; - font-size: 10pt; - font-family: "Source Serif Pro", "Times New Roman", serif; -} diff --git a/docs/images/daylight_spectrum_dvd.jpg b/docs/images/daylight_spectrum_dvd.jpg deleted file mode 100644 index d01242e..0000000 Binary files a/docs/images/daylight_spectrum_dvd.jpg and /dev/null differ diff --git a/docs/images/electronics_whole.jpg b/docs/images/electronics_whole.jpg deleted file mode 100644 index faaf751..0000000 Binary files a/docs/images/electronics_whole.jpg and /dev/null differ diff --git a/docs/images/hsv_cylinder.png b/docs/images/hsv_cylinder.png deleted file mode 100644 index 265f3e0..0000000 Binary files a/docs/images/hsv_cylinder.png and /dev/null differ diff --git a/docs/images/preamp_back.jpg b/docs/images/preamp_back.jpg deleted file mode 100644 index 0af495d..0000000 Binary files a/docs/images/preamp_back.jpg and /dev/null differ diff --git a/docs/images/preamp_front.jpg b/docs/images/preamp_front.jpg deleted file mode 100644 index 62fad28..0000000 Binary files a/docs/images/preamp_front.jpg and /dev/null differ diff --git a/docs/images/preamp_schematic.jpg b/docs/images/preamp_schematic.jpg deleted file mode 100644 index 6be7bbd..0000000 Binary files a/docs/images/preamp_schematic.jpg and /dev/null differ diff --git a/docs/images/processed_plot_cheap_rgb.svg b/docs/images/processed_plot_cheap_rgb.svg deleted file mode 100644 index 019d3c9..0000000 --- a/docs/images/processed_plot_cheap_rgb.svg +++ /dev/null @@ -1,2453 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/raw_plot_cheap_rgb.svg b/docs/images/raw_plot_cheap_rgb.svg deleted file mode 100644 index 049aa74..0000000 --- a/docs/images/raw_plot_cheap_rgb.svg +++ /dev/null @@ -1,2574 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/rgb_cube.svg b/docs/images/rgb_cube.svg deleted file mode 100644 index 8af7a00..0000000 --- a/docs/images/rgb_cube.svg +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - G+ - - - - - - - - R+ - - - - B+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - R- - - - - B- - - - - - - - - G- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - R : 83 - - - G : 150 - - - B : 60 - - G: 150 - B: 60 - R: 83 - - - - - - - - R - G - B - - - R - G - B - - - R 255 - G 255 - B 255 - - - - - \ No newline at end of file diff --git a/docs/images/spectrograph_step1_parts.jpg b/docs/images/spectrograph_step1_parts.jpg deleted file mode 100644 index 107220a..0000000 Binary files a/docs/images/spectrograph_step1_parts.jpg and /dev/null differ diff --git a/docs/images/spectrograph_step2.jpg b/docs/images/spectrograph_step2.jpg deleted file mode 100644 index b678372..0000000 Binary files a/docs/images/spectrograph_step2.jpg and /dev/null differ diff --git a/docs/images/spectrograph_step3.jpg b/docs/images/spectrograph_step3.jpg deleted file mode 100644 index acd6d5e..0000000 Binary files a/docs/images/spectrograph_step3.jpg and /dev/null differ diff --git a/docs/images/spectrograph_step4_complete.jpg b/docs/images/spectrograph_step4_complete.jpg deleted file mode 100644 index d23560d..0000000 Binary files a/docs/images/spectrograph_step4_complete.jpg and /dev/null differ diff --git a/docs/images/zeus_hammer_breadboard.jpg b/docs/images/zeus_hammer_breadboard.jpg deleted file mode 100644 index 08efebb..0000000 Binary files a/docs/images/zeus_hammer_breadboard.jpg and /dev/null differ diff --git a/docs/images/zeus_hammer_breadboard_original.jpg b/docs/images/zeus_hammer_breadboard_original.jpg deleted file mode 100644 index 4f8f34e..0000000 Binary files a/docs/images/zeus_hammer_breadboard_original.jpg and /dev/null differ diff --git a/docs/images/zeus_hammer_schematic.jpg b/docs/images/zeus_hammer_schematic.jpg deleted file mode 100644 index 0e6f483..0000000 Binary files a/docs/images/zeus_hammer_schematic.jpg and /dev/null differ diff --git a/docs/images/zeus_hammer_schematic_original.jpg b/docs/images/zeus_hammer_schematic_original.jpg deleted file mode 100644 index b50b3a0..0000000 Binary files a/docs/images/zeus_hammer_schematic_original.jpg and /dev/null differ diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index b1c292c..0000000 --- a/docs/index.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - jaseg.net | jaseg.net - - - -
- - - - - - -
- - - - -
- - - - - - - - -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/index.xml b/docs/index.xml deleted file mode 100644 index af0a31a..0000000 --- a/docs/index.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - jaseg.net - https://jaseg.net/ - Recent content on jaseg.net - Hugo -- gohugo.io - en-us - Thu, 03 May 2018 11:59:37 +0200 - - - - - - Zeus Hammer - https://jaseg.net/posts/zeus-hammer/ - Thu, 03 May 2018 11:59:37 +0200 - - https://jaseg.net/posts/zeus-hammer/ - In case you were having an inferiority complex because your friends' IBM Model M keyboards are so much louder than the shitty rubber dome freebie you got with your pc... Here's the solution: Zeus Hammer, a simple typing cadence enhancer for PS/2 keyboards. -The connects to the keyboard's PS/2 clock line and briefly actuates a large solenoid on each key press. An interesting fact about PS/2 is that the clock line is only active as long as either the host computer or the input device actually want to send data. - - - - Multichannel Led Driver - https://jaseg.net/posts/multichannel-led-driver/ - Wed, 02 May 2018 11:31:14 +0200 - - https://jaseg.net/posts/multichannel-led-driver/ - - - - - Wifi Led Driver - https://jaseg.net/posts/wifi-led-driver/ - Wed, 02 May 2018 11:31:03 +0200 - - https://jaseg.net/posts/wifi-led-driver/ - - - - - Led Characterization - https://jaseg.net/posts/led-characterization/ - Wed, 02 May 2018 11:18:38 +0200 - - https://jaseg.net/posts/led-characterization/ - Preface Recently, I have been working on a small driver for ambient lighting using 12V LED strips like you can get inexpensively from China. I wanted to be able to just throw one of these somewhere, stick down some LED tape, hook it up to a small transformer and be able to control it through Wifi. When I was writing the firmware, I noticed that when fading between different colors, the colors look all wrong! - - - - \ No newline at end of file diff --git a/docs/posts/index.html b/docs/posts/index.html deleted file mode 100644 index bed5ad4..0000000 --- a/docs/posts/index.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - Posts | jaseg.net - - - -
- - - - - - -
- - - - -
- - - -

Posts

- - - - - - -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/posts/index.xml b/docs/posts/index.xml deleted file mode 100644 index 096d9cd..0000000 --- a/docs/posts/index.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - Posts on jaseg.net - https://jaseg.net/posts/ - Recent content in Posts on jaseg.net - Hugo -- gohugo.io - en-us - Thu, 03 May 2018 11:59:37 +0200 - - - - - - Zeus Hammer - https://jaseg.net/posts/zeus-hammer/ - Thu, 03 May 2018 11:59:37 +0200 - - https://jaseg.net/posts/zeus-hammer/ - In case you were having an inferiority complex because your friends' IBM Model M keyboards are so much louder than the shitty rubber dome freebie you got with your pc... Here's the solution: Zeus Hammer, a simple typing cadence enhancer for PS/2 keyboards. -The connects to the keyboard's PS/2 clock line and briefly actuates a large solenoid on each key press. An interesting fact about PS/2 is that the clock line is only active as long as either the host computer or the input device actually want to send data. - - - - Multichannel Led Driver - https://jaseg.net/posts/multichannel-led-driver/ - Wed, 02 May 2018 11:31:14 +0200 - - https://jaseg.net/posts/multichannel-led-driver/ - - - - - Wifi Led Driver - https://jaseg.net/posts/wifi-led-driver/ - Wed, 02 May 2018 11:31:03 +0200 - - https://jaseg.net/posts/wifi-led-driver/ - - - - - Led Characterization - https://jaseg.net/posts/led-characterization/ - Wed, 02 May 2018 11:18:38 +0200 - - https://jaseg.net/posts/led-characterization/ - Preface Recently, I have been working on a small driver for ambient lighting using 12V LED strips like you can get inexpensively from China. I wanted to be able to just throw one of these somewhere, stick down some LED tape, hook it up to a small transformer and be able to control it through Wifi. When I was writing the firmware, I noticed that when fading between different colors, the colors look all wrong! - - - - \ No newline at end of file diff --git a/docs/posts/led-characterization/index.html b/docs/posts/led-characterization/index.html deleted file mode 100644 index 06f369f..0000000 --- a/docs/posts/led-characterization/index.html +++ /dev/null @@ -1,459 +0,0 @@ - - - - - - Led Characterization | jaseg.net - - - -
- - - - - - -
- - - - -
- - - - - -
-
- - -
-

Preface

-

Recently, I have been working on a small driver for ambient lighting using 12V LED strips like you can get -inexpensively from China. I wanted to be able to just throw one of these somewhere, stick down some LED tape, hook it up -to a small transformer and be able to control it through Wifi. When I was writing the firmware, I noticed that when -fading between different colors, the colors look all wrong! This observation led me down a rabbit hole of color -perception and LED peculiarities.

-

The idea of the LED driver was that it can be used either with up to eight single-color LED tapes or, much more -interesting, with up to two RGB or RGBW (red-green-blue-white) LED tapes. For ambient lighting high color resolution was -really important so you could dim it down a lot without flickering. I ended up using the same driver stage I used in the -multichannel LED driver project for its great color resolution and low hardware requirements.

-
- An illustration of the RGB color cube. -
An illustration of the RGB color cube. - Picture by - Maklaan from Wikimedia Commons, - CC-BY-SA 3.0 -
-

To make setting colors over Wifi more intuitive I implemented support for HSV colors. RGB is fine for communication -between computers, but I think HSV is easier to work with when manually inputting colors from the command line. RGB is -close to how most monitors, cameras and the human visual apparatus work on a very low level but doesn't match -higher-level human color perception very well. When we describe a color we tend to think in terms of "hue" or -"brightness", and computing a measure of those from RGB values is not easy.

-
-
-

Colors and Color Spaces

-

Color spaces are a mathematical abstraction of the concept of color. When we say "RGB", most of the time we actually -mean sRGB, a standardized notion of how to map three numbers labelled "red", "green" and "blue" onto a perceived -color. HSV is an early attempt to more closely align these numbers with our perception. After HSV, a number of other -perceptual color spaces such as XYZ (CIE 1931) and CIE Lab/LCh were born, further improving this alignment. In -this mathematical model, mapping a color from one color space into another color space is just a coordinate -transformation.

-
- An illustration of the HSV color space as a cylinder. -
An illustration of the HSV color space as a cylinder. - Picture by - SharkD from Wikimedia Commons, - CC-BY-SA 3.0 -
-

CIE 1931 XYZ is much larger than any other color space, which is why it is a good basis to express other color spaces -in. In XYZ there are many coordinates that are outside of what the human eye can perceive. Below is an illustration of -the sRGB space within XYZ. The wireframe cube is (0,0,0) to (1,1,1) in XYZ. The colorful object in the middle is what -of sRGB fits inside XYZ, and the lines extending out from it indicate the space that can be expressed in sRGB but not in -XYZ. The fat white curve is a projection of the monochromatic spectral locus, that is the curve of points you get in -XYZ for pure visible wavelengths.

-

As you can see, sRGB is much smaller than XYZ or even the part within the monochromatic locus that we can perceive. In -particular in the blues and greens we loose a lot of colors to sRGB.

-
- -
Illustration of the measured sRGB color space within XYZ. The thick, white line is the spectral - locus. - - mkv/h264 download / - webm download -
-

The wrong colors I got when fading between colors were caused by this coordinate transformation being askew. Thinking -over the problem, there are several sources for imperfections:

-
    -
  • The LED driver may not be entirely linear. For most modulations such as PWM the brightness will be linear starting -from a certain value, but there is probably an offset caused by imperfect edges of the LED current. This offset can be -compensated with software calibration. I built a calibration setup for driver linearity in the multichannel LED -driver project. Below are pictures of ringing on the edges of an LED driver's waveform.
  • -
  • The red, green and blue channels of the LEDs used on the LED tape are not matched. This skews the RGB color space. -In practice, the blue channel of my RGB tape to me looks much brighter than the red channel.
  • -
  • The precise colors of the red, green and blue channels of the LEDs are unknown. Though the red channel looks red, it -may be of a slightly different hue compared to the reference red used in sRGB which would also skew the RGB color -space.
  • -
-
-
- Strong ringing on the LED voltage waveform edge at about
-        100% overshoot during about 70% of the cycle time. -
The shift register logic output of the multichannel LED driver directly driving a small mosfet's - gate through an inch or so of PCB trace caused extremely bad ringing at high driving - frequencies.
-
- Weak ringing on the LED voltage waveform edge at about 30%
-        overshoot during about 20% of the cycle time. -
Adding a resistor dampened the ringing somewhat, but ultimately it cannot be eliminated - entirely.
-
-

These last two errors are tricky to compensate. What I needed for that was basically a model of the perceived colors -of the LED tape's color channels. A way of doing his is to record the spectra of all color channels and then evaluate -their respective XYZ coordinates. If all three channels are measured in one go with the same setup the relative -magnitudes of the channels in XYZ will be accurate.

-

To map any color to the LEDs, the color's XYZ coordinates simply have to be mapped onto the linear coordinate system -produced by these three points within XYZ. LEDs are mostly linear in their luminous flux vs. current characteristic so -this model will be adequate. The spectral integrals mapping the channels' measured responses to XYZ need only be -calculated once and their results can be used as scaling factors thereafter.

-
-
-

Measuring the spectrum

-

In order to compensate for the cheap LED tape's non-ideal performance I had to measure the LED's red, green and blue -channels' spectra. The obvious thing would be to go out and buy a spectrograph, or ask someone to borrow theirs. The -former is kind of expensive, and I did not want to wait two weeks for the thing to arrive. The latter I could probably -not do every time I got new LED tape. Thus the only choice was to build my own.

-

Luckily, building your own spectrometer is really easy. The first thing you need is something that splits incident light -into its constituent wavelengths. In professional devices this is called the `monochromator`_, since it allows extraction -of small color bands from the spectrum. The second thing is some sort of optics that project the incident light onto a -screen behind the monochromator. In professional devices lenses or curved mirrors are used. In a simple homebrew job a -pinhole as you would use in a camera obscura does a remarkably nice job.

-

For the monochromator component several things could be used. A prism would work, but I did not have any. The -alternative is a diffraction grating. Professional gratings are quite specialized pieces of equipment and thus -rather expensive. Luckily, there is a common household item that works almost as well: A regular CD or DVD. The -microscopic grooves that are used to record data in a CD or DVD work the same as the grooves in a professional -diffraction grating.

-
-
-

Household spectra

-

From this starting point, a few seconds on my favorite search engine yielded an article by two researchers from the -National Science Museum in Tokyo providing a nice blueprint for a simple cardboard-and-DVD construction for use in -classrooms. I replicated their device using a DVD and it worked beautifully. Daylight and several types of small LEDs I -had around did show the expected spectra. Small red, yellow, green, and blue LEDs showed narrow spectra, daylight one -continuous broad one, and white LEDs a continuous broad one with a distinct bright spot in the blue part. The -single-color LED spectra are quite narrow since they are determined by the LED's semiconductor's band gap, which is -specific to the semiconductor used and is quite precise. White LEDs are in fact a blue LED chip covered with a so-called -phosphor. This phosphor is not elementary phosphorus but an anorganic compound that absorbs the LED chip's blue light -and re-emits a broader spectrum of more yellow-ish wavelengths instead. The final LED spectrum is a superposition of -both spectra, with some of the original blue light leaking through the phosphor mixing with the broadband yellow -spectrum of the phosphor.

-
-
- -
The ingredients. The cup of coffee and Madoka Magica DVD set are essential to the eventual - function of the appartus.
-
- -
Step 1: Cut to size and mark down all holes as described in the manual
-
-
- -
Step 2: Cut out all holes
-
- -
The finished result with the back side showing. The viewing window is on the bottom of the other - side.
-
-

Now that I had a spectrograph, I needed a somewhat predictable way of measuring the spectrum it gave me.

-
-
-

Measuring a spectrum

-

Pointing a camera at the spectrograph would be the obvious thing to do. This produces pretty images but has one critical -flaw: I wanted to acquire quantitative measurements of brightness across the spectrum. Since I don't have a precise -technical datasheet specifying the spectral response of any of my cameras I can't compare the absolute brightness of -different colors on their pictures. Some other sensor was needed.

-
- -
The daylight spectrum as seen using a DVD as a grating. - Picture by - Xofc from Wikimedia Commons, - CC-BY-SA 4.0 -
-
-

Measuring light intensity

-

Looking around my lab, I found a bag of SFH2701 visible-light photodiodes. Their -datasheet includes their spectral response so I can compensate for that, allowing precise-ish absolute intensity -measurements. Just like LEDs, photodiodes are extremely linear across several orders of magnitude. The datasheet of the -classic BPW34 photodiode shows that this photodiode's light current is exactly proportional to illuminance over at -least three orders of magnitude. The SFH2701 datasheet does not include a similar graph but its performance will be -similar. The SFH2701 photodiodes I had at hand were perfect for the job compared to the vintage BPW34 since their -active sensing area is really small (0.6mm by 0.6mm) compared to the BPW34 (a whopping 3mm by 3mm). If I were to use a -BPW34 I would have to insert some small apterture in front of it so it does not catch too broad a part of the -spectrum at once. The SFH2701 is small enough that if I just point it at the projected spectrum directly I will -already get only a small part of the spectrum inside its 0.6mm active area.

-

To convert the photodiode's tiny photocurrent into a measurable voltage I built another copy of the transimpedance -amplifier circuit I already used in the multichannel LED driver. A transimpedance amplifier is an -amplifiert that produces a large voltage from a small current. The weird name comes from the fact that it works kind of -like an amplified resistor (which can be generalized as an impedance electrically). Apply a current to a resistor and -you get a voltage. A transimpedance amplifiert does the same with the difference that its input always stays at 0V, -making it look like an ideal current sink to the connected current source.

-

Transimpedance amplifiers are common in optoelectronics to convert small photocurrents to voltages. In this instance I -built a very simple circuit with a dampened transimpedance amplifier stage followed by a simple RC filter for noise -rejection and a regular non-inverting amplifier using another op-amp from the same chip to further boost the filtered -transimpedance amplifier output. I put all the passives setting amplifier response (the gain-setting resistors and the -filter resistor and capacitors) on a small removable adapter so I could easily change them if necessary. I put a small -trimpot on the virtual ground both amplifers use as a reference so I could trim that if necessary.

-
- A drawing of the photodiode preamplifier's schematic -
The photodiode preamplifier schematic. Schematic drawn with an unlicensed copy of - DaveCAD.
-

Following are pictures of the preamplifier board. The connectors on the top-left side are two copies of the analog -signal for the ADC and a small panel meter. The SMA connector is used as the photodiode input since coax cables are -generally low-leakage and have built-in shielding. The circuit is powered via the micro-USB connector and the analog -ground bias voltage can be adjusted using the trimpot.

-

For easy replacement, all passives setting gain and frequency response are on a small, pluggable carrier PCB made from a -SMD-to-DIP adapter.

-

Flying-wire construction is just fine for this low-frequency circuit. In a high-speed photodiode preamp, the -transimpedance amplifier circuit would be highly sensitive to stray capacitance, but we're not aiming at high speed -here.

-
-
- -
The front side of the preamplifier board.
-
- -
The wiring of the photodiode preamp.
-
-

Given a way to measure intensity what remains missing is a way to scan a single photodiode across the spectrum.

-
-
-

Scanning the projection

-

A cheap linear stage can be found in any old CD or DVD drive. These drives use a small linear stage based on a -stepper-driven screw to move the laser unit radially. Removing the laser unit and connecting a leftover stepper driver -module I was left with a small linear stage with about 45 steps per cm without microstepping enabled. The driver I used -was an A4988 module that required at least 8V motor drive voltage. I used a small micro USB-input boost converter -module to generate a stable 10V supply for the motor driver, with the USB's 5V rail used as a logic supply for the motor -driver.

-

The SFH2701 can easily be mounted to the linear stage using a small SMD breakout board glued in place with thin wires -connecting it to the transimpedance amplifier. The DVD drive linear stage is not very strong so it is important that -this wire does not put too much strain on it.

-

Above the photodiode, I mounted a small piece of paper on the linear stage to be used as a projection screen to align -the linear stage in front of the spectrometer viewing window. A line on the screen paper points to the photodiode die in -parallel to the linear stage allowing precise alignment.

-

The whole unit with photodiode preamplifier, linear stage, photodiode and stepper motor driver finally looks like this:

-
- The complete electronics setup of the spectrograph. In the back
-    there is the DVD drive stepper stage. In front of it, mounted on a piece of wood are a small USB-to-12V
-    switching-regulator module to power the stepper motor in the top left, below on the bottom left is the
-    photodiode preamp and on the right is a breadboard with the stepper driver module and lots of jumper wires
-    interconnecting everything. On the right of the breadboard, a buspirate is attached to interface everything to a
-    computer. On the bottom edge of the piece of wood, two LED panel meters are mounted for readout of the preamp
-    output and the stepper supply voltages. -
The complete electronics setup. The buspirate on the right interfaces to a computer and controls the - stepper driver and ADC'es the preamp output. The two panel meters show the preamp output and stepper voltage for - setup.
-

The projection of the spectrum can be adjusted by moving the light source relative to the entry slot and by moving -around the grating DVD.

-
-
-

The capture process

-

To capture a spectrum, first the light source has to be mounted near the spectrograph's entry slot. The LED tape I -tested I just taped face-down directly into it. Next, the grating DVD has to be adjusted to make sure the spectrum -covers a sensible part of the photodiode's path. Mostly, this boils down to adjusting the photodiode distance and height -to match the vertical extent and wiggling the grating DVD to adjust the projection's horizontal position.

-

After the optics are set-up, the photodiode preamplifier has to be adjusted. In my experiments, most LED tape at 5GΩ -required a high-ish amplification. The goal in this step is to maximize the peak response of the preamp to be just -shy of its VCC rail to make best use of its dynamic range. To adjust the pre-amp, I took several very coarsely-spaced -measurements to give me an estimate of the peak while I did not yet know its precise location.

-

Since stray daylight totally swamped out the weak projection of the LED's spectrum I shielded the entire setup with a -small box made of black cardboard and two black t-shirts on top. This shielding proved adequate for all my measurements -but I had to be careful not to accidentially move the DVD that was stuck into the spectrograph with the shielding -t-shirts.

-

For capturing a single spectrum I wrote a small python script that will automatically move the stepper in adjustable -intervals and take two measurements at each point, one with the LED tape off that can be used for offset calibration and -one with the LED tape on. All measurements are stored in a sqlite database that can then be accesssed from other -scripts.

-

I built a small script that shows the progress of the current run and an jupyter notebook for data analysis. The jupyter -notebook is capable of live-updating a graph with the in-progress spectrum's data. This was quite useful as a sanity -check for when I made some mistake easy to spot in the resulting data.

-

After one color channel is captured, the LED tape has to be manually set to the next color and the next measurement can -begin.

-
- A plot with three wide peaks, two large peaks on both sides and
-    one smaller one in the middle. The middle one overlaps the two on the sides. The large ones are about 2.5V in
-    amplitude. Overall, the plot is about 300 stepper steps wide with each peak being around 130 steps wide. -
A plot of the raw preamp output voltage versus stepper position. From left to right, the three peaks - are blue, green and red. Step 0 corresponds to the bottommost stepper position and the shortest wavelength. -
-
-
-

Data analysis

-

Data analysis consists of three major steps: Offset- and stray light removal, wavelength and amplitude calibration and -color space mapping.

-
-

Offset removal

-

The first task is to remove the offset caused by dark current as well as stray light of the LED's bright primary -reflection on the DVD. The LED is very bright and only a small part of its light gets reflected by the grating towards -the photodiode screen. The remaining part of the light is reflected onto the table in front of the DVD spectrograph. -Though I covered all of this with black cardboard, some of that light ultimately gets reflected onto the photodiode. -This causes a large offset, in particular in the blue part of the spectrum since in this part the photodiode is closest -to the spectrograph's opening.

-

The composite offset can be approximated with a second-order polynomial that is fitted to all the data outside of the -main peak's area. Since at this point the wavelength of each data point is still unknown this is done with a rough first -estimate of the three colors' peaks' locations and widths.

-
-
-

Wavelength- and amplitude calibration

-

The photodiode's response is strongly wavelength-dependent. In particular in the blue band, the photodiode's sensitivity -gets very poor down to about 20% at the edge to ultraviolet. This effect is strong enough to move the apparent location -of the blue peak towards red.

-

The problem is that in order to remove this non-linearity, we would already have to know the wavelength of the measured -light. Since I don't, I settled for a two-step process. First, a coarse wavelength calibration is done relative to the -red peak and the short-wavelength edge of the blue peak. The photodiode measurements are then sensitivity-corrected -using this coarse measurement. Then all three channel peaks are measured in the resulting data and a fine wavelength -estimate is produced by a least-squares fit of a linear function. This fine estimate is then used for a second -sensitivity correction of all original measurements and the scale is changed from stepper motor step count to -wavelength in nanometers.

-
- A plot with three wide peaks, all three of different
-    heights. The leftmost peak is highest at 6nA, the middle peak lowest at 1.6nA and the rightmost peak in between
-    at 4nA.  The middle one overlaps the two on the sides.  Overall, the plot spans about 300nm on its x axis with
-    each peak being around 100nm wide. -
A plot of the processed measurements. From left to right, the three peaks are blue, green and red. -
-
- - -
-
-

Color space mapping

-

Finally, to achieve the objective of measuring the LED tape's channels' precise color coordinates the measured spetra -have to be matched against the color spaces' color matching functions. The color matching functions describe how -strong the color space's idealized standard observer would react to light at a particular wavelength. Going from a -measured spectrum to color coordinates XYZ works by integrating over the product of the measurement and each color -coordinate's color matching function.

-

The result are three color coordinates X, Y and Z for each channel R, G and B yielding nine coordinates in total. When -written as a matrix conversion between XYZ color space and LED-RGB color space is as simple as multiplying that matrix -(or its inverse) and a vector from one of the color spaces.

-

In XYZ space, the set of colors that can be produced with this LED tape is described by the parallelepiped spanned by -the three channel's XYZ vectors. In the following figures, you can see a three-dimensional model of the RGB LED's color -space (colorful) as well as sRGB (white) for comparison plotted within CIE 1931 XYZ. There is no natural map to scale -both so for this illustration the LED color space has been scaled to fit. These figures were made with blender and a few -lines of python. The blender project file including all settings and the python script to generate the color space -models can be found in the project repo.

-
- -
Illustration of the measured LED color space scaled to fit within XYZ with sRGB (light gray) for - comparison. The thick, white line is the spectral locus. - - mkv/h264 download / - webm download -
-

As you can see, the result is pretty disappointing. The LED's color space parallepiped is very narrow, which is because -the blue channel is much brighter than the other two channels. An easy fix for this is to scale-up the RGB space and -drop any values outside XYZ. The scaling factor is a trade-off between color space coverage and brightness. You can -produce the most colors when you clip all channels to brightness of the weakest channel (green in this case), but that -will make the result very dim. Scaling brightness like that stretches the RGB parallelepiped along its major axis. Up to -a point the number of possible colors (the gamut) increases at expense of maximum brightness. When the parallelepiped is -stretched far enought for all three channel vectors to be outside the 1,1,1 XYZ-cube, maximum brightness continues to -decrease but the gamut stays constant. I don't know a simple scientific way to solve this problem, so I just played -around with a couple of factors and settled on 2.5 as a reasonable compromise. Below is an illustration.

-
- -
Illustration of the measured LED color space at scale factor 2.5 within XYZ with sRGB (light gray) - for comparison. The thick, white line is the spectral locus. - - mkv/h264 download / - webm download -
-
-
-
-
-

Firmware implementation

-

In the end, the above measurements yield two matrices: One for mapping XYZ to RGB, and one for mapping RGB to XYZ. Of -the several versions of CIE XYZ I chose the CIE 1931 XYZ color space as a basis for the firmware because it is most -popular. Mapping a color coordinate in one color space to the other is as simple as performing nine floating-point -multiplications and six additions. Mapping Lab or Lch to RGB is done by first mapping Lab/Lch to XYZ, then XYZ to RGB. -Lab to XYZ is somewhat complex since it requires a floating-point power for gamma correction, but any self-respecting -libc will have one of those so this is still no problem. Lch also requires floating-point sine and cosine functions, but -these should still be no problem on most hardware.

-

My implementation of these conversions in the ESP8266 firmware of my Wifi LED driver can be found on Github.

-
-
-
- -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/posts/multichannel-led-driver/index.html b/docs/posts/multichannel-led-driver/index.html deleted file mode 100644 index a5a20ae..0000000 --- a/docs/posts/multichannel-led-driver/index.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - Multichannel Led Driver | jaseg.net - - - -
- - - - - - -
- - - - -
- - - - - -
-
- - - -
-
- -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/posts/wifi-led-driver/index.html b/docs/posts/wifi-led-driver/index.html deleted file mode 100644 index 7f9d4ae..0000000 --- a/docs/posts/wifi-led-driver/index.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - Wifi Led Driver | jaseg.net - - - -
- - - - - - -
- - - - -
- - - - - -
-
- - - -
-
- -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/posts/zeus-hammer/index.html b/docs/posts/zeus-hammer/index.html deleted file mode 100644 index 4d3e872..0000000 --- a/docs/posts/zeus-hammer/index.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - Zeus Hammer | jaseg.net - - - -
- - - - - - -
- - - - -
- - - - - -
-
- - -

In case you were having an inferiority complex because your friends' IBM Model M keyboards are so much louder than the -shitty rubber dome freebie you got with your pc... Here's the solution: Zeus Hammer, a simple typing cadence enhancer -for PS/2 keyboards.

- -

The connects to the keyboard's PS/2 clock line and briefly actuates a large solenoid on each key press. An interesting -fact about PS/2 is that the clock line is only active as long as either the host computer or the input device actually -want to send data. In case of a keyboard that's the case when a key is pressed or when the host changes the keyboard's -LED state, otherwise the clock line is silent. We ignore the LED activity for now as it's generally coupled to key -presses. By just triggering an NE555 configured as astable flipflop we can stretch each train of clock pulses to a -pulse a few tens of milliseconds long that is enough to actuate the solenoid.

-/images/zeus_hammer_schematic.jpg -

Since PS/2 sends each key press and key release separately this circuit will pulse twice per keystroke. It would be -possible to ignore one of them but I figure the added noise just adds to the experience.

-

Built on a breadboard, the circuit looks like this.

-/images/zeus_hammer_breadboard.jpg -

The completed system looks like this.

- -

Since my solenoid did not have a tensioning spring I used a rubber band and some vinyl tape to make an adjustable -tensioner. The small orange USB hub serves as an end-stop because I had nothing else of the right shape. The sound and -resonance of the thing can be adjusted to taste by moving the end stop, adjusting the tensioning rubber and tuning the -excitation duration using the potentiometer. My particular solenoid was a bit slow so I added some pieces of circuit -board as shims between the plunger and the case to limit the plunger's travel inside the solenoid core. Here is another -video of the thing in action in which I tune and de-tune the mechanical resonance using the potentiometer.

- -
-
- -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/sitemap.xml b/docs/sitemap.xml deleted file mode 100644 index 2bb2752..0000000 --- a/docs/sitemap.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - https://jaseg.net/posts/zeus-hammer/ - 2018-05-03T11:59:37+02:00 - - - - https://jaseg.net/posts/multichannel-led-driver/ - 2018-05-02T11:31:14+02:00 - - - - https://jaseg.net/posts/wifi-led-driver/ - 2018-05-02T11:31:03+02:00 - - - - https://jaseg.net/posts/led-characterization/ - 2018-05-02T11:18:38+02:00 - - - - https://jaseg.net/categories/ - 0 - - - - https://jaseg.net/posts/ - 2018-05-03T11:59:37+02:00 - 0 - - - - https://jaseg.net/tags/ - 0 - - - - https://jaseg.net/ - 2018-05-03T11:59:37+02:00 - 0 - - - \ No newline at end of file diff --git a/docs/tags/index.html b/docs/tags/index.html deleted file mode 100644 index 0f1438d..0000000 --- a/docs/tags/index.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - Tags | jaseg.net - - - -
- - - - - - -
- - - - -
- - -

Tags

- -
    - -
- -
- - - - -
- ©2018 by Sebastian Götte. This work is licensed under - CC-BY-SA 4.0. -
-
- - - diff --git a/docs/tags/index.xml b/docs/tags/index.xml deleted file mode 100644 index 0a11fed..0000000 --- a/docs/tags/index.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - Tags on jaseg.net - https://jaseg.net/tags/ - Recent content in Tags on jaseg.net - Hugo -- gohugo.io - en-us - - - - - - \ No newline at end of file diff --git a/docs/video/led_within_srgb_fancy_camera_path_scale=2.5.mkv b/docs/video/led_within_srgb_fancy_camera_path_scale=2.5.mkv deleted file mode 100644 index 0a1eece..0000000 Binary files a/docs/video/led_within_srgb_fancy_camera_path_scale=2.5.mkv and /dev/null differ diff --git a/docs/video/led_within_srgb_fancy_camera_path_scale=2.5.webm b/docs/video/led_within_srgb_fancy_camera_path_scale=2.5.webm deleted file mode 100644 index 04d355c..0000000 Binary files a/docs/video/led_within_srgb_fancy_camera_path_scale=2.5.webm and /dev/null differ diff --git a/docs/video/led_within_srgb_scale=1.0.mkv b/docs/video/led_within_srgb_scale=1.0.mkv deleted file mode 100644 index 69dfccf..0000000 Binary files a/docs/video/led_within_srgb_scale=1.0.mkv and /dev/null differ diff --git a/docs/video/led_within_srgb_scale=1.0.webm b/docs/video/led_within_srgb_scale=1.0.webm deleted file mode 100644 index 8034882..0000000 Binary files a/docs/video/led_within_srgb_scale=1.0.webm and /dev/null differ diff --git a/docs/video/led_within_srgb_scale=2.5.mkv b/docs/video/led_within_srgb_scale=2.5.mkv deleted file mode 100644 index a7fba0b..0000000 Binary files a/docs/video/led_within_srgb_scale=2.5.mkv and /dev/null differ diff --git a/docs/video/led_within_srgb_scale=2.5.webm b/docs/video/led_within_srgb_scale=2.5.webm deleted file mode 100644 index d0c9135..0000000 Binary files a/docs/video/led_within_srgb_scale=2.5.webm and /dev/null differ diff --git a/docs/video/led_within_srgb_scale=3.mkv b/docs/video/led_within_srgb_scale=3.mkv deleted file mode 100644 index 94c7750..0000000 Binary files a/docs/video/led_within_srgb_scale=3.mkv and /dev/null differ diff --git a/docs/video/led_within_srgb_scale=3.webm b/docs/video/led_within_srgb_scale=3.webm deleted file mode 100644 index 3dc88cc..0000000 Binary files a/docs/video/led_within_srgb_scale=3.webm and /dev/null differ diff --git a/docs/video/sRGB.mkv b/docs/video/sRGB.mkv deleted file mode 100644 index 903c719..0000000 Binary files a/docs/video/sRGB.mkv and /dev/null differ diff --git a/docs/video/sRGB.webm b/docs/video/sRGB.webm deleted file mode 100644 index 737cc1b..0000000 Binary files a/docs/video/sRGB.webm and /dev/null differ diff --git a/docs/video/scale=1.mkv b/docs/video/scale=1.mkv deleted file mode 100644 index 410896e..0000000 Binary files a/docs/video/scale=1.mkv and /dev/null differ diff --git a/docs/video/scale=1.webm b/docs/video/scale=1.webm deleted file mode 100644 index dc599be..0000000 Binary files a/docs/video/scale=1.webm and /dev/null differ diff --git a/docs/video/scale=2.5.mkv b/docs/video/scale=2.5.mkv deleted file mode 100644 index 6ff3619..0000000 Binary files a/docs/video/scale=2.5.mkv and /dev/null differ diff --git a/docs/video/scale=2.5.webm b/docs/video/scale=2.5.webm deleted file mode 100644 index 6a6a860..0000000 Binary files a/docs/video/scale=2.5.webm and /dev/null differ diff --git a/docs/video/scale=5.mkv b/docs/video/scale=5.mkv deleted file mode 100644 index b4e7e65..0000000 Binary files a/docs/video/scale=5.mkv and /dev/null differ diff --git a/docs/video/scale=5.webm b/docs/video/scale=5.webm deleted file mode 100644 index 0298a11..0000000 Binary files a/docs/video/scale=5.webm and /dev/null differ diff --git a/research/colorspace/Untitled.ipynb b/research/colorspace/Colorspace Visualization.ipynb similarity index 100% rename from research/colorspace/Untitled.ipynb rename to research/colorspace/Colorspace Visualization.ipynb diff --git a/static/images/daylight_spectrum_dvd.jpg b/static/images/daylight_spectrum_dvd.jpg deleted file mode 100644 index d01242e..0000000 Binary files a/static/images/daylight_spectrum_dvd.jpg and /dev/null differ diff --git a/static/images/driver_ringing_strong.jpg b/static/images/driver_ringing_strong.jpg deleted file mode 100644 index 0419a0e..0000000 Binary files a/static/images/driver_ringing_strong.jpg and /dev/null differ diff --git a/static/images/driver_ringing_weak.jpg b/static/images/driver_ringing_weak.jpg deleted file mode 100644 index 12f9c5d..0000000 Binary files a/static/images/driver_ringing_weak.jpg and /dev/null differ diff --git a/static/images/electronics_whole.jpg b/static/images/electronics_whole.jpg deleted file mode 100644 index faaf751..0000000 Binary files a/static/images/electronics_whole.jpg and /dev/null differ diff --git a/static/images/hsv_cylinder.png b/static/images/hsv_cylinder.png deleted file mode 100644 index 265f3e0..0000000 Binary files a/static/images/hsv_cylinder.png and /dev/null differ diff --git a/static/images/preamp_back.jpg b/static/images/preamp_back.jpg deleted file mode 100644 index 0af495d..0000000 Binary files a/static/images/preamp_back.jpg and /dev/null differ diff --git a/static/images/preamp_front.jpg b/static/images/preamp_front.jpg deleted file mode 100644 index 62fad28..0000000 Binary files a/static/images/preamp_front.jpg and /dev/null differ diff --git a/static/images/preamp_schematic.jpg b/static/images/preamp_schematic.jpg deleted file mode 100644 index 6be7bbd..0000000 Binary files a/static/images/preamp_schematic.jpg and /dev/null differ diff --git a/static/images/processed_plot_cheap_rgb.svg b/static/images/processed_plot_cheap_rgb.svg deleted file mode 100644 index 019d3c9..0000000 --- a/static/images/processed_plot_cheap_rgb.svg +++ /dev/null @@ -1,2453 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/images/raw_plot_cheap_rgb.svg b/static/images/raw_plot_cheap_rgb.svg deleted file mode 100644 index 049aa74..0000000 --- a/static/images/raw_plot_cheap_rgb.svg +++ /dev/null @@ -1,2574 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/images/rgb_cube.svg b/static/images/rgb_cube.svg deleted file mode 100644 index 8af7a00..0000000 --- a/static/images/rgb_cube.svg +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - G+ - - - - - - - - R+ - - - - B+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - R- - - - - B- - - - - - - - - G- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - R : 83 - - - G : 150 - - - B : 60 - - G: 150 - B: 60 - R: 83 - - - - - - - - R - G - B - - - R - G - B - - - R 255 - G 255 - B 255 - - - - - \ No newline at end of file diff --git a/static/images/spectrograph_step1_parts.jpg b/static/images/spectrograph_step1_parts.jpg deleted file mode 100644 index 107220a..0000000 Binary files a/static/images/spectrograph_step1_parts.jpg and /dev/null differ diff --git a/static/images/spectrograph_step2.jpg b/static/images/spectrograph_step2.jpg deleted file mode 100644 index b678372..0000000 Binary files a/static/images/spectrograph_step2.jpg and /dev/null differ diff --git a/static/images/spectrograph_step3.jpg b/static/images/spectrograph_step3.jpg deleted file mode 100644 index acd6d5e..0000000 Binary files a/static/images/spectrograph_step3.jpg and /dev/null differ diff --git a/static/images/spectrograph_step4_complete.jpg b/static/images/spectrograph_step4_complete.jpg deleted file mode 100644 index d23560d..0000000 Binary files a/static/images/spectrograph_step4_complete.jpg and /dev/null differ diff --git a/static/images/zeus_hammer_breadboard.jpg b/static/images/zeus_hammer_breadboard.jpg deleted file mode 100644 index 08efebb..0000000 Binary files a/static/images/zeus_hammer_breadboard.jpg and /dev/null differ diff --git a/static/images/zeus_hammer_breadboard_original.jpg b/static/images/zeus_hammer_breadboard_original.jpg deleted file mode 100644 index 4f8f34e..0000000 Binary files a/static/images/zeus_hammer_breadboard_original.jpg and /dev/null differ diff --git a/static/images/zeus_hammer_schematic.jpg b/static/images/zeus_hammer_schematic.jpg deleted file mode 100644 index 0e6f483..0000000 Binary files a/static/images/zeus_hammer_schematic.jpg and /dev/null differ diff --git a/static/images/zeus_hammer_schematic_original.jpg b/static/images/zeus_hammer_schematic_original.jpg deleted file mode 100644 index b50b3a0..0000000 Binary files a/static/images/zeus_hammer_schematic_original.jpg and /dev/null differ diff --git a/static/video/led_within_srgb_fancy_camera_path_scale=2.5.mkv b/static/video/led_within_srgb_fancy_camera_path_scale=2.5.mkv deleted file mode 100644 index 0a1eece..0000000 Binary files a/static/video/led_within_srgb_fancy_camera_path_scale=2.5.mkv and /dev/null differ diff --git a/static/video/led_within_srgb_fancy_camera_path_scale=2.5.webm b/static/video/led_within_srgb_fancy_camera_path_scale=2.5.webm deleted file mode 100644 index 04d355c..0000000 Binary files a/static/video/led_within_srgb_fancy_camera_path_scale=2.5.webm and /dev/null differ diff --git a/static/video/led_within_srgb_scale=1.0.mkv b/static/video/led_within_srgb_scale=1.0.mkv deleted file mode 100644 index 69dfccf..0000000 Binary files a/static/video/led_within_srgb_scale=1.0.mkv and /dev/null differ diff --git a/static/video/led_within_srgb_scale=1.0.webm b/static/video/led_within_srgb_scale=1.0.webm deleted file mode 100644 index 8034882..0000000 Binary files a/static/video/led_within_srgb_scale=1.0.webm and /dev/null differ diff --git a/static/video/led_within_srgb_scale=2.5.mkv b/static/video/led_within_srgb_scale=2.5.mkv deleted file mode 100644 index a7fba0b..0000000 Binary files a/static/video/led_within_srgb_scale=2.5.mkv and /dev/null differ diff --git a/static/video/led_within_srgb_scale=2.5.webm b/static/video/led_within_srgb_scale=2.5.webm deleted file mode 100644 index d0c9135..0000000 Binary files a/static/video/led_within_srgb_scale=2.5.webm and /dev/null differ diff --git a/static/video/led_within_srgb_scale=3.mkv b/static/video/led_within_srgb_scale=3.mkv deleted file mode 100644 index 94c7750..0000000 Binary files a/static/video/led_within_srgb_scale=3.mkv and /dev/null differ diff --git a/static/video/led_within_srgb_scale=3.webm b/static/video/led_within_srgb_scale=3.webm deleted file mode 100644 index 3dc88cc..0000000 Binary files a/static/video/led_within_srgb_scale=3.webm and /dev/null differ diff --git a/static/video/sRGB.mkv b/static/video/sRGB.mkv deleted file mode 100644 index 903c719..0000000 Binary files a/static/video/sRGB.mkv and /dev/null differ diff --git a/static/video/sRGB.webm b/static/video/sRGB.webm deleted file mode 100644 index 737cc1b..0000000 Binary files a/static/video/sRGB.webm and /dev/null differ diff --git a/static/video/scale=1.mkv b/static/video/scale=1.mkv deleted file mode 100644 index 410896e..0000000 Binary files a/static/video/scale=1.mkv and /dev/null differ diff --git a/static/video/scale=1.webm b/static/video/scale=1.webm deleted file mode 100644 index dc599be..0000000 Binary files a/static/video/scale=1.webm and /dev/null differ diff --git a/static/video/scale=2.5.mkv b/static/video/scale=2.5.mkv deleted file mode 100644 index 6ff3619..0000000 Binary files a/static/video/scale=2.5.mkv and /dev/null differ diff --git a/static/video/scale=2.5.webm b/static/video/scale=2.5.webm deleted file mode 100644 index 6a6a860..0000000 Binary files a/static/video/scale=2.5.webm and /dev/null differ diff --git a/static/video/scale=5.mkv b/static/video/scale=5.mkv deleted file mode 100644 index b4e7e65..0000000 Binary files a/static/video/scale=5.mkv and /dev/null differ diff --git a/static/video/scale=5.webm b/static/video/scale=5.webm deleted file mode 100644 index 0298a11..0000000 Binary files a/static/video/scale=5.webm and /dev/null differ