1111import org .pmw .tinylog .Logger ;
1212import rx .Scheduler ;
1313
14+ import java .io .IOException ;
15+ import java .nio .ByteBuffer ;
1416import java .util .concurrent .TimeUnit ;
1517import java .util .concurrent .atomic .AtomicBoolean ;
1618import java .util .concurrent .atomic .AtomicReference ;
@@ -37,17 +39,17 @@ public final class Bar30PressureSensor implements Barometer, Thermometer {
3739
3840 private final AtomicReference <TemperatureValue > temperature = new AtomicReference <>(new ExternalTemperatureValue ());
3941
42+ private final AtomicBoolean firstReading = new AtomicBoolean (true );
43+
4044 private final I2C channel ;
4145
42- private final Scheduler scheduler ;
46+ private final Scheduler . Worker worker ;
4347
4448 private final long conversionTime ;
4549
46- private final AtomicBoolean ready = new AtomicBoolean (false );
47-
4850 public Bar30PressureSensor (final I2C channel , final Scheduler scheduler , final long conversionTime ) {
4951 this .channel = channel ;
50- this .scheduler = scheduler ;
52+ this .worker = scheduler . createWorker () ;
5153 this .conversionTime = conversionTime ;
5254 init ();
5355 }
@@ -63,102 +65,131 @@ public TemperatureValue temperature() {
6365 }
6466
6567 private void init () {
66- scheduler . createWorker () .schedule (() -> {
68+ worker .schedule (() -> {
6769 channel .write (RESET );
68- scheduler . createWorker () .schedule (() -> {
69- final short [] crc = new short [8 ];
70+ worker .schedule (() -> {
71+ final long [] crc = new long [8 ];
7072 for (byte i = 0 ; i < 7 ; i ++) {
7173 final byte [] c = channel .read ((byte ) (PROM_READ + i * 2 ), 2 );
72- crc [i ] = (short ) ((c [0 ] << 8 ) | c [1 ]);
74+ final ByteBuffer byteBuffer = ByteBuffer .allocate (4 );
75+ byteBuffer .put ((byte ) 0 );
76+ byteBuffer .put ((byte ) 0 );
77+ byteBuffer .put (c [0 ]);
78+ byteBuffer .put (c [1 ]);
79+ byteBuffer .flip ();
80+ crc [i ] = byteBuffer .asIntBuffer ().get ();
7381 }
74- final byte crcRead = ( byte ) ( crc [0 ] >> 12 ) ;
75- final byte crcCalculated = crc4 (crc );
82+ final long crcRead = crc [0 ] >> 12 ;
83+ final long crcCalculated = crc4 (crc );
7684
7785 if (crcCalculated == crcRead ) {
78- ready .set (true );
79- scheduler .createWorker ().schedule (() -> this .convert (crc ));
86+ worker .schedule (() -> this .convert (crc ));
8087 } else {
8188 Logger .error ("Could not initialize the MS5837 pressure sensor" );
8289 }
8390 }, conversionTime , TimeUnit .MILLISECONDS );
8491 });
8592 }
8693
87- private static byte crc4 (final short [] prom ) {
88- short remainder = 0 ;
89-
90- prom [0 ] = (short ) ((prom [0 ]) & 0x0FFF );
94+ private static long crc4 (final long [] prom ) {
95+ long remainder = 0 ;
96+ prom [0 ] = (prom [0 ]) & 0x0FFF ;
9197 prom [7 ] = 0 ;
9298
93- for (byte i = 0 ; i < 16 ; i ++) {
99+ for (int i = 0 ; i < 16 ; i ++) {
94100 if (i % 2 == 1 ) {
95- remainder ^= ( short ) (( prom [i >> 1 ]) & 0x00FF ) ;
101+ remainder ^= prom [i >> 1 ] & 0x00FF ;
96102 } else {
97- remainder ^= ( short ) ( prom [i >> 1 ] >> 8 ) ;
103+ remainder ^= prom [i >> 1 ] >> 8 ;
98104 }
99- for (byte nBit = 8 ; nBit > 0 ; nBit --) {
105+ for (int nBit = 8 ; nBit > 0 ; nBit --) {
100106 if ((remainder & 0x8000 ) != 0 ) {
101- remainder = (short ) (( remainder << 1 ) ^ 0x3000 ) ;
107+ remainder = (remainder << 1 ) ^ 0x3000 ;
102108 } else {
103- remainder = ( short ) ( remainder << 1 ) ;
109+ remainder = remainder << 1 ;
104110 }
105111 }
106112 }
107-
108- remainder = (short ) ((remainder >> 12 ) & 0x000F );
109-
110- return (byte ) remainder ;
113+ remainder = (remainder >> 12 ) & 0x000F ;
114+ return remainder ;
111115 }
112116
113- private void convert (final short [] crc ) {
117+ private void convert (final long [] crc ) {
114118 channel .write (CONVERT_D1 );
115- scheduler .createWorker ().schedule (() -> {
116- final byte [] d1Bytes = channel .read (ADC_READ , 3 );
117- final int d1 = (((d1Bytes [0 ] << 8 ) | d1Bytes [1 ]) << 8 ) | d1Bytes [2 ];
119+ worker .schedule (() -> {
120+ final byte [] d1Bytes ;
121+ try {
122+ d1Bytes = channel .readUnsafe (ADC_READ , 3 );
123+ } catch (final IOException e ) {
124+ worker .schedule (() -> convert (crc ));
125+ return ;
126+ }
127+ final ByteBuffer d1ByteBuffer = ByteBuffer .allocate (4 );
128+ d1ByteBuffer .put ((byte ) 0 );
129+ d1ByteBuffer .put (d1Bytes [0 ]);
130+ d1ByteBuffer .put (d1Bytes [1 ]);
131+ d1ByteBuffer .put (d1Bytes [2 ]);
132+ d1ByteBuffer .flip ();
133+ final int d1 = d1ByteBuffer .asIntBuffer ().get ();
118134 channel .write (CONVERT_D2 );
119- scheduler .createWorker ().schedule (() -> {
120- channel .write (ADC_READ );
121- final byte [] d2Bytes = channel .read (ADC_READ , 3 );
122- final int d2 = (((d2Bytes [0 ] << 8 ) | d2Bytes [1 ]) << 8 ) | d2Bytes [2 ];
135+ worker .schedule (() -> {
136+ final byte [] d2Bytes ;
137+ try {
138+ d2Bytes = channel .readUnsafe (ADC_READ , 3 );
139+ } catch (final IOException e ) {
140+ worker .schedule (() -> convert (crc ));
141+ return ;
142+ }
143+ final ByteBuffer d2ByteBuffer = ByteBuffer .allocate (4 );
144+ d2ByteBuffer .put ((byte ) 0 );
145+ d2ByteBuffer .put (d2Bytes [0 ]);
146+ d2ByteBuffer .put (d2Bytes [1 ]);
147+ d2ByteBuffer .put (d2Bytes [2 ]);
148+ d2ByteBuffer .flip ();
149+ final int d2 = d2ByteBuffer .asIntBuffer ().get ();
123150 calculate (crc , d1 , d2 );
124- scheduler . createWorker () .schedule (() -> convert (crc ));
151+ worker .schedule (() -> convert (crc ));
125152 }, conversionTime , TimeUnit .MILLISECONDS );
126-
127153 }, conversionTime , TimeUnit .MILLISECONDS );
128154 }
129155
130- private void calculate (final short [] crc , final int d1 , final int d2 ) {
131-
132- final double dT = d2 - crc [5 ] * 256.0 ;
133- final double sens = crc [1 ] * 32768.0 + (crc [3 ] * dT ) / 256.0 ;
134- final double off = crc [2 ] * 65536.0 + (crc [4 ] * dT ) / 128.0 ;
135- final double t = 2000.0 + dT * crc [6 ] / 8388608.0 ;
136-
137- double iSens = 0 ;
138- double iOff = 0 ;
139- double iT = 0 ;
140-
141- if (t / 100.0 < 20.0 ) {
142- // low temp
143- iT = 3.0 * dT * dT / 8589934592.0 ;
144- iOff = 3.0 * (t - 2000.0 ) * (t - 2000.0 ) / 2.0 ;
145- iSens = 5.0 * (t - 2000.0 ) * (t - 2000.0 ) / 8.0 ;
146- if (t / 100.0 < -15.0 ) {
147- //Very low temp
148- iOff = iOff + 7 * (t + 1500.0 ) * (t + 1500.0 );
149- iSens = iSens + 4 * (t + 1500.0 ) * (t + 1500.0 );
156+ private void calculate (final long [] crc , final int d1 , final int d2 ) {
157+
158+ final long dT = d2 - crc [5 ] * 256 ;
159+ final long sens1 = crc [1 ] * 32768 + (crc [3 ] * dT ) / 256 ;
160+ final long off1 = crc [2 ] * 65536 + (crc [4 ] * dT ) / 128 ;
161+ final long t1 = 2000 + dT * crc [6 ] / 8388608 ;
162+
163+ long sens2 = 0 ;
164+ long off2 = 0 ;
165+ long t2 = 0 ;
166+
167+ if (t1 >= 2000 ) {
168+ t2 = 2 * (dT * dT ) / 137438953472L ;
169+ off2 = ((t1 - 2000 ) * (t1 - 2000 )) / 16 ;
170+ sens2 = 0 ;
171+ } else if (t1 < 2000 ) {
172+ t2 = 3 * (dT * dT ) / 8589934592L ;
173+ off2 = 3 * ((t1 - 2000 ) * (t1 - 2000 )) / 2 ;
174+ sens2 = 5 * ((t1 - 2000 ) * (t1 - 2000 )) / 8 ;
175+ if (t1 < -1500 ) {
176+ off2 = off2 + 7 * ((t1 + 1500 ) * (t1 + 1500 ));
177+ sens2 = sens2 + 4 * ((t1 + 1500 ) * (t1 + 1500 ));
150178 }
151- } else if (t / 100.0 >= 20.0 ) {
152- //High temp
153- iT = 2.0 * dT * dT / 137438953472.0 ;
154- iOff = 1.0 * (t - 2000.0 ) * (t - 2000.0 ) / 16.0 ;
155- iSens = 0.0 ;
156179 }
157180
158- final double off2 = off - iOff ;
159- final double sens2 = sens - iSens ;
160-
161- temperature .set (new ExternalTemperatureValue ((float ) ((t - iT ) / 100.0 )));
162- pressure .set (new ExternalPressureValue ((float ) ((((d1 * sens2 ) / 2097152.0 - off2 ) / 8192.0 ) / 10 )));
181+ final double t = t1 - t2 ;
182+ final double off = off1 - off2 ;
183+ final double sens = sens1 - sens2 ;
184+
185+ final float tFinal = (float ) (t / 100.0 );
186+ final float pFinal = (float ) ((((d1 * sens ) / 2097152 ) - off ) / 8192 ) / 100 ;
187+ if (firstReading .getAndSet (false )
188+ || (Math .abs (tFinal - temperature .get ().getTemperature ()) / temperature .get ().getTemperature () < 0.1
189+ && Math .abs (pFinal - pressure .get ().getPressure ()) / pressure .get ().getPressure () < 0.1 )
190+ ) {
191+ temperature .set (new ExternalTemperatureValue (tFinal ));
192+ pressure .set (new ExternalPressureValue (pFinal ));
193+ }
163194 }
164195}
0 commit comments