Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

2. Fledex: Some simple tests

livebooks/2_fledex_first_steps.livemd

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.4"}
])

# we define a couple of aliases to not have to type that much
alias Fledex.Leds
alias Fledex.LedStrip
alias Fledex.Driver.Impl.Kino
alias Fledex.Driver.Impl.Spi
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} =
  LedStrip.start_link(%{
    timer: %{only_dirty_update: false},
    led_strip: %{
      merge_strategy: :cap,
      # [Kino, Spi],
      driver_modules: [Kino],
      config: %{
        Kino => %{
          update_freq: 1,
          color_correction: Fledex.Color.Correction.no_color_correction()
          # frame: frame
        }
        #        Spi => %{
        #          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 ->
      LedStrip.set_leds(namespace, [0xFF0000, 0x000000, 0x000000, 0x000000, 0x00000])
      Process.sleep(600)
      LedStrip.set_leds(namespace, [0x000000, 0xFF0000, 0x000000, 0x000000, 0x00000])
      Process.sleep(600)
      LedStrip.set_leds(namespace, [0x000000, 0x000000, 0xFF0000, 0x000000, 0x00000])
      Process.sleep(600)
      LedStrip.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0xFF0000, 0x00000])
      Process.sleep(600)
      LedStrip.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0x000000, 0xFF0000])
      Process.sleep(600)
    end)
  end

  def blue(namespace) do
    Enum.each(1..10, fn _index ->
      LedStrip.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0x000000, 0x0000FF, 0x00FF00])
      Process.sleep(600)
      LedStrip.set_leds(namespace, [0x000000, 0x000000, 0x000000, 0x0000FF, 0x000000, 0x00FF00])
      Process.sleep(600)
      LedStrip.set_leds(namespace, [0x000000, 0x000000, 0x0000FF, 0x000000, 0x000000, 0x00FF00])
      Process.sleep(600)
      LedStrip.set_leds(namespace, [0x000000, 0x0000FF, 0x000000, 0x000000, 0x000000, 0x00FF00])
      Process.sleep(600)
      LedStrip.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.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 ->
      Leds.leds(50)
      |> Leds.gradient(0xff0000, 0x0000ff, %{num_leds: 50})
      |> 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

LedStrup.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

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

We can drop the namespaces to see what happens

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

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

LedStrip.define_namespace(:john)
LedStrip.define_namespace(:jane)
LedStrip.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)