LED Pret Gedurende die Feestyd
Elektronika en Pret
Dit is 'n rukkie sedert ek laas opgewonde was en iets reggekry het wat my bly aanspoor. Aanvanklik was ek nie baie lus om al my goed in te pak voordat ek huiswaarts gekeer het nie. Dit is die Arduino Starter kit, my gereedskap kassie, die ander gereedskap kas, my boeke, die skootrekenars en tasse. Boonop moes ek nog huis skoonmaak ook voordat ek vir 'n paar weke Bloemfontein toe vertrek.
Nou is Kersfees van die naweek verby en uiteindelik het ek vanoggend daarin geslaag om die laaste stukkie van my Slim Liguitstralende Diode (LED) legkaart aanmekaar te sit.
Daar is eintlik so baie deeltjies in die storie dat ek sukkel om iewers te begin! Dalk moet ek begin met my aanlyn inkopies voordat ek vanuit die Kaap weg is. Dit is mos nou so gerieflik om deur Takealot iets te koop en dan dit afgelewer te kry waar ek ook al is. Dus het ek geloer na 'n Antwire Buck-Boost-Converter wat ek aan die sonpaneel se battery wil koppel, 'n Sonoff Slim LED strook en 'n Gizzu UPS UPS (Gizzu 8800mAh Mini UPS Dual DC) vir my ma se WiFi router.
Die Buck-Boost-Converter het ek gekry om seker te maak dat daar 'n konstante of beheerde vloei van krag is nadat ek my vorige WiFi router uitgebrand het... 'n Duur les. Hierdie Antwire kan 'n bron van 5.5 tot 30V in neem, en dan 0.5 tot 30V uitsit. Wat hierdie vir my so 'n goeie item maak is dat dit 'n LCD skerm het wat die inlaat en uitlaat volts wys asook die verbruik in Amps of Watts.
Die Gizzu UPS het ek vir die WiFi Router gekry - ek vat nie weer 'n kans nie! Ek het amper so een by my woonstel in Muizenberg. Gedurende loadshedding kan ek gemaklik deur die hele tyd gaan met internet verbinding. Hierdie een is nie so grĂȘnd nie, maar kan 2 uitlate van krag verskaf, in 5, 9 of 12V (afsonderlik).
Laastens is dan die Sonoff Slim LED strook. Dit is waar die pret begin! Die strook is programmeerbaar, maar dit is nie 'n addresseerbare strook nie, dus sal al die liggies tegelyk dieselfde vertoon. Maar dit is steeds baie oulik!
Programmeerbare LED Strook
'n Vriend het my van die LED stroke van Sonoff bewus gemaak en daarom het ek dit gekry, min wetende dat dit my vir 'n hele ruk besig gaan hou. Ek het baie geleer omdat ek die probleem van 5V op die Arduino, en 12V vir die LED moes oorkom. Tesame met dit wou ek graag ook die strook beheer en moes ek verder leer (of eerder, hersien) hoe MOSFET en transistors werk.
In van my vorige projekte het ek geleer hoe om MOSFET transistors te gebruik, maar kan nie onthou of ek al ooit gewone transistors gebruik het nie. Ek het toe ek laas keer van Bloemfontein af terug Kaap toe is, 'n ou kragtoevoer komponent saam geneem en al die komponente desoldeer. Daar het ek 'n magdom C945 NPN en A733 PNP transistors bymekaar gemaak.
In hierdie projek het ek eers met die MOSFET transistors probeer om my stroombaan aan die gang te kry. Die probleem wat opgeduik het is dat die Arduino Starter kit slegs twee MOSFET transistors het en ek het drie nodig om al drie kleure, rooi, groen en blou, te beheer.
Alles het mooi gewerk met die MOSFET transistors. Ek het eers mooi opgelees oor die NPN transistors om seker te maak dat ek nie goed sal uitbrand of misbruik nie. Omdat ek skrikkerig is het ek eers alles getoets met CircuitJS en selfs toe was ek onseker... Gister-aand het ek alles mooi oordink en vroeg vanoggend het ek opgestaan en die C945 transistor op die broodbord geplak en alles met die multi-meter getoets sodat daar nie enige verrassings is nie. Tot my blydskap het alles gewerk soos die teorie verduidelik het! Nou hardloop my hele projek sonder enige probleme. Ek reken ek gaan die MOSFETs vervang met 2 c945 NPN transistors omdat hulle ietwat goedkoper is lyk of dit aan my behoeftes voldoen.
Wiskunde Hersiening
Min wetende dat ek weer wiskunde goed moet doen, het ek begin wonder hoe ek op 'n
beter manier die egalige oorgang van waardes kan beheer. Kort voor lank het ek
besef dat 'n sinus-golf vir my so iets sal kan doen! Nou, dit is jare gelede
dat ek daarmee gewerk het, en daar is baie spinnerakke. Ek moes iewers 'n
grafiek oplossing kry, iets soos gnu-plot
, maar wou nie weer alles leer om dit
aan die gang te kry nie. Met my soektog op die web kom ek toe op Function Plot
af en kon ek na 'n rukkie se rondspeel weer sin maak van hoe die trigonometriese
funksies werk en hoe ek dit kan gebruik om 'n mooi "pulsende" effek te maak met
die LED strook.
Ek mis wiskunde so bietjie, en wens ek het beter opgelet op skool. Daar is so
baie plekke waar dit gebruik kan word, maar dit is net nie so voor die hand
liggend nie. Dalk is hierdie die begin van iets nuuts, wie weet? Ek het vanoggend
die eerste keer werklik die nut van die abs
-funksie gevind toe ek die probleem
van negatiewe waardes probeer oplos. In plaas van 'n vol sinus-golf, kry ek twee
positiewe duine, waar dit andersins 'n duin en 'n vallei sou maak.
Daar is nou verskeie maniere hoe ek die waardes na die LED strook skryf en ek leer nog, maar dit is nog 'n leer proses. Dit voel elke keer of daar 'n beter manier is. En dan werk manier a beter vir iets as manier b. So dit gaan nog tyd vat om meer te wete te kom voordat ek die "beste" manier kan kry.
Projek in Kode
Die projek maak gebruik van clj-firmata
om per USB kabel met die Arduino Uno R3 te kommunikeer.
(ns lcd-mosfet
(:require [firmata.core :as f]
[clojure.string :as str]))
(def board (f/open-serial-board :auto-detect))
(def colours
{:red 3
:blue 5
:green 6})
Ek het die bord opgestel om die PWM (Pulse Width Modulation) punte 3, 5 en 6 te gebruik:
(defn init-strip-lights [board]
(doseq [[_ pin] colours]
(f/set-pin-mode board pin :pwm)
(f/set-analog board pin 0)))
(init-strip-lights board)
Dan 'n paar nuts-fuknsies om met sinus te werk, die benaming is nie baie akkuraat nie:
(defn to-five-digits [v]
(-> (format "%020.5f" v)
(str/replace #"\," ".")
(Double/parseDouble)))
(defn fx-sin [deg]
(-> deg
(Math/toRadians)
(Math/sin)
(to-five-digits)))
(defn fx-sin-inverse [deg]
(-> deg
(Math/toRadians)
(+ Math/PI)
(Math/sin)
(+ 1)
(to-five-digits)))
(defn fx-square [deg]
(Math/round (Math/sin (Math/toRadians deg))))
'n Funksie om 'n geleidelike "puls" te maak:
(defn pulse
[board & [{:keys [times duration fx clrs]
:or {times 1
fx #'fx-sin
duration 500
clrs [:red :green :blue]}}]]
(let [vals (->> (range 0 185 5)
(map #(-> (fx %) (* 255)))
(repeat times)
(flatten))
sleep (/ duration (count vals))]
(doseq [x vals]
(doseq [clr clrs]
(f/set-analog board (get colours clr) (int x)))
(Thread/sleep sleep))))
"Wit" lig aan en af, al die kleure op vol sterkte en almal af:
(defn white-on [board]
(doseq [pin (vals colours)]
(f/set-analog board pin 255)))
(defn white-off [board]
(doseq [pin (vals colours)]
(f/set-analog board pin 0)))
En dan 'n baie eksperimentele stuk om tussen rooi, groen en blou te meng. Dit lyk oulik, maar doen nog nie alles wat ek wil hĂȘ nie:
(defn fx-abs-sin-x+pi-div
[deg div]
(-> deg
(Math/toRadians)
(+ (/ Math/PI div))
(Math/sin)
(Math/abs)
(to-five-digits)))
(defn ^{:experimental true
:doc "This is still a WIP trying to find the best function to display different colours."}
cycle-colours
[board]
(doseq [vs
(->> (range 0 3650 1)
(map (fn [deg]
[(fx-abs-sin-x+pi-div deg 4)
(fx-abs-sin-x+pi-div deg 1)
(fx-abs-sin-x+pi-div deg 2)])))]
#_(println (map #(-> % (* 255) (int)) vs))
(doseq [[pin v] (zipmap (vals colours) vs)]
(f/set-analog board pin (-> v (* 255) (int))))
(Thread/sleep 5)))
(comment
(cycle-colours board)
(white-on board)
(white-off board)
(pulse board
{:clrs [:green :blue :red]
:fx #'fx-sin
:times 1
:duration 2000})
(doseq [clr (into (keys colours) (repeat 2 (keys colours)))]
(pulse board
{:clrs (if (seq? clr) clr [clr])
:fx #'fx-sin
:times 1
:duration 500}))
#_())
Funksies om 'n patroon te genereer en om dit terug te speel. Dit was die eerste probeerslag en laat veel te wense oor, maar dit werk! Die vermenging van patrone is nie watwonders nie, veral omdat die patrone ewe lank moet wees voordat hulle saam gesmelt kan word. Aan die begin het dit sin gemaak, nou dink ek nie meer dat dit die beste manier is nie.
(defn gen-pattern
[pin & [{:keys [fx duration times]
:or {fx #'fx-sin
duration 1000
times 1}}]]
(let [vals
(->> (range 0 185 5)
(map #(-> (fx %) (* 255)))
(repeat times)
(flatten)
(map (fn [v] [pin (int v)])))
sleep (/ duration (count vals))
pattern
(->> [:sleep sleep]
(constantly)
(repeatedly)
(interleave vals)
(partition 2))]
pattern))
(defn flash-pattern [board pattern-coll]
(doseq [steps pattern-coll]
(let [to-write (remove (comp #(= % :sleep) first) steps)
sleep (filter (comp #(= % :sleep) first) steps)]
(doseq [[pin v] to-write] (f/set-analog board pin v))
(when sleep
(doseq [[_ s] sleep] (Thread/sleep s))))))
(comment
(flash-pattern
board
(gen-pattern 3
{:fx #(Math/round (Math/sin (Math/toRadians %)))
:times 5}))
(do
(flash-pattern board (gen-pattern 5 {:fxx #'fx-sin-inverse}))
(flash-pattern board (gen-pattern 3 {:fxx #'fx-sin})))
(doseq [x (range 5)]
(flash-pattern
board
(map
(comp (partial sort-by (comp keyword? first))
(partial distinct)
(partial partition 2)
flatten)
(partition 2
(interleave
(gen-pattern 5 {})
(gen-pattern 3 {:fx #'fx-sin-inverse}))))))
#_())
Ek gaan nog met dit rondspeel, maar vir 'n begin is ek baie gelukkig met die resultaat. Ek moes my brein bietjie strek en beide ou en nuwe velde verken, wat dit baie lekker gemaak het.