//THIS DOES NOT WORK IN ESP_IDF NEWER VERSION!!! (in platform io)
///led pin -> GPIO_NUM_2
///antenna pin -> GPIO_NUM_5
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "driver/ledc.h"
#include <time.h>
#include <sys/time.h>
#include <esp_sntp.h>
// WiFi parameters
#define WIFI_SSID "Wokwi-GUEST"
//ssid
#define WIFI_PASS ""
//password
//led pin
#define LED_PIN GPIO_NUM_2
//ant pin
#define ANT_PIN GPIO_NUM_5
// Event group
static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
// Wifi event handler
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch (event->event_id) {
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
break;
default:
break;
}
return ESP_OK;
}
// Main task
void main_task(void *pvParameter)
{
tcpip_adapter_ip_info_t ip_info;
// wait for connection
printf("Waiting for connection to the wifi network... \n");
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
printf("Connected!\n");
// print the local IP address
ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
printf("IP Address: %s\n", ip4addr_ntoa(&ip_info.ip));
printf("Subnet mask: %s\n", ip4addr_ntoa(&ip_info.netmask));
printf("Gateway: %s\n", ip4addr_ntoa(&ip_info.gw));
while (1) {
vTaskDelay(1000 / portTICK_RATE_MS);
}
}
// Connection code
void connect_wifi()
{
printf("ESP-IDF version used: ");
printf(IDF_VER"\n");
// disable the default wifi logging
esp_log_level_set("wifi", ESP_LOG_NONE);
// initialize NVS
ESP_ERROR_CHECK(nvs_flash_init());
// create the event group to handle wifi events
wifi_event_group = xEventGroupCreate();
// initialize the tcp stack
tcpip_adapter_init();
// initialize the wifi event handler
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
// initialize the wifi stack in STAtion mode with config in RAM
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
// configure the wifi connection and start the interface
wifi_config_t wifi_config = {
.sta = {
.ssid = WIFI_SSID,
.password = WIFI_PASS,
},
};
// start the main task
xTaskCreate(&main_task, "main_task", 2048, NULL, 5, NULL);
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
printf("Connecting to %s\n", WIFI_SSID);
}
/// NTP CODE
void time_sync_notification_cb(struct timeval *tv)
{
printf("%s","Sync Notification!\n");
}
void init_sntp()
{
printf("%s","Initializing SNTP\n");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "2.pool.ntp.org");
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH); //remove this if you want updated time instatly
sntp_init();
}
///TIME TO DCF CODE
//bin to bcd
int Bin2Bcd(int dato) {
int msb, lsb;
if (dato < 10)
return dato;
msb = (dato / 10) << 4;
lsb = dato % 10;
return msb + lsb;
}
int impulseArray[60];
int actualHours, actualMinutes, actualSecond, actualDay, actualMonth, actualYear, DayOfW;
int impulseCount;
void CodeTime()
{
time_t now;
time(&now);
struct tm *dcf = localtime(&now);
DayOfW = dcf->tm_wday;
if (DayOfW == 0) DayOfW = 7;
actualDay = dcf->tm_mday;
actualMonth = dcf->tm_mon + 1;
actualYear = dcf->tm_year % 100;
actualHours = dcf->tm_hour;
actualMinutes = dcf->tm_min; // DCF77 transmitts the next minute
if (actualMinutes >= 60) {
actualMinutes = 0;
actualHours++;
}
actualSecond = dcf->tm_sec;
if (actualSecond == 60) actualSecond = 0;
int n, Tmp, TmpIn;
int ParityCount = 0;
//we put the first 20 bits of each minute at a logical zero value
for (n = 0; n < 20; n++) impulseArray[n] = 1;
// set DST bit
if (dcf->tm_isdst == 0) {
impulseArray[18] = 2; // CET or DST OFF
} else {
impulseArray[17] = 2; // CEST or DST ON
}
//bit 20 must be 1 to indicate active time
impulseArray[20] = 2;
//calculates the bits for the minutes
TmpIn = Bin2Bcd(actualMinutes);
for (n = 21; n < 28; n++) {
Tmp = TmpIn & 1;
impulseArray[n] = Tmp + 1;
ParityCount += Tmp;
TmpIn >>= 1;
}
if ((ParityCount & 1) == 0)
impulseArray[28] = 1;
else
impulseArray[28] = 2;
//calculates bits for the hours
ParityCount = 0;
TmpIn = Bin2Bcd(actualHours);
for (n = 29; n < 35; n++) {
Tmp = TmpIn & 1;
impulseArray[n] = Tmp + 1;
ParityCount += Tmp;
TmpIn >>= 1;
}
if ((ParityCount & 1) == 0)
impulseArray[35] = 1;
else
impulseArray[35] = 2;
ParityCount = 0;
//calculate the bits for the actual Day of Month
TmpIn = Bin2Bcd(actualDay);
for (n = 36; n < 42; n++) {
Tmp = TmpIn & 1;
impulseArray[n] = Tmp + 1;
ParityCount += Tmp;
TmpIn >>= 1;
}
TmpIn = Bin2Bcd(DayOfW);
for (n = 42; n < 45; n++) {
Tmp = TmpIn & 1;
impulseArray[n] = Tmp + 1;
ParityCount += Tmp;
TmpIn >>= 1;
}
//calculates the bits for the actualMonth
TmpIn = Bin2Bcd(actualMonth);
for (n = 45; n < 50; n++) {
Tmp = TmpIn & 1;
impulseArray[n] = Tmp + 1;
ParityCount += Tmp;
TmpIn >>= 1;
}
//calculates the bits for actual year
TmpIn = Bin2Bcd(actualYear); // 2 digit year
for (n = 50; n < 58; n++) {
Tmp = TmpIn & 1;
impulseArray[n] = Tmp + 1;
ParityCount += Tmp;
TmpIn >>= 1;
}
//equal date
if ((ParityCount & 1) == 0)
impulseArray[58] = 1;
else
impulseArray[58] = 2;
//last missing pulse
impulseArray[59] = 0; // No pulse
}
//dcf out
void DcfOut() {
switch (impulseCount++) {
case 0:
if (impulseArray[actualSecond] != 0) {
gpio_set_level(LED_PIN, 0); //invert this to make default low
ledcWrite(0, 0);
}
break;
case 1:
if (impulseArray[actualSecond] == 1) {
gpio_set_level(LED_PIN, 1); //invert this to make default low
ledcWrite(0, 127);
}
break;
case 2:
gpio_set_level(LED_PIN, 1); //invert this to make default low
ledcWrite(0, 127);
break;
case 9:
impulseCount = 0;
if (actualSecond == 1 || actualSecond == 15 || actualSecond == 21 || actualSecond == 29 ) printf("%s","-");
if (actualSecond == 36 || actualSecond == 42 || actualSecond == 45 || actualSecond == 50 ) printf("%s","-");
if (actualSecond == 28 || actualSecond == 35 || actualSecond == 58 ) printf("%s","P");
if (impulseArray[actualSecond] == 1) printf("%d", 0);
if (impulseArray[actualSecond] == 2) printf("%d", 1);
if (actualSecond == 59 ) {
static time_t now;
time(&now);
printf("%s", ctime(&now));
}
break;
}
CodeTime();
}
//transmitter init (ledc)
void init_transmitter()
{
gpio_reset_pin(ANT_PIN);
gpio_set_direction(ANT_PIN, GPIO_MODE_OUTPUT);
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, // resolution of PWM duty
.freq_hz = 77500, // frequency of PWM signal
.speed_mode = LEDC_LOW_SPEED_MODE, // timer mode
.timer_num = LEDC_TIMER_0, // timer index
.clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock
};
// Set configuration of timer0 for high speed channels
ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel = {
.channel = LEDC_CHANNEL_0,
.duty = 0,
.gpio_num = ANT_PIN,
.speed_mode = LEDC_HIGH_SPEED_MODE,
.hpoint = 0,
.timer_sel = LEDC_TIMER_0
};
ledc_channel_config(&ledc_channel);
ledc_fade_func_install(0);
}
// Main application
void app_main()
{
gpio_reset_pin(LED_PIN);
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
init_transmitter();
const char* timezone = "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"; //EU timezone
setenv("TZ",timezone,1);
tzset();
connect_wifi();
init_sntp();
while(1){
DcfOut();
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}