maximkulkin / esp-homekit-demo

Demo of Apple HomeKit accessory server library
MIT License
808 stars 233 forks source link

Homekit temperature sensor with LCD screen #358

Closed sam632 closed 4 years ago

sam632 commented 4 years ago

Hi, I have tried to add an lcd screen to the HomeKit temperature sensor in order to display the temperature and humidity on the screen. The code (attached below) works initially, displaying the following:

Before

But then when I connect it to my phone through the home app it changes to this:

After

I can then reset the device with the built in reset button on the WEMOS D1 mini and it works fine after that but I would rather not have to reset it after connecting to a device.

#include <stdio.h>
#include <espressif/esp_wifi.h>
#include <espressif/esp_sta.h>
#include <espressif/esp_common.h>
#include <esp/uart.h>
#include <esp8266.h>
#include <FreeRTOS.h>
#include <task.h>

//For LCD Screen
#include <i2c/i2c.h>
#include <hd44780/hd44780.h>

//For Homekit
#include <homekit/homekit.h>
#include <homekit/characteristics.h>

//#include <wifi_config.h>
#include "wifi.h"

//For Temperature Sensor
#include <dht/dht.h>

//LCD pins
#define I2C_BUS 0
#define SCL_PIN 5
#define SDA_PIN 4
#define ADDR 0x27

//Sensor pin defined in Makefile
#ifndef SENSOR_PIN
#error SENSOR_PIN is not specified
#endif

static void wifi_init() {
    struct sdk_station_config wifi_config = {
        .ssid = WIFI_SSID,
        .password = WIFI_PASSWORD,
    };

    sdk_wifi_set_opmode(STATION_MODE);
    sdk_wifi_station_set_config(&wifi_config);
    sdk_wifi_station_connect();
}

const int led_gpio = 5; //D1, the GPIO pin that is connected to the LED

void led_write(bool on) {
    gpio_write(led_gpio, on ? 1 : 0);
}

void led_init() {
    gpio_enable(led_gpio, GPIO_OUTPUT);
    led_write(false);
}

//Degree symbol
static const uint8_t char_data[] = {
    0x0E, 0x0A, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const hd44780_t lcd = {
    .i2c_dev.bus = I2C_BUS,
    .i2c_dev.addr = ADDR,
    .font = HD44780_FONT_5X8,
    .lines = 2,
    .pins = {
        .rs = 0,
        .e  = 2,
        .d4 = 4,
        .d5 = 5,
        .d6 = 6,
        .d7 = 7,
        .bl = 3
    },
    .backlight = true
};

void lcd_init() {
    i2c_init(I2C_BUS, SCL_PIN, SDA_PIN, I2C_FREQ_100K);

    hd44780_init(&lcd);
    hd44780_upload_character(&lcd, 0, char_data);

    hd44780_gotoxy(&lcd, 0, 0);
    hd44780_puts(&lcd, "Temp:");

    hd44780_gotoxy(&lcd, 14, 0);
    hd44780_puts(&lcd, "\x08");
    hd44780_gotoxy(&lcd, 15, 0);
    hd44780_puts(&lcd, "C");

    hd44780_gotoxy(&lcd, 0, 1);
    hd44780_puts(&lcd, "Humidity:");

    hd44780_gotoxy(&lcd, 12, 1);
    hd44780_puts(&lcd, "%");
}

void temperature_sensor_identify_task(void *_args) {
    // We identify the WEMOS by flashing an LED.
    for (int i=0; i<3; i++) {
        for (int j=0; j<2; j++) {
            led_write(true);
            vTaskDelay(200 / portTICK_PERIOD_MS);
            led_write(false);
            vTaskDelay(200 / portTICK_PERIOD_MS);
        }
        vTaskDelay(500 / portTICK_PERIOD_MS);
    }
    led_write(false);
    vTaskDelete(NULL);
}

void temperature_sensor_identify(homekit_value_t _value) {
    printf("Temperature sensor identify\n");
    xTaskCreate(temperature_sensor_identify_task, "Temperature sensor identify", 128, NULL, 2, NULL);
}

void reset_configuration_task() {
    //Flash the LED first before we start the reset
    for (int i=0; i<3; i++) {
        led_write(true);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        led_write(false);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
    printf("Resetting Wifi Config\n");
    wifi_config_reset();
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    printf("Resetting HomeKit Config\n");
    homekit_server_reset();
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    printf("Restarting\n");
    sdk_system_restart();
    vTaskDelete(NULL);
}

void reset_configuration() {
    printf("Resetting Sensor configuration\n");
    xTaskCreate(reset_configuration_task, "Reset configuration", 256, NULL, 2, NULL);
}

homekit_characteristic_t temperature = HOMEKIT_CHARACTERISTIC_(CURRENT_TEMPERATURE, 0);
homekit_characteristic_t humidity    = HOMEKIT_CHARACTERISTIC_(CURRENT_RELATIVE_HUMIDITY, 0);

void temperature_sensor_task(void *_args) {
    gpio_set_pullup(SENSOR_PIN, false, false);

    float humidity_value, temperature_value;

    char temp[6], hum[4];

    while (1) {
        bool success = dht_read_float_data(
            DHT_TYPE_DHT11, SENSOR_PIN,
            &humidity_value, &temperature_value
        );
        if (success) {

            hd44780_gotoxy(&lcd, 10, 0);
            snprintf(temp, 5, "%f\n", temperature_value);
            hd44780_puts(&lcd, temp);

            hd44780_gotoxy(&lcd, 10, 1);
            snprintf(hum, 3, "%f\n", humidity_value);
            hd44780_puts(&lcd, hum);

            temperature.value.float_value = temperature_value;
            humidity.value.float_value = humidity_value;

            homekit_characteristic_notify(&temperature, HOMEKIT_FLOAT(temperature_value));
            homekit_characteristic_notify(&humidity, HOMEKIT_FLOAT(humidity_value));

        } else {
            printf("Could not read data from sensor\n");
        }

        vTaskDelay(3000 / portTICK_PERIOD_MS);
    }
}

void temperature_sensor_init() {
    xTaskCreate(temperature_sensor_task, "Temperatore Sensor", 256, NULL, 2, NULL);
}

homekit_accessory_t *accessories[] = {
    HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_thermostat, .services=(homekit_service_t*[]) {
        HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "Temperature Sensor"),
            HOMEKIT_CHARACTERISTIC(MANUFACTURER, "Sam"),
            HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "0012345"),
            HOMEKIT_CHARACTERISTIC(MODEL, "MyTemperatureSensor"),
            HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "1.0.0"),
            HOMEKIT_CHARACTERISTIC(IDENTIFY, temperature_sensor_identify),
            NULL
        }),
        HOMEKIT_SERVICE(TEMPERATURE_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "Temperature Sensor"),
            &temperature,
            NULL
        }),
        HOMEKIT_SERVICE(HUMIDITY_SENSOR, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "Humidity Sensor"),
            &humidity,
            NULL
        }),
        NULL
    }),
    NULL
};

homekit_server_config_t config = {
    .accessories = accessories,
    .password = "111-11-111",
    .setupId="2SA8", //For QR Code
};

//void on_wifi_ready() {
//    homekit_server_init(&config);
//}

void user_init(void) {
    uart_set_baud(0, 115200);

//    wifi_config_init("Temperature_Sensor", NULL, on_wifi_ready);
    wifi_init();
    led_init();
    lcd_init();
    temperature_sensor_init();
    homekit_server_init(&config);

}
maximkulkin commented 4 years ago

I have built this setup and your code worked fine for me:

IMG_0613

When I was searching for correct I2C address, I've seen stack overflow errors reported for temperature task. You're using 256 for it's stack size. Maybe it makes sense to increase it. Though when everything is set up properly, this message is not reported.

PS Not sure why, but despite me using 1602 with PCF8574-based LCD controller, I2C addresses 0x20-0x27 did not work for me. It worked when I tried using 0x3F address.

sam632 commented 4 years ago

Ok, I have increased the stack size but the problem still occurs, however I can deal with having to turn it on and off once after connecting to HomeKit.

Yes I have seen other people having the same problem, where 0x27 does not work but 0x3F does, no idea why. Thanks for your help.

alexandrerochasalles commented 3 years ago

Hi guys, first of all great job, and I'm sorry about the completely stupid question, but I'm very noob in this scenario.

Is it possible to compile using Arduino IDE, and if it's, how to include all this libraries? I have tried but couldn't find it at all.

Thanks a lot.

peros550 commented 3 years ago

This is repo is not compatible with Arduino, but someone ported it, you may want to check this: https://github.com/Mixiaoxiao/Arduino-HomeKit-ESP8266

Not sure though how stable it is

alexandrerochasalles commented 3 years ago

This is repo is not compatible with Arduino, but someone ported it, you may want to check this: https://github.com/Mixiaoxiao/Arduino-HomeKit-ESP8266

Not sure though how stable it is

Thank you my friend!!

sam632 commented 3 years ago

I was new to this when I started but the instructions are very easy to follow and there are a couple of videos on youtube such as https://youtu.be/b5VU_UWzeNI

If you have a mac just install docker and follow the instructions :)