|
2 | 2 |
|
3 | 3 | import android.util.Log;
|
4 | 4 |
|
5 |
| -import io.pslab.communication.ScienceLab; |
6 |
| -import io.pslab.communication.peripherals.I2C; |
7 |
| - |
8 | 5 | import java.io.IOException;
|
9 |
| -import java.util.ArrayList; |
10 |
| -import java.util.Arrays; |
| 6 | +import java.util.List; |
11 | 7 | import java.util.concurrent.TimeUnit;
|
12 | 8 |
|
13 |
| -/** |
14 |
| - * Created by akarshan on 4/15/17. |
15 |
| - */ |
| 9 | +import io.pslab.communication.ScienceLab; |
| 10 | +import io.pslab.communication.peripherals.I2C; |
16 | 11 |
|
| 12 | +/* |
| 13 | + * See https://www.digikey.in/htmldatasheets/production/1640693/0/0/1/tsl2560-tsl2561-datasheet.html |
| 14 | + */ |
17 | 15 | public class TSL2561 {
|
18 |
| - private String TAG = "TSL2561"; |
19 |
| - private int VISIBLE = 2; // channel 0 - channel 1 |
20 |
| - private int INFRARED = 1; // channel 1 |
21 |
| - private int FULLSPECTRUM = 0; // channel 0 |
| 16 | + private static final String TAG = TSL2561.class.getSimpleName(); |
22 | 17 |
|
23 |
| - private int READBIT = 0x01; |
24 |
| - private int COMMAND_BIT = 0x80; // Must be 1 |
| 18 | + /* See https://github.com/adafruit/TSL2561-Arduino-Library/blob/master/TSL2561.h for all constants. */ |
25 | 19 |
|
26 |
| - private int CONTROL_POWERON = 0x03; |
27 |
| - private int CONTROL_POWEROFF = 0x00; |
| 20 | + private static final byte COMMAND_BIT = (byte) 0x80; // Must be 1 |
| 21 | + private static final byte WORD_BIT = (0x20); // 1 = read/write word (rather than byte) |
28 | 22 |
|
29 |
| - private int REGISTER_CONTROL = 0x00; |
30 |
| - private int REGISTER_TIMING = 0x01; |
31 |
| - private int REGISTER_ID = 0x0A; |
| 23 | + private static final byte CONTROL_POWERON = 0x03; |
| 24 | + private static final byte CONTROL_POWEROFF = 0x00; |
32 | 25 |
|
33 |
| - private int INTEGRATIONTIME_13MS = 0x00; // 13.7ms |
34 |
| - private int INTEGRATIONTIME_101MS = 0x01; // 101ms |
35 |
| - private int INTEGRATIONTIME_402MS = 0x02; // 402ms |
| 26 | + private static final byte REGISTER_CONTROL = 0x00; |
| 27 | + private static final byte REGISTER_TIMING = 0x01; |
| 28 | + private static final byte REGISTER_ID = 0x0A; |
| 29 | + private static final byte REGISTER_CHAN0_LOW = 0x0C; |
| 30 | + private static final byte REGISTER_CHAN1_LOW = 0x0E; |
36 | 31 |
|
37 |
| - private int GAIN_1X = 0x00; // No gain |
38 |
| - private int GAIN_16X = 0x10; // 16x gain |
39 |
| - private int GAIN_OX; |
| 32 | + private static final byte INTEGRATIONTIME_13MS = 0x00; // 13.7ms |
| 33 | + private static final byte INTEGRATIONTIME_101MS = 0x01; // 101ms |
| 34 | + private static final byte INTEGRATIONTIME_402MS = 0x02; // 402ms |
40 | 35 |
|
41 |
| - private int ADDRESS = 0x39; // addr normal |
42 |
| - private int timing = INTEGRATIONTIME_13MS; |
43 |
| - private int gain = GAIN_16X; |
| 36 | + private static final byte GAIN_0X = 0x00; // No gain |
| 37 | + private static final byte GAIN_16X = 0x10; // 16x gain |
44 | 38 |
|
45 |
| - public String name = "TSL2561 Luminosity"; |
46 |
| - public int NUMPLOTS = 3; |
47 |
| - public String[] PLOTNAMES = {"Full", "IR", "Visible"}; |
| 39 | + /** |
| 40 | + * Normal address is 0x39, but it may also be configured to 0x29 or 0x49. |
| 41 | + * We use the normal address first before querying the alternatives. |
| 42 | + */ |
| 43 | + private static final byte[] ADDRESSES = new byte[]{0x39, 0x29, 0x49}; |
| 44 | + private byte address; |
| 45 | + private byte timing = INTEGRATIONTIME_13MS; |
| 46 | + private byte gain = GAIN_16X; |
48 | 47 |
|
49 |
| - private I2C i2c; |
50 |
| - private int full, infra; |
51 |
| - private ArrayList<Integer> infraList, fullList; |
52 |
| - private ArrayList<java.io.Serializable> setGain = new ArrayList<java.io.Serializable>(Arrays.asList("1x", "16x")); |
53 |
| - private ArrayList<java.io.Serializable> setTiming = new ArrayList<java.io.Serializable>(Arrays.asList(0, 1, 2)); |
| 48 | + private final I2C i2c; |
54 | 49 |
|
55 | 50 | public TSL2561(I2C i2c, ScienceLab scienceLab) throws IOException, InterruptedException {
|
56 | 51 | this.i2c = i2c;
|
57 | 52 | // set timing 101ms & 16x gain
|
58 | 53 | if (scienceLab.isConnected()) {
|
| 54 | + |
| 55 | + /* Here we probe if any of the expected I2C addresses has an ID in the expected format. |
| 56 | + * If no sensor is available with the given ID, the value 0xFFFFFFFF will be returned. |
| 57 | + * If a different value is returned, we can check for the expected value (see data sheet |
| 58 | + * for details). |
| 59 | + */ |
| 60 | + for (byte addr : ADDRESSES) { |
| 61 | + address = addr; |
| 62 | + /* We disable the sensor before probing since it will not return the expected value |
| 63 | + * if it is still active due to a previous data capture. |
| 64 | + */ |
| 65 | + disable(); |
| 66 | + Log.d(TAG, "Checking address 0x" + Integer.toHexString(address)); |
| 67 | + int id = i2c.readByte(address, REGISTER_ID); |
| 68 | + if (id != 0xffffffff && (id & 0x0A) == 0x0A) { |
| 69 | + Log.d(TAG, "TSL2561 found!"); |
| 70 | + break; |
| 71 | + } else { |
| 72 | + Log.d(TAG, "TSL2561 not found."); |
| 73 | + } |
| 74 | + } |
| 75 | + |
59 | 76 | enable();
|
60 | 77 | _wait();
|
61 |
| - i2c.writeBulk(ADDRESS, new int[]{0x80 | 0x01, 0x01 | 0x10}); |
62 |
| - //full scale luminosity |
63 |
| - infraList = i2c.readBulk(ADDRESS, 0x80 | 0x20 | 0x0E, 2); |
64 |
| - fullList = i2c.readBulk(ADDRESS, 0x80 | 0x20 | 0x0C, 2); |
65 |
| - full = (fullList.get(1) << 8) | fullList.get(0); |
66 |
| - infra = (infraList.get(1) << 8) | infraList.get(0); |
67 |
| - |
68 |
| - Log.v(TAG, "Full - " + Integer.toString(full)); |
69 |
| - Log.v(TAG, "Infrared - " + Integer.toString(infra)); |
70 |
| - Log.v(TAG, "Visible -" + Integer.toString(full - infra)); |
| 78 | + i2c.writeBulk(address, new int[]{COMMAND_BIT | REGISTER_TIMING, timing | gain}); |
71 | 79 | }
|
72 | 80 | }
|
73 | 81 |
|
74 | 82 | public int getID() throws IOException {
|
75 |
| - ArrayList<Integer> _ID_ = i2c.readBulk(ADDRESS, REGISTER_ID, 1); |
| 83 | + List<Integer> _ID_ = i2c.readBulk(address, REGISTER_ID, 1); |
76 | 84 | int ID = Integer.parseInt(Character.getNumericValue(_ID_.get(0)) + "", 16);
|
77 |
| - Log.d("ID", Integer.toString(ID)); |
| 85 | + Log.d(TAG, "ID: " + ID); |
78 | 86 | return ID;
|
79 | 87 | }
|
80 | 88 |
|
81 | 89 | public int[] getRaw() throws IOException {
|
82 |
| - fullList = i2c.readBulk(ADDRESS, 0x80 | 0x20 | 0x0E, 2); |
83 |
| - infraList = i2c.readBulk(ADDRESS, 0x80 | 0x20 | 0x0C, 2); |
| 90 | + List<Integer> infraList = i2c.readBulk(address, COMMAND_BIT | WORD_BIT | REGISTER_CHAN1_LOW, 2); |
| 91 | + List<Integer> fullList = i2c.readBulk(address, COMMAND_BIT | WORD_BIT | REGISTER_CHAN0_LOW, 2); |
84 | 92 | if (!infraList.isEmpty()) {
|
85 |
| - full = (fullList.get(0) << 8) | fullList.get(0); |
86 |
| - infra = (infraList.get(0) << 8) | infraList.get(0); |
| 93 | + int full = ((fullList.get(1) & 0xff) << 8) | fullList.get(0) & 0xff; |
| 94 | + int infra = ((infraList.get(1) & 0xff) << 8) | infraList.get(0) & 0xff; |
87 | 95 | return (new int[]{full, infra, full - infra});
|
88 | 96 | } else
|
89 | 97 | return null;
|
90 | 98 | }
|
91 | 99 |
|
92 |
| - public void setGain(String _gain_) throws IOException { |
93 |
| - if (_gain_.equals("1x")) |
94 |
| - gain = GAIN_1X; |
| 100 | + public void setGain(String gain) throws IOException { |
| 101 | + if (gain.equals("1x")) |
| 102 | + this.gain = GAIN_0X; |
95 | 103 |
|
96 |
| - else if (_gain_.equals("16x")) |
97 |
| - gain = GAIN_16X; |
98 |
| - else |
99 |
| - gain = GAIN_OX; |
100 |
| - i2c.writeBulk(ADDRESS, new int[]{COMMAND_BIT | REGISTER_TIMING, gain | timing}); |
101 |
| - } |
| 104 | + else if (gain.equals("16x")) |
| 105 | + this.gain = GAIN_16X; |
102 | 106 |
|
103 |
| - public void setTiming(int timing) throws IOException { |
104 |
| - Log.v(TAG, new int[]{13, 101, 404}[timing] + "mS"); |
105 |
| - this.timing = timing; |
106 |
| - i2c.writeBulk(ADDRESS, new int[]{COMMAND_BIT | REGISTER_TIMING, gain | timing}); |
| 107 | + i2c.writeBulk(address, new int[]{COMMAND_BIT | REGISTER_TIMING, this.gain | timing}); |
107 | 108 | }
|
108 | 109 |
|
109 | 110 | private void enable() throws IOException {
|
110 |
| - i2c.writeBulk(ADDRESS, new int[]{COMMAND_BIT | REGISTER_CONTROL, CONTROL_POWERON}); |
| 111 | + i2c.writeBulk(address, new int[]{COMMAND_BIT | REGISTER_CONTROL, CONTROL_POWERON}); |
111 | 112 | }
|
112 | 113 |
|
113 | 114 | public void disable() throws IOException {
|
114 |
| - i2c.writeBulk(ADDRESS, new int[]{COMMAND_BIT | REGISTER_CONTROL, CONTROL_POWEROFF}); |
| 115 | + i2c.writeBulk(address, new int[]{COMMAND_BIT | REGISTER_CONTROL, CONTROL_POWEROFF}); |
115 | 116 | }
|
116 | 117 |
|
117 | 118 | private void _wait() throws InterruptedException {
|
118 |
| - if (timing == INTEGRATIONTIME_13MS) TimeUnit.MILLISECONDS.sleep(14); |
119 |
| - if (timing == INTEGRATIONTIME_101MS) TimeUnit.MILLISECONDS.sleep(102); |
120 |
| - if (timing == INTEGRATIONTIME_402MS) TimeUnit.MILLISECONDS.sleep(403); |
121 |
| - |
| 119 | + switch (timing) { |
| 120 | + case INTEGRATIONTIME_13MS: { |
| 121 | + TimeUnit.MILLISECONDS.sleep(14); |
| 122 | + break; |
| 123 | + } |
| 124 | + case INTEGRATIONTIME_101MS: { |
| 125 | + TimeUnit.MILLISECONDS.sleep(102); |
| 126 | + break; |
| 127 | + } |
| 128 | + case INTEGRATIONTIME_402MS: |
| 129 | + default: { |
| 130 | + TimeUnit.MILLISECONDS.sleep(403); |
| 131 | + } |
| 132 | + } |
122 | 133 | }
|
123 | 134 |
|
124 | 135 | }
|
0 commit comments