Add read sensor retry

Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21
This commit is contained in:
Theo Arends 2018-07-10 22:12:16 +02:00
parent e7a21887d3
commit 8fdcbaa8e1
9 changed files with 163 additions and 150 deletions

View File

@ -1,4 +1,5 @@
/* 6.1.0a
* Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21
* Change SHT1x driver to provide better instant results
* Fix DHT driver mixing values for different sensors (#1797)
* Change DHT driver to provide better instant results and add decimals to DHT11 (#3164)

View File

@ -471,6 +471,7 @@ const char S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s%d\":\"%d
const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}";
const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}";
const char JSON_SNS_TEMP[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}";
const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}";
const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";

View File

@ -95,6 +95,8 @@ typedef unsigned long power_t; // Power (Relay) type
#define LOGSZ 512 // Max number of characters in log
#define MIN_MESSZ 893 // Min number of characters in MQTT message
#define SENSOR_MAX_MISS 5 // Max number of missed sensor reads before deciding it's offline
#ifdef USE_MQTT_TLS
#define WEB_LOG_SIZE 2000 // Max number of characters in weblog
#else

View File

@ -2080,6 +2080,12 @@ void AddLogSerial(byte loglevel)
AddLogSerial(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter);
}
void AddLogMissed(char *sensor, uint8_t misses)
{
snprintf_P(log_data, sizeof(log_data), PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses);
AddLog(LOG_LEVEL_DEBUG);
}
/*********************************************************************************************\
*
\*********************************************************************************************/

View File

@ -26,11 +26,10 @@
#define W1_CONVERT_TEMP 0x44
#define W1_READ_SCRATCHPAD 0xBE
#define DS18B20_MAX_MISS 5
float ds18b20_temperature = 0;
uint8_t ds18b20_last_result = 0;
uint8_t ds18b20_valid = 0;
uint8_t ds18x20_pin = 0;
char ds18b20_types[] = "DS18B20";
/*********************************************************************************************\
* Embedded stripped and tuned OneWire library
@ -136,12 +135,12 @@ void Ds18b20Convert()
// delay(750); // 750ms should be enough for 12bit conv
}
void Ds18b20Read()
boolean Ds18b20Read()
{
uint8_t data[9];
int8_t sign = 1;
if (ds18b20_last_result) { ds18b20_last_result--; }
if (ds18b20_valid) { ds18b20_valid--; }
/*
if (!OneWireReadBit()) { // Check end of measurement
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_BUSY));
@ -162,11 +161,12 @@ void Ds18b20Read()
sign = -1;
}
ds18b20_temperature = ConvertTemp(sign * temp12 * 0.0625);
ds18b20_last_result = DS18B20_MAX_MISS;
return;
ds18b20_valid = SENSOR_MAX_MISS;
return true;
}
}
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR));
return false;
}
/********************************************************************************************/
@ -177,27 +177,33 @@ void Ds18b20EverySecond()
if (uptime &1) {
Ds18b20Convert(); // Start conversion, takes up to one second
} else {
Ds18b20Read(); // Read temperature
if (!Ds18b20Read()) { // Read temperature
AddLogMissed(ds18b20_types, ds18b20_valid);
}
}
}
void Ds18b20Show(boolean json)
{
if (ds18b20_last_result) { // Check for valid temperature
if (ds18b20_valid) { // Check for valid temperature
char temperature[10];
dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature);
if(json) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"DS18B20\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, temperature);
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMP, mqtt_data, ds18b20_types, temperature);
#ifdef USE_DOMOTICZ
if (0 == tele_period) { DomoticzSensor(DZ_TEMP, temperature); }
if (0 == tele_period) {
DomoticzSensor(DZ_TEMP, temperature);
}
#endif // USE_DOMOTICZ
#ifdef USE_KNX
if (0 == tele_period) { KnxSensor(KNX_TEMPERATURE, ds18b20_temperature); }
if (0 == tele_period) {
KnxSensor(KNX_TEMPERATURE, ds18b20_temperature);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "DS18B20", temperature, TempUnit());
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ds18b20_types, temperature, TempUnit());
#endif // USE_WEBSERVER
}
}

View File

@ -33,7 +33,6 @@
#define W1_WRITE_SCRATCHPAD 0x4E
#define W1_READ_SCRATCHPAD 0xBE
#define DS18X20_MAX_MISS 5
#define DS18X20_MAX_SENSORS 8
const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850";
@ -43,12 +42,12 @@ uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID,
struct DS18X20STRUCT {
uint8_t address[8];
uint8_t index;
uint8_t result;
uint8_t valid;
float temperature;
} ds18x20_sensor[DS18X20_MAX_SENSORS];
uint8_t ds18x20_sensors = 0;
uint8_t ds18x20_pin = 0;
char ds18x20_types[9];
char ds18x20_types[12];
/*********************************************************************************************\
* Embedded tuned OneWire library
@ -289,7 +288,7 @@ void Ds18x20Convert()
// delay(750); // 750ms should be enough for 12bit conv
}
void Ds18x20Read(uint8_t sensor)
bool Ds18x20Read(uint8_t sensor)
{
uint8_t data[9];
int8_t sign = 1;
@ -298,7 +297,7 @@ void Ds18x20Read(uint8_t sensor)
float temp9 = 0.0;
uint8_t index = ds18x20_sensor[sensor].index;
if (ds18x20_sensor[index].result) { ds18x20_sensor[index].result--; }
if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; }
for (uint8_t retry = 0; retry < 3; retry++) {
OneWireReset();
OneWireSelect(ds18x20_sensor[index].address);
@ -319,8 +318,8 @@ void Ds18x20Read(uint8_t sensor)
temp9 = (data[0] >> 1) * sign;
}
ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0));
ds18x20_sensor[index].result = DS18X20_MAX_MISS;
return;
ds18x20_sensor[index].valid = SENSOR_MAX_MISS;
return true;
case DS1822_CHIPID:
case DS18B20_CHIPID:
if (data[4] != 0x7F) {
@ -340,17 +339,33 @@ void Ds18x20Read(uint8_t sensor)
sign = -1;
}
ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16
ds18x20_sensor[index].result = DS18X20_MAX_MISS;
return;
ds18x20_sensor[index].valid = SENSOR_MAX_MISS;
return true;
case MAX31850_CHIPID:
temp14 = (data[1] << 8) + (data[0] & 0xFC);
ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); // Divide by 16
ds18x20_sensor[index].result = DS18X20_MAX_MISS;
return;
ds18x20_sensor[index].valid = SENSOR_MAX_MISS;
return true;
}
}
}
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR));
return false;
}
void Ds18x20Name(uint8_t sensor)
{
uint8_t index = sizeof(ds18x20_chipids);
while (index) {
if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) {
break;
}
index--;
}
GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types);
if (ds18x20_sensors > 1) {
snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s-%d"), ds18x20_types, sensor +1);
}
}
/********************************************************************************************/
@ -361,7 +376,10 @@ void Ds18x20EverySecond()
Ds18x20Convert(); // Start conversion, takes up to one second
} else {
for (uint8_t i = 0; i < ds18x20_sensors; i++) {
Ds18x20Read(i); // Read temperature
if (!Ds18x20Read(i)) { // Read temperature
Ds18x20Name(i);
AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid);
}
}
}
}
@ -369,25 +387,15 @@ void Ds18x20EverySecond()
void Ds18x20Show(boolean json)
{
char temperature[10];
char stemp[12];
bool domoticz_flag = true;
for (uint8_t i = 0; i < ds18x20_sensors; i++) {
uint8_t index = ds18x20_sensor[i].index;
if (ds18x20_sensor[index].result) { // Check for valid temperature
if (ds18x20_sensor[index].valid) { // Check for valid temperature
dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature);
uint8_t idx = sizeof(ds18x20_chipids);
while (idx) {
if (ds18x20_sensor[ds18x20_sensor[idx].index].address[0] == ds18x20_chipids[idx]) {
break;
}
idx--;
}
GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), idx, kDs18x20Types);
Ds18x20Name(i);
snprintf_P(stemp, sizeof(stemp), PSTR("%s-%d"), ds18x20_types, i +1);
if (json) {
if (1 == ds18x20_sensors) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, temperature);
@ -396,12 +404,11 @@ void Ds18x20Show(boolean json)
for (byte j = 0; j < 6; j++) {
sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); // Skip sensor type and crc
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, stemp, address, temperature);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, address, temperature);
}
#ifdef USE_DOMOTICZ
if ((0 == tele_period) && domoticz_flag) {
if ((0 == tele_period) && (0 == i)) {
DomoticzSensor(DZ_TEMP, temperature);
domoticz_flag = false;
}
#endif // USE_DOMOTICZ
#ifdef USE_KNX
@ -411,7 +418,7 @@ void Ds18x20Show(boolean json)
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, (1 == ds18x20_sensors) ? ds18x20_types : stemp, temperature, TempUnit());
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ds18x20_types, temperature, TempUnit());
#endif // USE_WEBSERVER
}
}

View File

@ -121,12 +121,11 @@ boolean DhtRead(byte sensor)
}
}
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DHT D_RECEIVED " %02X, %02X, %02X, %02X, %02X =? %02X"),
dht_data[0], dht_data[1], dht_data[2], dht_data[3], dht_data[4], (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF);
AddLog(LOG_LEVEL_DEBUG);
if (dht_data[4] != ((dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF)) {
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE));
uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF;
if (dht_data[4] != checksum) {
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %02X, %02X, %02X, %02X, %02X =? %02X"),
dht_data[0], dht_data[1], dht_data[2], dht_data[3], dht_data[4], checksum);
AddLog(LOG_LEVEL_DEBUG);
return false;
}

View File

@ -34,11 +34,10 @@ enum {
SHT1X_CMD_SOFT_RESET = B00011110
};
#define SHT_MAX_MISS 5
uint8_t sht_sda_pin;
uint8_t sht_scl_pin;
uint8_t sht_type = 0;
char sht_types[] = "SHT1X";
uint8_t sht_valid = 0;
float sht_temperature = 0;
float sht_humidity = 0;
@ -148,7 +147,7 @@ boolean ShtRead()
sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear;
sht_temperature = ConvertTemp(sht_temperature);
sht_valid = SHT_MAX_MISS;
sht_valid = SENSOR_MAX_MISS;
return true;
}
@ -173,36 +172,40 @@ void ShtDetect()
void ShtEverySecond()
{
if (!(uptime %3)) { ShtRead(); } // Update every 3 seconds
if (sht_type && !(uptime %3)) { // Update every 3 seconds
if (!ShtRead()) {
AddLogMissed(sht_types, sht_valid);
}
}
}
void ShtShow(boolean json)
{
if (sht_type) {
if (sht_valid) {
char temperature[10];
char humidity[10];
if (sht_type && sht_valid) {
char temperature[10];
char humidity[10];
dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature);
dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity);
dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature);
dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity);
if (json) {
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, "SHT1X", temperature, humidity);
if (json) {
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, sht_types, temperature, humidity);
#ifdef USE_DOMOTICZ
if (0 == tele_period) DomoticzTempHumSensor(temperature, humidity);
if (0 == tele_period) {
DomoticzTempHumSensor(temperature, humidity);
}
#endif // USE_DOMOTICZ
#ifdef USE_KNX
if (0 == tele_period) {
KnxSensor(KNX_TEMPERATURE, sht_temperature);
KnxSensor(KNX_HUMIDITY, sht_humidity);
}
if (0 == tele_period) {
KnxSensor(KNX_TEMPERATURE, sht_temperature);
KnxSensor(KNX_HUMIDITY, sht_humidity);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "SHT1X", temperature, TempUnit());
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "SHT1X", humidity);
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sht_types, temperature, TempUnit());
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sht_types, humidity);
#endif // USE_WEBSERVER
}
}
}
}

View File

@ -58,8 +58,11 @@ const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?";
uint8_t htu_address;
uint8_t htu_type = 0;
uint8_t delay_temp;
uint8_t delay_humidity = 50;
uint8_t htu_delay_temp;
uint8_t htu_delay_humidity = 50;
uint8_t htu_valid = 0;
float htu_temperature = 0;
float htu_humidity = 0;
char htu_types[7];
uint8_t HtuCheckCrc8(uint16_t data)
@ -135,87 +138,62 @@ void HtuInit()
HtuSetResolution(HTU21_RES_RH12_T14);
}
float HtuReadHumidity(void)
boolean HtuRead()
{
uint8_t checksum = 0;
uint16_t sensorval = 0;
float humidity = 0.0;
Wire.beginTransmission(HTU21_ADDR);
Wire.write(HTU21_READHUM);
if (Wire.endTransmission() != 0) {
return 0.0; // In case of error
}
delay(delay_humidity); // Sensor time at max resolution
Wire.requestFrom(HTU21_ADDR, 3);
if (3 <= Wire.available()) {
sensorval = Wire.read() << 8; // MSB
sensorval |= Wire.read(); // LSB
checksum = Wire.read();
}
if (HtuCheckCrc8(sensorval) != checksum) {
return 0.0; // Checksum mismatch
}
sensorval ^= 0x02; // clear status bits
humidity = 0.001907 * (float)sensorval - 6;
if (humidity > 100) {
return 100.0;
}
if (humidity < 0) {
return 0.01;
}
return humidity;
}
float HtuReadTemperature()
{
uint8_t checksum=0;
uint16_t sensorval=0;
float t;
if (htu_valid) { htu_valid--; }
Wire.beginTransmission(HTU21_ADDR);
Wire.write(HTU21_READTEMP);
if (Wire.endTransmission() != 0) {
return 0.0; // In case of error
}
delay(delay_temp); // Sensor time at max resolution
if (Wire.endTransmission() != 0) { return false; } // In case of error
delay(htu_delay_temp); // Sensor time at max resolution
Wire.requestFrom(HTU21_ADDR, 3);
if (3 == Wire.available()) {
sensorval = Wire.read() << 8; // MSB
sensorval |= Wire.read(); // LSB
sensorval = Wire.read() << 8; // MSB
sensorval |= Wire.read(); // LSB
checksum = Wire.read();
}
if (HtuCheckCrc8(sensorval) != checksum) {
return 0.0; // Checksum mismatch
if (HtuCheckCrc8(sensorval) != checksum) { return false; } // Checksum mismatch
htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85);
Wire.beginTransmission(HTU21_ADDR);
Wire.write(HTU21_READHUM);
if (Wire.endTransmission() != 0) { return false; } // In case of error
delay(htu_delay_humidity); // Sensor time at max resolution
Wire.requestFrom(HTU21_ADDR, 3);
if (3 <= Wire.available()) {
sensorval = Wire.read() << 8; // MSB
sensorval |= Wire.read(); // LSB
checksum = Wire.read();
}
if (HtuCheckCrc8(sensorval) != checksum) { return false; } // Checksum mismatch
sensorval ^= 0x02; // clear status bits
htu_humidity = 0.001907 * (float)sensorval - 6;
if (htu_humidity > 100) { htu_humidity = 100.0; }
if (htu_humidity < 0) { htu_humidity = 0.01; }
if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) {
htu_humidity = 0.0;
}
if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) {
htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity;
}
t = ConvertTemp(0.002681 * (float)sensorval - 46.85);
return t;
}
float HtuCompensatedHumidity(float humidity, float temperature)
{
if(humidity == 0.00 && temperature == 0.00) {
return 0.0;
}
if(temperature > 0.00 && temperature < 80.00) {
return (-0.15)*(25-temperature)+humidity;
}
return humidity;
htu_valid = SENSOR_MAX_MISS;
return true;
}
/********************************************************************************************/
void HtuDetect()
{
if (htu_type) {
return;
}
if (htu_type) { return; }
htu_address = HTU21_ADDR;
htu_type = HtuReadDeviceId();
@ -224,8 +202,8 @@ void HtuDetect()
HtuInit();
switch (htu_type) {
case HTU21_CHIPID:
delay_temp = 50;
delay_humidity = 16;
htu_delay_temp = 50;
htu_delay_humidity = 16;
break;
case SI7021_CHIPID:
index++; // 3
@ -233,13 +211,13 @@ void HtuDetect()
index++; // 2
case SI7013_CHIPID:
index++; // 1
delay_temp = 12;
delay_humidity = 23;
htu_delay_temp = 12;
htu_delay_humidity = 23;
break;
default:
index = 4;
delay_temp = 50;
delay_humidity = 23;
htu_delay_temp = 50;
htu_delay_humidity = 23;
}
GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes);
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, htu_types, htu_address);
@ -247,31 +225,41 @@ void HtuDetect()
}
}
void HtuEverySecond()
{
if (uptime &1) {
HtuDetect();
} else {
if (htu_type) {
if (!HtuRead()) {
AddLogMissed(htu_types, htu_valid);
}
}
}
}
void HtuShow(boolean json)
{
if (htu_type) {
if (htu_type && htu_valid) {
char temperature[10];
char humidity[10];
float t = HtuReadTemperature();
float h = HtuReadHumidity();
h = HtuCompensatedHumidity(h, t);
dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
dtostrfd(h, Settings.flag2.humidity_resolution, humidity);
dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature);
dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity);
if (json) {
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, temperature, humidity);
#ifdef USE_DOMOTICZ
if (0 == tele_period) DomoticzTempHumSensor(temperature, humidity);
if (0 == tele_period) {
DomoticzTempHumSensor(temperature, humidity);
}
#endif // USE_DOMOTICZ
#ifdef USE_KNX
if (0 == tele_period) {
KnxSensor(KNX_TEMPERATURE, t);
KnxSensor(KNX_HUMIDITY, h);
KnxSensor(KNX_TEMPERATURE, htu_temperature);
KnxSensor(KNX_HUMIDITY, htu_humidity);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, htu_types, temperature, TempUnit());
@ -293,8 +281,8 @@ boolean Xsns08(byte function)
if (i2c_flg) {
switch (function) {
case FUNC_PREP_BEFORE_TELEPERIOD:
HtuDetect();
case FUNC_EVERY_SECOND:
HtuEverySecond();
break;
case FUNC_JSON_APPEND:
HtuShow(1);