|
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