Id2 12
Id2 12
Week 12
input/output devices
project suggestions
using shields: the LoLShield
outputs D0
D1
2
shield: game controller
3
shield: wi-fi
long range
• ≈ 100 m indoors
4
shields: backplanes
5
devices: sensors
6
devices: sensors
touch button
sound light
temperature distance
7
devices: actuators
servo motor
8
devices: displays
9
shields: displays
10
shields: displays
• 14 × 9 array of LEDs
• uses 12 digital pins (D2 to D13)
• each LED individually addressable
– ‘Charlieplexing’ connects many LEDs to a few pins
(see Wikipedia entry for fascinating details)
• library hides complexity of addressing
– LedSign::Set(), LedSign::Clear(), etc.
– double-buffering for smooth scrolling
11
complete project suggestions: easy
A0
4M7
GND
display results on
• serial plotter [see week 2], or a
• self-calibrating [week 4] bar-graph display [week 7]
12
complete project suggestions: easy
push-button toggle
a toggle switch alternates between ‘on’ and ‘off’ switch switch
push on on
• to make it go on and then off, you have to press it twice release off on
push on off
13
complete project suggestions: easy
void setup(void) {
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, OUTPUT);
}
int state = 0; // light off
void loop(void) {
if (0 == digitalRead(2)) { // pressed
state = 1 - state; // toggle
digitalWrite(4, state);
while (0 == digitalRead(2))
delay(50);
}
}
4. electronic dice
use a 7-segment LED [week 8] to display a random value from 1 to 6
push button to ‘roll’ the dice
• don’t forget to de-bounce the button!
for extra realism:
• display a rapid sequence of random numbers until the dice stops ‘rolling’
while (buttonPressed) {
for (int i = 0; i < 10; i += 1) {
int digit = random(1, 7); // random number between 1 and 6
displayDigit(digit);
delay(100);
}
}
for extra satisfaction (medium difficulty): add a second button and second display
• you now have two electronic dice!
15
complete project suggestions: easy
16
complete project suggestions: easy
b0 b1 bN-2 bN-1
2R 2R 2R 2R
R R R VOUT
2R
GND
17
complete project suggestions: easy
18
complete project suggestions: medium
19
complete project suggestions: medium
20
complete project suggestions: medium
21
complete project suggestions: advanced
5V VDD
SCK 3
D13 SCK
MISO
D12
microcontroller
MCP4822
MOSI 4 8
D11 SDI VOUTA
analogue
D10
SSN1
VOUTB
6 outputs
SSN2 2
D9 CS
5
D8 LDAC
GND VSS
7
(the lab reference material from week 11 shows how to communicate with the DAC)
22
complete project suggestions: advanced
download sine.h from the ID2 Team, General channel, Files/Libraries section
• it contains a table of 4096 integers describing a sine wave
• it also defines a function for you: sine(N) = 2048 + 2047 sin(2πN ÷ 4096)
use a TimerOne interrupt [week 9] and sine() to output a sample every 50 µs
#include "sine.h" // download from the web site
const long rate = 20000; // number of output samples per second
void setup(void) {
Timer1.initialize(1000000L / rate); // microseconds between samples
Timer1.attachInterrupt(timer); // sample generator function
}
volatile unsigned int angle = 0, omega = 1000 * 4096L / rate;
void timer(void) {
setDAC(sine(angle)); // sine() is defined in "sine.h"
angle += omega;
}
use the same sine wave table and sine() function to generate three sine waves
• use three pairs of ‘phase’ and ‘omega’ variables to scan the table
simultaneously
• add the three sample values together, divide the result by 3, send to DAC
• for major chords, use: f0 , f1 = 45 f0 , f2 = 32 f0
• for minor chords, use: f0 , f1 = 56 f0 , f2 = 32 f0
• use a push button to swap between major/minor
• use another push button to change f0 so that you can play several chords
– e.g., it might cycle f0 between 1000 Hz, 1333 Hz, and 1500 Hz
– then f1 and f2 are recalculated based on f0
– you should now be able to ‘play the blues’ on your microcontroller
24
complete project suggestions: advanced
use an analogue input (or SPI ADC) to show the result on the serial plotter
25
complete project suggestions: advanced
10 nF
150
5V
1M
1M
pulse detector
microcontroller
place next
to each other
- 560 nF
MCP6002 +
+ MCP6002 A0
1M
10k
GND
1k
+
10 uF
26
complete project suggestions: advanced
challenge: add two 7-segment displays showing pulse rate in beats per minute
27
complete project suggestions: difficult
transmitter
previous 1 x7 x6 x5 x4 x3 x2 x1 x0 1
digital time
output
330 GND
receiver IR photodiode
1 x7 x6 x5 x4 x3 x2 x1 x0 1
analogue
input
4M7 5V read data bits
verify start bit verify stop bit
Note: the photodiode must be synchronise on start of frame (wait for rising edge)
connected ‘backwards’ to work!
challenges
• any of the challenges that you have not already completed
29
your project
ask the instructors about anything you are having difficulty with
• time is short, and help is always available
• do not become blocked because you cannot understand something
• use e-mail to ask for help or advice: [email protected]
(or one of the channels in our MS Teams team)
30
next weeks
week 15:
• project presentations: hard limit 5 (five) minutes per team
• send me slides (PDF) demo movies (avi, mov, mp4) before Week 15 class
• all team members must speak during the presentation
– what is the project (especially if you invented it)?
– why did you choose that project?
– video demonstration (optional but recommended)
– what was difficult?
– what did you learn?
31
exercises
look at (do not take, yet) some of the devices I have brought with me today
practice with a complex device: Lots of LEDs, ‘LoL Shield’
32
LoL Shield API
#include "Charliplexing.h"
LedSign::Init(uint8_t mode = 0)
initializes the library. The mode argument can be used to enable support for
double-buffering (DOUBLE_BUFFER) and/or greyscale (GRAYSCALE).
LedSign::SetBrightness(uint8_t brightness)
sets the overall brightness of the screen, between 0 and 127.
LedSign::Set(uint8_t x, uint8_t y, uint8_t c = 1)
turns on the LED at coordinates (x, y). To turn it on full brightness, the value 7 should be
passed as the third argument c.
LedSign::Clear(uint8_t c = 0)
sets the brightness of all the LEDs to c. (The default value 0 turns them all off.)
LedSign::Flip(bool blocking = false)
swaps the front and back buffers, if double-buffering is enabled.
LedSign::Horizontal(uint8_t y, uint8_t c = 0)
fills an entire row with the specified value (0 for off, 7 for full on).
LedSign::Vertical(uint8_t x, uint8_t c = 0)
fills an entire column with the specified value (0 for off, 7 for full on).
33