Peripheral devices¶
Learning goals: The usage of different peripheral devices in the extension board of Pico, producing graphics to the screen, sensors
Additional material¶
These links only for your information, it might be good to take a look at these when searching for examples or if you want to implement some additional fun stuff for the device. In this course, the students are given a template project for the laboratory exercises. The exercises and the final project of the course are done based on this template.
- Pico SDK documentation, lot of useful information
- FreeRTOS API documentation
- JTKJ Hat library SDK
Briefly¶
The Raspeberry Pico HAT that we are currently calling TKJ HAT, contains the following sensor and actuators:
- Red led
- RGB led
- Two switch buttons
- MEMS microphone ICS-41350
- Piezo speaker
- 0.96 in OLED SSD1306 display
- HDC2021 Temperature and Humidity sensor
- VEML6030 Ambient Light sensor
- ICM-42670 (6 Axis motion tracking) IMU
Here you can find all the peripheral devices and datasheets easily, more detailed information is available below.
Sensors and other peripherals¶
Next up, we have information about the different sensors of the extension board, their registers and communication with those sensors via the i2c bus. There are many sensors and functionalities integrated to these peripheral devices, but here we are only presenting the main use cases of them.
If you wish to use other functionalities provided by the sensors, you need to find the information required by yourself from the datasheets / libraries. Course staff will at least try to help you with this.
TKJHAT SDK¶
In the laboratory exercise, the students are given a ready-made program template, which includes the 'TKJHAT SDK library, that include the functions to initialize those sensors and to request for data from them. You can find all those functions in TKJ SDK documentation . The library can be found in the /lib/TKJHAT folder of the project delivered in laboratory sessions.
The Pins to which each one of the sensor / actuator is connected can be found from the
Pins.hFor every sensor connected to the I2C, there are at least two functions that need to be used. In the following representation
xx in the name of a function means the name of a sensor, for example hdc2021 and the yyy the type of value to be read (e.g temperature).init_xxconfigures the sensor and in some cases turns it on to start the measurements.xx_read_yyyfunction is used to request for data from the sensor. The function takes in different parameters depending on the type of the sensor in question.
Actuators (LED, buzzer, display) and the microphone have their own API.
In some cases, the code might contain gaps in implementations of the functions in the
TKJ SDK-folder, which the students need to fill in by themselves- The code of the libraries is not meant to be modified in different capacities.
Reading a datasheet¶
The purpose of this course is not to familiarize the students with datasheets, yet there are a couple of important things to consider.
In datasheets (and pictures of them) below bit order numbers are given in form
[15:0], which means the bits 15 (MSB) - 0 (LSB) of a 16-bit number. This order means that the most significant bit is the first one (largest order number) and the least significant bit is the last one.In some datasheets, a conversion formula is given to measurement units, for example
x.x per LSB. This means the resolution of the sensor, or in other words the smallest difference in measurable unit that the sensor is able to recognize. Now in this example, if the value of the register is n, the measured value can be calculated in a given unit with the formula n * x.x.Red LED¶
Default Board LED
PINS¶
#define RED_LED_PIN 14 #define LED1 RED_LED_PIN
Main functions in the SDK¶
void init_led(void); void toggle_led(void); void blink_led (int n); void set_led_status (bool status)
RGB LED¶
Color of the LED can be defined. Not yet possible control the brightness.
PINS¶
#define RGB_LED_R 18
#define RGB_LED_G 19
#define RGB_LED_B 20
Main functions in the SDK¶
void init_rgb_led(void);
void rgb_led_write(uint8_t r, uint8_t g, uint8_t b);
void stop_rgb_led();
Switch buttons¶
Two standard switch buttons connected to a pull down resistor (active high)
PINS¶
#define SW1_PIN 02
#define SW2_PIN 22
#define BUTTON1 SW1_PIN
#define BUTTON2 SW2_PIN
Main functions in the SDK¶
void init_sw1(void);
void init_sw2(void);
Buzzer¶
Estandar piezo buzzer with higher gain at 4Khz. PKM13 is normal and simple buzzer, that you can include in your program by using the functions introduced below. The pin driving the buzzer is available via BUZZER_PIN.
Datasheet and other files¶
PINS¶
#define BUZZER_PIN 17
Main functions in the SDK¶
void init_buzzer(void);
void buzzer_play_tone(uint32_t frequency, uint32_t duration_ms);
void buzzer_turn_off(void);
void deinit_buzzer(void);
Mems Microphone¶
A low‐power, low‐noise digital MEMS microphone, generating PDM mono audio signal.
Datasheet and other files¶
PINS¶
#define PDM_DATA 16
#define PDM_CLK 15
Main functions in the SDK¶
int init_pdm_microphone(void);
int init_microphone_sampling(void);
void end_microphone_sampling(void);
void pdm_microphone_set_callback(pdm_samples_ready_handler_t handler);
int get_microphone_samples(int16_t *buffer, size_t samples);
0.96 inches OLED display¶
The SSD1306 chip integrates a 0.96-inch monocolor OLED display with 128x64 pixels. The OLED display doesn’t require backlight.
Datasheet and other files¶
PINS¶
Connected to default I2C pins
#define DEFAULT_I2C_SDA_PIN 12
#define DEFAULT_I2C_SCL_PIN 13
Communication via i2c bus¶
| Device address | SSD1306_I2C_ADDRESS |
We use the external library for communication. The SDK provides some helpers functions on top of that.
Main functions in the SDK¶
void init_display(void);
void write_text(const char *text);
void write_text_xy(int16_t x0, int16_t y0, const char *text);
void set_text_cursor (int16_t x0, int16_t y0);
void draw_circle(int16_t x0, int16_t y0, int16_t r, bool fill);
void draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1);
void draw_square(uint32_t x, uint32_t y, uint32_t w, uint32_t h, bool fill);
void clear_display(void);
void stop_display(void);
HDC2021¶
HDC2021 is a multi-use sensor, that provides information about temperature and humidity. Both of these measurements are available as 16-bit numbers, and it has been divided between MSB and LSB bytes to different registers. It is connected to the I2C.
Datasheet and other files¶
PINS¶
Connected to default I2C pins
#define DEFAULT_I2C_SDA_PIN 12
#define DEFAULT_I2C_SCL_PIN 13
Communication via i2c bus¶
| Device address | HDC2021_I2C_ADDR |
| Data register address | HDC2021_TEMP_LOW and HDC2021_TEMP_HIGH (temperature) |
| HDC_2021_HUMIDITY_LOW and HDC_2021_HUMIDITY_HIGH(humidity) | |
| Transmission | txBuffer[0]: data register address |
| Receiving | rxBuffer[0]: LSB-byte of the data register |
| rxBuffer[1]: MSB-byte of the data register |
Main functions in the SDK¶
void init_hdc2021 (void);
void stop_hdc2021 (void);
void hdc2021_read_temperature(void);
void hdc2021_read_humidity(void);
Temperature¶
We can calculate the temperature in celsius from bits
[15:0] with the help of following formula: (temperature[15:0]/2^16)*165 - 40, where temperature[15:0] is the value read from registers.Humidity¶
From the 16-bit value assembled from register bits
[15:0] we can calculate the relative humidity with this formula: (humidity[15:0]/65536)*100, where humidity[15:0] is the register value.VEML6030¶
With VEML6030, we get to know the ambient light level of our environment. We can read this information from its registers and convert it to lux by using a formula.
Datasheet and other files¶
PINS¶
Connected to default I2C pins
#define DEFAULT_I2C_SDA_PIN 12
#define DEFAULT_I2C_SCL_PIN 13
Main functions in the SDK¶
void init_veml6030 (void);
uint32_t veml6030_read_light(void);
uint16_t _veml6030_read_register(uint8_t reg);
void stop_veml6030 (void);
Ambient light¶
The register is read as two 8-bit values, which are then ordered into a 16-bit number by using bitwise operations. The resulting 16-bit value is converted into lux by using a conversion formula. The formula for this sensor is:
als_data[15:0] * 0.5376This formula gives the right result with standard settings, and if you want to tune them, you also need to change the multiplier used in the formula. Datasheet can help you a lot in this task.
Communication via i2c bus¶
| Device address | VEML6030_I2C_ADDR |
| Data register address | VEML6030_ALS_REG |
| Transmission | txBuffer[0]: data register address |
| Receiving | rxBuffer[0]: LSB-byte of the data register |
| rxBuffer[1]: MSB-byte of the data register |
ICM-42670-P¶
IMU Sensor able to detect linear accelaration and angular accelaration in the x, y and z. The linear acceleration is normalized to the gravity and the angular acceleration in degrees per second (dps)
Datasheet and other files¶
PINS¶
Connected to default I2C pins
#define DEFAULT_I2C_SDA_PIN 12
#define DEFAULT_I2C_SCL_PIN 13
Main functions in the SDK¶
int init_ICM42670(void);
int start_sensor_with_default_values(void);
int ICM42670_read_sensor_data(float *ax, float *ay, float *az,
float *gx, float *gy, float *gz,
float *t);
Acceleration and gyroscope¶
Like we can see from the image, the read operation of these registers produces 12 8-bit values, that can be combined into six different values: the gyroscope values in x- y- and z-axes, and the corresponding values for accelerometer. These values too need to be converted into human-readable values with a formula. In standard configuration of the sensor, this configuration can be performed by using the following formulas:
gyro_value[0:15] / 131, where gyro_value can be x- y- or z-axis register value of the gyroscopeaccel_value[0:15] / 8192, where accel_value can be x- y- or z-axis register value of the accelerometer.Communication via i2c bus¶
| Device address | ICM42670_I2C_ADDR |
| Data register address | ICM42670_SENSOR_DATA_START_REG |
| Transmission | txBuffer[0]: data register address |
| Receiving | rxBuffer[0]: accelerometer x-axis MSB-byte |
| rxBuffer[1]: accelerometer x-axis LSB-byte | |
| rxBuffer[2]: accelerometer y-axis MSB-byte | |
| rxBuffer[3]: accelerometer y-axis LSB-byte | |
| rxBuffer[4]: accelerometer z-axis MSB-byte | |
| rxBuffer[5]: accelerometer z-axis LSB-byte | |
| rxBuffer[6]: gyroscope x-axis MSB-byte | |
| rxBuffer[7]: gyroscope x-axis LSB-byte | |
| rxBuffer[8]: gyroscope y-axis MSB-byte | |
| rxBuffer[9]: gyroscope y-axis LSB-byte | |
| rxBuffer[10]: gyroscope z-axis MSB-byte | |
| rxBuffer[11]: gyroscope z-axis LSB-byte |