haas/fall2026/c4eng/projects/cat0.md
... ...
@@ -0,0 +1,443 @@
1
+# ENGR1050 C for Engineers
2
+
3
+# PROJECT: Create A Theremin (CAT0)
4
+
5
+## OBJECTIVE
6
+
7
+Before we can make an instrument that plays by waving your hand, we need
8
+to understand its two parts. We commence our exploration of two new
9
+components from the electronics kit: an ultrasonic distance sensor that
10
+measures how far away things are, and a passive buzzer that makes the
11
+sounds we tell it to.
12
+
13
+## PROCESS
14
+
15
+Do note, the productive way to go about this project involves taking the
16
+following steps:
17
+
18
+ * starting early
19
+ * reading the project page
20
+ * asking questions regarding things you do not know, are not clear on,
21
+ or are confused about
22
+ * as information, concepts, processes become clear, that is something
23
+ you can contribute to the project documentation (so you can better
24
+ remember)
25
+
26
+If you start too late, and do not ask questions, and do not have enough
27
+time and don't know what is going on, you are not doing the project
28
+correctly.
29
+
30
+## OBTAIN THE PROJECT FILES
31
+
32
+To assist with consistency across all implementations, data files for use
33
+with this project are available on lab46 as a `grabit`. Please copy the
34
+data to your private semester repository under an appropriate project
35
+directory to begin work, and ensure your implementation properly works
36
+with the provided data.
37
+
38
+The project should be obtained by the **Sunday prior to the due date**.
39
+
40
+```
41
+lab46:~/SEMESTER/c4eng$ grabit c4eng cat0
42
+```
43
+
44
+Please study any provided code and supporting documents, and look up,
45
+experiment, and ask questions on aspects that you do not understand.
46
+
47
+## OPERATING THE PROJECT
48
+
49
+These projects will have two paths to them, depending on which device you
50
+are using:
51
+
52
+ * Raspberry Pi single board computer (4/5) using the `wiringPi` library
53
+ * Raspberry Pi Pico microcontroller
54
+
55
+```
56
+lab46:~/SEMESTER/c4eng/cat0$ make
57
+Please select which development environment:
58
+
59
+ make wiringpi - using the Raspberry Pi with wiringpi library
60
+ make pico - using the Raspberry Pi pico
61
+
62
+after which, you can use 'make' to build
63
+lab46:~/SEMESTER/c4eng/cat0$
64
+```
65
+
66
+Run the `make` command with the category representing the path you will
67
+be working with for this project.
68
+
69
+After which, if you do an `ls`, you will see a cyan-colored file called
70
+`cat0.c`. This is the C file you will be editing for this project.
71
+
72
+Go ahead and view it, study the code, eventually make any changes, save
73
+and return to the command-line.
74
+
75
+To build it, you simply run: `make`
76
+
77
+If there are no errors, it will build, and you proceed from there.
78
+
79
+## MAINTAINING YOUR REPOSITORY
80
+
81
+Be sure to keep your repository up-to-date, regularly committing changes
82
+to files.
83
+
84
+As a reminder, here are the suggested steps:
85
+
86
+ -1. `make clean` <-- remove all unnecessary files
87
+ 0. `git status` <-- see the current state of things
88
+ 1. `git pull` <-- pull down any changes from elsewhere
89
+ 2. `git add` <-- add each new or modified file
90
+ 2a. `git add ./` <-- try this the first time
91
+ 3. `git commit -m "your message"` <-- make a snapshot
92
+ 4. `git push`
93
+
94
+## UNDERSTANDING THE TECHNOLOGY
95
+
96
+### The ultrasonic sensor (HC-SR04)
97
+
98
+The sensor has two "eyes": one is a speaker that emits a burst of
99
+ultrasound (too high-pitched for us to hear), and the other is a
100
+microphone listening for that burst to bounce back. It has four pins:
101
+
102
+ * **VCC** and **GND**: power (the sensor runs on 5 volts)
103
+ * **Trig** (trigger): an input to the sensor. A HIGH pulse here, at
104
+ least 10 microseconds long, tells the sensor to take a measurement.
105
+ * **Echo**: an output from the sensor. It goes HIGH when the burst is
106
+ sent, and goes LOW when the echo returns.
107
+
108
+The sensor in our kit is rated for distances of 2cm to 200cm.
109
+
110
+Note what the sensor does NOT do: it does not tell us a distance. It
111
+gives us a **time**: the length of time Echo stayed HIGH. Turning that
112
+time into a distance is our job (and our math). Sound travels at about
113
+343 meters per second, which is 0.0343 centimeters per microsecond. Since
114
+the time measured covers the trip to the object AND back, we only want
115
+half of it:
116
+
117
+```
118
+distance (cm) = time (us) * 0.0343 / 2 which is about time (us) / 58
119
+```
120
+
121
+Check your understanding: if Echo stays HIGH for 1160 microseconds, how
122
+far away is the object?
123
+
124
+Timing a pulse this short means our program sits in a tight loop, reading
125
+the Echo pin as fast as it can, noting the time when it changes. If Echo
126
+never changes (nothing in range, a wire fell out), a naive loop would
127
+wait forever, so the code you are given gives up after a while and
128
+reports that no echo was received. Your code needs to handle that case.
129
+
130
+Sensors are not perfect. Readings wobble. Soft surfaces (clothing, foam)
131
+absorb sound; angled surfaces bounce it off in the wrong direction. You
132
+will see this for yourself.
133
+
134
+### The passive buzzer
135
+
136
+Our kit contains TWO kinds of buzzer, and they look similar:
137
+
138
+ * an **active** buzzer contains its own oscillator. Apply power, and
139
+ it makes sound. Remove power, and it stops. Its pitch is built in:
140
+ we can only turn it ON or OFF.
141
+ * a **passive** buzzer is just a speaker element: it makes sound only
142
+ when we feed it a rapidly switching signal, and the pitch it makes
143
+ is whatever frequency we feed it.
144
+
145
+We need to be able to change the pitch, so **we want the passive
146
+buzzer**. To tell them apart:
147
+
148
+ * an active buzzer often has a label covering the hole where the
149
+ sound comes out (though not always)
150
+ * turn them over: the bottom of an active buzzer is sealed (it hides a
151
+ circuit and a crystal), while the bottom of a passive buzzer is open,
152
+ and you can see a circuit board, coils, and a magnet through the pin
153
+ holes
154
+
155
+If you use the wrong buzzer you will find out quickly: an active buzzer
156
+will make the same tone no matter what frequency we ask for, and a
157
+passive buzzer given steady power will just click.
158
+
159
+**Frequency** is how many times per second something repeats, measured in
160
+Hertz (Hz). For sound, frequency is pitch: the higher the frequency, the
161
+higher the note. The concert A that orchestras tune to (the A above
162
+middle C) is 440Hz. Doubling a frequency raises the note by an
163
+**octave**. Dividing an octave into twelve equal steps (the twelve
164
+semitones of the piano keyboard) means each step multiplies the frequency
165
+by the twelfth root of 2 (about 1.0595).
166
+
167
+The passive buzzer in our kit has a resonant frequency of 2000Hz, meaning
168
+it is loudest there. Notes far from 2000Hz will sound weaker.
169
+
170
+On the Raspberry Pi, the `wiringPi` library provides `softTone`
171
+functionality: `softToneCreate()` prepares a pin, and `softToneWrite()`
172
+sets the frequency (0 for silence) while a background thread does the
173
+rapid switching for us. On the pico, we use its PWM hardware to produce
174
+the switching, and the code provided has `tone_setup()` and `tone_play()`
175
+functions to do so (study them!).
176
+
177
+## TASK
178
+
179
+Taking our knowledge of GPIOs, LEDs, and now the ultrasonic distance
180
+sensor and the passive buzzer:
181
+
182
+ * wire up the ultrasonic distance sensor (two unique GPIO pins: one
183
+ for trigger, one for echo)
184
+ * wire up the passive buzzer to its own unique GPIO pin
185
+ * get the provided code working: it plays a test tone, then measures
186
+ the distance continuously, flagging when an object is within a
187
+ threshold distance. On the Raspberry Pi it reports the distance on
188
+ the screen. The pico has no screen, so it lights its onboard LED
189
+ whenever an object is within the threshold
190
+ * extend the code as described below
191
+
192
+![theremin circuit](images/cat0_circuit.jpg)
193
+
194
+### The circuit
195
+
196
+You will be building two small circuits (they are the same circuits found
197
+in the Freenove tutorial). Pin choices are defined at the top of your
198
+`cat0.c` file; if you wire to different pins, change the values there.
199
+
200
+**Ultrasonic sensor**
201
+
202
+| Sensor pin | Raspberry Pi | Pico |
203
+| ---------- | ------------------------------- | -------------------------- |
204
+| VCC | 5V (physical pin 2) | VBUS (physical pin 40) |
205
+| GND | GND (physical pin 6) | GND (physical pin 38) |
206
+| Trig | wiringPi 4 (GPIO23, pin 16) | GP2 (physical pin 4) |
207
+| Echo | wiringPi 5 (GPIO24, pin 18) | GP3 (physical pin 5) |
208
+
209
+**IMPORTANT: Echo must go through a voltage divider.** The sensor is
210
+powered by 5 volts, so its Echo output is a 5 volt signal. The GPIO pins
211
+on both the Raspberry Pi and the pico are 3.3 volt devices, and are NOT 5
212
+volt tolerant: connecting Echo directly can damage the pin (or the whole
213
+board). Three 1k ohm resistors fix this:
214
+
215
+```
216
+ Echo ----[ 1k ohm ]----+---- to GPIO (wiringPi 5 / GP3)
217
+ |
218
+ +----[ 1k ohm ]----[ 1k ohm ]---- GND
219
+```
220
+
221
+The resistors split the 5 volts in a 1:2 ratio, leaving 5 * 2/3, which is
222
+about 3.3 volts at the GPIO. Trig is fine connected directly: the GPIO is
223
+sending 3.3 volts to the sensor, which the sensor understands.
224
+
225
+**Passive buzzer**
226
+
227
+The buzzer draws more current than a GPIO pin should supply, so we have
228
+the GPIO control a transistor, which in turn switches the buzzer:
229
+
230
+| Connection | Goes to |
231
+| ------------------------------------------------- | ---------------------- |
232
+| GPIO (Pi: wiringPi 0 / pico: GP4, physical pin 6) | 1k ohm resistor |
233
+| other end of 1k ohm resistor | transistor base |
234
+| transistor emitter | GND |
235
+| transistor collector | buzzer negative (-) |
236
+| buzzer positive (+) | 5V |
237
+
238
+For the Raspberry Pi, wiringPi 0 is GPIO17 (physical pin 11), and 5V is
239
+physical pin 2 (or 4). For the pico, 5V is VBUS (physical pin 40). The
240
+GPIO only ever touches the 1k ohm resistor and the transistor base: the 5
241
+volts goes no further than the buzzer and the transistor's collector.
242
+
243
+The transistor in the kit is an NPN type (S8050). Make sure you have the
244
+correct leg for each of the emitter, base, and collector: with the flat
245
+side facing you and the legs pointing down, they are (left to right)
246
+**E**mitter, **B**ase, **C**ollector. If the buzzer never sounds, or
247
+sounds constantly, check the orientation and your connections!
248
+
249
+### The extensions
250
+
251
+The code you are given works, but it has some deliberate gaps, and what
252
+you fill in here you will need in the next project (where we turn this
253
+into an instrument). Read all of the provided code carefully, and make
254
+sure you understand every line: you may be asked to explain it.
255
+
256
+You are to:
257
+
258
+**1. Calibrate your sensor.** Use a ruler or tape measure to place an
259
+object (a book, a flat piece of cardboard) at known distances in front of
260
+the sensor, and compare what the sensor reports. Fill in the calibration
261
+table in the comments at the top of the source file with readings at 10,
262
+25, 50, 100, and 150cm, and notes on what you notice: how far off is it?
263
+Does the reading jump around? What happens closer than 2cm? What happens
264
+with a soft object (try your sleeve) or an angled one?
265
+
266
+(The pico has no screen, so the only thing it can tell you is whether the
267
+distance is within `THRESHOLD`, by lighting its LED. To find what it
268
+believes the distance to be, find the smallest `THRESHOLD` that lights
269
+the LED with your object at each ruler distance. The comments in the
270
+source file explain.)
271
+
272
+**2. Finish `play_note()`.** This function is given a frequency (in
273
+Hertz) and a duration (in milliseconds), and sounds that note for that
274
+duration. As provided, it starts the note, and waits... but never ends
275
+it: after the first note, the buzzer just keeps sounding. A note should
276
+be followed by silence (for `NOTEGAP` milliseconds), so that notes played
277
+back to back are distinct from each other, and so that the buzzer is
278
+quiet when we are done. Study the function, and complete it.
279
+
280
+**3. Play a scale.** Create an **array** holding the frequencies of the C
281
+major scale, from the C just below the A of 440Hz up to the C an octave
282
+above it (eight notes), and use a loop and your `play_note()` to play
283
+each note in turn at startup, in place of the single test note. Do not
284
+write eight separate `play_note()` calls!
285
+
286
+Some guidance:
287
+
288
+ * the notes of a major scale are spaced (in semitones) whole step,
289
+ whole step, half step, whole step, whole step, whole step, half step.
290
+ A whole step is two semitones, a half step is one
291
+ * you may hard-code the frequencies in your array, or calculate them
292
+ (from 440Hz and the semitone relationship above, with the `pow()`
293
+ function from `math.h`). If you hard-code them, cite where you
294
+ found them. Either way, they should sound like a scale!
295
+
296
+**4. Finish `sample_distance()`.** A single reading can be noisy, or fail
297
+altogether, so this function takes several (`SAMPLES` of them), stores
298
+the good ones in an **array**, and returns the **median** of them: the
299
+middle value, after sorting them from smallest to largest. As provided,
300
+it does nearly everything: it takes the readings, keeps only the
301
+successful ones, reports no reading if every one of them failed, and
302
+returns the middle value of the array. But the values are never sorted,
303
+so what it returns is simply the third reading, not the median!
304
+
305
+The loops that perform a "bubble sort" are provided; what is missing is
306
+what goes inside them: the comparison and the swap. Complete it. Then:
307
+
308
+ * if you end up with an even number of good readings, there are two
309
+ middle values. The provided function returns the upper one. Decide
310
+ if that is what you want (or if you would rather average the two)
311
+ and document your decision in a comment
312
+ * test it: move an object in and out of range, wave your hand across
313
+ the sensor, and observe how steadily it behaves compared to a single
314
+ reading (on the Pi, watch the reported distance; on the pico, watch
315
+ the LED when your object sits right around `THRESHOLD`)
316
+
317
+As you do this, consider the trade-off the constants in this function
318
+represent. What does taking more samples do for the smoothness of your
319
+readings? What does it do for how quickly your program notices that
320
+something has moved? Experiment with `SAMPLES` and `SAMPLEGAP`. We will
321
+care about this a great deal in the next project.
322
+
323
+## EXECUTION
324
+
325
+If on the pico, follow the process for downloading the binary file and
326
+programming your pico. The pico has no screen: its onboard LED is how
327
+it tells you what the sensor sees (lit means something is within
328
+`THRESHOLD`), and the buzzer is how you know it is alive.
329
+
330
+If on the full Raspberry Pi, you have a green executable you can run just
331
+as we've done in our other projects.
332
+
333
+## STRATEGY
334
+
335
+The general flow of the process (one way of going about it, anyway) can
336
+be described as follows:
337
+
338
+```
339
+INITIALIZE THE GPIOS AND THE BUZZER
340
+FOR EACH NOTE IN THE SCALE ARRAY:
341
+ PLAY THE NOTE FOR A MOMENT
342
+
343
+REPEAT INFINITELY:
344
+ OBTAIN THE MEDIAN DISTANCE
345
+ REPORT THE DISTANCE (ON THE PI), OR THAT THERE WAS NO READING
346
+ SHOULD AN OBJECT BE WITHIN THE THRESHOLD:
347
+ FLAG IT (LIGHT THE LED ON THE PICO)
348
+ DELAY BRIEFLY
349
+
350
+REPEAT BLOCK
351
+```
352
+
353
+And for the median function (the parts provided, and the parts you
354
+finish):
355
+
356
+```
357
+GIVEN NOTHING (THE SENSOR IS ALREADY SET UP):
358
+ REPEAT FOR EACH OF THE SAMPLES TO BE TAKEN:
359
+ MEASURE THE DISTANCE
360
+ SHOULD THE MEASUREMENT HAVE SUCCEEDED:
361
+ STORE IT IN THE NEXT FREE SPOT IN THE ARRAY
362
+ PAUSE FOR THE SENSOR TO SETTLE
363
+
364
+ SHOULD NO MEASUREMENTS HAVE SUCCEEDED:
365
+ RETURN NO READING
366
+
367
+ SORT THE VALUES THAT WERE STORED
368
+ RETURN THE MIDDLE ONE
369
+```
370
+
371
+## SUBMISSION
372
+
373
+To be successful in this project, the following criteria (or their
374
+equivalent) must be met:
375
+
376
+ * Project must be submit on time, by the deadline.
377
+ * Late submissions will lose 33% credit per day, with the submission
378
+ window closing on the 3rd day following the deadline.
379
+ * All code must compile cleanly (no warnings or errors)
380
+ * Compile with the `-Wall` and `--std=gnu18` compiler flags
381
+ * All requested functionality must conform to stated requirements
382
+ (either in this document or in a comment banner in the source code
383
+ files themselves).
384
+ * Executed programs must display in a manner similar to provided output
385
+ * Output formatted, where applicable, must match that of project
386
+ requirements
387
+ * Processing must be correct based on input given and output requested
388
+ * Output, if applicable, must be correct based on values input
389
+ * Code must be nicely and consistently indented
390
+ * Code must be consistently written, to strive for readability from
391
+ having a consistent style throughout
392
+ * Code must be commented
393
+ * Any "to be implemented" comments **MUST** be removed
394
+ * These "to be implemented" comments, if still present at
395
+ evaluation time, will result in points being deducted.
396
+ * Sufficient comments explaining the point of provided logic **MUST**
397
+ be present
398
+ * No global variables (without instructor approval), no goto
399
+ statements, no calling of main()!
400
+ * Track/version the source code in your lab46 semester repository
401
+ * Submit a copy of your source code to me using the `submit` tool
402
+ (`make submit` on lab46 will do this) by the deadline.
403
+
404
+### Submit Tool Usage
405
+
406
+Let's say you have completed work on the project, and are ready to
407
+submit, you would do the following:
408
+
409
+```
410
+lab46:~/SEMESTER/c4eng/cat0$ make submit
411
+```
412
+
413
+You should get some sort of confirmation indicating successful submission
414
+if all went according to plan. If not, check for typos and or locational
415
+mismatches.
416
+
417
+What I'll be looking for:
418
+
419
+### RUBRIC
420
+
421
+I'll be evaluating the project based on the following criteria:
422
+
423
+```
424
+286:cat0:final tally of results (286/286)
425
+*:cat0:used grabit to obtain project by the Sunday prior to duedate [13/13]
426
+*:cat0:post a short video to the class DISCORD [26/26]
427
+*:cat0:ultrasonic sensor trigger and echo hooked to unique GPIOs [26/26]
428
+*:cat0:passive buzzer hooked to its own unique GPIO [13/13]
429
+*:cat0:distance correctly measured and reported (pico: via LED) [26/26]
430
+*:cat0:calibration table completed, with observations [39/39]
431
+*:cat0:no echo, out of range is handled (no hang, no bogus values) [13/13]
432
+*:cat0:play_note() completed: each note ends, followed by short silence [26/26]
433
+*:cat0:C major scale played from an array of frequencies using a loop [52/52]
434
+*:cat0:sample_distance() completed: values sorted, true median returned [39/39]
435
+*:cat0:code tracked in lab46 semester repo [13/13]
436
+```
437
+
438
+### Additionally
439
+
440
+ * Solutions not abiding by spirit of project will be subject to a 50% overall deduction
441
+ * Solutions not utilizing descriptive why and how comments will be subject to a 25% overall deduction
442
+ * Solutions not utilizing indentation to promote scope and clarity or otherwise maintaining consistency in code style and presentation will be subject to a 25% overall deduction
443
+ * Solutions not organized and easy to read (assume a terminal at least 90 characters wide, 40 characters tall) are subject to a 25% overall deduction
haas/fall2026/c4eng/projects/cat1.md
... ...
@@ -0,0 +1,356 @@
1
+# ENGR1050 C for Engineers
2
+
3
+# PROJECT: Create A Theremin (CAT1)
4
+
5
+## OBJECTIVE
6
+
7
+Make music (or at least noise) by waving your hand around! We bring
8
+together the ultrasonic distance sensor and passive buzzer we explored in
9
+cat0, and have our program turn distance into pitch.
10
+
11
+## PROCESS
12
+
13
+Do note, the productive way to go about this project involves taking the
14
+following steps:
15
+
16
+ * starting early
17
+ * reading the project page
18
+ * asking questions regarding things you do not know, are not clear on,
19
+ or are confused about
20
+ * as information, concepts, processes become clear, that is something
21
+ you can contribute to the project documentation (so you can better
22
+ remember)
23
+
24
+If you start too late, and do not ask questions, and do not have enough
25
+time and don't know what is going on, you are not doing the project
26
+correctly.
27
+
28
+## OBTAIN THE PROJECT FILES
29
+
30
+To assist with consistency across all implementations, data files for use
31
+with this project are available on lab46 as a `grabit`. Please copy the
32
+data to your private semester repository under an appropriate project
33
+directory to begin work, and ensure your implementation properly works
34
+with the provided data.
35
+
36
+The project should be obtained by the **Sunday prior to the due date**.
37
+
38
+```
39
+lab46:~/SEMESTER/c4eng$ grabit c4eng cat1
40
+```
41
+
42
+Please study any provided code and supporting documents, and look up,
43
+experiment, and ask questions on aspects that you do not understand.
44
+
45
+## OPERATING THE PROJECT
46
+
47
+These projects will have two paths to them, depending on which device you
48
+are using:
49
+
50
+ * Raspberry Pi single board computer (4/5) using the `wiringPi` library
51
+ * Raspberry Pi Pico microcontroller
52
+
53
+```
54
+lab46:~/SEMESTER/c4eng/cat1$ make
55
+Please select which development environment:
56
+
57
+ make wiringpi - using the Raspberry Pi with wiringpi library
58
+ make pico - using the Raspberry Pi pico
59
+
60
+after which, you can use 'make' to build
61
+lab46:~/SEMESTER/c4eng/cat1$
62
+```
63
+
64
+Run the `make` command with the category representing the path you will
65
+be working with for this project.
66
+
67
+After which, if you do an `ls`, you will see a cyan-colored file called
68
+`cat1.c`. This is the C file you will be editing for this project.
69
+
70
+Go ahead and view it, study the code, eventually make any changes, save
71
+and return to the command-line.
72
+
73
+To build it, you simply run: `make`
74
+
75
+If there are no errors, it will build, and you proceed from there.
76
+
77
+## MAINTAINING YOUR REPOSITORY
78
+
79
+Be sure to keep your repository up-to-date, regularly committing changes
80
+to files.
81
+
82
+As a reminder, here are the suggested steps:
83
+
84
+ -1. `make clean` <-- remove all unnecessary files
85
+ 0. `git status` <-- see the current state of things
86
+ 1. `git pull` <-- pull down any changes from elsewhere
87
+ 2. `git add` <-- add each new or modified file
88
+ 2a. `git add ./` <-- try this the first time
89
+ 3. `git commit -m "your message"` <-- make a snapshot
90
+ 4. `git push`
91
+
92
+## UNDERSTANDING THE TECHNOLOGY
93
+
94
+A **theremin** is an unusual musical instrument: you play it without
95
+touching it. The performer moves their hands near (but not touching) a
96
+pair of antennas, and the distance of the hand from an antenna controls
97
+the pitch (one hand) and volume (the other). We're going to build a
98
+simplified cousin of this with the parts in our kit: one "antenna" (the
99
+ultrasonic sensor), controlling pitch.
100
+
101
+You already know how the pieces work from cat0:
102
+
103
+ * the sensor gives us a time, which we convert to a distance
104
+ * the passive buzzer makes whatever frequency we tell it to
105
+
106
+What is new is the connection between them. We need a **mapping**: a rule
107
+that takes a distance and produces a frequency. Mappings are everywhere
108
+in engineering (a thermostat maps a temperature to a heater setting; a
109
+throttle pedal maps a position to an engine speed). Designing one
110
+involves choices, and no single choice is "right":
111
+
112
+ * which direction? Does bringing your hand closer raise the pitch, or
113
+ lower it?
114
+ * over what range? Sensor readings span 2 to 200cm, but your arm
115
+ doesn't. Pick the nearest and farthest distances that matter
116
+ * to what frequencies? The buzzer will be easiest to hear near its
117
+ 2000Hz resonance, but a theremin is no fun with only a narrow range
118
+ * with what shape? Does moving your hand 10cm change the pitch by the
119
+ same amount no matter where you are in the range?
120
+
121
+On that last point: our ears do not perceive pitch linearly. Going from
122
+200Hz to 400Hz sounds like the same musical interval (an octave) as going
123
+from 1000Hz to 2000Hz, even though the first difference is 200Hz and the
124
+second is 1000Hz. A mapping in which equal movements of your hand produce
125
+equal *ratios* of frequency will therefore sound more natural than one
126
+producing equal *differences*. Try both!
127
+
128
+## TASK
129
+
130
+Taking our knowledge of GPIOs, the ultrasonic sensor, and the passive
131
+buzzer:
132
+
133
+ * assemble the circuit from cat0 (if it is still standing, you are
134
+ done with this step)
135
+ * rework the provided code so that the pitch of the buzzer follows the
136
+ distance of your hand from the sensor, as described below
137
+ * play it! Post a video of you performing to the class DISCORD
138
+
139
+![theremin circuit](images/cat0_circuit.jpg)
140
+
141
+### The circuit
142
+
143
+It's the same as in cat0. For quick reference (pin choices are defined at
144
+the top of your `cat1.c` file; if you wire to different pins, change the
145
+values there):
146
+
147
+| Connection | Raspberry Pi | Pico |
148
+| ---------------------------- | --------------------------- | -------------------------- |
149
+| Sensor VCC | 5V (physical pin 2) | VBUS (physical pin 40) |
150
+| Sensor GND | GND (physical pin 6) | GND (physical pin 38) |
151
+| Sensor Trig | wiringPi 4 (GPIO23, pin 16) | GP2 (physical pin 4) |
152
+| Sensor Echo (via divider) | wiringPi 5 (GPIO24, pin 18) | GP3 (physical pin 5) |
153
+| Buzzer (via 1k and S8050) | wiringPi 0 (GPIO17, pin 11) | GP4 (physical pin 6) |
154
+
155
+The sensor's Echo MUST go through the voltage divider (1k ohm to the
156
+GPIO, then two 1k ohm resistors in series to ground), as the Echo output
157
+is 5 volts and our GPIOs are not 5 volt tolerant. The buzzer's positive
158
+leg connects to 5V, its negative leg to the transistor's collector, the
159
+transistor's emitter to ground, and the GPIO connects to the transistor's
160
+base through a 1k ohm resistor. See cat0 for the details.
161
+
162
+### The theremin
163
+
164
+The code you are given has ONE threshold: if something is closer than
165
+`THRESHOLD`, a single steady tone sounds (and on the pico, the onboard
166
+LED lights), otherwise it is silent. It's a doorbell, not an instrument.
167
+
168
+Your task is to make the pitch a continuous function of distance:
169
+
170
+ * if no echo was received, or the object is farther than the farthest
171
+ distance you chose: silence
172
+ * otherwise, calculate a frequency from the distance and sound it,
173
+ such that the pitch follows your hand smoothly as it moves
174
+ * at or closer than the nearest distance you chose, the pitch stays at
175
+ its extreme (it does not keep climbing or falling, nor wrap around
176
+ or go negative)
177
+ * the frequency you produce must always remain within the lowest and
178
+ highest frequencies you chose
179
+ * on the pico, the onboard LED lights while the instrument is sounding.
180
+ On the Raspberry Pi, display the distance and frequency being played
181
+ * on the Raspberry Pi, the distance must still be reported (the pico,
182
+ having no screen, is judged by its pitch and its LED)
183
+
184
+Some guidance:
185
+
186
+ * a function that is given a distance and returns a frequency,
187
+ `distance_to_frequency()`, is provided in your source file, along
188
+ with starting values for the range (`NEARDIST`, `FARDIST`, `LOWFREQ`,
189
+ `HIGHFREQ`). It works, but is not yet the instrument you want: as
190
+ given, farther is *higher*, and the sweep is linear. Read its
191
+ comments, make the changes they ask for, and **hook it up in
192
+ `main()`** (it is not called as given). Test it by itself (does the
193
+ nearest distance give your lowest or highest frequency, as intended?
194
+ What about halfway between?)
195
+
196
+ * a convenient way to think about the mapping is to first find how far
197
+ along your range of distances the hand is, as a **fraction** from 0
198
+ (at the nearest distance) to 1 (at the farthest):
199
+
200
+ ```
201
+ fraction = (distance - nearest) / (farthest - nearest)
202
+ ```
203
+
204
+ then use that fraction to find your way between your frequencies.
205
+ Be mindful of integer versus floating point division!
206
+ * to move linearly between two values, you scale the difference by the
207
+ fraction, and add it to where you started. To move by equal
208
+ *ratios*, you instead scale the *ratio* of the endpoints... which
209
+ involves raising it to the power of the fraction (see `pow()` in
210
+ `math.h`)
211
+ * carry over what you did in cat0: copy your finished `sample_distance()`
212
+ (and the constants it needs) into `cat1.c`, and use it to keep the
213
+ pitch from jittering. But consider the trade-off you
214
+ were asked about there: if your instrument takes a third of a second
215
+ to notice your hand has moved, it will feel sluggish. How many
216
+ samples (and how long a pause between them) make for a pleasant
217
+ instrument? Choose your values deliberately, and explain your choice
218
+ in a comment
219
+ * you will find that your instrument is much more pleasant to play if
220
+ you pick your constants (nearest and farthest distance, lowest and
221
+ highest frequency, number of samples, delays) with some thought, and
222
+ give each a descriptive `#define` name. Plan to try several settings
223
+ * on the Raspberry Pi, the buzzer's tones are generated by a background
224
+ thread that shares the processor with the rest of your program. If
225
+ you notice odd behavior in your readings while the buzzer is sounding,
226
+ that may be why. Make note of it in your comments if you do
227
+ * the sensor is most reliable when aimed squarely at a flat surface.
228
+ Your hand will do, but your sleeve may not!
229
+
230
+For those wishing to go further (not required, and no extra credit, but
231
+cool): instead of letting the pitch slide freely, snap it to the nearest
232
+note of a musical scale (use the array of frequencies from cat0), and
233
+your hand will be able to play recognizable tunes. How wide a band of
234
+distance should each note get?
235
+
236
+## EXECUTION
237
+
238
+If on the pico, follow the process for downloading the binary file and
239
+programming your pico. The pico has no screen: the onboard LED lights
240
+while your instrument is sounding, and what you hear is your feedback.
241
+
242
+If on the full Raspberry Pi, you have a green executable you can run just
243
+as we've done in our other projects.
244
+
245
+## STRATEGY
246
+
247
+The general flow of the process (one way of going about it, anyway) can
248
+be described as follows:
249
+
250
+```
251
+INITIALIZE THE GPIOS AND THE BUZZER
252
+REPEAT INFINITELY:
253
+ OBTAIN THE MEDIAN DISTANCE
254
+
255
+ SHOULD THERE BE NO READING, OR THE OBJECT BE BEYOND THE FARTHEST:
256
+ SILENCE THE BUZZER
257
+ TURN OFF THE LED (IF ON THE PICO)
258
+ REPORT THAT NOTHING IS THERE (ON THE PI)
259
+ OTHERWISE:
260
+ DETERMINE THE FREQUENCY FOR THE DISTANCE
261
+ SOUND THE BUZZER AT THAT FREQUENCY
262
+ TURN ON THE LED (IF ON THE PICO)
263
+ REPORT THE DISTANCE AND FREQUENCY (ON THE PI)
264
+
265
+ DELAY BRIEFLY
266
+
267
+REPEAT BLOCK
268
+```
269
+
270
+And for your frequency function, a linear approach:
271
+
272
+```
273
+GIVEN A DISTANCE:
274
+ SHOULD THE DISTANCE BE AT OR BELOW THE NEAREST:
275
+ TREAT IT AS THE NEAREST
276
+ SHOULD THE DISTANCE BE ABOVE THE FARTHEST:
277
+ TREAT IT AS THE FARTHEST
278
+ FIND HOW FAR ALONG THE RANGE THE DISTANCE IS, AS A FRACTION OF 0 TO 1
279
+ MOVE THAT FRACTION OF THE WAY FROM ONE END OF THE FREQUENCY RANGE TO
280
+ THE OTHER
281
+ RETURN THE RESULTING FREQUENCY
282
+```
283
+
284
+## SUBMISSION
285
+
286
+To be successful in this project, the following criteria (or their
287
+equivalent) must be met:
288
+
289
+ * Project must be submit on time, by the deadline.
290
+ * Late submissions will lose 33% credit per day, with the submission
291
+ window closing on the 3rd day following the deadline.
292
+ * All code must compile cleanly (no warnings or errors)
293
+ * Compile with the `-Wall` and `--std=gnu18` compiler flags
294
+ * All requested functionality must conform to stated requirements
295
+ (either in this document or in a comment banner in the source code
296
+ files themselves).
297
+ * Executed programs must display in a manner similar to provided output
298
+ * Output formatted, where applicable, must match that of project
299
+ requirements
300
+ * Processing must be correct based on input given and output requested
301
+ * Output, if applicable, must be correct based on values input
302
+ * Code must be nicely and consistently indented
303
+ * Code must be consistently written, to strive for readability from
304
+ having a consistent style throughout
305
+ * Code must be commented
306
+ * Any "to be implemented" comments **MUST** be removed
307
+ * These "to be implemented" comments, if still present at
308
+ evaluation time, will result in points being deducted.
309
+ * Sufficient comments explaining the point of provided logic **MUST**
310
+ be present
311
+ * No global variables (without instructor approval), no goto
312
+ statements, no calling of main()!
313
+ * Track/version the source code in your lab46 semester repository
314
+ * Submit a copy of your source code to me using the `submit` tool
315
+ (`make submit` on lab46 will do this) by the deadline.
316
+
317
+### Submit Tool Usage
318
+
319
+Let's say you have completed work on the project, and are ready to
320
+submit, you would do the following:
321
+
322
+```
323
+lab46:~/SEMESTER/c4eng/cat1$ make submit
324
+```
325
+
326
+You should get some sort of confirmation indicating successful submission
327
+if all went according to plan. If not, check for typos and or locational
328
+mismatches.
329
+
330
+What I'll be looking for:
331
+
332
+### RUBRIC
333
+
334
+I'll be evaluating the project based on the following criteria:
335
+
336
+```
337
+312:cat1:final tally of results (312/312)
338
+*:cat1:used grabit to obtain project by the Sunday prior to duedate [13/13]
339
+*:cat1:post a short video of your theremin to the class DISCORD [13/13]
340
+*:cat1:sensor and buzzer hooked to unique GPIOs [26/26]
341
+*:cat1:distance correctly measured and reported [26/26]
342
+*:cat1:no echo, out of range silences the buzzer (no hang) [26/26]
343
+*:cat1:distance-to-frequency function completed and tuned [52/52]
344
+*:cat1:pitch changes continuously as the distance changes [78/78]
345
+*:cat1:frequency kept within chosen bounds [26/26]
346
+*:cat1:readings smoothed with median of samples (from cat0) [26/26]
347
+*:cat1:LED (pico), frequency display (Pi) indicates instrument sounding [13/13]
348
+*:cat1:code tracked in lab46 semester repo [13/13]
349
+```
350
+
351
+### Additionally
352
+
353
+ * Solutions not abiding by spirit of project will be subject to a 50% overall deduction
354
+ * Solutions not utilizing descriptive why and how comments will be subject to a 25% overall deduction
355
+ * Solutions not utilizing indentation to promote scope and clarity or otherwise maintaining consistency in code style and presentation will be subject to a 25% overall deduction
356
+ * Solutions not organized and easy to read (assume a terminal at least 90 characters wide, 40 characters tall) are subject to a 25% overall deduction