View Source 2. Fledex: Some simple tests

# We start to define some libraries we need. If you are running on a laptop
# the libraries will be loaded, but on a nerves_livebook you can only use
# what has been compiled in.
Mix.install([
  {:fledex, "~>0.2"},
])

# we define a couple of aliases to not have to type that much
alias Fledex.Leds
alias Fledex.LedsDriver
alias Fledex.LedStripDriver.KinoDriver
alias Fledex.LedStripDriver.SpiDriver
alias Fledex.Color.Correction

:ok

Section

Fledex has several drivers which can also be used in parallel. It's probably best to only use a single driver to start with. The Kino driver does not have any hardware dependency and therefore is probably a good start to ensure that the library is loaded correctly.

# frame = Kino.Frame.new() |> Kino.render()

{:ok, pid} =
  LedsDriver.start_link(%{
    timer: %{only_dirty_update: false},
    led_strip: %{
      merge_strategy: :cap,
      # [KinoDriver, SpiDriver],
      driver_modules: [KinoDriver],
      config: %{
        KinoDriver => %{
          update_freq: 1,
          color_correction: Fledex.Color.Correction.no_color_correction()
          # frame: frame
        }
        #        SpiDriver => %{
        #          color_correction:
        #            Correction.define_correction(
        #              Correction.Color.typical_smd5050(),
        #              Correction.Temperature.uncorrected_temperature()
        #            )
        #        }
      }
    }
  })

We now define a couple of helper functions. The first 2 functions are talking binaries directly with the LED driver, the latter two are making use of the Leds client module that helps to create nice effects like a rainbow.

defmodule Helpers do
  def red(namespace) do
    Enum.each(1..10, fn _index ->
      LedsDriver.set_leds(namespace, [0xFF0000, 0x000000, 0x000000, 0x000000, 0x00000])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x000000, 0xFF0000, 0x000000, 0x000000, 0x00000])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x000000, 0x000000, 0xFF0000, 0x000000, 0x00000])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0xFF0000, 0x00000])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0x000000, 0xFF0000])
      Process.sleep(600)
    end)
  end

  def blue(namespace) do
    Enum.each(1..10, fn _index ->
      LedsDriver.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0x000000, 0x0000FF, 0x00FF00])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0x0000FF, 0x000000, 0x00FF00])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x000000, 0x000000, 0x0000FF, 0x000000, 0x000000, 0x00FF00])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x000000, 0x0000FF, 0x000000, 0x000000, 0x000000, 0x00FF00])
      Process.sleep(600)
      LedsDriver.set_leds(namespace, [0x0000FF, 0x000000, 0x000000, 0x000000, 0x000000, 0x00FF00])
      Process.sleep(600)
    end)
  end

  def rainbow(namespace) do
    Enum.each(0..10000, fn index ->
      config = %{
        num_leds: 50,
        reversed: true
      }

      Leds.leds(50)
      |> Leds.func(:rainbow, config)
      |> Leds.send(%{namespace: namespace, offset: index})

      # before sending the next update we sleep a bit
      Process.sleep(100)
    end)
  end

  def gradient(namespace) do
    Enum.each(0..10000, fn index ->
      config = %{
        num_leds: 50,
        start_color: 0xFF0000,
        end_color: 0x0000FF
      }

      Leds.leds(50)
      |> Leds.func(:gradient, config)
      |> Leds.send(%{namespace: namespace, offset: index, rotate_left: true})

      # before sending the next update we sleep a bit
      Process.sleep(100)
    end)
  end
end

Now use the above functions. We can run the functions by spawning a new thread. This allows to also see what happens if another thread works in parallel. Here we create a rainbow effect that will be send with an changing offset so that the rainbow rotates through the LEDs

LedsDriver.define_namespace(:default)
spawn(fn -> Helpers.rainbow(:default) end)

Here we create a gradient between red and blue. Also this one we let rotate through

LedsDriver.define_namespace(:gradient)
spawn(fn -> Helpers.gradient(:gradient) end)

We can drop the namespaces to see what happens

LedsDriver.drop_namespace(:john)
LedsDriver.drop_namespace(:jane)
LedsDriver.drop_namespace(:default)
LedsDriver.drop_namespace(:gradient)

This test is running a couple of different ligth definitions in parallel.

LedsDriver.define_namespace(:john)
LedsDriver.define_namespace(:jane)
LedsDriver.define_namespace(:default)

spawn(fn -> Helpers.blue(:jane) end)
spawn(fn -> Helpers.red(:john) end)
spawn(fn -> Helpers.rainbow(:default) end)

Once we are done we should stop our GenServer (even thoguh I rarely run this one ;-))

GenServer.stop(pid)