Skip to content

Commit 01ccb53

Browse files
zelenskiCS107E BOT
authored andcommitted
release sensor input lecture
commit 4bb0e454363a70200d673f290dc349cf8c77eb39 Author: Julie Zelenski <[email protected]> Date: Mon Nov 18 00:18:49 2024 -0800 release sensor input lecture
1 parent c460052 commit 01ccb53

35 files changed

+778
-1
lines changed

_data/unreleased.csv

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ permalink,title,released
66
"/lectures/Guest/","Guest",false
77
"/lectures/InfoSession/","Course Info Session",false
88
"/lectures/OOP/","Object-oriented programming",false
9-
"/lectures/Sensors/","Sensors",false
109
"/lectures/Sensors2/","Sensors output",false
1110
"/lectures/Wrap/","Wrap or There and Back Again",false

lectures/Sensors/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
released: true
3+
permalink: /lectures/Sensors/
4+
title: Sensor Input
5+
readings: |
6+
+ Wikipedia entry [analog-to-digital conversion](https://en.wikipedia.org/wiki/Analog-to-digital_converter)
7+
+ Readings for [i2c](/readings/i2c.pdf) and [spi](/readings/spi.pdf) protocols, sample driver code in `$CS107E`
8+
+ An excellent reference book for exploring sensors is "Make: Encyclopedia of Electronic Components Volume 3: Sensors" by Charles Platt and Fredrik Jansson. You can access the online version via Stanford Libraries Safari Books portal <https://searchworks.stanford.edu/view/13211489>.
9+
---
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
NAME = accel_demo
2+
3+
EXTRAS = $(CS107E)/extras/d1_peripherals
4+
5+
ARCH = -march=rv64im -mabi=lp64
6+
ASFLAGS = $(ARCH)
7+
CFLAGS = $(ARCH) -g -Og -I$$CS107E/include -I$(EXTRAS) -Wall -ffreestanding
8+
LDFLAGS = -nostdlib -L$$CS107E/lib -T memmap.ld
9+
LDLIBS = -lmango -lmango_gcc
10+
11+
# vpath to find source files for d1 peripheral modules in extras
12+
# if no such file in build directory
13+
vpath %.c $(EXTRAS)
14+
15+
all : $(NAME).bin
16+
17+
%.bin: %.elf
18+
riscv64-unknown-elf-objcopy $< -O binary $@
19+
20+
%.elf: %.o i2c.o
21+
riscv64-unknown-elf-gcc $(LDFLAGS) $^ $(LDLIBS) -o $@
22+
23+
%.o: %.c
24+
riscv64-unknown-elf-gcc $(CFLAGS) -c $< -o $@
25+
26+
%.o: %.s
27+
riscv64-unknown-elf-as $(ASFLAGS) $< -o $@
28+
29+
run: $(NAME).bin
30+
mango-run $<
31+
32+
clean:
33+
rm -f *.o *.bin *.elf *.list *~
34+
35+
.PHONY: all clean run
36+
.PRECIOUS: %.elf %.o
37+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Gy-521 3-axis accelerometer+gyroscope i2c sensor
2+
3+
https://componentslibrary.com/gy-521-datasheet.html
4+
https://protosupplies.com/product/mpu-6050-gy-521-3-axis-accel-gryo-sensor-module/
5+
6+
Uses i2c driver
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Gy-521 3-axis accelerometer+gyroscope i2c sensor
3+
* Sample code below shows raw accel readings, no calibration/correction
4+
*
5+
* https://componentslibrary.com/gy-521-datasheet.html
6+
* https://protosupplies.com/product/mpu-6050-gy-521-3-axis-accel-gryo-sensor-module/
7+
*/
8+
#include "assert.h"
9+
#include "i2c.h"
10+
#include "printf.h"
11+
#include "timer.h"
12+
#include "uart.h"
13+
14+
typedef struct {
15+
short x, y, z; // expressed in mg
16+
} axes_t;
17+
18+
enum gy521_register {
19+
GY_WHO_AM_I = 0x75,
20+
CONFIG_ACCEL = 0x1C,
21+
READINGS_ACCEL = 0x3B,
22+
PWR_MGMT_1 = 0x6B,
23+
};
24+
25+
static i2c_device_t *gy521_init(void) {
26+
uint8_t addr = 0x68; // confirm device addr with datasheet, components can differ!
27+
i2c_device_t *dev = i2c_new(addr);
28+
const uint8_t EXPECTED = addr; // expect device addr
29+
assert(i2c_read_reg(dev, GY_WHO_AM_I) == EXPECTED);
30+
i2c_write_reg(dev, PWR_MGMT_1, 0); // wake from sleep
31+
i2c_write_reg(dev, CONFIG_ACCEL, 0); // config accel for range -+2g, scale factor 16384
32+
return dev;
33+
}
34+
35+
short extract_reading(uint8_t *bytes) {
36+
short scale_factor = 16384; // 16384 is 1g (1g == 1000mg)
37+
short reading = ((int8_t)bytes[0] << 8) + bytes[1];
38+
return (1000 * reading)/scale_factor;
39+
}
40+
41+
void gy521_read(i2c_device_t *dev, axes_t *p) {
42+
uint8_t bytes[6]; // accel readings: x/y/z 2-byte big-endian
43+
i2c_read_reg_n(dev, READINGS_ACCEL, bytes, sizeof(bytes));
44+
p->x = extract_reading(&bytes[0]);
45+
p->y = extract_reading(&bytes[2]);
46+
p->z = extract_reading(&bytes[4]);
47+
}
48+
49+
void main(void) {
50+
uart_init();
51+
i2c_init();
52+
i2c_device_t *gy = gy521_init();
53+
while (1) {
54+
axes_t a;
55+
gy521_read(gy, &a);
56+
printf("Reading x= %5dmg, y= %5dmg, z= %5dmg)\n", a.x, a.y, a.z);
57+
timer_delay(1);
58+
}
59+
}
1.2 MB
Binary file not shown.
1.1 MB
Binary file not shown.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
NAME = adc_demo
2+
EXTRAS = $(CS107E)/extras/d1_peripherals
3+
4+
ARCH = -march=rv64im -mabi=lp64
5+
ASFLAGS = $(ARCH)
6+
CFLAGS = $(ARCH) -g -Og -I$$CS107E/include -I$(EXTRAS) -Wall -ffreestanding
7+
LDFLAGS = -nostdlib -L$$CS107E/lib -T memmap.ld
8+
LDLIBS = -lmango -lmango_gcc
9+
10+
# vpath to find source files for d1 peripheral modules in extras
11+
# if no such file in build directory
12+
vpath %.c $(EXTRAS)
13+
14+
all : $(NAME).bin
15+
16+
%.bin: %.elf
17+
riscv64-unknown-elf-objcopy $< -O binary $@
18+
19+
%.elf: %.o spi.o mcp3008.o
20+
riscv64-unknown-elf-gcc $(LDFLAGS) $^ $(LDLIBS) -o $@
21+
22+
%.o: %.c
23+
riscv64-unknown-elf-gcc $(CFLAGS) -c $< -o $@
24+
25+
%.o: %.s
26+
riscv64-unknown-elf-as $(ASFLAGS) $< -o $@
27+
28+
run: $(NAME).bin
29+
mango-run $<
30+
31+
clean:
32+
rm -f *.o *.bin *.elf *.list *~
33+
34+
.PHONY: all clean run
35+
.PRECIOUS: %.elf %.o
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
The MCP3008 is a 8-channel 10-bit analog to digital converter (ADC).
2+
3+
It is set up to read the x,y coordinates from an analog joystick.
4+
5+
See
6+
- https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008
7+
- http://blog.falafel.com/mcp3008-analog-to-digital-conversion
8+
9+
Wire the MCP3008 to the Pi as follows:
10+
11+
MCP3008 VDD to Pi 3.3V
12+
MCP3008 VREF to Pi 3.3V
13+
MCP3008 AGND to Pi GND
14+
MCP3008 DGND to Pi GND
15+
MCP3008 CLK to Pi SCLK
16+
MCP3008 DOUT to Pi MISO
17+
MCP3008 DIN to Pi MOSI
18+
MCP3008 CS/SHDN to Pi CS
19+
20+
doc/ contains
21+
22+
- datasheet
23+
- circuit diagram
24+
- spi protocol
25+
26+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* File: adc_demo.c
2+
* ---------------
3+
* SPI + MCP3008 adc test
4+
*
5+
* Breadboard configured for analog inputs:
6+
* 2-axis joystick channels 0/1
7+
* Photoresistor channel 6
8+
* Force sensor channel 7
9+
*/
10+
11+
#include "assert.h"
12+
#include "uart.h"
13+
#include "mcp3008.h"
14+
#include "printf.h"
15+
#include "strings.h"
16+
#include "timer.h"
17+
18+
static const int MAX_VALUE = 1024;
19+
20+
#define STRINGIFY_IMPL(x) #x
21+
#define AS_STRING(x) STRINGIFY_IMPL(x)
22+
#define ANSI_ESC(n) "\e[" AS_STRING(n) "m"
23+
24+
#define RED ANSI_ESC(41)
25+
#define GREEN ANSI_ESC(42)
26+
#define YELLOW ANSI_ESC(43)
27+
#define BLUE ANSI_ESC(44)
28+
#define MAGENTA ANSI_ESC(45)
29+
#define CYAN ANSI_ESC(46)
30+
#define WHITE ANSI_ESC(47)
31+
#define NORMAL ANSI_ESC(0)
32+
33+
34+
static void print_analog_scale(int val, const char *label, const char *color) {
35+
assert(val <= MAX_VALUE);
36+
int quanta = 30;
37+
int on_quantized = val/quanta;
38+
int off_quantized = MAX_VALUE/quanta - on_quantized;
39+
char buf_on[on_quantized+1];
40+
char buf_off[off_quantized+1];
41+
memset(buf_off, ' ', sizeof(buf_off));
42+
memset(buf_on, '-', sizeof(buf_on));
43+
buf_on[sizeof(buf_on)-1] = '\0';
44+
buf_off[sizeof(buf_off)-1] = '\0';
45+
printf("%12s [%s%s%s%s]", label, color, buf_on, NORMAL, buf_off);
46+
}
47+
48+
static void print_dashboard(int vert, int horiz, int light, int force){
49+
printf("\f\n mcp3008 Readings \n\n");
50+
print_analog_scale(vert, "Joy vert", CYAN);
51+
print_analog_scale(horiz, "Joy horiz", GREEN);
52+
printf("\n\n");
53+
print_analog_scale(light, "Light:", WHITE);
54+
printf("\n\n");
55+
print_analog_scale(force, "Force:", RED);
56+
}
57+
58+
void main(void) {
59+
gpio_init();
60+
uart_init();
61+
mcp3008_init();
62+
printf("Starting program %s\n\n", __FILE__);
63+
64+
while (1) {
65+
int vert = mcp3008_read(0);
66+
int horiz = mcp3008_read(1);
67+
int light = mcp3008_read(6);
68+
int force = mcp3008_read(7);
69+
print_dashboard(vert, horiz, light, force);
70+
timer_delay_ms(100);
71+
}
72+
}

0 commit comments

Comments
 (0)