Last active
September 4, 2015 02:51
-
-
Save safiire/2a6f793f55aa7b2826a6 to your computer and use it in GitHub Desktop.
RC Filter Circuit simulation in Scheme
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;;; RC Filter Simulation | |
| ;; Calculates the frequency response of an RC filter | |
| ;; and displays it with ASCII art | |
| ;; This is just a program I always write to learn a new programming language | |
| ;; I tried out Scheme's lazy lists for this | |
| ;; | |
| ;; Frequency Response | |
| ;; ---------------------------------------------------------------- | |
| ;; |****************************** | | |
| ;; | ***** | | |
| ;; | *** | | |
| ;; | *** | | |
| ;; | ** | | |
| ;; | ** | | |
| ;; | *** | | |
| ;; | *** | | |
| ;; | ***** | | |
| ;; | ********| | |
| ;; | | | |
| ;; ---------------------------------------------------------------- | |
| ;; | |
| ;; 2015 Saf Allen | |
| (use numbers) | |
| (use mathh) | |
| (use matchable) | |
| (use lazy-lists) | |
| ;; Some definitions | |
| (define pi 3.141592653589793) | |
| (define tau (* 2 pi)) | |
| (define vertical 10) | |
| (define horizontal 64) | |
| ;; Create a resistor | |
| (define (make-resistor r) | |
| (cons 'resistor r)) | |
| ;; Create a capacitor | |
| (define (make-capacitor c) | |
| (cons 'capacitor c)) | |
| ;; Get resistance | |
| (define (resistance component) | |
| (match component | |
| [('resistor . r) r] | |
| [('capacitor . _) 0] )) | |
| ;; Get capacitance | |
| (define (capacitance component) | |
| (match component | |
| [('resistor . _) 0] | |
| [('capacitor . c) c])) | |
| ;; Get impedance | |
| (define (impedance component frequency) | |
| (match component | |
| [('resistor . r) r] | |
| [('capacitor . c) (make-rectangular 0 (- (expt (* tau frequency c) -1)))])) | |
| ;; Make an RC filter | |
| (define (make-rc-filter r c) | |
| (cons r c)) | |
| ;; What is the filter cutoff? | |
| (define (filter-cutoff filter) | |
| (let ((resistor (car filter)) | |
| (capacitor (cdr filter))) | |
| (expt (* tau (resistance resistor) (capacitance capacitor)) -1))) | |
| ;; What is the total impedance of the circuit? | |
| (define (total-impedance filter frequency) | |
| (let ((resistor (car filter)) | |
| (capacitor (cdr filter))) | |
| (+ (impedance resistor frequency) (impedance capacitor frequency)))) | |
| ;; What is the total current of the circuit? | |
| (define (total-current filter voltage frequency) | |
| (/ voltage (total-impedance filter frequency))) | |
| ;; What is the voltage across the resistor? | |
| (define (voltage-across-resistor filter voltage frequency) | |
| (let ((resistor (car filter))) | |
| (* (total-current filter voltage frequency) (impedance resistor frequency)))) | |
| ;; What is the voltage across the capacitor? | |
| (define (voltage-across-capacitor filter voltage frequency) | |
| (let ((capacitor (cdr filter))) | |
| (* (total-current filter voltage frequency) (impedance capacitor frequency)))) | |
| ;; Convert MIDI note to frequency | |
| (define (midi->frequency midi) | |
| (* 440 (expt 2 (/ (- midi 69) 12)))) | |
| ;; Do a frequency sweep over every second MIDI note | |
| (define (frequency-sweep filter) | |
| (Map (lambda (midi) | |
| (let ( | |
| (frequency (midi->frequency midi)) | |
| (voltage 1)) | |
| (magnitude (voltage-across-capacitor filter voltage frequency)))) (Filter even? (Cardinals)))) | |
| ;; Make a list containing x, n times | |
| (define (repeat x n) | |
| (if (zero? n) | |
| '() | |
| (cons x (repeat x (- n 1))))) | |
| ;; Maps floating point voltages from 0-1 into integers from 0-{vertical height of graph} | |
| (define (voltage->integers sweep) | |
| (map (lambda (voltage) | |
| (round (* voltage vertical))) sweep)) | |
| ;; Display an ascii filter sweep | |
| (define (display-sweep sweep) | |
| (let ( | |
| (line (list->string (repeat #\- horizontal))) | |
| (vert '(10 9 8 7 6 5 4 3 2 1 0)) | |
| (responses (voltage->integers sweep))) | |
| (print "Frequency Response") | |
| (display " ") | |
| (print line) | |
| (for-each (lambda (vert) | |
| (display "|") | |
| (for-each (lambda (response) | |
| (if (= vert response) | |
| (display "*") | |
| (display " "))) responses) | |
| (print "|")) vert) | |
| (print line))) | |
| ;; Main | |
| (define (main args) | |
| (let* ( | |
| (resistor (make-resistor 220)) | |
| (capacitor (make-capacitor 0.000001)) | |
| (filter (make-rc-filter resistor capacitor)) | |
| (infinite-sweep (frequency-sweep filter)) | |
| (midi-sweep (List->list (Take horizontal infinite-sweep)))) | |
| (display-sweep midi-sweep) | |
| (print "Filter cutoff is at:") | |
| (print (filter-cutoff filter)))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment