8000 Merge pull request #635 from menesesleonardo/patch-1 · mike2nl/esp32-snippets@297db2c · GitHub
[go: up one dir, main page]

Skip to content

Commit 297db2c

Browse files
authored
Merge pull request nkolban#635 from menesesleonardo/patch-1
Create pcf8523
2 parents ed1de4b + 1d976d2 commit 297db2c

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed

hardware/rtc/pcf8523.c

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#include <apps/sntp/sntp.h>
2+
#include <driver/i2c.h>
3+
#include <esp_log.h>
4+
#include <freertos/FreeRTOS.h>
5+
#include <freertos/task.h>
6+
#include <lwip/sockets.h>
7+
#include <stdio.h>
8+
#include <time.h>
9+
#include "errorhandle_func.h"
10+
10000 11+
#include "sdkconfig.h"
12+
13+
#define SDA_PIN 23
14+
#define SCL_PIN 22
15+
#define RTC_ADDRESS 0x68 // most I2C rtcs have their address on 0x68. any doubt check with i2c scanner snippet
16+
17+
static char tag[] = "RTC";
18+
19+
static uint8_t intToBCD(uint8_t num) {
20+
return ((num / 10) << 4) | (num%10);
21+
}
22+
23+
static uint8_t bcdToInt(uint8_t bcd) {
24+
// 0x10
25+
return ((bcd >> 4) * 10) + (bcd & 0x0f);;
26+
}
27+
28+
29+
void initI2C() {
30+
i2c_config_t conf;
31+
conf.mode = I2C_MODE_MASTER;
32+
conf.sda_io_num = SDA_PIN;
33+
conf.scl_io_num = SCL_PIN;
34+
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
35+
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
36+
conf.master.clk_speed = 100000;
37+
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf));
38+
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0));
39+
}
40+
41+
/*
42+
* PCF8523 slightly changed its 7 bytes encoded in BCD:
43+
* 03h - Seconds - 00-59
44+
* 04h - Minutes - 00-59
45+
* 05h - Hours - 00-23
46+
* 06h - monthday - 01-31
47+
* 07h - weekday - 00-06
48+
* 08h - Month - 01-12
49+
* 09h - Year - 00-99
50+
*
51+
*/
52+
time_t rtc_readValue() {
53+
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
54+
ESP_ERROR_CHECK(i2c_master_start(cmd));
55+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (RTC_ADDRESS << 1) | I2C_MASTER_WRITE, true /* expect ack */));
56+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, 0x03, 1)); // start address
57+
ESP_ERROR_CHECK(i2c_master_start(cmd));
58+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (RTC_ADDRESS << 1) | I2C_MASTER_READ, true /* expect ack */));
59+
uint8_t data[7];
60+
ESP_ERROR_CHECK(i2c_master_read(cmd, data, 7, false));
61+
ESP_ERROR_CHECK(i2c_master_stop(cmd));
62+
COMMANDCHECKOKERR(i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS),"RTC COMMAND");
63+
i2c_cmd_link_delete(cmd);
64+
65+
int i;
66+
for (i=0; i<7; i++) {
67+
ESP_LOGD(tag, "%d: 0x%.2x", i, data[i]);
68+
}
69+
70+
struct tm tm;
71+
tm.tm_sec = bcdToInt(data[0]);
72+
tm.tm_min = bcdToInt(data[1]);
73+
tm.tm_hour = bcdToInt(data[2]);
74+
tm.tm_mday = bcdToInt(data[3]);
75+
tm.tm_mon = bcdToInt(data[5]) - 1; // 0-11 - Note: The month on the PCF8523 is 1-12.
76+
tm.tm_year = bcdToInt(data[6]) + 100; // Years since 1900
77+
time_t readTime = mktime(&tm);
78+
return readTime;
79+
}
80+
81+
void rtc_writeValue(time_t newTime) {
82+
ESP_LOGD(tag, ">> writeValue: %ld", newTime);
83+
struct tm tm;
84+
gmtime_r(&newTime, &tm);
85+
char buf[30];
86+
ESP_LOGD(tag, " - %s", asctime_r(&tm, buf));
87+
88+
esp_err_t errRc;
89+
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
90+
ESP_ERROR_CHECK(i2c_master_start(cmd));
91+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (RTC_ADDRESS << 1) | I2C_MASTER_WRITE, 1 /* expect ack */));
92+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, 0x03, 1));
93+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, intToBCD(tm.tm_sec), 1)); // seconds
94+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, intToBCD(tm.tm_min), 1 )); // minutes
95+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, intToBCD(tm.tm_hour), 1 )); // hours
96+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, intToBCD(tm.tm_mday), 1)); // date of month
97+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, intToBCD(tm.tm_wday+1), 1 )); // week day
98+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, intToBCD(tm.tm_mon+1), 1)); // month
99+
ESP_ERROR_CHECK(i2c_master_write_byte(cmd, intToBCD(tm.tm_year-100), 1)); // year
100+
ESP_ERROR_CHECK(i2c_master_stop(cmd));
101+
errRc = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
102+
if (errRc != 0) {
103+
ESP_LOGE(tag, "i2c_master_cmd_begin: %d", errRc);
104+
}
105+
i2c_cmd_link_delete(cmd);
106+
}
107+
108+
109+
/*
110+
implement in your time function
111+
@Kolban created a nice one, here is my contribution.
112+
113+
esp_err_t sntp_update(){
114+
115+
static const char *tag = "TIME_SETUP";
116+
esp_err_t ret;
117+
char buffer[20];
118+
EventBits_t bitreturn;
119+
TickType_t waittime = 10000/portTICK_PERIOD_MS;
120+
121+
122+
bitreturn = xEventGroupWaitBits(event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, waittime);
123+
124+
if((bitreturn & BIT0) != 0){
125+
126+
printf("going online\n");
127+
128+
}
129+
else printf("going offline\n");
130+
131+
132+
// initialize the SNTP service
133+
sntp_setoperatingmode(SNTP_OPMODE_POLL);
134+
// to create SNTP server variable make a #define statement i.e. "pool.ntp.org"
135+
sntp_setservername(0, CONFIG_SNTP_SERVER);
136+
sntp_init();
137+
138+
initI2C();
139+
140+
time_t t;
141+
struct tm timertc;
142+
t = rtc_readValue();
143+
localtime_r(&t, &timertc);
144+
145+
strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", &timertc);
146+
ESP_LOGI(tag,"Current time in rtc (GTM) is: %s\n\n", buffer);
147+
148+
// wait for the service to set the time
149+
time_t now;
150+
struct tm timeinfo;
151+
time(&now);
152+
localtime_r(&now, &timeinfo);
153+
int counter = 0;
154+
155+
// try for a minute to get time from network
156+
while((timeinfo.tm_year < (2018 - 1900)) && (counter < 12))
157+
{
158+
159+
ESP_LOGW(tag,"Time outdated, waiting...\n");
160+
vTaskDelay(5000 / portTICK_PERIOD_MS);
161+
time(&now);
162+
localtime_r(&now, &timeinfo);
163+
counter ++;
164+
}
165+
166+
if((timeinfo.tm_year < (2018 - 1900)) && (counter == 12)){
167+
ESP_LOGE(tag, "TIMEOUT");
168+
169+
170+
// stick to rtc time
171+
now = rtc_readValue();
172+
173+
}
174+
else{
175+
// update rtc time
176+
rtc_writeValue(now);
177+
}
178+
179+
180+
// to create timezone variable make a #define statement i.e. "COT+5"
181+
setenv("TZ",CONFIG_TIMEZONE_TZ, 1);
182+
tzset();
183+
184+
// print the actual time in location
185+
localtime_r(&now, &timeinfo);
186+
strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", &timeinfo);
187+
ESP_LOGI(tag,"Current time in your Location: %s\n\n", buffer);
188+
189+
// check time set in rtc in case it was updated from network
190+
t = rtc_readValue();
191+
localtime_r(&t, &timertc);
192+
strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", &timertc);
193+
ESP_LOGI(tag,"Current time in rtc (GTM) is: %s\n\n", buffer);
194+
195+
ret = ESP_OK;
196+
197+
return ret;
198+
}
199+
200+
*/

0 commit comments

Comments
 (0)
0