Skip to content

Commit 6e647c6

Browse files
authored
Additional examples for specific h/w by our interns (#171)
adc/microphone_adc - Read analog values from a microphone and plot the measured sound amplitude. i2c/bmp280_i2c - Read and convert temperature and pressure data from a BMP280 sensor, attached to an I2C bus. i2c/lis3dh_i2c - Read acceleration and temperature value from a LIS3DH sensor via I2C i2c/mcp9808_i2c - Read temperature, set limits and raise alerts when limits are surpassed. i2c/mma8451_i2c - Read acceleration from a MMA8451 accelerometer and set range and precision for the data. i2c/mpl3115a2_i2c - Interface with an MPL3115A2 altimeter, exploring interrupts and advanced board features, via I2C. i2c/oled_i2c - Convert and display a bitmap on a 128x32 SSD1306-driven OLED display i2c/pa1010d_i2c - Read GPS location data, parse and display data via I2C. i2c/pcf8523_i2c - Read time and date values from a real time clock. Set current time and alarms on it. uart/lcd_uart - Display text and symbols on a 16x02 RGB LCD display via UART
1 parent fabb762 commit 6e647c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2440
-0
lines changed

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ App|Description
2020
[hello_adc](adc/hello_adc)|Display the voltage from an ADC input.
2121
[joystick_display](adc/joystick_display)|Display a Joystick X/Y input based on two ADC inputs.
2222
[adc_console](adc/adc_console)|An interactive shell for playing with the ADC. Includes example of free-running capture mode.
23+
[microphone_adc](adc/microphone_adc)|Read analog values from a microphone and plot the measured sound amplitude.
2324

2425
### Clocks
2526

@@ -76,8 +77,16 @@ App|Description
7677
App|Description
7778
---|---
7879
[bus_scan](i2c/bus_scan) | Scan the I2C bus for devices and display results.
80+
[bmp280_i2c](i2c/bmp280_i2c) | Read and convert temperature and pressure data from a BMP280 sensor, attached to an I2C bus.
7981
[lcd_1602_i2c](i2c/lcd_1602_i2c) | Display some text on a generic 16x2 character LCD display, via I2C.
82+
[lis3dh_i2c](i2c/lis3dh_i2c) | Read acceleration and temperature value from a LIS3DH sensor via I2C
83+
[mcp9808_i2c](i2c/mcp9808_i2c) | Read temperature, set limits and raise alerts when limits are surpassed.
84+
[mma8451_i2c](i2c/mma8451_i2c) | Read acceleration from a MMA8451 accelerometer and set range and precision for the data.
85+
[mpl3115a2_i2c](i2c/mpl3115a2_i2c) | Interface with an MPL3115A2 altimeter, exploring interrupts and advanced board features, via I2C.
8086
[mpu6050_i2c](i2c/mpu6050_i2c) | Read acceleration and angular rate values from a MPU6050 accelerometer/gyro, attached to an I2C bus.
87+
[oled_i2c](i2c/oled_i2c) | Convert and display a bitmap on a 128x32 SSD1306-driven OLED display
88+
[pa1010d_i2c](i2c/pa1010d_i2c) | Read GPS location data, parse and display data via I2C.
89+
[pcf8523_i2c](i2c/pcf8523_i2c) | Read time and date values from a real time clock. Set current time and alarms on it.
8190

8291
### Interpolator
8392

@@ -172,6 +181,7 @@ App|Description
172181
App|Description
173182
---|---
174183
[hello_uart](uart/hello_uart) | Print some text from one of the UART serial ports, without going through `stdio`.
184+
[lcd_uart](uart/lcd_uart) | Display text and symbols on a 16x02 RGB LCD display via UART
175185
[uart_advanced](uart/uart_advanced) | Use some other UART features like RX interrupts, hardware control flow, and data formats other than 8n1.
176186

177187
### USB Device

adc/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ if (NOT PICO_NO_HARDWARE)
33
add_subdirectory(dma_capture)
44
add_subdirectory(hello_adc)
55
add_subdirectory(joystick_display)
6+
add_subdirectory(microphone_adc)
67
endif ()

adc/microphone_adc/CMakeLists.txt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_executable(microphone_adc
2+
microphone_adc.c
3+
)
4+
5+
# pull in common dependencies and adc hardware support
6+
target_link_libraries(microphone_adc pico_stdlib hardware_adc)
7+
8+
# create map/bin/hex file etc.
9+
pico_add_extra_outputs(microphone_adc)
10+
11+
# add url via pico_set_program_url
12+
example_auto_set_url(microphone_adc)

adc/microphone_adc/README.adoc

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
= Attaching a microphone using the ADC
2+
3+
This example code shows how to interface the Raspberry Pi Pico with a standard analog microphone via the onboard analog to digital converter (ADC). In this example, we use an ICS-40180 breakout board by SparkFun but any analog microphone should be compatible with this tutorial. SparkFun have https://learn.sparkfun.com/tutorials/mems-microphone-hookup-guide[written a guide] for this board that goes into more detail about the board and how it works.
4+
5+
[TIP]
6+
======
7+
An analog to digital converter (ADC) is responsible for reading continually varying input signals that may range from 0 to a specified reference voltage (in the Pico's case this reference voltage is set by the supply voltage and can be measured on pin 35, ADC_VREF) and converting them into binary, i.e. a number that can be digitally stored.
8+
======
9+
10+
The Pico has a 12-bit ADC (ENOB of 8.7-bit, see https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf[RP2040 datasheet section 4.9.3 for more details]), meaning that a read operation will return a number ranging from 0 to 4095 (2^12 - 1) for a total of 4096 possible values. Therefore, the resolution of the ADC is 3.3/4096, so roughly steps of 0.8 millivolts. The SparkFun breakout uses an OPA344 operational amplifier to boost the signal coming from the microphone to voltage levels that can be easily read by the ADC. An important side effect is that a bias of 0.5*Vcc is added to the signal, even when the microphone is not picking up any sound.
11+
12+
The ADC provides us with a raw voltage value but when dealing with sound, we're more interested in the amplitude of the audio signal. This is defined as one half the peak-to-peak amplitude. Included with this example is a very simple Python script that will plot the voltage values it receives via the serial port. By tweaking the sampling rates, and various other parameters, the data from the microphone can be analysed in various ways, such as in a Fast Fourier Transform to see what frequencies make up the signal.
13+
14+
[[microphone_adc_plotter_image]]
15+
[pdfwidth=75%]
16+
.Example output from included Python script
17+
image::microphone_adc_plotter.png[]
18+
19+
== Wiring information
20+
21+
Wiring up the device requires 3 jumpers, to connect VCC (3.3v), GND, and AOUT. The example here uses ADC0, which is GP26. Power is supplied from the 3.3V pin.
22+
23+
WARNING: Most boards will take a range of VCC voltages from the Pico's default 3.3V to the 5 volts commonly seen on other microcontrollers. Ensure your board doesn't output an analogue signal greater than 3.3V as this may result in permanent damage to the Pico's ADC.
24+
25+
[[ics-40180-adc_wiring]]
26+
[pdfwidth=75%]
27+
.Wiring Diagram for ICS-40180 microphone breakout board.
28+
image::microphone_adc_bb.png[]
29+
30+
== List of Files
31+
32+
CMakeLists.txt:: CMake file to incorporate the example in to the examples build tree.
33+
microphone_adc.c:: The example code.
34+
35+
== Bill of Materials
36+
37+
.A list of materials required for the example
38+
[[ics-40180-adc-bom-table]]
39+
[cols=3]
40+
|===
41+
| *Item* | *Quantity* | Details
42+
| Breadboard | 1 | generic part
43+
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
44+
| ICS-40180 microphone breakout board or similar | 1 | https://www.sparkfun.com/products/18011[From SparkFun]
45+
| M/M Jumper wires | 3 | generic part
46+
|===
47+
48+

adc/microphone_adc/microphone_adc.c

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <stdio.h>
8+
#include "pico/stdlib.h"
9+
#include "hardware/gpio.h"
10+
#include "hardware/adc.h"
11+
#include "hardware/uart.h"
12+
#include "pico/binary_info.h"
13+
14+
/* Example code to extract analog values from a microphone using the ADC
15+
with accompanying Python file to plot these values
16+
17+
Connections on Raspberry Pi Pico board, other boards may vary.
18+
19+
GPIO 26/ADC0 (pin 31)-> AOUT or AUD on microphone board
20+
3.3v (pin 36) -> VCC on microphone board
21+
GND (pin 38) -> GND on microphone board
22+
*/
23+
24+
#define ADC_NUM 0
25+
#define ADC_PIN (26 + ADC_NUM)
26+
#define ADC_VREF 3.3
27+
#define ADC_RANGE (1 << 12)
28+
#define ADC_CONVERT (ADC_VREF / (ADC_RANGE - 1))
29+
30+
int main() {
31+
stdio_init_all();
32+
printf("Beep boop, listening...\n");
33+
34+
bi_decl(bi_program_description("Analog microphone example for Raspberry Pi Pico")); // for picotool
35+
bi_decl(bi_1pin_with_name(ADC_PIN, "ADC input pin"));
36+
37+
adc_init();
38+
adc_gpio_init( ADC_PIN);
39+
adc_select_input( ADC_NUM);
40+
41+
uint adc_raw;
42+
while (1) {
43+
adc_raw = adc_read(); // raw voltage from ADC
44+
printf("%.2f\n", adc_raw * ADC_CONVERT);
45+
sleep_ms(10);
46+
}
47+
48+
return 0;
49+
}

adc/microphone_adc/microphone_adc.fzz

70.2 KB
Binary file not shown.
161 KB
Loading
59 KB
Loading

adc/microphone_adc/plotter.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env python3
2+
3+
# Grabs raw data from the Pico's UART and plots it as received
4+
5+
# Install dependencies:
6+
# python3 -m pip install pyserial matplotlib
7+
8+
# Usage: python3 plotter <port>
9+
# eg. python3 plotter /dev/ttyACM0
10+
11+
# see matplotlib animation API for more: https://matplotlib.org/stable/api/animation_api.html
12+
13+
import serial
14+
import sys
15+
import matplotlib.pyplot as plt
16+
import matplotlib.animation as animation
17+
from matplotlib.lines import Line2D
18+
19+
# disable toolbar
20+
plt.rcParams['toolbar'] = 'None'
21+
22+
class Plotter:
23+
def __init__(self, ax):
24+
self.ax = ax
25+
self.maxt = 250
26+
self.tdata = [0]
27+
self.ydata = [3.3/2]
28+
self.line = Line2D(self.tdata, self.ydata)
29+
30+
self.ax.add_line(self.line)
31+
self.ax.set_ylim(0, 3.3)
32+
self.ax.set_xlim(0, self.maxt)
33+
34+
def update(self, y):
35+
lastt = self.tdata[-1]
36+
if lastt - self.tdata[0] >= self.maxt: # drop old frames
37+
self.tdata = self.tdata[1:]
38+
self.ydata = self.ydata[1:]
39+
self.ax.set_xlim(self.tdata[0], self.tdata[0] + self.maxt)
40+
41+
t = lastt + 1
42+
self.tdata.append(t)
43+
self.ydata.append(y)
44+
self.line.set_data(self.tdata, self.ydata)
45+
return self.line,
46+
47+
48+
def serial_getter():
49+
# grab fresh ADC values
50+
# note sometimes UART drops chars so we try a max of 5 times
51+
# to get proper data
52+
while True:
53+
for i in range(5):
54+
line = ser.readline()
55+
try:
56+
line = float(line)
57+
except ValueError:
58+
continue
59+
break
60+
yield line
61+
62+
if len(sys.argv) < 2:
63+
raise Exception("Ruh roh..no port specified!")
64+
65+
ser = serial.Serial(sys.argv[1], 115200, timeout=1)
66+
67+
fig, ax = plt.subplots()
68+
plotter = Plotter(ax)
69+
70+
ani = animation.FuncAnimation(fig, plotter.update, serial_getter, interval=1,
71+
blit=True, cache_frame_data=False)
72+
73+
ax.set_xlabel("Samples")
74+
ax.set_ylabel("Voltage (V)")
75+
fig.canvas.manager.set_window_title('Microphone ADC example')
76+
fig.tight_layout()
77+
plt.show()

i2c/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
if (NOT PICO_NO_HARDWARE)
2+
add_subdirectory(bmp280_i2c)
23
add_subdirectory(bus_scan)
34
add_subdirectory(lcd_1602_i2c)
5+
add_subdirectory(lis3dh_i2c)
6+
add_subdirectory(mcp9808_i2c)
7+
add_subdirectory(mma8451_i2c)
8+
add_subdirectory(mpl3115a2_i2c)
49
add_subdirectory(mpu6050_i2c)
10+
add_subdirectory(oled_i2c)
11+
add_subdirectory(pa1010d_i2c)
12+
add_subdirectory(pcf8523_i2c)
513
endif ()

i2c/bmp280_i2c/CMakeLists.txt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_executable(bmp280_i2c
2+
bmp280_i2c.c
3+
)
4+
5+
# pull in common dependencies and additional i2c hardware support
6+
target_link_libraries(bmp280_i2c pico_stdlib hardware_i2c)
7+
8+
# create map/bin/hex file etc.
9+
pico_add_extra_outputs(bmp280_i2c)
10+
11+
# add url via pico_set_program_url
12+
example_auto_set_url(bmp280_i2c)

i2c/bmp280_i2c/README.adoc

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
= Attaching a BMP280 temp/pressure sensor via I2C
2+
3+
This example code shows how to interface the Raspberry Pi Pico with the popular BMP280 temperature and air pressure sensor manufactured by Bosch. A similar variant, the BME280, exists that can also measure humidity. There is another example that uses the BME280 device but talks to it via SPI as opposed to I2C.
4+
5+
The code reads data from the sensor's registers every 500 milliseconds and prints it via the onboard UART. This example operates the BMP280 in _normal_ mode, meaning that the device continuously cycles between a measurement period and a standby period at a regular interval we can set. This has the advantage that subsequent reads do not require configuration register writes and is the recommended mode of operation to filter out short-term disturbances.
6+
7+
[TIP]
8+
======
9+
The BMP280 is highly configurable with 3 modes of operation, various oversampling levels, and 5 filter settings. Find the datasheet online (https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf) to explore all of its capabilities beyond the simple example given here.
10+
======
11+
12+
== Wiring information
13+
14+
Wiring up the device requires 4 jumpers, to connect VCC (3.3v), GND, SDA and SCL. The example here uses the default I2C port 0, which is assigned to GPIO 4 (SDA) and 5 (SCL) in software. Power is supplied from the 3.3V pin from the Pico.
15+
16+
WARNING: The BMP280 has a maximum supply voltage rating of 3.6V. Most breakout boards have voltage regulators that will allow a range of input voltages of 2-6V, but make sure to check beforehand.
17+
18+
[[bmp280_i2c_wiring]]
19+
[pdfwidth=75%]
20+
.Wiring Diagram for BMP280 sensor via I2C.
21+
image::bmp280_i2c_bb.png[]
22+
23+
== List of Files
24+
25+
CMakeLists.txt:: CMake file to incorporate the example into the examples build tree.
26+
bmp280_i2c.c:: The example code.
27+
28+
== Bill of Materials
29+
30+
.A list of materials required for the example
31+
[[bmp280_i2c-bom-table]]
32+
[cols=3]
33+
|===
34+
| *Item* | *Quantity* | Details
35+
| Breadboard | 1 | generic part
36+
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
37+
| BMP280-based breakout board | 1 | https://shop.pimoroni.com/products/bmp280-breakout-temperature-pressure-altitude-sensor[from Pimoroni]
38+
| M/M Jumper wires | 4 | generic part
39+
|===
40+
41+

0 commit comments

Comments
 (0)