Skip to content

Commit 9b7826a

Browse files
authored
fix: fix data acquisition from SHT21 temperature and humidity sensor (#2774)
1 parent 4225790 commit 9b7826a

File tree

6 files changed

+98
-93
lines changed

6 files changed

+98
-93
lines changed

app/src/main/java/io/pslab/activity/SensorActivity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.content.Intent;
44
import android.os.AsyncTask;
55
import android.os.Bundle;
6+
import android.util.Log;
67
import android.view.Menu;
78
import android.view.MenuItem;
89
import android.widget.ArrayAdapter;
@@ -192,7 +193,7 @@ protected Void doInBackground(Void... voids) {
192193
// Perform I2C scan to detect connected sensors
193194
detectedSensors = i2c.scan(null);
194195
} catch (IOException | NullPointerException e) {
195-
e.printStackTrace();
196+
Log.w(TAG, "Error scanning for sensors", e);
196197
}
197198
}
198199

app/src/main/java/io/pslab/communication/CommunicationHandler.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,10 @@ public class CommunicationHandler {
2929
private UsbSerialDriver driver;
3030
private UsbSerialPort port;
3131
public UsbDevice mUsbDevice;
32-
List<UsbSerialDriver> drivers;
3332

3433
public static final int DEFAULT_READ_BUFFER_SIZE = 32 * 1024;
35-
public static final int DEFAULT_WRITE_BUFFER_SIZE = 32 * 1024;
3634

3735
private byte[] mReadBuffer;
38-
private byte[] mWriteBuffer;
3936

4037
public CommunicationHandler(UsbManager usbManager) {
4138
this.mUsbManager = usbManager;
@@ -45,7 +42,7 @@ public CommunicationHandler(UsbManager usbManager) {
4542
customTable.addProduct(PSLAB_VENDOR_ID_V6, PSLAB_PRODUCT_ID_V6, Cp21xxSerialDriver.class);
4643

4744
UsbSerialProber prober = new UsbSerialProber(customTable);
48-
drivers = prober.findAllDrivers(usbManager);
45+
List<UsbSerialDriver> drivers = prober.findAllDrivers(usbManager);
4946

5047
if (drivers.isEmpty()) {
5148
Log.d(TAG, "No drivers found");
@@ -56,7 +53,6 @@ public CommunicationHandler(UsbManager usbManager) {
5653
mUsbDevice = driver.getDevice();
5754
}
5855
mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE];
59-
mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE];
6056
}
6157

6258
public void open(int baudRate) throws IOException {
@@ -115,7 +111,7 @@ public int read(byte[] dest, int bytesToBeRead, int timeoutMillis) throws IOExce
115111
bytesToBeReadTemp -= readNow;
116112
}
117113
}
118-
Log.v("Bytes Read", "" + numBytesRead);
114+
Log.v(TAG, "Bytes Read: " + numBytesRead);
119115
return numBytesRead;
120116
}
121117

@@ -135,7 +131,7 @@ public int readCdcAcm(byte[] dest, int bytesToBeRead, int timeoutMillis) throws
135131
bytesToBeReadTemp -= readNow;
136132
}
137133
}
138-
Log.v("Bytes Read", "" + numBytesRead);
134+
Log.v(TAG, "Bytes Read: " + numBytesRead);
139135
return numBytesRead;
140136
}
141137

app/src/main/java/io/pslab/communication/peripherals/I2C.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
package io.pslab.communication.peripherals;
22

3-
import android.os.SystemClock;
43
import android.util.Log;
54

6-
import io.pslab.communication.CommandsProto;
7-
import io.pslab.communication.PacketHandler;
8-
95
import java.io.IOException;
106
import java.util.ArrayList;
117
import java.util.Arrays;
128
import java.util.LinkedHashMap;
139
import java.util.Map;
1410

11+
import io.pslab.communication.CommandsProto;
12+
import io.pslab.communication.PacketHandler;
13+
1514
/**
1615
* Created by viveksb007 on 28/3/17.
1716
*/
@@ -140,6 +139,16 @@ public int readStatus() throws IOException {
140139
return val;
141140
}
142141

142+
/**
143+
* Reads data from an I2C device.
144+
*
145+
* @param deviceAddress address of the device to read from
146+
* @param registerAddress address of the register to read from
147+
* @param bytesToRead number of bytes to read from the device
148+
* @return bytes read from the device plus a status byte as the last element (so this will be
149+
* {@code bytesToRead} plus one)
150+
* @throws IOException if data cannot be read
151+
*/
143152
public ArrayList<Integer> readBulk(int deviceAddress, int registerAddress, int bytesToRead) throws IOException {
144153
packetHandler.sendByte(commandsProto.I2C_HEADER);
145154
packetHandler.sendByte(commandsProto.I2C_READ_BULK);

app/src/main/java/io/pslab/communication/sensors/SHT21.java

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,43 @@
22

33
import android.util.Log;
44

5-
import io.pslab.communication.ScienceLab;
6-
import io.pslab.communication.peripherals.I2C;
7-
85
import java.io.IOException;
9-
import java.util.ArrayList;
10-
import java.util.Arrays;
6+
import java.util.List;
117
import java.util.concurrent.TimeUnit;
128

9+
import io.pslab.communication.ScienceLab;
10+
import io.pslab.communication.peripherals.I2C;
11+
1312
/**
14-
* Created by akarshan on 4/16/17.
13+
* Implementation of communication with SHT21 temperature / humidity sensor.
14+
* <p>
15+
* See <a href="https://sensirion.com/media/documents/120BBE4C/63500094/Sensirion_Datasheet_Humidity_Sensor_SHT21.pdf">
16+
* Datasheet SHT21</a> for the calculations for temperature and humidity.
17+
* <p>
18+
* Example code for CRC calculation can be found in the ZIP file
19+
* <a href="https://sensirion.com/resource/software/code/sht21">Sample code SHT21</a>
1520
*/
16-
1721
public class SHT21 {
18-
private String TAG = "SHT21";
19-
private int RESET = 0XFE;
20-
private int TEMP_ADDRESS = 0xF3;
21-
private int HUMIDITY_ADDRESS = 0xF5;
22-
private int selected = 0xF3;
23-
private int ADDRESS = 0x40;
2422

25-
public int NUMPLOTS = 1;
26-
public String[] PLOTNAMES = {"Data"};
27-
public String name = "Humidity/Temperature";
23+
public enum Mode {
24+
TEMPERATURE(TEMP_ADDRESS), HUMIDITY(HUMIDITY_ADDRESS);
2825

29-
public ArrayList<String> selectParameter = new ArrayList<>(Arrays.asList("temperature", "humidity"));
30-
private I2C i2c;
26+
final int registerAddress;
27+
28+
Mode(int registerAddress) {
29+
this.registerAddress = registerAddress;
30+
}
31+
}
32+
33+
private static final String TAG = SHT21.class.getSimpleName();
34+
private static final int RESET = 0XFE;
35+
private static final int TEMP_ADDRESS = 0xE3;
36+
private static final int HUMIDITY_ADDRESS = 0xE5;
37+
private static final int ADDRESS = 0x40;
38+
39+
private Mode selected = Mode.TEMPERATURE;
40+
41+
private final I2C i2c;
3142

3243
public SHT21(I2C i2c, ScienceLab scienceLab) throws IOException, InterruptedException {
3344
this.i2c = i2c;
@@ -41,38 +52,27 @@ private void init() throws IOException, InterruptedException {
4152
TimeUnit.MILLISECONDS.sleep(100);
4253
}
4354

44-
private ArrayList<Double> rawToTemp(ArrayList<Byte> vals) {
45-
double v;
46-
ArrayList<Double> v1 = new ArrayList<>();
47-
if (vals.size() != 0) {
48-
v = (vals.get(0) << 8) | (vals.get(1) & 0xFC);
49-
v *= 175.72;
50-
v /= (1 << 16);
51-
v -= 46.85;
52-
v1.add(v);
53-
return v1;
55+
private static Double rawToTemp(List<Integer> vals) {
56+
if (vals.size() >= 2) {
57+
double v = ((vals.get(0) & 0xFF) << 8) | (vals.get(1) & 0xFC);
58+
return -46.85 + 175.72 * (v / (1 << 16));
5459
} else return null;
5560
}
5661

57-
private ArrayList<Double> rawToRH(ArrayList<Byte> vals) {
58-
double v;
59-
ArrayList<Double> v1 = new ArrayList<>();
60-
if (vals.size() != 0) {
61-
v = (vals.get(0) << 8) | (vals.get(1) & 0xFC);
62-
v *= 125.;
63-
v /= (1 << 16);
64-
v -= 6;
65-
v1.add(v);
66-
return v1;
62+
private static Double rawToRH(List<Integer> vals) {
63+
if (vals.size() >= 2) {
64+
double v = ((vals.get(0) & 0xFF) << 8) | (vals.get(1) & 0xFC);
65+
return -6 + 125 * (v / (1 << 16));
6766
} else return null;
6867
}
6968

70-
private static int calculateChecksum(ArrayList<Byte> data, int numberOfBytes) {
69+
private static int calculateChecksum(List<Integer> data, int numberOfBytes) {
7170

7271
//CRC
73-
int POLYNOMIAL = 0x131, byteCtr, crc = 0;
72+
final int POLYNOMIAL = 0x31;
73+
int crc = 0;
7474
//calculates 8-Bit checksum with given polynomial
75-
for (byteCtr = 0; byteCtr < numberOfBytes; byteCtr++) {
75+
for (int byteCtr = 0; byteCtr < numberOfBytes; byteCtr++) {
7676
crc ^= data.get(byteCtr);
7777
for (int bit = 8; bit > 0; bit--) {
7878
if ((crc & 0X80) != 0)
@@ -84,29 +84,29 @@ private static int calculateChecksum(ArrayList<Byte> data, int numberOfBytes) {
8484
return crc;
8585
}
8686

87-
public void selectParameter(String param) {
88-
if (param.equals("temperature"))
89-
selected = TEMP_ADDRESS;
90-
else if (param.equals("humidity"))
91-
selected = HUMIDITY_ADDRESS;
87+
public void setMode(Mode mode) {
88+
selected = mode;
9289
}
9390

94-
public ArrayList<Double> getRaw() throws IOException, InterruptedException {
95-
ArrayList<Byte> vals;
96-
i2c.writeBulk(ADDRESS, new int[]{selected});
97-
if (selected == TEMP_ADDRESS)
91+
public Double getRaw() throws IOException, InterruptedException {
92+
List<Integer> vals;
93+
i2c.writeBulk(ADDRESS, new int[]{selected.registerAddress});
94+
if (selected == Mode.TEMPERATURE)
9895
TimeUnit.MILLISECONDS.sleep(100);
99-
else if (selected == HUMIDITY_ADDRESS)
96+
else if (selected == Mode.HUMIDITY)
10097
TimeUnit.MILLISECONDS.sleep(50);
101-
vals = i2c.simpleRead(ADDRESS, 3);
102-
if (vals.size() != 0) {
103-
if (calculateChecksum(vals, 2) != vals.get(2))
104-
Log.v(TAG, vals.toString());
98+
vals = i2c.readBulk(ADDRESS, selected.registerAddress, 3);
99+
if (vals.isEmpty()) {
100+
Log.v(TAG, "No data received.");
101+
return null;
102+
} else if ((calculateChecksum(vals, 2) & 0xFF) != (vals.get(2) & 0xFF)) {
103+
Log.v(TAG, "Error in checksum.");
105104
return null;
106105
}
107-
if (selected == TEMP_ADDRESS)
106+
107+
if (selected == Mode.TEMPERATURE)
108108
return rawToTemp(vals);
109-
else if (selected == HUMIDITY_ADDRESS)
109+
else if (selected == Mode.HUMIDITY)
110110
return rawToRH(vals);
111111
else
112112
return null;

app/src/main/java/io/pslab/fragment/ThermometerDataFragment.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.pslab.fragment;
22

3+
import static android.content.Context.SENSOR_SERVICE;
4+
import static io.pslab.others.CSVLogger.CSV_DIRECTORY;
5+
36
import android.graphics.Bitmap;
47
import android.graphics.Color;
58
import android.hardware.Sensor;
@@ -10,17 +13,16 @@
1013
import android.os.Bundle;
1114
import android.os.Environment;
1215
import android.os.Handler;
13-
import androidx.annotation.NonNull;
14-
15-
import com.google.android.material.snackbar.Snackbar;
16-
import androidx.fragment.app.Fragment;
17-
18-
import androidx.preference.PreferenceManager;
16+
import android.util.Log;
1917
import android.view.LayoutInflater;
2018
import android.view.View;
2119
import android.view.ViewGroup;
2220
import android.widget.TextView;
2321

22+
import androidx.annotation.NonNull;
23+
import androidx.fragment.app.Fragment;
24+
import androidx.preference.PreferenceManager;
25+
2426
import com.github.anastr.speedviewlib.PointerSpeedometer;
2527
import com.github.mikephil.charting.charts.LineChart;
2628
import com.github.mikephil.charting.components.Legend;
@@ -29,6 +31,7 @@
2931
import com.github.mikephil.charting.data.Entry;
3032
import com.github.mikephil.charting.data.LineData;
3133
import com.github.mikephil.charting.data.LineDataSet;
34+
import com.google.android.material.snackbar.Snackbar;
3235

3336
import java.io.File;
3437
import java.io.FileNotFoundException;
@@ -58,12 +61,10 @@
5861
import io.pslab.others.CustomSnackBar;
5962
import io.pslab.others.ScienceLabCommon;
6063

61-
import static android.content.Context.SENSOR_SERVICE;
62-
import static io.pslab.others.CSVLogger.CSV_DIRECTORY;
63-
6464
public class ThermometerDataFragment extends Fragment implements OperationCallback {
6565

66-
private static final String TEMPERATURE = "temperature";
66+
private static final String TAG = ThermometerDataFragment.class.getSimpleName();
67+
6768
private static final CSVDataLine CSV_HEADER = new CSVDataLine()
6869
.add("Timestamp")
6970
.add("DateTime")
@@ -123,7 +124,7 @@ public static ThermometerDataFragment newInstance() {
123124

124125
public static void setParameters(int updatePeriod, String type, String unit) {
125126
ThermometerDataFragment.updatePeriod = updatePeriod;
126-
ThermometerDataFragment.sensorType = Integer.valueOf(type);
127+
ThermometerDataFragment.sensorType = Integer.parseInt(type);
127128
ThermometerDataFragment.unit = unit;
128129

129130
}
@@ -356,11 +357,10 @@ public void saveGraph() {
356357
File.separator + CSV_DIRECTORY + File.separator + thermoSensor.getSensorName() +
357358
File.separator + CSVLogger.FILE_NAME_FORMAT.format(new Date()) + "_graph.jpg"));
358359
} catch (FileNotFoundException e) {
359-
e.printStackTrace();
360+
Log.e(TAG, "Unable to save bitmap", e);
360361
}
361362
}
362363

363-
364364
private void setupInstruments() {
365365
setUnit();
366366
XAxis x = mChart.getXAxis();
@@ -582,15 +582,15 @@ private void initiateThermoSensor(int type) {
582582
data = i2c.scan(null);
583583
if (data.contains(0x39)) {
584584
SHT21 sensorSHT21 = new SHT21(i2c, scienceLab);
585-
sensorSHT21.selectParameter(TEMPERATURE);
585+
sensorSHT21.setMode(SHT21.Mode.TEMPERATURE);
586586
sensorType = 1;
587587
} else {
588588
CustomSnackBar.showSnackBar(getActivity().findViewById(android.R.id.content),
589589
getString(R.string.sensor_not_connected_tls), null, null, Snackbar.LENGTH_SHORT);
590590
sensorType = 0;
591591
}
592592
} catch (IOException | InterruptedException e) {
593-
e.printStackTrace();
593+
Log.e(TAG, "Unable to get data from sensor.", e);
594594
}
595595
} else {
596596
CustomSnackBar.showSnackBar(getActivity().findViewById(android.R.id.content),

0 commit comments

Comments
 (0)