Skip to content

Commit ecff2ea

Browse files
committed
[SHT1x] Remove delays in reading sensor
Use a state to process reading temp and hum or keep error. The state is handled in the 10/sec call and when a new measurement is ready it will schedule itself to read the new values. See letscontrolit#2407
1 parent 1a70776 commit ecff2ea

File tree

1 file changed

+113
-65
lines changed

1 file changed

+113
-65
lines changed

src/_P031_SHT1X.ino

Lines changed: 113 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
#define PLUGIN_VALUENAME1_031 "Temperature"
1010
#define PLUGIN_VALUENAME2_031 "Humidity"
1111

12+
#define P031_IDLE 0
13+
#define P031_WAIT_TEMP 1
14+
#define P031_WAIT_HUM 2
15+
#define P031_MEAS_READY 3
16+
#define P031_COMMAND_NO_ACK 4
17+
#define P031_NO_DATA 5
18+
1219
class P031_data_struct: public PluginTaskData_base
1320
{
1421
public:
@@ -25,69 +32,85 @@ public:
2532
_dataPin = data_pin;
2633
_clockPin = clock_pin;
2734
input_mode = pullUp ? INPUT_PULLUP : INPUT;
35+
state = P031_IDLE;
2836

2937
pinMode(_dataPin, input_mode); /* Keep Hi-Z except when sending data */
3038
pinMode(_clockPin, OUTPUT);
3139
resetSensor();
3240
return readStatus();
3341
}
3442

43+
bool process() {
44+
switch (state) {
45+
case P031_IDLE: return false; // Nothing changed, nothing to do
46+
case P031_WAIT_TEMP: {
47+
if (digitalRead(_dataPin) == LOW) {
48+
float tempRaw = readData(16);
49+
// Temperature conversion coefficients from SHT1X datasheet for version 4
50+
const float d1 = -39.7; // 3.5V
51+
const float d2 = 0.01; // 14-bit
52+
tempC = d1 + (tempRaw * d2);
53+
state = P031_WAIT_HUM; // Wait for humidity
54+
sendCommand(SHT1X_CMD_MEASURE_RH);
55+
}
56+
break;
57+
}
58+
case P031_WAIT_HUM:
59+
{
60+
if (digitalRead(_dataPin) == LOW) {
61+
float raw = readData(16);
62+
63+
// Temperature conversion coefficients from SHT1X datasheet for version 4
64+
const float c1 = -2.0468;
65+
const float c2 = 0.0367;
66+
const float c3 = -1.5955E-6;
67+
const float t1 = 0.01;
68+
const float t2 = 0.00008;
69+
70+
float rhLinear = c1 + c2 * raw + c3 * raw * raw;
71+
rhTrue = (tempC - 25) * (t1 + t2 * raw) + rhLinear;
72+
/*
73+
String log = F("SHT1X : Read humidity (raw): ");
74+
log += String(raw);
75+
log += F(" (Linear): ");
76+
log += String(rhLinear);
77+
log += F(" (True): ");
78+
log += String(rhTrue);
79+
addLog(LOG_LEVEL_DEBUG, log);
80+
*/
81+
state = P031_MEAS_READY; // Measurement ready
82+
return true;
83+
}
84+
break;
85+
}
86+
case P031_MEAS_READY: return true;
87+
default:
88+
// It is already an error state, just return.
89+
return false;
90+
}
91+
// Compute timeout
92+
if (timePassedSince(sendCommandTime) > 320) {
93+
state = P031_NO_DATA; // No data after 320 msec
94+
}
95+
return false;
96+
}
3597

36-
float readTemperature()
37-
{
38-
float tempRaw, tempC;
39-
98+
void startMeasurement() {
99+
state = P031_WAIT_TEMP; // Wait for temperature
40100
sendCommand(SHT1X_CMD_MEASURE_TEMP);
41-
awaitResult();
42-
tempRaw = readData(16);
43-
44-
// Temperature conversion coefficients from SHT1X datasheet for version 4
45-
const float d1 = -39.7; // 3.5V
46-
const float d2 = 0.01; // 14-bit
47-
48-
tempC = d1 + (tempRaw * d2);
49-
/*
50-
String log = F("SHT1X : Read temperature (raw): ");
51-
log += String(tempRaw);
52-
log += F(" (Celcius): ");
53-
log += String(tempC);
54-
addLog(LOG_LEVEL_DEBUG, log);
55-
*/
56-
return tempC;
57101
}
58102

59-
float readRelHumidity(float tempC)
60-
{
61-
float raw, rhLinear, rhTrue;
62-
63-
sendCommand(SHT1X_CMD_MEASURE_RH);
64-
awaitResult();
65-
raw = readData(16);
66-
67-
// Temperature conversion coefficients from SHT1X datasheet for version 4
68-
const float c1 = -2.0468;
69-
const float c2 = 0.0367;
70-
const float c3 = -1.5955E-6;
71-
const float t1 = 0.01;
72-
const float t2 = 0.00008;
73-
74-
rhLinear = c1 + c2 * raw + c3 * raw * raw;
75-
rhTrue = (tempC - 25) * (t1 + t2 * raw) + rhLinear;
76-
/*
77-
String log = F("SHT1X : Read humidity (raw): ");
78-
log += String(raw);
79-
log += F(" (Linear): ");
80-
log += String(rhLinear);
81-
log += F(" (True): ");
82-
log += String(rhTrue);
83-
addLog(LOG_LEVEL_DEBUG, log);
84-
*/
85-
return rhTrue;
103+
bool measurementReady() {
104+
return state == P031_MEAS_READY;
86105
}
87106

107+
bool hasError() {
108+
return state > P031_MEAS_READY;
109+
}
88110

89111
void resetSensor()
90112
{
113+
state = P031_IDLE;
91114
delay(11);
92115
for (int i=0; i<9; i++) {
93116
digitalWrite(_clockPin, HIGH);
@@ -105,6 +128,7 @@ public:
105128

106129
void sendCommand(const byte cmd)
107130
{
131+
sendCommandTime = millis();
108132
pinMode(_dataPin, OUTPUT);
109133

110134
// Transmission Start sequence
@@ -130,21 +154,8 @@ public:
130154
delayMicroseconds(1); /* Give the sensor time to release the data line */
131155
if (digitalRead(_dataPin) != HIGH) ackerror = true;
132156
}
133-
134157
if (ackerror) {
135-
// addLog(LOG_LEVEL_ERROR, F("SHT1X : Sensor did not ACK command"));
136-
}
137-
}
138-
139-
void awaitResult()
140-
{
141-
// Maximum 320ms for 14 bit measurement
142-
for (int i=0; i<16; i++) {
143-
if (digitalRead(_dataPin) == LOW) return;
144-
delay(20);
145-
}
146-
if (digitalRead(_dataPin) != LOW) {
147-
// addLog(LOG_LEVEL_ERROR, F("SHT1X : Data not ready"));
158+
state = P031_COMMAND_NO_ACK;
148159
}
149160
}
150161

@@ -175,9 +186,14 @@ public:
175186
return val;
176187
}
177188

189+
float tempC = 0.0;
190+
float rhTrue = 0.0;
191+
unsigned long sendCommandTime;
192+
193+
int input_mode;
178194
byte _dataPin = 0;
179195
byte _clockPin = 0;
180-
int input_mode;
196+
byte state = P031_IDLE;
181197
};
182198

183199

@@ -248,14 +264,46 @@ boolean Plugin_031(byte function, struct EventStruct *event, String& string)
248264
break;
249265
}
250266

267+
case PLUGIN_TEN_PER_SECOND:
268+
{
269+
P031_data_struct *P031_data =
270+
static_cast<P031_data_struct *>(getPluginTaskData(event->TaskIndex));
271+
if (nullptr != P031_data) {
272+
if (P031_data->process()) {
273+
// Measurement ready, schedule new read.
274+
schedule_task_device_timer(event->TaskIndex, millis() + 10);
275+
}
276+
}
277+
success = true;
278+
break;
279+
}
280+
251281
case PLUGIN_READ:
252282
{
253283
P031_data_struct *P031_data =
254284
static_cast<P031_data_struct *>(getPluginTaskData(event->TaskIndex));
255285
if (nullptr != P031_data) {
256-
UserVar[event->BaseVarIndex] = P031_data->readTemperature();
257-
UserVar[event->BaseVarIndex+1] = P031_data->readRelHumidity(UserVar[event->BaseVarIndex]);
258-
success = true;
286+
if (P031_data->measurementReady()) {
287+
UserVar[event->BaseVarIndex] = P031_data->tempC;
288+
UserVar[event->BaseVarIndex+1] = P031_data->rhTrue;
289+
success = true;
290+
P031_data->state = P031_IDLE;
291+
} else if (P031_data->state == P031_IDLE) {
292+
P031_data->startMeasurement();
293+
} else if (P031_data->hasError()) {
294+
// Log error
295+
switch (P031_data->state) {
296+
case P031_COMMAND_NO_ACK:
297+
addLog(LOG_LEVEL_ERROR, F("SHT1X : Sensor did not ACK command"));
298+
break;
299+
case P031_NO_DATA:
300+
addLog(LOG_LEVEL_ERROR, F("SHT1X : Data not ready"));
301+
break;
302+
default:
303+
break;
304+
}
305+
P031_data->state = P031_IDLE;
306+
}
259307
}
260308
break;
261309
}

0 commit comments

Comments
 (0)