inital source files
This commit is contained in:
parent
1056b525d6
commit
0dd50d05af
9
software/CMakeLists.txt
Normal file
9
software/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
set(EXTRA_COMPONENT_DIRS $ENV{ESP_IDF_LIB_PATH}/components)
|
||||||
|
|
||||||
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
|
# in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(smart-oil-heating-control-system)
|
7
software/main/CMakeLists.txt
Normal file
7
software/main/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
idf_component_register(SRCS "main.c"
|
||||||
|
"http_metrics.c"
|
||||||
|
"inputs.c"
|
||||||
|
"outputs.c"
|
||||||
|
"control.c"
|
||||||
|
"safety.c"
|
||||||
|
INCLUDE_DIRS ".")
|
19
software/main/Kconfig.projbuild
Normal file
19
software/main/Kconfig.projbuild
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
menu "Smart Oil Heating Control System"
|
||||||
|
|
||||||
|
config SSID
|
||||||
|
string "SSID"
|
||||||
|
default "my WiFi SSID"
|
||||||
|
config WIFI_PASSWORD
|
||||||
|
string "WIFI_PASSWORD"
|
||||||
|
default "my WIFI Password"
|
||||||
|
config STATIC_IP_ADDR
|
||||||
|
string "Static IPv4 address"
|
||||||
|
default "192.168.0.42"
|
||||||
|
config STATIC_IP_NETMASK
|
||||||
|
string "Static IPv4 netmask"
|
||||||
|
default "255.255.0.0"
|
||||||
|
config STATIC_GATEWAY_IP_ADDR
|
||||||
|
string "Static IPv4 gateway address"
|
||||||
|
default "192.168.0.1"
|
||||||
|
|
||||||
|
endmenu
|
0
software/main/control.c
Normal file
0
software/main/control.c
Normal file
0
software/main/control.h
Normal file
0
software/main/control.h
Normal file
154
software/main/http_metrics.c
Normal file
154
software/main/http_metrics.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
#include "http_metrics.h"
|
||||||
|
|
||||||
|
static EventGroupHandle_t s_wifi_event_group;
|
||||||
|
|
||||||
|
static const char *TAG = "esp32-env-exp-http_metrics";
|
||||||
|
|
||||||
|
char caHtmlResponse[HTML_RESPONSE_SIZE];
|
||||||
|
SemaphoreHandle_t xMutexAccessMetricResponse = NULL;
|
||||||
|
|
||||||
|
void vSetMetrics(sMetric* paMetrics, uint16_t u16Size) {
|
||||||
|
|
||||||
|
if( xSemaphoreTake( xMutexAccessMetricResponse, ( TickType_t ) 100 ) == pdTRUE )
|
||||||
|
{
|
||||||
|
memset(caHtmlResponse,0,strlen(caHtmlResponse));
|
||||||
|
for(uint16_t u16Index = 0U; u16Index < u16Size; u16Index++) {
|
||||||
|
char caValueBuffer[64];
|
||||||
|
sprintf(caValueBuffer, " %f", paMetrics[u16Index].fMetricValue);
|
||||||
|
//printf("%s\n", caValueBuffer);
|
||||||
|
strcat(caHtmlResponse, paMetrics[u16Index].caMetricName);
|
||||||
|
strcat(caHtmlResponse, caValueBuffer);
|
||||||
|
strcat(caHtmlResponse, "\n");
|
||||||
|
}
|
||||||
|
xSemaphoreGive( xMutexAccessMetricResponse );
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "[SET] Unable to obtain mutex for metric response");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void event_handler(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
|
||||||
|
{
|
||||||
|
esp_wifi_connect();
|
||||||
|
}
|
||||||
|
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
||||||
|
{
|
||||||
|
esp_wifi_connect();
|
||||||
|
ESP_LOGI(TAG, "Retry to connect to the AP");
|
||||||
|
}
|
||||||
|
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
||||||
|
{
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
|
ESP_LOGI(TAG, "Got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect_wifi(void)
|
||||||
|
{
|
||||||
|
s_wifi_event_group = xEventGroupCreate();
|
||||||
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
|
esp_netif_t *my_sta = esp_netif_create_default_wifi_sta();
|
||||||
|
esp_netif_dhcpc_stop(my_sta);
|
||||||
|
esp_netif_ip_info_t ip_info;
|
||||||
|
ip_info.ip.addr = ipaddr_addr(CONFIG_STATIC_IP_ADDR);
|
||||||
|
ip_info.gw.addr = ipaddr_addr(CONFIG_STATIC_GATEWAY_IP_ADDR);
|
||||||
|
ip_info.netmask.addr = ipaddr_addr(CONFIG_STATIC_IP_NETMASK);
|
||||||
|
esp_netif_set_ip_info(my_sta, &ip_info);
|
||||||
|
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
esp_event_handler_instance_t instance_any_id;
|
||||||
|
esp_event_handler_instance_t instance_got_ip;
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||||
|
ESP_EVENT_ANY_ID,
|
||||||
|
&event_handler,
|
||||||
|
NULL,
|
||||||
|
&instance_any_id));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
|
||||||
|
IP_EVENT_STA_GOT_IP,
|
||||||
|
&event_handler,
|
||||||
|
NULL,
|
||||||
|
&instance_got_ip));
|
||||||
|
|
||||||
|
wifi_config_t wifi_config = {
|
||||||
|
.sta = {
|
||||||
|
.ssid = CONFIG_SSID,
|
||||||
|
.password = CONFIG_WIFI_PASSWORD,
|
||||||
|
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||||
|
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||||
|
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||||
|
pdFALSE,
|
||||||
|
pdFALSE,
|
||||||
|
portMAX_DELAY);
|
||||||
|
|
||||||
|
if (bits & WIFI_CONNECTED_BIT)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Connected to ap SSID:%s", CONFIG_SSID);
|
||||||
|
}
|
||||||
|
else if (bits & WIFI_FAIL_BIT)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Failed to connect to SSID:%s", CONFIG_SSID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Unexpected event");
|
||||||
|
}
|
||||||
|
vEventGroupDelete(s_wifi_event_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t get_metrics_handler(httpd_req_t *req)
|
||||||
|
{
|
||||||
|
if( xSemaphoreTake( xMutexAccessMetricResponse, ( TickType_t ) 100 ) == pdTRUE )
|
||||||
|
{
|
||||||
|
esp_err_t err = httpd_resp_send(req, caHtmlResponse, HTTPD_RESP_USE_STRLEN);
|
||||||
|
xSemaphoreGive( xMutexAccessMetricResponse );
|
||||||
|
return err;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "[GET] Unable to obtain mutex for metric response");
|
||||||
|
return httpd_resp_send(req, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_uri_t uri_get = {
|
||||||
|
.uri = "/metrics",
|
||||||
|
.method = HTTP_GET,
|
||||||
|
.handler = get_metrics_handler,
|
||||||
|
.user_ctx = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
httpd_handle_t setup_server(void)
|
||||||
|
{
|
||||||
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
|
config.server_port = 9100;
|
||||||
|
httpd_handle_t server = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
xMutexAccessMetricResponse = xSemaphoreCreateBinary();
|
||||||
|
if(xMutexAccessMetricResponse == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Unable to create mutex for metric response");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(300*60)); //wait 5min before restart
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
|
xSemaphoreGive( xMutexAccessMetricResponse );
|
||||||
|
|
||||||
|
if (httpd_start(&server, &config) == ESP_OK)
|
||||||
|
{
|
||||||
|
httpd_register_uri_handler(server, &uri_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
40
software/main/http_metrics.h
Normal file
40
software/main/http_metrics.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef H_HTTPS_METRICS
|
||||||
|
#define H_HTTPS_METRICS
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "spi_flash_mmap.h"
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include <lwip/sockets.h>
|
||||||
|
#include <lwip/sys.h>
|
||||||
|
#include <lwip/api.h>
|
||||||
|
#include <lwip/netdb.h>
|
||||||
|
|
||||||
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
|
#define WIFI_FAIL_BIT BIT1
|
||||||
|
#define HTML_RESPONSE_SIZE 256U
|
||||||
|
#define METRIC_NAME_MAX_SIZE 64U
|
||||||
|
#define METRIC_MAX_COUNT 32U
|
||||||
|
|
||||||
|
typedef struct _metric {
|
||||||
|
char caMetricName[METRIC_NAME_MAX_SIZE];
|
||||||
|
float fMetricValue;
|
||||||
|
} sMetric;
|
||||||
|
|
||||||
|
|
||||||
|
void connect_wifi(void);
|
||||||
|
httpd_handle_t setup_server(void);
|
||||||
|
void vSetMetrics(sMetric* paMetrics, uint16_t u16Size);
|
||||||
|
|
||||||
|
#endif /* H_HTTPS_METRICS */
|
0
software/main/inputs.c
Normal file
0
software/main/inputs.c
Normal file
0
software/main/inputs.h
Normal file
0
software/main/inputs.h
Normal file
181
software/main/main.c
Normal file
181
software/main/main.c
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
#include <esp_system.h>
|
||||||
|
#include <bmp280.h>
|
||||||
|
#include <dht.h>
|
||||||
|
#include <aht.h>
|
||||||
|
#include <veml7700.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include "freertos/timers.h"
|
||||||
|
|
||||||
|
#include "http_metrics.h"
|
||||||
|
|
||||||
|
#define I2C_MASTER_SCL 19
|
||||||
|
#define I2C_MASTER_SDA 18
|
||||||
|
|
||||||
|
#define BMP280
|
||||||
|
#define DHT11
|
||||||
|
//#define AHT10
|
||||||
|
//#define VEML7700
|
||||||
|
|
||||||
|
#ifdef DHT11
|
||||||
|
#define CONFIG_EXAMPLE_DATA_GPIO 17
|
||||||
|
#define SENSOR_TYPE DHT_TYPE_DHT11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AHT10
|
||||||
|
#define AHT_TYPE AHT_TYPE_AHT1x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char *TAG = "smart-oil-heater-control-system";
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "starting ...");
|
||||||
|
|
||||||
|
//Initialize NVS
|
||||||
|
esp_err_t ret = nvs_flash_init();
|
||||||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
connect_wifi(); //will return if successful
|
||||||
|
setup_server();
|
||||||
|
|
||||||
|
sMetric aMetrics[METRIC_MAX_COUNT];
|
||||||
|
|
||||||
|
/*Sensor Init*/
|
||||||
|
ESP_ERROR_CHECK(i2cdev_init());
|
||||||
|
|
||||||
|
#ifdef BMP280
|
||||||
|
bmp280_params_t params;
|
||||||
|
bmp280_init_default_params(¶ms);
|
||||||
|
bmp280_t devBMP280;
|
||||||
|
memset(&devBMP280, 0, sizeof(bmp280_t));
|
||||||
|
ESP_ERROR_CHECK(bmp280_init_desc(&devBMP280, BMP280_I2C_ADDRESS_0, 0, I2C_MASTER_SDA, I2C_MASTER_SCL));
|
||||||
|
ESP_ERROR_CHECK(bmp280_init(&devBMP280, ¶ms));
|
||||||
|
bool bme280p = devBMP280.id == BME280_CHIP_ID;
|
||||||
|
ESP_LOGI(TAG, "BMP280: found %s\n", bme280p ? "BME280" : "BMP280");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AHT10
|
||||||
|
aht_t devAHT10 = {0};
|
||||||
|
devAHT10.mode = AHT_MODE_NORMAL;
|
||||||
|
devAHT10.type = AHT_TYPE;
|
||||||
|
ESP_ERROR_CHECK(aht_init_desc(&devAHT10, AHT_I2C_ADDRESS_GND, 0, I2C_MASTER_SDA, I2C_MASTER_SCL));
|
||||||
|
ESP_ERROR_CHECK(aht_init(&devAHT10));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VEML7700
|
||||||
|
i2c_dev_t veml7700_device;
|
||||||
|
veml7700_config_t veml7700_configuration;
|
||||||
|
|
||||||
|
memset(&veml7700_device, 0, sizeof(i2c_dev_t));
|
||||||
|
memset(&veml7700_configuration, 0, sizeof(veml7700_config_t));
|
||||||
|
|
||||||
|
// initialize the device struct
|
||||||
|
ESP_ERROR_CHECK(veml7700_init_desc(&veml7700_device, I2C_NUM_0, I2C_MASTER_SDA, I2C_MASTER_SCL));
|
||||||
|
|
||||||
|
// check if the device is available
|
||||||
|
ESP_ERROR_CHECK(veml7700_probe(&veml7700_device));
|
||||||
|
|
||||||
|
/* set configuration parameters
|
||||||
|
* select gain 1/8 coastest resolution but the sensor will most likely not
|
||||||
|
* over-saturated
|
||||||
|
*/
|
||||||
|
veml7700_configuration.gain = VEML7700_GAIN_DIV_8;
|
||||||
|
|
||||||
|
/* set the time to integrate the light values. more time will lead to a finer
|
||||||
|
* resolution but will be over-saturated earlier
|
||||||
|
*/
|
||||||
|
veml7700_configuration.integration_time = VEML7700_INTEGRATION_TIME_100MS;
|
||||||
|
|
||||||
|
// interrupt is not used
|
||||||
|
veml7700_configuration.persistence_protect = VEML7700_PERSISTENCE_PROTECTION_4;
|
||||||
|
veml7700_configuration.interrupt_enable = 1;
|
||||||
|
veml7700_configuration.shutdown = 0;
|
||||||
|
|
||||||
|
// write the configuration to the device
|
||||||
|
ESP_ERROR_CHECK(veml7700_set_config(&veml7700_device, &veml7700_configuration));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "running");
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
|
uint16_t u16MetricCounter = 0U;
|
||||||
|
|
||||||
|
/*Wifi RSSI*/
|
||||||
|
wifi_ap_record_t ap;
|
||||||
|
esp_wifi_sta_get_ap_info(&ap);
|
||||||
|
printf("WiFi RSSI: %d\n", ap.rssi);
|
||||||
|
strcpy(aMetrics[u16MetricCounter].caMetricName, "wifi_rssi");
|
||||||
|
aMetrics[0].fMetricValue = ap.rssi;
|
||||||
|
u16MetricCounter++;
|
||||||
|
|
||||||
|
#ifdef BMP280
|
||||||
|
if ((bmp280_read_float(&devBMP280, &aMetrics[u16MetricCounter].fMetricValue, &aMetrics[u16MetricCounter+1].fMetricValue, 0) == ESP_OK))
|
||||||
|
{
|
||||||
|
strcpy(aMetrics[u16MetricCounter].caMetricName, "bmp280_temperature");
|
||||||
|
strcpy(aMetrics[u16MetricCounter+1].caMetricName, "bmp280_pressure");
|
||||||
|
printf("(BMP280) Temperature: %.2f C, Pressure: %.2f Pa\n", aMetrics[u16MetricCounter].fMetricValue, aMetrics[u16MetricCounter+1].fMetricValue);
|
||||||
|
u16MetricCounter++;
|
||||||
|
u16MetricCounter++;
|
||||||
|
} else {
|
||||||
|
printf("(BMP280) Temperature/pressure reading failed\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AHT10
|
||||||
|
if ((aht_get_data(&devAHT10, &aMetrics[u16MetricCounter].fMetricValue, &aMetrics[u16MetricCounter+1].fMetricValue) == ESP_OK))
|
||||||
|
{
|
||||||
|
strcpy(aMetrics[u16MetricCounter].caMetricName, "aht10_temperature");
|
||||||
|
strcpy(aMetrics[u16MetricCounter+1].caMetricName, "aht10_humidity");
|
||||||
|
printf("(AHT10) Temperature: %.2f C, Humidity: %.2f %% \n", aMetrics[u16MetricCounter].fMetricValue, aMetrics[u16MetricCounter+1].fMetricValue);
|
||||||
|
u16MetricCounter++;
|
||||||
|
u16MetricCounter++;
|
||||||
|
} else {
|
||||||
|
printf("(AHT10) Temperature/Humidity reading failed\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DHT11
|
||||||
|
if ((dht_read_float_data(SENSOR_TYPE, CONFIG_EXAMPLE_DATA_GPIO, &aMetrics[u16MetricCounter].fMetricValue, &aMetrics[u16MetricCounter+1].fMetricValue) == ESP_OK))
|
||||||
|
{
|
||||||
|
strcpy(aMetrics[u16MetricCounter].caMetricName, "dht11_humidity");
|
||||||
|
strcpy(aMetrics[u16MetricCounter+1].caMetricName, "dht11_temperature");
|
||||||
|
printf("(DHT11) Humidity: %.2f %%, Temperature: %.2f C\n", aMetrics[u16MetricCounter].fMetricValue, aMetrics[u16MetricCounter+1].fMetricValue);
|
||||||
|
u16MetricCounter++;
|
||||||
|
u16MetricCounter++;
|
||||||
|
} else {
|
||||||
|
printf("(DHT11) Temperature/pressure reading failed\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VEML7700
|
||||||
|
uint32_t u32AmbientLight = 0U;
|
||||||
|
uint32_t u32WhiteChannel = 0U;
|
||||||
|
if ((veml7700_get_ambient_light(&veml7700_device, &veml7700_configuration, &u32AmbientLight) == ESP_OK) && (veml7700_get_white_channel(&veml7700_device, &veml7700_configuration, &u32WhiteChannel) == ESP_OK))
|
||||||
|
{
|
||||||
|
aMetrics[u16MetricCounter].fMetricValue = u32AmbientLight;
|
||||||
|
aMetrics[u16MetricCounter+1].fMetricValue = u32WhiteChannel;
|
||||||
|
strcpy(aMetrics[u16MetricCounter].caMetricName, "veml7700_ambient_light");
|
||||||
|
strcpy(aMetrics[u16MetricCounter+1].caMetricName, "veml7700_white_channel");
|
||||||
|
printf("(VEML7700) Ambient light: %.2f lux, White channel: %.2f lux\n", aMetrics[u16MetricCounter].fMetricValue, aMetrics[u16MetricCounter+1].fMetricValue);
|
||||||
|
u16MetricCounter++;
|
||||||
|
u16MetricCounter++;
|
||||||
|
} else {
|
||||||
|
printf("(VEML7700) light reading failed\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
vSetMetrics(aMetrics, u16MetricCounter);
|
||||||
|
}
|
||||||
|
}
|
0
software/main/output.h
Normal file
0
software/main/output.h
Normal file
0
software/main/outputs.c
Normal file
0
software/main/outputs.c
Normal file
0
software/main/safety.c
Normal file
0
software/main/safety.c
Normal file
0
software/main/safety.h
Normal file
0
software/main/safety.h
Normal file
Loading…
Reference in New Issue
Block a user