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
This commit is contained in:
Graham Sanderson
2021-10-25 12:30:57 -05:00
committed by GitHub
parent fabb762f75
commit 6e647c6f26
59 changed files with 2440 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
add_executable(pcf8523_i2c
pcf8523_i2c.c
)
# pull in common dependencies and additional i2c hardware support
target_link_libraries(pcf8523_i2c pico_stdlib hardware_i2c)
# create map/bin/hex file etc.
pico_add_extra_outputs(pcf8523_i2c)
# add url via pico_set_program_url
example_auto_set_url(pcf8523_i2c)

View File

@@ -0,0 +1,35 @@
= Attaching a PCF8523 Real Time Clock via I2C
This example code shows how to interface the Raspberry Pi Pico to the PCF8523 Real Time Clock
======
This example allows you to set the current time and date to initialise it and then refreshes it every half-second. Additionally it lets you set an alarm for a particular time + date and raises an alert accordingly. More information about the module is available at https://learn.adafruit.com/adafruit-pcf8523-real-time-clock.
======
== Wiring information
Wiring up the device requires 4 jumpers, to connect VDD, GND, SDA and SCL. The example here uses I2C port 0, which is assigned to GPIO 4 (SDA) and 5 (SCL) in software. Power is supplied from the 5V pin.
[[pcf8523_i2c_wiring]]
[pdfwidth=75%]
.Wiring Diagram for PCF8523.
image::pc8523_i2c.png[]
== List of Files
CMakeLists.txt:: CMake file to incorporate the example in to the examples build tree.
pcf8523_i2c.c:: The example code.
== Bill of Materials
.A list of materials required for the example
[[pcf8523-bom-table]]
[cols=3]
|===
| *Item* | *Quantity* | Details
| Breadboard | 1 | generic part
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
| PCF8523 board| 1 | https://www.adafruit.com/product/3295
| M/M Jumper wires | 4 | generic part
|===

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@@ -0,0 +1,164 @@
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/i2c.h"
/* Example code to talk to a PCF8520 Real Time Clock module
Connections on Raspberry Pi Pico board, other boards may vary.
GPIO PICO_DEFAULT_I2C_SDA_PIN (On Pico this is 4 (physical pin 6)) -> SDA on PCF8520 board
GPIO PICO_DEFAULT_I2C_SCK_PIN (On Pico this is 5 (physical pin 7)) -> SCL on PCF8520 board
5V (physical pin 40) -> VCC on PCF8520 board
GND (physical pin 38) -> GND on PCF8520 board
*/
// By default these devices are on bus address 0x68
static int addr = 0x68;
#ifdef i2c_default
static void pcf8520_reset() {
// Two byte reset. First byte register, second byte data
// There are a load more options to set up the device in different ways that could be added here
uint8_t buf[] = {0x00, 0x58};
i2c_write_blocking(i2c_default, addr, buf, 2, false);
}
static void pcf820_write_current_time() {
// buf[0] is the register to write to
// buf[1] is the value that will be written to the register
uint8_t buf[2];
//Write values for the current time in the array
//index 0 -> second: bits 4-6 are responsible for the ten's digit and bits 0-3 for the unit's digit
//index 1 -> minute: bits 4-6 are responsible for the ten's digit and bits 0-3 for the unit's digit
//index 2 -> hour: bits 4-5 are responsible for the ten's digit and bits 0-3 for the unit's digit
//index 3 -> day of the month: bits 4-5 are responsible for the ten's digit and bits 0-3 for the unit's digit
//index 4 -> day of the week: where Sunday = 0x00, Monday = 0x01, Tuesday... ...Saturday = 0x06
//index 5 -> month: bit 4 is responsible for the ten's digit and bits 0-3 for the unit's digit
//index 6 -> year: bits 4-7 are responsible for the ten's digit and bits 0-3 for the unit's digit
//NOTE: if the value in the year register is a multiple for 4, it will be considered a leap year and hence will include the 29th of February
uint8_t current_val[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
for (int i = 3; i < 10; ++i) {
buf[0] = i;
buf[1] = current_val[i - 3];
i2c_write_blocking(i2c_default, addr, buf, 2, false);
}
}
static void pcf8520_read_raw(uint8_t *buffer) {
// For this particular device, we send the device the register we want to read
// first, then subsequently read from the device. The register is auto incrementing
// so we don't need to keep sending the register we want, just the first.
// Start reading acceleration registers from register 0x3B for 6 bytes
uint8_t val = 0x03;
i2c_write_blocking(i2c_default, addr, &val, 1, true); // true to keep master control of bus
i2c_read_blocking(i2c_default, addr, buffer, 7, false);
}
void pcf8520_set_alarm() {
// buf[0] is the register to write to
// buf[1] is the value that will be written to the register
uint8_t buf[2];
// Default value of alarm register is 0x80
// Set bit 8 of values to 0 to activate that particular alarm
// Index 0 -> minute: bits 4-5 are responsible for the ten's digit and bits 0-3 for the unit's digit
// Index 1 -> hour: bits 4-6 are responsible for the ten's digit and bits 0-3 for the unit's digit
// Index 2 -> day of the month: bits 4-5 are responsible for the ten's digit and bits 0-3 for the unit's digit
// Index 3 -> day of the week: where Sunday = 0x00, Monday = 0x01, Tuesday... ...Saturday = 0x06
uint8_t alarm_val[4] = {0x01, 0x80, 0x80, 0x80};
// Write alarm values to registers
for (int i = 10; i < 14; ++i) {
buf[0] = (uint8_t) i;
buf[1] = alarm_val[i - 10];
i2c_write_blocking(i2c_default, addr, buf, 2, false);
}
}
#endif
void pcf8520_check_alarm() {
// Check bit 3 of control register 2 for alarm flags
uint8_t status[1];
uint8_t val = 0x01;
i2c_write_blocking(i2c_default, addr, &val, 1, true); // true to keep master control of bus
i2c_read_blocking(i2c_default, addr, status, 1, false);
if ((status[0] & 0x08) == 0x08) {
printf("ALARM RINGING");
} else {
printf("Alarm not triggered yet");
}
}
void pcf8520_convert_time(int conv_time[7], const uint8_t raw_time[7]) {
// Convert raw data into time
conv_time[0] = (10 * (int) ((raw_time[0] & 0x70) >> 4)) + ((int) (raw_time[0] & 0x0F));
conv_time[1] = (10 * (int) ((raw_time[1] & 0x70) >> 4)) + ((int) (raw_time[1] & 0x0F));
conv_time[2] = (10 * (int) ((raw_time[2] & 0x30) >> 4)) + ((int) (raw_time[2] & 0x0F));
conv_time[3] = (10 * (int) ((raw_time[3] & 0x30) >> 4)) + ((int) (raw_time[3] & 0x0F));
conv_time[4] = (int) (raw_time[4] & 0x07);
conv_time[5] = (10 * (int) ((raw_time[5] & 0x10) >> 4)) + ((int) (raw_time[5] & 0x0F));
conv_time[6] = (10 * (int) ((raw_time[6] & 0xF0) >> 4)) + ((int) (raw_time[6] & 0x0F));
}
int main() {
stdio_init_all();
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
#warning i2c/pcf8520_i2c example requires a board with I2C pins
puts("Default I2C pins were not defined");
#else
printf("Hello, PCF8520! Reading raw data from registers...\n");
// This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico)
i2c_init(i2c_default, 400 * 1000);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
// Make the I2C pins available to picotool
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
pcf8520_reset();
pcf820_write_current_time();
pcf8520_set_alarm();
pcf8520_check_alarm();
uint8_t raw_time[7];
int real_time[7];
char days_of_week[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
while (1) {
pcf8520_read_raw(raw_time);
pcf8520_convert_time(real_time, raw_time);
printf("Time: %02d : %02d : %02d\n", real_time[2], real_time[1], real_time[0]);
printf("Date: %s %02d / %02d / %02d\n", days_of_week[real_time[4]], real_time[3], real_time[5], real_time[6]);
pcf8520_check_alarm();
sleep_ms(500);
// Clear terminal
printf("\e[1;1H\e[2J");
}
return 0;
}
#endif