4 ms·
(defn pid-transducer [set-point k-p k-i k-d] (fn [xf] (let [pid (volatile! (make-pid set-point k-d k-i k-d))] (fn ([] (xf))
by eutectic 12y ago
(defn pid-transducer [set-point k-p k-i k-d]
(fn [xf]
(let [pid (volatile! (make-pid set-point k-d k-i k-d))]
(fn
([] (xf))
([result] (xf result))
([result input]
(vswap! pid (fn [p] (calculate-pid p input)))
(xf result (:output @pid)))))))
If guessing that the first 'k-d' on the third line should be a 'k-p'. I'm glad this bug didn't mess up your eggs!
- pi-rat 12y agoDoh!! Thanks, post updated! No wonder it seemed to converge faster when I added a tiny derivative. (The gains were pretty much just guesswork, did two runs with just water before adding the eggs. It's a one evening toy setup after all, so don't want to spend too much time calibrating the pid loop)
- lomnakkus 12y agoPlease take this in the ha-ha-only-serious spirit: I wonder if a static type system would have caught the error in this case...?
- pi-rat 12y agoProbably not unless you make k-p, k-i, k-d types - as they are simply floats. Checking for unused function arguments however would have caught this error. Running a linter (such as eastwood) in clojure does the trick: $ lein eastwood '{:linters [:unused-fn-args]}' == Eastwood 0.1.4 Clojure 1.7.0-alpha2 JVM 1.8.0_05 == Linting pid.core == {:linter :unused-fn-args, :msg "Function args [k-p (line 32, column 33)] of (or within) pid-transducer are never used", :file "pid/core.clj", :line 32, :column 1} Sadly it only works if you actually use it, and I'm a lazy bastard :p
- lemming 12y agoIf you used Cursive, it would have marked that parameter as unused right in your editor. Even lazy bastards get the advantages!