//Exemplo 20
//Monitoramento Ambiental usando UART e I2C
//Não foi possível fazer comunicação SPI usando algum display do wokwi e o SDK
#include <stdio.h>
#include <string.h>
#include <stdarg.h> // Para funções variádicas
#include "pico/stdlib.h"
#include "ssd1306.h"
#include "hardware/adc.h"
#include "hardware/i2c.h"
#include "pico/time.h"
#include <math.h> // Biblioteca para usar a função log()
// Configuração do OLED
#define OLED_ADDR 0x3C
ssd1306_t oled;
// Configuração do RTC e do NTC
#define SDA_PIN 4
#define SCL_PIN 5
#define I2C_PORT i2c0
#define RTC_ADDR 0x68
#define NTC_PIN 26 // Pino ADC conectado ao NTC
#define BETA 3950 // Coeficiente Beta do termistor
#define V_REF 3.3 // Tensão de referência (3.3V)
// Função para converter a leitura do ADC em temperatura em Celsius
float analog_to_temperature(uint16_t analog_value) {
float analog_value_10bit = (analog_value * 1023.0) / 4095.0;
if (analog_value_10bit <= 0) {
return NAN;
}
float celsius = 1.0 / (log(1.0 / (1023.0 / analog_value_10bit - 1.0)) / BETA + 1.0 / 298.15) - 273.15;
return celsius;
}
// Função para ler o RTC
void rtc_read(uint8_t *time_data) {
i2c_write_blocking(I2C_PORT, RTC_ADDR, &(uint8_t){0x00}, 1, true);
i2c_read_blocking(I2C_PORT, RTC_ADDR, time_data, 7, false);
}
// Função para formatar os dados do RTC
void format_time(uint8_t *rtc_data, char *time_buffer, char *date_buffer) {
const char *days_of_week[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
const char *months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
uint8_t seconds = (rtc_data[0] & 0x0F) + ((rtc_data[0] >> 4) * 10);
uint8_t minutes = (rtc_data[1] & 0x0F) + ((rtc_data[1] >> 4) * 10);
uint8_t hours = (rtc_data[2] & 0x0F) + ((rtc_data[2] >> 4) * 10);
uint8_t day_of_week = rtc_data[3] - 1;
uint8_t date = (rtc_data[4] & 0x0F) + ((rtc_data[4] >> 4) * 10);
uint8_t month = (rtc_data[5] & 0x0F) + ((rtc_data[5] >> 4) * 10);
uint16_t year = 2000 + (rtc_data[6] & 0x0F) + ((rtc_data[6] >> 4) * 10);
snprintf(time_buffer, 64, "%s, %02d:%02dh", days_of_week[day_of_week], hours, minutes);
snprintf(date_buffer, 64, "%d %s %d", date, months[month - 1], year);
}
// Função para exibir mensagens no OLED
void oled_display(const char *line1, const char *line2, const char *line3) {
ssd1306_clear(&oled);
ssd1306_draw_string(&oled, 0, 0, 1, line1);
ssd1306_draw_string(&oled, 0, 16, 1, line2);
ssd1306_draw_string(&oled, 0, 32, 1, line3);
ssd1306_show(&oled);
}
int main() {
stdio_init_all();
// Inicializa o ADC para leitura do NTC
adc_init();
adc_gpio_init(NTC_PIN);
adc_select_input(0);
// Inicializa o I2C e o OLED
i2c_init(I2C_PORT, 100000);
gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SDA_PIN);
gpio_pull_up(SCL_PIN);
if (!ssd1306_init(&oled, 128, 64, OLED_ADDR, I2C_PORT)) {
printf("Erro ao inicializar o display OLED.\n");
return -1;
}
uint8_t rtc_data[7];
char time_buffer[64], date_buffer[64];
char temperature_buffer[64];
while (true) {
// Ler temperatura
uint16_t analog_value = adc_read();
float temperature = analog_to_temperature(analog_value);
// Ler e formatar os dados do RTC
rtc_read(rtc_data);
format_time(rtc_data, time_buffer, date_buffer);
// Formatar temperatura
if (!isnan(temperature)) {
snprintf(temperature_buffer, 64, "Temperature: %.2f C", temperature);
} else {
snprintf(temperature_buffer, 64, "Error reading temp");
}
// Exibir dados no OLED
oled_display(time_buffer, date_buffer, temperature_buffer);
// Exibir dados na UART
printf("%s\n%s\n%s\n", time_buffer, date_buffer, temperature_buffer);
sleep_ms(1000);
}
return 0;
}
Loading
pi-pico-w
pi-pico-w