Тут должна быть КДПВ, но на нее не хватило бюджета.
Замотивировавшись ответом от Tarson на мой комментарий к статье https://geektimes.ru/post/292801/ решил написать про основы программирования ESP8266 на C под FreeRTOS. Подробности под катом.
Шаг 0 — устройство
Для начала надо обзавестись устройством c ESP8266, желательно, чтобы там был разведен USB to UART, чтобы не пришлось городить программатор. Я свои бесчеловечные опыты провожу на NodeMCU.
Итак, шаг 1 — собираем тулчейн.
Для начала надо обзавестись компьютером с установленным на нем дистрибутивом Linux (у меня OpenSUSE Leap). Идем на гитхаб по ссылке тыц, читаем инструкцию по сборке, устанавливаем необходимые зависимости, клонируем репозиторий, и собираем. Я клонировал в /opt/ESP и перед сборкой правил Makefile, выставив переменные:
STANDALONE = n
VENDOR_SDK = 2.1.0
Далее можно в ~/.bashrc добавить в PATH путь к бинарникам тулчейна:
export PATH=/opt/ESP/esp-open-sdk/xtensa-lx106-elf/bin:$PATH
Шаг 2 — получаем SDK
Идем на гитхаб (тыньк), читаем инструкции, клонируем (например в /opt/ESP). Далее задаем любимым способом (например через ~/.bashrc) переменную окружения ESP8266_SDK_PATH:
export ESP8266_SDK_PATH=/opt/ESP/esp-open-rtos
Шаг 3 — создаем проект
Заходим в директорию examples в директории с SDK и копируем любой понравившийся пример. Импортируем/открываем проект в любимой среде разработки, мазохисты могут использовать текстовый редактор. Я предпочитаю NetBeans — у него неплохая поддержка C/C++ проектов, в том числе на основе Makefile. Собирается проект с помощью make, прошивается с помощью make flash. В файле local.mk можно настроить параметры для прошивки своего устройства (размер и режим обращения к флеш памяти, например).
Шаг 4 — программируем
Проводим анализ требований, предметной области, составляем ТЗ согласно ГОСТ 34.602-89, после чего можно начинать писать код. :) Светодиодами мигать не буду, т. к. их у меня нет, поэтому в качестве HelloWorld будет чтение данных с датчика AM2302 (он же DHT22) и отправка их по протоколу MQTT на сервер.
Для того, чтобы использовать дополнительные модули, например MQTT или DHT, их необходимо добавить в Makefile:
PROGRAM=fffmeteo
EXTRA_COMPONENTS = extras/paho_mqtt_c extras/dht
include $(ESP8266_SDK_PATH)/common.mk
#ifndef MAIN_H
#define MAIN_H
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <semphr.h>
#define DEBUG
#ifdef DEBUG
#define debug(args...) printf("--- "); printf(args)
#define SNTP_DEBUG_ENABLED true
#else
#define debug(args...)
#define SNTP_DEBUG_ENABLED false
#endif
#define WIFI_SSID "kosmonaFFFt"
#define WIFI_PASS "mysupermegapassword"
#define MQTT_HOST "m11.cloudmqtt.com"
#define MQTT_PORT 16464
#define MQTT_USER "kosmonaFFFt"
#define MQTT_PASS "mysupermegapassword"
#define MQTT_TOPIC "/meteo"
#define NTP_SERVER "pool.ntp.org"
#define UART0_BAUD 9600
#define STACK_SIZE 512
#define INIT_TASK_PRIORITY (configTIMER_TASK_PRIORITY + 1)
#define MEASUREMENT_TASK_PRIORITY (INIT_TASK_PRIORITY + 1)
#define SENDING_DATA_TASK_PRIORITY (MEASUREMENT_TASK_PRIORITY + 1)
#define MEASUREMENTS_PERIOD_S 59
#define MAX_MEASUREMENTS_COUNT 16
#define SEND_PERIOD_S 120
#define RUN_SNTP_SYNC_PERIOD 5
#define MS(x) (x / portTICK_PERIOD_MS)
#define AM2302_PIN 5
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __cplusplus
}
#endif
#endif /* MAIN_H */
#include "main.h"
#include "sntp.h"
#include <esp/uart.h>
#include <espressif/esp_common.h>
#include <paho_mqtt_c/MQTTESP8266.h>
#include <paho_mqtt_c/MQTTClient.h>
#include <dht/dht.h>
//-----------------------------------------------------------------------------+
// Measurements task section. |
//-----------------------------------------------------------------------------+
struct measurement_results
{
time_t timestamp;
int am2302_humidity;
int am2302_temperature;
};
static QueueHandle_t measurements_queue;
void measurement_task(void *arg)
{
int16_t humidity;
int16_t temperature;
struct measurement_results measurements;
while (true)
{
debug("MEASUREMENTS: Start measurements...n");
measurements.timestamp = time(NULL);
bool success = dht_read_data(DHT_TYPE_DHT22, AM2302_PIN, &humidity, &temperature);
if (success && temperature >= -500 && temperature <= 1500 && humidity >= 0 && humidity <= 1000)
{
measurements.am2302_humidity = humidity;
measurements.am2302_temperature = temperature;
}
else
{
debug("MEASUREMENT: Error! Cannot read data from AM2302!!!n");
measurements.am2302_humidity = INT_MIN;
measurements.am2302_temperature = INT_MIN;
}
debug("MEASUREMENTS: Measurements finished...n");
xQueueSendToBack(measurements_queue, &measurements, MS(250));
vTaskDelay(MS(MEASUREMENTS_PERIOD_S * 1000));
}
vTaskDelete(NULL);
}
//-----------------------------------------------------------------------------+
// Sending data task section. |
//-----------------------------------------------------------------------------+
static uint8_t mqtt_buf[512];
static uint8_t mqtt_readbuf[128];
void sending_data_task(void *arg)
{
mqtt_network_t network;
mqtt_network_new(&network);
mqtt_client_t client = mqtt_client_default;
mqtt_packet_connect_data_t data = mqtt_packet_connect_data_initializer;
uint8_t sntp_sync_counter = 0;
while (true)
{
debug("MQTT: ConnectNetwork...n");
int err = mqtt_network_connect(&network, MQTT_HOST, MQTT_PORT);
if (err)
{
debug("MQTT: Error!!! ConnectNetwork ERROR!n");
vTaskDelay(MS(5 * 1000));
continue;
}
else
{
debug("MQTT: ConnectNetwork success...n");
}
// TODO: add check for errors!!!
// TODO: replace magic constants!!!
mqtt_client_new(&client, &network, 5000, mqtt_buf, 100, mqtt_readbuf, 100);
data.willFlag = 0;
data.MQTTVersion = 3;
data.clientID.cstring = "fff";
data.username.cstring = MQTT_USER;
data.password.cstring = MQTT_PASS;
data.keepAliveInterval = 10;
data.cleansession = 0;
err = mqtt_connect(&client, &data);
if (err)
{
debug("MQTT: Error!!! MQTTConnect ERROR!n");
vTaskDelay(MS(5 * 1000));
continue;
}
else
{
debug("MQTT: MQTTConnect success...n");
}
struct measurement_results msg;
while (xQueueReceive(measurements_queue, &msg, 0) == pdTRUE)
{
if (msg.am2302_humidity == INT_MIN || msg.am2302_temperature == INT_MIN)
{
debug("MQTT: Got invalid message, no publishing!!!n");
continue;
}
debug("MQTT: Got message to publish...n");
debug(" timestamp: %ldn", msg.timestamp);
debug(" am2302_humidity: %.1fn", msg.am2302_humidity / 10.0);
debug(" am2302_temperature: %.1fn", msg.am2302_temperature / 10.0);
msg.timestamp = htonl(msg.timestamp);
msg.am2302_humidity = htonl(msg.am2302_humidity);
msg.am2302_temperature = htonl(msg.am2302_temperature);
mqtt_message_t message;
message.payload = &msg;
message.payloadlen = sizeof (msg);
message.dup = 0;
message.qos = MQTT_QOS1;
message.retained = 0;
err = mqtt_publish(&client, MQTT_TOPIC, &message);
if (err)
{
debug("MQTT: Error!!! Error while publishing message!n");
}
else
{
debug("MQTT: Successfully publish message...n");
}
}
mqtt_disconnect(&client);
mqtt_network_disconnect(&network);
++sntp_sync_counter;
if (sntp_sync_counter == RUN_SNTP_SYNC_PERIOD)
{
sntp_sync(NTP_SERVER, NULL, arg);
sntp_sync_counter = 0;
}
vTaskDelay(MS(SEND_PERIOD_S * 1000));
}
vTaskDelete(NULL);
}
//-----------------------------------------------------------------------------+
// Init task section. |
//-----------------------------------------------------------------------------+
/**
* This semaphore is taken during sntp sync and released after it finished.
*/
static SemaphoreHandle_t init_task_sem;
/**
* Set time and free init task semaphore.
* @param error unused
* @param arg unused
*/
void init_sntp_callback(int8_t error, void* arg)
{
time_t ts = time(NULL);
debug("TIME: %s", ctime(&ts));
xSemaphoreGive(init_task_sem);
}
/**
* Connection parameters.
*/
static struct sdk_station_config STATION_CONFIG = {
.ssid = WIFI_SSID,
.password = WIFI_PASS,
};
void init_task(void* arg)
{
debug("INIT: setting pins...n");
gpio_set_pullup(AM2302_PIN, false, false);
debug("INIT: Set station parameters...n");
sdk_wifi_station_set_auto_connect(false);
sdk_wifi_station_set_config(&STATION_CONFIG);
debug("Station parameters has been set.n");
debug("INIT: Connecting to AP...n");
sdk_wifi_station_connect();
while (sdk_wifi_station_get_connect_status() != STATION_GOT_IP)
{
vTaskDelay(MS(1000));
}
debug("INIT: Connection to AP has been estabilished...n");
debug("INIT: Start SNTP synchronization...n");
init_task_sem = xSemaphoreCreateMutex();
if (!init_task_sem)
{
debug("INIT: Cannot create init task semaphore!!!");
return;
}
xSemaphoreTake(init_task_sem, 0);
sntp_init();
sntp_sync(NTP_SERVER, init_sntp_callback, arg);
BaseType_t result = pdFALSE;
while (true)
{
debug("INIT: Trying to take init task semaphore...n");
result = xSemaphoreTake(init_task_sem, MS(5 * 1000));
if (result == pdTRUE)
{
debug("INIT: Init task semaphore is taken...n");
break;
}
}
measurements_queue = xQueueCreate(MAX_MEASUREMENTS_COUNT, sizeof (struct measurement_results));
if (!measurements_queue)
{
debug("INIT: ERROR!!! Cannot create queue for measurements!n");
goto fail;
}
result = xTaskCreate(measurement_task, "measurement_task", STACK_SIZE, NULL, MEASUREMENT_TASK_PRIORITY, NULL);
if (result == pdFAIL)
{
debug("INIT: Measurement task creation failed!!!n");
goto fail;
}
debug("INIT: Measurement task created...n");
result = xTaskCreate(sending_data_task, "send_data_task", STACK_SIZE, NULL, SENDING_DATA_TASK_PRIORITY, NULL);
if (result == pdFAIL)
{
debug("INIT: Send task creation failed!!!n");
goto fail;
}
debug("INIT: Send data task created...n");
fail:
vSemaphoreDelete(init_task_sem);
vTaskDelete(NULL);
}
//-----------------------------------------------------------------------------+
// Application entry point. |
//-----------------------------------------------------------------------------+
void user_init(void)
{
debug("USER_INIT: SDK version: %sn", sdk_system_get_sdk_version());
debug("USER_INIT: sizeof (int): %dn", sizeof (int));
debug("USER_INIT: sizeof (float): %dn", sizeof (float));
debug("USER_INIT: sizeof (time_t): %dn", sizeof (time_t));
uart_set_baud(0, UART0_BAUD);
BaseType_t result = xTaskCreate(init_task, (const char * const) "init_task", STACK_SIZE, NULL, INIT_TASK_PRIORITY, NULL);
if (!result)
{
debug("USER_INIT: Cannot create init task!!!");
return;
}
}
#ifndef SNTP_H
#define SNTP_H
#include <time.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define SNTP_ERR_OK 0
#define SNTP_ERR_CONTEXT -1
#define SNTP_ERR_DNS -2
#define SNTP_ERR_UDP_PCB_ALLOC -3
#define SNTP_ERR_PBUF_ALLOC -4
#define SNTP_ERR_SEND -5
#define SNTP_ERR_RECV_ADDR_PORT -6;
#define SNTP_ERR_RECV_SIZE -7
#define SNTP_ERR_RECV_MODE -8
#define SNTP_ERR_RECV_STRATUM -9
typedef void (*sntp_sync_callback)(int8_t error, void *arg);
void sntp_init();
void sntp_sync(char *server, sntp_sync_callback callback, void *callback_arg);
time_t sntp_get_rtc_time(int32_t *us);
void sntp_update_rtc(time_t t, uint32_t us);
#ifdef __cplusplus
}
#endif
#endif /* SNTP_H */
#include "main.h"
#include "sntp.h"
#include <time.h>
#include <string.h>
#include <lwip/ip_addr.h>
#include <lwip/err.h>
#include <lwip/dns.h>
#include <lwip/udp.h>
#include <esp/rtc_regs.h>
#include <espressif/esp_common.h>
#define TIMER_COUNT RTC.COUNTER
/**
* Daylight settings.
* Base calculated with value obtained from NTP server (64 bits).
*/
#define SNTP_BASE (*((uint64_t*) RTC.SCRATCH))
/**
* Timer value when base was obtained.
*/
#define SNTP_TIME_REF (RTC.SCRATCH[2])
/**
* Calibration value.
*/
#define SNTP_CALIBRATION (RTC.SCRATCH[3])
/**
* SNTP modes.
*/
#define SNTP_MODE_CLIENT 0x03
#define SNTP_MODE_SERVER 0x04
#define SNTP_MODE_BROADCAST 0x05
/**
* Kiss-of-death code.
*/
#define SNTP_STRATUM_KOD 0x00
#define SNTP_OFFSET_LI_VN_MODE 0
#define SNTP_OFFSET_STRATUM 1
#define SNTP_OFFSET_RECEIVE_TIME 32
#define DIFF_SEC_1900_1970 (2208988800UL)
struct sntp_message
{
uint8_t li_vn_mode;
uint8_t stratum;
uint8_t poll;
uint8_t precision;
uint32_t root_delay;
uint32_t root_dispersion;
uint32_t reference_identifier;
uint32_t reference_timestamp[2];
uint32_t originate_timestamp[2];
uint32_t receive_timestamp[2];
uint32_t transmit_timestamp[2];
} __attribute__ ((packed));
struct sntp_sync_context
{
ip_addr_t ip_address;
sntp_sync_callback callback;
void* callback_arg;
};
void sntp_init()
{
SNTP_BASE = 0;
SNTP_CALIBRATION = 1;
SNTP_TIME_REF = TIMER_COUNT;
}
void on_dns_found(const char* name, ip_addr_t* ipaddr, void* arg);
void on_udp_recv(void* arg, struct udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port);
void sntp_sync(char* server, sntp_sync_callback callback, void* callback_arg)
{
int result = ERR_OK;
debug("SNTP: Start SNTP synchronization, allocating memory for context...n");
struct sntp_sync_context* context = malloc(sizeof (struct sntp_sync_context));
if (!context)
{
debug("SNTP: Error!!! Cannot allocate memory for context!n");
result = SNTP_ERR_CONTEXT;
goto fail;
}
context->callback = callback;
context->callback_arg = callback_arg;
debug("SNTP: Context successfully allocated...n");
debug("SNTP: Start DNS lookup...n");
err_t err = dns_gethostbyname(server, &(context->ip_address), on_dns_found, context);
if (!(err == ERR_OK || err == ERR_INPROGRESS))
{
debug("SNTP: Error!!! DNS lookup error!n");
result = SNTP_ERR_DNS;
goto fail;
}
return;
fail:
if (context)
{
free(context);
}
if (callback)
{
callback(result, callback_arg);
}
}
//
//==============================================================================================================================================================
//
void on_dns_found(const char* name, ip_addr_t* ipaddr, void* arg)
{
debug("SNTP: Start DNS lookup successfully finished...n");
int result = ERR_OK;
struct sntp_sync_context* context = arg;
sntp_sync_callback callback = context->callback;
void* callback_arg = context->callback_arg;
debug("SNTP: Creating upd_pcb...n");
struct udp_pcb* sntp_pcb = udp_new();
if (!sntp_pcb)
{
debug("SNTP: Error!!! Cannot allocate udp_pcb!n");
result = SNTP_ERR_UDP_PCB_ALLOC;
goto fail;
}
debug("SNTP: Successfully created upd_pcb...n");
debug("SNTP: Allocating pbuf...n");
struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, sizeof (struct sntp_message), PBUF_RAM);
if (!p)
{
debug("SNTP: Error!!! DNS lookup error!n");
result = SNTP_ERR_PBUF_ALLOC;
goto fail;
}
struct sntp_message* message = p->payload;
memset(message, 0, sizeof (struct sntp_message));
message->li_vn_mode = 0b00100011; // li = 00, vn = 4, mode = 3
debug("SNTP: Pbuf allocated successfully...n");
debug("SNTP: Sending data to server...n");
udp_recv(sntp_pcb, on_udp_recv, context);
err_t err = udp_sendto(sntp_pcb, p, ipaddr, 123);
pbuf_free(p);
if (err != ERR_OK)
{
debug("SNTP: Error!!! data sending error!n");
result = SNTP_ERR_SEND;
goto fail;
}
debug("SNTP: Data sent...n");
return;
fail:
if (context)
{
free(context);
}
if (sntp_pcb)
{
udp_remove(sntp_pcb);
}
if (callback)
{
callback(result, callback_arg);
}
}
void on_udp_recv(void* arg, struct udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port)
{
debug("SNTP: Response has successfully received...n");
int result = ERR_OK;
struct sntp_sync_context* context = arg;
sntp_sync_callback callback = context->callback;
void* callback_arg = context->callback_arg;
debug("SNTP: Checking response size...n");
if (p->tot_len < sizeof (struct sntp_message))
{
debug("SNTP: Error!!! Invalid response size!n");
result = SNTP_ERR_RECV_SIZE;
goto fail;
}
debug("SNTP: Response size is OK...n");
debug("SNTP: Checking mode...n");
u8_t mode = 0x0;
pbuf_copy_partial(p, &mode, sizeof (mode), SNTP_OFFSET_LI_VN_MODE);
mode &= 0b00000111;
if (mode != SNTP_MODE_SERVER && mode != SNTP_MODE_BROADCAST)
{
debug("SNTP: Error!!! Invalid mode!n");
result = SNTP_ERR_RECV_MODE;
goto fail;
}
debug("SNTP: Mode is OK...n");
debug("SNTP: Checking stratum...n");
u8_t stratum = 0x0;
pbuf_copy_partial(p, &stratum, sizeof (stratum), SNTP_OFFSET_STRATUM);
if (stratum == SNTP_STRATUM_KOD)
{
debug("SNTP: Error!!! Kiss of death!n");
result = SNTP_ERR_RECV_STRATUM;
goto fail;
}
debug("SNTP: Stratum is OK...n");
debug("SNTP: Updating system timer...n");
uint32_t receive_time[2];
pbuf_copy_partial(p, &receive_time, 2 * sizeof (uint32_t), SNTP_OFFSET_RECEIVE_TIME);
time_t t = ntohl(receive_time[0]) - DIFF_SEC_1900_1970;
uint32_t us = ntohl(receive_time[1]) / 4295;
sntp_update_rtc(t, us);
debug("SNTP: System timer updated...n");
fail:
if (context)
{
free(context);
}
if (pcb)
{
udp_remove(pcb);
}
if (callback)
{
callback(result, callback_arg);
}
}
/**
* Check if a timer wrap has occurred. Compensate sntp_base reference
* if affirmative.
* TODO: think about multitasking and race conditions.
*/
inline void sntp_check_timer_wrap(uint32_t current_value)
{
if (current_value < SNTP_TIME_REF)
{
// Timer wrap has occurred, compensate by subtracting 2^32 to ref.
SNTP_BASE -= 1LLU << 32;
}
}
/**
* Return secs. If us is not a null pointer, fill it with usecs
*/
time_t sntp_get_rtc_time(int32_t *us)
{
time_t secs;
uint32_t tim;
uint64_t base;
tim = TIMER_COUNT;
// Check for timer wrap.
sntp_check_timer_wrap(tim);
base = SNTP_BASE + tim - SNTP_TIME_REF;
secs = base * SNTP_CALIBRATION / (1000000U << 12);
if (us)
{
*us = base * SNTP_CALIBRATION % (1000000U << 12);
}
return secs;
}
/**
* Update RTC timer. Called by SNTP module each time it receives an update.
*/
void sntp_update_rtc(time_t t, uint32_t us)
{
// Apply daylight and timezone correction
// DEBUG: Compute and print drift
int64_t sntp_current = SNTP_BASE + TIMER_COUNT - SNTP_TIME_REF;
int64_t sntp_correct = (((uint64_t) us + (uint64_t) t * 1000000U) << 12) / SNTP_CALIBRATION;
debug("RTC Adjust: drift = %ld ticks, cal = %dn", (time_t) (sntp_correct - sntp_current), SNTP_CALIBRATION);
SNTP_TIME_REF = TIMER_COUNT;
SNTP_CALIBRATION = sdk_system_rtc_clock_cali_proc();
SNTP_BASE = (((uint64_t) us + (uint64_t) t * 1000000U) << 12) / SNTP_CALIBRATION;
}
/**
* Syscall implementation. doesn't seem to use tzp.
*/
int _gettimeofday_r(struct _reent* r, struct timeval* tp, void* tzp)
{
// Syscall defined by xtensa newlib defines tzp as void*
// So it looks like it is not used. Also check tp is not NULL
if (tzp || !tp)
{
return EINVAL;
}
tp->tv_sec = sntp_get_rtc_time((int32_t*) & tp->tv_usec);
return 0;
}
Лирическое отступление по поводу наличия своего кода синхронизации времени по SNTP: в extensions из SDK уже есть такой модуль, но мне он почему-то не понравился (давно было, уже не помню почему), поэтому я тот код нагло скопипастил и доработал под себя.
Работает все просто: при старте контроллера запускается задача инициализации, которая подключается к точке доступа, синхронизирует время по SNTP, запускает задичи измерения температуры с влажностью и отправки данных на сервер, после чего самоубивается. Задачка измерения опрашивает датчик раз в 59 секунд и складывает результаты в очередь, задача отправки запускается раз в 2 минуты, читает данные из очереди и отправляет на MQTT сервер.
Теоретичесик, можно писать и на C++,
Шаг 5 — заключение, куда же без него.
Таким вот нехитрым образом, с помощью языка C и рук с небольшим радиусом кривизны можно запрограммировать контроллер ESP8266. Основное преимущество данного подхода перед скриптовыми решениями (например LUA или MicroPython) в полном контроле над составом и ресурсами прошивки, и возможность впихнуть больше функциональности при ограниченных ресурсах контроллера. Так же есть вариант использования RTOS SDK или NONOS SDK от Espressif, но с первым у меня не срослось, а второй не пробовал использовать. Если кому-то будет интересно, а так же когда сам разберусь, могу написать следующий туториал про OTA (обновление прошивки по воздуху).
Немного результатов работы данного кода:
SDK version: 0.9.9
--- USER_INIT: sizeof (int): 4
--- USER_INIT: sizeof (float): 4
--- USER_INIT: sizeof (time_t): 4
mode : sta(18:fe:34:d2:c5:a7)
add if0
--- INIT: setting pins...
--- INIT: Set station parameters...
--- Station parameters has been set.
--- INIT: Connecting to AP...
scandone
add 0
aid 2
cnt
connected with kosmonaFFFt, channel 1
dhcp client start...
ip:192.168.1.21,mask:255.255.255.0,gw:192.168.1.1
--- INIT: Connection to AP has been estabilished...
--- INIT: Start SNTP synchronization...
--- SNTP: Start SNTP synchronization, allocating memory for context...
--- SNTP: Context successfully allocated...
--- SNTP: Start DNS lookup...
--- INIT: Trying to take init task semaphore...
--- SNTP: Start DNS lookup successfully finished...
--- SNTP: Creating upd_pcb...
--- SNTP: Successfully created upd_pcb...
--- SNTP: Allocating pbuf...
--- SNTP: Pbuf allocated successfully...
--- SNTP: Sending data to server...
--- SNTP: Data sent...
--- SNTP: Response has successfully received...
--- SNTP: Checking response size...
--- SNTP: Response size is OK...
--- SNTP: Checking mode...
--- SNTP: Mode is OK...
--- SNTP: Checking stratum...
--- SNTP: Stratum is OK...
--- SNTP: Updating system timer...
--- RTC Adjust: drift = 1220897578 ticks, cal = 1
--- SNTP: System timer updated...
--- TIME: Thu Sep 21 19:20:36 2017
--- INIT: Init task semaphore is taken...
--- MEASUREMENTS: Start measurements...
--- MEASUREMENTS: Measurements finished...
--- INIT: Measurement task created...
--- MQTT: ConnectNetwork...
--- INIT: Send data task created...
--- MQTT: ConnectNetwork success...
--- MQTT: MQTTConnect success...
--- MQTT: Got message to publish...
--- timestamp: 1506021636
--- am2302_humidity: 55.8
--- am2302_temperature: 23.4
--- MQTT: Successfully publish message...
--- MEASUREMENTS: Start measurements...
--- MEASUREMENTS: Measurements finished...
--- MEASUREMENTS: Start measurements...
--- MEASUREMENTS: Measurements finished...
--- MQTT: ConnectNetwork...
--- MQTT: ConnectNetwork success...
--- MQTT: MQTTConnect success...
--- MQTT: Got message to publish...
--- timestamp: 1506021694
--- am2302_humidity: 55.2
--- am2302_temperature: 23.8
--- MQTT: Successfully publish message...
--- MQTT: Got message to publish...
--- timestamp: 1506021751
--- am2302_humidity: 56.5
--- am2302_temperature: 24.4
--- MQTT: Successfully publish message...
--- MEASUREMENTS: Start measurements...
--- MEASUREMENTS: Measurements finished...
--- MEASUREMENTS: Start measurements...
--- MEASUREMENTS: Measurements finished...
--- MQTT: ConnectNetwork...
--- MQTT: ConnectNetwork success...
--- MQTT: MQTTConnect success...
--- MQTT: Got message to publish...
--- timestamp: 1506021807
--- am2302_humidity: 53.0
--- am2302_temperature: 24.7
--- MQTT: Successfully publish message...
--- MQTT: Got message to publish...
--- timestamp: 1506021863
--- am2302_humidity: 52.3
--- am2302_temperature: 24.8
--- MQTT: Successfully publish message...
--- MEASUREMENTS: Start measurements...
--- MEASUREMENTS: Measurements finished...
--- MEASUREMENTS: Start measurements...
--- MEASUREMENTS: Measurements finished...
--- MQTT: ConnectNetwork...
--- MQTT: ConnectNetwork success...
--- MQTT: MQTTConnect success...
--- MQTT: Got message to publish...
--- timestamp: 1506021919
--- am2302_humidity: 52.0
--- am2302_temperature: 24.9
--- MQTT: Successfully publish message...
--- MQTT: Got message to publish...
--- timestamp: 1506021975
--- am2302_humidity: 53.3
--- am2302_temperature: 25.2
--- MQTT: Successfully publish message...
P.S. Для работы с UART на PC рекомендую использовать minicom (консоль), или cutecom (GUI).
Полезные ссылки:
Автор: Антон