/****************************************************************************** * * Project Name: WS603A Demo Program * File name: WS603a.java * Version: 0.6 beta 04/05/09 * * * Copyright (C) 2009 by T. Bitson - All rights reserved. * * This class provides the interface to the new WS603A 1-Wire weather instrument * * The WS603A shares the 1-Wire bus with an internal microcontroller that may be * reading or writing to the internal DS2760. Therefore,there is an increased * chance that a read or write command will fail. * The code below for reading wind speed, direction, and setting the LEDS will * retry 3 times before declaring a failure. * *****************************************************************************/ package WS603aDemo; import com.dalsemi.onewire.*; import com.dalsemi.onewire.adapter.*; import com.dalsemi.onewire.container.*; public class WS603a { // calibration constants private static final int NORTH_OFFSET = 0; // DS2760 memory read constants private static final byte READ_PARAM_CMD = (byte)0xA0; private static final byte READ_DATA_CMD = (byte)0xA1; private static final byte LED_CNTRL_CMD = (byte)0xA2; private static final byte WIND_SPD_CAL_CMD = (byte)0xA3; private static final byte WIND_DIR_CAL_CMD = (byte)0xA4; private static final byte DATA_END_BYTE = (byte)0x1E; private static final byte CAL_END_BYTE = (byte)0x0E; private static final byte LED_END_BYTE = (byte)0x2E; private static final byte WRITE_ADDR = (byte)0x80; private static final byte READ_ADDR = (byte)0x88; public static final byte LED_HIGH = (byte)0x07; public static final byte LED_MED = (byte)0x03; public static final byte LED_LOW = (byte)0x01; public static final byte LED_OFF = (byte)0x00; // class variables // Adapter private DSPortAdapter adapter; // data array for reading and writing to the WS603A byte[] byteArray = new byte[8]; // debug mode - set to true to enable diagnostic prints private static boolean debugFlag = false; // The WS603A uses a DS2760, which is Container 30 OneWireContainer30 wsDevice = null; public WS603a(DSPortAdapter adapter, String ws603bDeviceID) { // get instances of the 1-wire device wsDevice = new OneWireContainer30(adapter, ws603bDeviceID); try { // initialize WS603A to read data byteArray[0] = READ_DATA_CMD; writeBytes(1, DATA_END_BYTE); } catch (Exception e) { System.out.println("Error Initializing WS603A: " + e); System.out.println("Verify the anemometer is properly connected"); System.out.println("and the device serial number is correct"); System.exit(1); } } public float getTemperature() { float temp = -999.9f; int errors = 0; if (debugFlag) { System.out.print("Temperature: Device = " + wsDevice.getName()); System.out.print(" ID = " + wsDevice.getAddressAsString() + "\n"); } while (errors < 3) { try { byte[] state = wsDevice.readDevice(); wsDevice.doTemperatureConvert(state); sleep(250); state = wsDevice.readDevice(); temp = (float)wsDevice.getTemperature(state); // convert to degs F - comment out to get degrees C temp = temp * 9.0f/5.0f + 32f; // if we got here, data should be good return temp; } catch (OneWireException e) { errors++; System.out.println("***** Temp Retry"); if (errors >= 3) { System.out.println("Error Reading Temperature: " + e); } } } return -999.9f; } public float getWindSpeed() { float windSpeed = 0f; if (wsDevice != null) { try { if (debugFlag) { System.out.print("Wind Speed: Device = " + wsDevice.getName()); System.out.print(" ID = " + wsDevice.getAddressAsString() + "\n"); } // read DS603A data by updating the byte array updateBytes(); // wind speed is 2nd byte. Calc wind speed in MPH windSpeed = byteArray[1] * 2.453f * 1000f/3600f; } catch (Exception e) { System.out.println("Error Reading Wind Speed: " + e); windSpeed = -999.9f; } } return windSpeed; } public int getWindDir() { int windDir = 0; if (debugFlag) { System.out.print("Wind Dir: Device = " + wsDevice.getName()); System.out.print(" ID = " + wsDevice.getAddressAsString() + "\n"); } try { // read DS603A data by updating the byte array // if getting wind direction right after wind speed, the data for wind // direction is valid, and an update is not required. updateBytes(); // wind speed is 3rd byte windDir = byteArray[2]; } catch (Exception e) { System.out.println("Error Reading Wind Direction: " + e); windDir = -999; } return windDir; } public void setLEDMode(int mode, int redLevel, int blueLevel) { if (debugFlag) System.out.print(" LED Mode Command = " + mode + "\n"); // mode = 0 is manual control of the LEDs // mode = 1 to 6 is auto blink mode // level are defined above, i.e. LED_HIGH, LED_OFF, erc. byteArray[0] = LED_CNTRL_CMD; // command byteArray[1] = (byte)mode; // mode // set manual mode level if (mode == 0) { if (redLevel == LED_OFF && blueLevel == LED_OFF) byteArray[2] = (byte)0x00; // off else byteArray[2] = (byte)(0x80 | (redLevel << 4) | blueLevel); } else // auto sequence mode { byteArray[2] = (byte)mode; // 0ff } byteArray[3] = (byte)0x00; //auto level byteArray[4] = (byte)0x00; // threshold try { writeBytes(5, LED_END_BYTE); } catch (Exception e) { System.out.println("Error wrting WS603A during setLEDMode(): " + e); } } // routine to read the calibration values public void getCalValues() { byte[] byteArray = new byte[8]; if (wsDevice != null) { try { if (debugFlag) { System.out.print("Wind Speed: Device = " + wsDevice.getName()); System.out.print(" ID = " + wsDevice.getAddressAsString() + "\n"); } // read cal values byteArray[0] = READ_PARAM_CMD; writeBytes(1, CAL_END_BYTE); sleep(1000); wsDevice.readBytes(READ_ADDR, byteArray, 0, 7); System.out.println("Response Byte = 0x" + (Integer.toHexString(byteArray[0] & 0x00ff).toUpperCase())); System.out.println("Light Mode = 0x" + (Integer.toHexString(byteArray[1] & 0x00ff).toUpperCase())); System.out.println("Speed Cal = 0x" + (Integer.toHexString(byteArray[2] & 0x00ff).toUpperCase())); System.out.println("Direction Cal = 0x" + (Integer.toHexString(byteArray[3] & 0x00ff).toUpperCase())); System.out.println("Light Threshold= 0x" + (Integer.toHexString(byteArray[4] & 0x00ff).toUpperCase())); System.out.println("Unused = 0x" + (Integer.toHexString(byteArray[5] & 0x00ff).toUpperCase())); System.out.println("Verify Byte = 0x" + (Integer.toHexString(byteArray[6] & 0x00ff).toUpperCase())); System.out.println("\n"); sleep(1000); // set back WS603A to read data byteArray[0] = READ_DATA_CMD; writeBytes(1, DATA_END_BYTE); } catch (Exception e) { System.out.println("Error Reading Cal Values: " + e); } } } public void putCalValues() { // TBD } private void updateBytes() throws Exception { int errors = 0; while (errors < 3) { try { wsDevice.readBytes(READ_ADDR, byteArray, 0, 7); // add checksum check // if we got here, read was OK if (debugFlag) { System.out.println("Wind Speed"); System.out.println("Response Byte = 0x" + (Integer.toHexString(byteArray[0] & 0x00ff).toUpperCase())); System.out.println("Wind Speed = 0x" + (Integer.toHexString(byteArray[1] & 0x00ff).toUpperCase())); System.out.println("Wind Direction = 0x" + (Integer.toHexString(byteArray[2] & 0x00ff).toUpperCase())); System.out.println("Light Status = 0x" + (Integer.toHexString(byteArray[3] & 0x00ff).toUpperCase())); System.out.println("Light Level = 0x" + (Integer.toHexString(byteArray[4] & 0x00ff).toUpperCase())); System.out.println("Voltage = 0x" + (Integer.toHexString(byteArray[5] & 0x00ff).toUpperCase())); System.out.println("Verify Byte = 0x" + (Integer.toHexString(byteArray[6] & 0x00ff).toUpperCase())); System.out.println("\n"); } return; } catch (OneWireException e) { errors++; if (errors >= 3) throw new Exception(e); System.out.println("***** ReadBytes() Retry"); sleep(50); } } } // routine to write the data array to the WS, adding the checksum byte and // the end byte private void writeBytes(int len, byte endByte) throws Exception { int i; int errors = 0; while (errors < 3) { try { // send command bytes for (i = 0; i < len; i++) { if (debugFlag) System.out.println("Sending Byte[" + i + "] = 0x" + (Integer.toHexString(byteArray[i] & 0x00ff).toUpperCase())); wsDevice.writeByte(WRITE_ADDR + i, byteArray[i]); } // send checksum wsDevice.writeByte(WRITE_ADDR + i, calcCheckSum(i)); // next byte in array i++; // now send the endByte wsDevice.writeByte(WRITE_ADDR + i, endByte); // send byte // if we got here, all is well return; } catch (OneWireException e) { errors++; if (errors >= 3) throw new Exception(e); System.out.println("***** WriteBytes() Retry"); } } } private byte calcCheckSum(int len) { byte sum = 0; for (int i = 0; i < len; i++) sum += byteArray[i]; if (debugFlag) System.out.println("Checksum = 0x" + (Integer.toHexString(sum & 0x00ff).toUpperCase())); return sum; } // convert direction value into compass direction string public static String getWindDirStr(int input) { String[] direction = { " ERR", " N ", "NNE", "NE ", "ENE", " E ", "ESE", "SE ", "SSE", " S ", "SSW", "SW ", "WSW", " W ", "WNW", "NW ", "NNW"}; if (debugFlag) System.out.println("GetWindDirectionString input = " + input + " and cal = " + NORTH_OFFSET); // valid inputs 0 thru 16 if (input < 0 || input >= 16) input = 16; else input = (input + NORTH_OFFSET) % 16; if (debugFlag) System.out.println("Wind Direction Decoded = " + input + " = " + direction[input]); return direction[input]; } // helper routine to simplfy the code public void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException e) {/* don't care */} } }