The source code for this web report is available here . Source code for the ESP32C3 boards are available here .

Transmitter program

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"

#include "esp_log.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_mac.h"
#include "espnow_utils.h"
#include "espnow.h"
#include "espnow_ctrl.h"
#include "driver/gpio.h"
#include "espnow_mem.h"
// #include "build/config/sdkconfig.h" // Posuango popianai do intellisense nopo, pokinomio' pogulu mamaal
/* Include only to shut up intellisense nagging */

#define KOTOS_1        2 // GPIO2, D0 id dulak / on the board
#define KOTOS_2        3 // GPIO3, D1 id dulak / on the board
#define KOTOS_3        4 // GPIO4, D2 id dulak / on the board

int prev1 = 0; int prev2 = 0; int prev3 = 0;
int current1 = 0; int current2 = 0; int current3 = 0;

uint8_t pagatadan[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Broadcast mode address
static const char *TAG = "sodusuhu";

typedef struct gamit {
    int buttonstate1;
    int buttonstate2;
    int buttonstate3;
    int buttonstate4;
    int buttonstate5;
    int buttonstate6;

} gamit;
gamit dolinon; // Mamadalin do poiloon id pampos Poniasan / For transfering data to transmitter function


static void ponimpuun_wifi()
{
    esp_event_loop_create_default();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
    ESP_ERROR_CHECK(esp_wifi_start());
}

// Initialize read pins
static void ponimpuun_pomiri(void)
{
    gpio_reset_pin(KOTOS_1);
    gpio_reset_pin(KOTOS_2);
    gpio_reset_pin(KOTOS_3);

    /* Tolu GPIO hiti nopo nga' pinisok / Three of these GPIO are buttons */
    gpio_set_direction(KOTOS_1, GPIO_MODE_INPUT);
    gpio_set_direction(KOTOS_2, GPIO_MODE_INPUT);
    gpio_set_direction(KOTOS_3, GPIO_MODE_INPUT);
}

// Function for reading GPIO pipns
static void pomiri(void) {
    current1 = gpio_get_level(KOTOS_1);
    current2 = gpio_get_level(KOTOS_2);
    current3 = gpio_get_level(KOTOS_3);

    if (prev1 == 0 && current1 == 1) {
        dolinon.buttonstate1 = 1;    
    }
    else {
        dolinon.buttonstate1 = 0;
    }

    if (prev2 == 0 && current2 == 1) {
        dolinon.buttonstate2 = 1;    
    }
    else {
        dolinon.buttonstate2 = 0;
    }

    if (prev3 == 0 && current3 == 1) {
        dolinon.buttonstate3 = 1;    
    }
    else {
        dolinon.buttonstate3 = 0;
    }
}

static void poniasan(void *arg) {
    esp_err_t sinuli  = ESP_OK;

    while (1) {
        pomiri();
        vTaskDelay(50 / portTICK_PERIOD_MS);
        esp_now_send(pagatadan, (uint8_t *) &dolinon, sizeof(dolinon));
        printf("\n%i\n", sinuli);
        printf("Switch 1: %d", dolinon.buttonstate1);
        printf("Switch 2: %d", dolinon.buttonstate2);
        printf("Switch 3: %d", dolinon.buttonstate3);
        prev1 = current1; prev2 = current2; prev3 = current3;
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }

    ESP_LOGI(TAG, "Poniasan nakalabus / Transmission exited");
    vTaskDelete(NULL);
}

static void ponimpuun_ponias(void) {
    xTaskCreate(poniasan, "Popotimpuun ponias / Initialize transmitter", 4 * 1024, NULL, tskIDLE_PRIORITY + 1, NULL);
}


void app_main(void)
{
    ponimpuun_pomiri();
    espnow_storage_init();

    ponimpuun_ponias();
    ponimpuun_wifi();

    espnow_config_t espnow_config = ESPNOW_INIT_CONFIG_DEFAULT();
    espnow_init(&espnow_config);
}

Receiver program

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "esp_log.h"
#include "esp_system.h"

#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"

#include "esp_wifi.h"
#include "esp_mac.h"
#include "espnow_utils.h"
#include "espnow.h"
#include "espnow_ctrl.h"
#include "driver/gpio.h"
#include "espnow_mem.h"

#include <sys/time.h> // Montok hiza / for time

//#include "build/config/sdkconfig.h" // Posuango popianai do intellisense nopo, pokinomio' pogulu mamaal
/* Only to silence intellisense nagging, comment before building */

#define KOTOS_1        2 // GPIO2, D0 id dulak / on board
#define KOTOS_2        3 // GPIO3, D1 id dulak / on board
#define KOTOS_3        4 // GPIO4, D2 id dulak / on board

#define BIRI_1         5 // GPIO5, D3 id dulak / on board
#define BIRI_2         6 // GPIO6, D4 id dulak / on board
#define BIRI_3         7 // GPIO7, D5 id dulak / on board

typedef struct gamit {
    int buttonstate1;
    int buttonstate2;
    int buttonstate3;
    int buttonstate4;
    int buttonstate5;
    int buttonstate6;

} gamit;
gamit dolinon; // Mamadalin do poiloon id pampos Koromitan / For transferring data to Receiving function

static const char *TAG = "sodusuhu";

void set_time(void) {
    struct timeval now;
    now.tv_sec = 1722541840; // Seconds since Unix epoch / Kiop tantad tinontok Unix
    now.tv_usec = 0;

    settimeofday(&now, NULL);
}

char* get_time(void) {
    time_t t = time(NULL);
    struct tm *tm = localtime(&t);
    return asctime(tm);
}

static void ponimpuun_wifi() // WiFi init
{
    esp_event_loop_create_default();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
    ESP_ERROR_CHECK(esp_wifi_start());
}

static void ponimpuun_kotos(void)
{
    gpio_reset_pin(KOTOS_1);
    gpio_reset_pin(KOTOS_2);
    gpio_reset_pin(KOTOS_3);

    /* Tolu GPIO hiti nopo nga' pinisok / These three GPIOs are buttons */
    gpio_set_direction(KOTOS_1, GPIO_MODE_OUTPUT);
    gpio_set_direction(KOTOS_2, GPIO_MODE_OUTPUT);
    gpio_set_direction(KOTOS_3, GPIO_MODE_OUTPUT);

    /* GPIO pomiri don tikid GPIO pinisok / Reader GPIOs for each GPIO buttons */
    gpio_set_direction(BIRI_1, GPIO_MODE_INPUT);
    gpio_set_direction(BIRI_2, GPIO_MODE_INPUT);
    gpio_set_direction(BIRI_3, GPIO_MODE_INPUT);

    gpio_set_level(KOTOS_1, 0);
    gpio_set_level(KOTOS_2, 0);
    gpio_set_level(KOTOS_3, 0);
}

void Koromitan(const uint8_t *pagatadan, const uint8_t *poiloon_mikot, int ninaru) {
    memcpy(&dolinon, poiloon_mikot, sizeof(dolinon));
    if (dolinon.buttonstate1 == 1) {
        gpio_set_level(KOTOS_1, !gpio_get_level(BIRI_1));
        ESP_LOGI(TAG, "Button 1 signal received at: %s", get_time());
    }
    
    if (dolinon.buttonstate2 == 1) {
        gpio_set_level(KOTOS_2, !gpio_get_level(BIRI_2));
        ESP_LOGI(TAG, "Button 2 signal received at: %s", get_time());
    }

    if (dolinon.buttonstate3 == 1) {
        gpio_set_level(KOTOS_3, !gpio_get_level(BIRI_3));
        ESP_LOGI(TAG, "Button 3 signal received at: %s", get_time());
    }

}

void app_main(void)
{
    for (int i = 0; i < 1; i++) {
        ponimpuun_kotos();
        set_time();
    }

    espnow_storage_init();
    ponimpuun_wifi();

    espnow_config_t espnow_config = ESPNOW_INIT_CONFIG_DEFAULT();
    espnow_init(&espnow_config);
    ESP_ERROR_CHECK(esp_now_register_recv_cb(Koromitan));
    ESP_LOGI(TAG, "Receive callback registered");
}

Data logging

The logging functionality requires a Powershell instance using the IDF frontend:

1
2
PS cd /path/to/idf/project
PS idf.py -p COMX monitor > logfile.txt

The log contents can be viewed as such:

1
PS Get-Content .\logfile.txt