//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // weather.c - To find what kind of weather station or if it is there. // There are also modules to find the direction of the weather // station and read/write output files // // Version: 2.00 // // // -------------------------------------------------------------------------- #include #include #include #include #include "ownet.h" #include "swt12.h" #include "weather.h" // defines #define MAXDEVICES 8 // family codes of devices #define TEMP_FAMILY 0x10 #define SWITCH_FAMILY 0x12 #define ATOD_FAMILY 0X20 #define COUNT_FAMILY 0x1D #define DIR_FAMILY 0x01 // misc #define MAXTEMPS 1 #define MAXSWITCH 1 #define MAXCOUNT 1 #define MAXATOD 1 #define MAXDIR 8 // external One Wire functions from nework layer extern void owSerialNum(int,uchar *,SMALLINT); extern SMALLINT owVerify(int,SMALLINT); // external One Wire functions from transaction layer extern SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT); // external One Wire functions from link layer extern void msDelay(int); // external functions defined in crcutil.c extern void setcrc16(int,ushort); extern ushort docrc16(int,ushort); // external functions defined in findtype.c SMALLINT FindDevices(int,uchar FamilySN[][8],SMALLINT,int); // extern prototypes extern int SetupAtoDControl(int, uchar *, uchar *, char *); extern int ReadAtoDResults(int portnum, int try_overdrive, uchar *, float *, uchar *); extern int DoAtoDConversion(int, int, uchar *); extern int WriteAtoD(int portnum, int try_overdrive, uchar SerialNum[8], uchar *ctrl, int start_address, int end_address); extern int ReadCounter(int, uchar *, int, unsigned long *); extern int ReadTemperature(int, uchar *, float *); extern long msGettick(void); extern int ToHex(char); extern int SetSwitch12(int portnum, uchar SerialNum[8], SwitchProps State); // local function prototypes int FindSetupWeather(int portnum, WeatherStruct *wet); int SetupWet(int portnum, WeatherStruct *wet, int nor); int ReadWet(int portnum, WeatherStruct *wet, float *temp, int *dir, double *revol); int GetDir(int portnum, WeatherStruct *wet); int TrueDir(int portnum, WeatherStruct *wet); int ParseData(char *inbuf, int insize, uchar *outbuf, int maxsize); static int conv[8] = {0,14,12,10,8,6,4,2}; static double conv_table[16][4] = { {0.06, 4.64, 4.64, 4.64}, {0.06, 0.06, 4.60, 4.60}, {4.64, 0.06, 4.64, 4.64}, {4.62, 0.06, 0.06, 4.60}, {4.64, 4.64, 0.06, 4.64}, {4.60, 4.60, 0.06, 0.06}, {4.64, 4.64, 4.64, 0.06}, {2.36, 4.62, 4.60, 0.06}, {2.38, 4.66, 4.66, 4.66}, {3.20, 3.20, 4.66, 4.64}, {4.66, 2.38, 4.66, 4.66}, {4.66, 3.18, 3.20, 4.64}, {4.66, 4.66, 2.38, 4.66}, {4.66, 4.66, 3.18, 3.18}, {4.66, 4.66, 4.66, 2.38}, {0.06, 4.62, 4.62, 2.34} }; // ------------------------------------------------------------------------- // SUBROUTINE - FindWeather // // This routine finds which weather station is attached to the 1-wire // network and returns the serial numbers for the weather station. If // it is the new weather station then it is not going to have an DS2401s. // // 'ds1820' - This will be the serial number for the DS1820 in the station // 'ds2423' - This will be the serial number for the DS2423 in the station // 'dsdir' - This will either be the DS2450 or the DS2406 serial num. // 'ds2401' - This will be the list of DS2401s if the old weather station. // // Returns: TRUE if a weather station is found and the listing of the // devices file is found or made. FALSE if a weather station // is not found or the device file is not found or can not be made. // int FindSetupWeather(int portnum, WeatherStruct *wet) { int ret = FALSE; FILE *fptr; char filename[] = "ini.txt"; char TempSN[190]; uchar SNs[90]; int i,j; int num; char msg[45]; wet->weather_a = FALSE; wet->weather_b = FALSE; wet->found_2401 = 0; wet->found_2423 = FALSE; wet->found_1820 = FALSE; wet->found_dir = FALSE; wet->north = 0; if((fptr = fopen(filename, "r")) == NULL) { printf("error opening file but try to create file\n"); // Create ini.txt if weather station has DS2450 // find the DS1820 temperature num = FindDevices(portnum, &wet->ds1820, TEMP_FAMILY, MAXTEMPS); // check if not at least 1 temperature device if(num == 0) wet->found_1820 = FALSE; else wet->found_1820 = TRUE; // find the DS2450 switch num = FindDevices(portnum, &wet->dsdir, ATOD_FAMILY, MAXATOD); // check if not at least 1 switch device if(num == 0) wet->found_dir = FALSE; else wet->found_dir = TRUE; // find the DS2423 switch num = FindDevices(portnum, &wet->ds2423, COUNT_FAMILY, MAXCOUNT); // check if not at least 1 count device if(num == 0) wet->found_2423 = FALSE; else wet->found_2423 = TRUE; // Create the output file ini.txt if(wet->found_1820 && wet->found_dir && wet->found_2423) { if(SetupAtoDControl(portnum, &wet->dsdir[0], &wet->ctrl[0], &msg[0])) if(WriteAtoD(portnum, FALSE, &wet->dsdir[0], &wet->ctrl[0], 0x08, 0x11)) { if((fptr = fopen(filename, "w")) == NULL) printf("error tring to create file\n"); else { wet->weather_b = TRUE; ret = TRUE; // Printing the Serial number for DS2450 printf("Found DS2450\n"); for(i=7; i>=0; i--) printf("%02X", wet->dsdir[i]); printf("\n"); for(i=7; i>=0; i--) fprintf(fptr, "%02X", wet->dsdir[i]); fprintf(fptr, "\n"); // Printing the Serial number for DS1820 printf("Found DS1820\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds1820[i]); printf("\n"); for(i=7; i>=0; i--) fprintf(fptr, "%02X", wet->ds1820[i]); fprintf(fptr, "\n"); // Printing the Serial number for DS2423 printf("Found DS2423\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds2423[i]); printf("\n"); for(i=7; i>=0; i--) fprintf(fptr, "%02X", wet->ds2423[i]); fprintf(fptr, "\n"); // Printing the Default Wind Direction printf("The Default Wind Direction is 0\n"); fprintf(fptr, "0\n"); } } } } else { num = fread(TempSN, sizeof(char), 189, fptr); num = ParseData(TempSN, num, &SNs[0], 90); if(!wet->weather_a && !wet->weather_b) { if(SNs[7] == 0x01) wet->weather_a = TRUE; else wet->weather_b = TRUE; } j = 0; while((SNs[7+8*j] == 0x01) || (SNs[7+8*j] == 0x20) || (SNs[7+8*j] == 0x12) || (SNs[7+8*j] == 0x1D) || (SNs[7+8*j] == 0x10)) { if(SNs[7+8*j] == 0x01) { for(i=0; i<8; i++) wet->ds2401[wet->found_2401][7-i] = SNs[8*j + i]; printf("Found DS2401\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds2401[wet->found_2401][i]); printf("\n"); wet->found_2401++; } if(SNs[7+8*j] == 0x20) { if(!wet->found_dir) { for(i=0; i<8; i++) wet->dsdir[7-i] = SNs[8*j + i]; owSerialNum(portnum, wet->dsdir, FALSE); if(!owVerify(portnum, FALSE)) ret = FALSE; wet->found_dir = TRUE; printf("Found DS2450\n"); for(i=7; i>=0; i--) printf("%02X", wet->dsdir[i]); printf("\n"); SetupAtoDControl(portnum, wet->dsdir, &wet->ctrl[0], &msg[0]); WriteAtoD(portnum, FALSE, wet->dsdir, &wet->ctrl[0], 0x08, 0x11); } } if(SNs[7+8*j] == 0x12) { if(!wet->found_dir) { for(i=0; i<8; i++) wet->dsdir[7-i] = SNs[8*j + i]; owSerialNum(portnum, wet->dsdir, FALSE); if(!owVerify(portnum, FALSE)) ret = FALSE; wet->found_dir = TRUE; printf("Found DS2406\n"); for(i=7; i>=0; i--) printf("%02X", wet->dsdir[i]); printf("\n"); } } if(SNs[7+8*j] == 0x1D) { for(i=0; i<8; i++) wet->ds2423[7-i] = SNs[8*j + i]; owSerialNum(portnum, wet->ds2423, FALSE); if(!owVerify(portnum, FALSE)) ret = FALSE; wet->found_2423 = TRUE; printf("Found DS2423\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds2423[i]); printf("\n"); } if(SNs[7+8*j] == 0x10) { for(i=0; i<8; i++) wet->ds1820[7-i] = SNs[8*j + i]; owSerialNum(portnum, wet->ds1820, FALSE); if(!owVerify(portnum, FALSE)) ret = FALSE; wet->found_1820 = TRUE; printf("Found DS1820\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds1820[i]); printf("\n"); } j++; } if(wet->weather_a) { if((TempSN[0xBB] <= 0x40) && (TempSN[0xBB] >= 0x30)) if((TempSN[0xBC] <= 0x40) && (TempSN[0xBC] >= 0x30)) wet->north = (TempSN[0xBB]-0x30)*10 + (TempSN[0xBC]-0x30); else wet->north = TempSN[0xBB] - 0x30; else wet->north = 0; if(wet->found_dir && wet->found_1820 && wet->found_2423 && (wet->found_2401 == 8)) ret = TRUE; } else if(wet->weather_b) { if((TempSN[0x33] <= 0x40) && (TempSN[0x33] >= 0x30)) if((TempSN[0x34] <= 0x40) && (TempSN[0x34] >= 0x30)) wet->north = (TempSN[0x33]-0x30)*10 + (TempSN[0x34]-0x30); else wet->north = TempSN[0x33] - 0x30; else wet->north = 0; if(wet->found_dir && wet->found_1820 && wet->found_2423) ret = TRUE; } } if(wet->weather_a || wet->weather_b) fclose(fptr); return ret; } // ------------------------------------------------------------------------- // SUBROUTINE - SetupWet // // This routine sets up a weather station given the serial numbers for the // weather station. // // Returns: TRUE, if the weather station was setup and FALSE if it was not. // int SetupWet(int portnum, WeatherStruct *wet, int nor) { int i,j; int ret = FALSE; char msg[45]; wet->north = nor; if((wet->ds2401 == NULL) || wet->weather_b) { wet->weather_b = TRUE; wet->weather_a = FALSE; // Setting up the DS2450 owSerialNum(portnum, wet->dsdir, FALSE); if(!owVerify(portnum, FALSE)) { printf("The DS2450 was not found.\n"); return FALSE; } else { // Printing the Serial number for DS2450 printf("Set DS2450\n"); for(i=7; i>=0; i--) printf("%02X", wet->dsdir[i]); printf("\n"); } // Setting up the DS1820 owSerialNum(portnum, wet->ds1820, FALSE); if(!owVerify(portnum, FALSE)) { printf("The DS1820 was not found.\n"); return FALSE; } else { // Printing the Serial number for DS1820 printf("Set DS1820\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds1820[i]); printf("\n"); } // Setting up the DS2423 owSerialNum(portnum, wet->ds2423, FALSE); if(!owVerify(portnum, FALSE)) { printf("The DS2423 was not found.\n"); return FALSE; } else { // Printing the Serial number for DS2423 printf("Set DS2423\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds2423[i]); printf("\n"); } if(SetupAtoDControl(portnum, &wet->dsdir[0], &wet->ctrl[0], &msg[0])) if(WriteAtoD(portnum, FALSE, &wet->dsdir[0], &wet->ctrl[0], 0x08, 0x11)) ret = TRUE; } else { wet->weather_a = TRUE; wet->weather_b = FALSE; printf("Set DS2401\n"); for(i=0; i<8; i++) { // Printing the Serial number for DS2401 for(j=7; j>=0; j--) printf("%02X", wet->ds2401[i][j]); printf("\n"); } // Setting up the DS2423 owSerialNum(portnum, wet->ds2423, FALSE); if(!owVerify(portnum, FALSE)) { printf("The DS2423 was not found.\n"); return FALSE; } else { // Printing the Serial number for DS2423 printf("Set DS2423\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds2423[i]); printf("\n"); } // Setting up the DS1820 owSerialNum(portnum, wet->ds1820, FALSE); if(!owVerify(portnum, FALSE)) { printf("The DS1820 was not found.\n"); return FALSE; } else { // Printing the Serial number for DS1820 printf("Set DS1820\n"); for(i=7; i>=0; i--) printf("%02X", wet->ds1820[i]); printf("\n"); } // Setting up the DS2406 owSerialNum(portnum, wet->dsdir, FALSE); if(!owVerify(portnum, FALSE)) { printf("The DS2406 was not found.\n"); return FALSE; } else { // Printing the Serial number for DS2406 printf("Set DS2450\n"); for(i=7; i>=0; i--) printf("%02X", wet->dsdir[i]); printf("\n"); } ret = TRUE; } return ret; } // ------------------------------------------------------------------------- // SUBROUTINE - ReadWet // // 'temp' - The temperature from the DS1820 in F // 'dir' - The wind direction from 0-15 // 'revol' - The wind speed in revolutions per second // // Returns: TRUE, if the reads were successfull and FALSE if they were not. // int ReadWet(int portnum, WeatherStruct *wet, float *temp, int *dir, double *revol) { int ret = TRUE; unsigned long start_count=0, end_count=0, start_time, end_time; float current_temp; // read the current counter // use this reference to calculate wind speed later if (!ReadCounter(portnum, &wet->ds2423[0], 15, &start_count)) { printf("\nError reading counter, verify device present:%d\n", (int)owVerify(portnum, FALSE)); ret = FALSE; } // get a time stamp (mS) start_time = msGettick(); // read the temperature and print in F if (ReadTemperature(portnum, &wet->ds1820[0],¤t_temp)) *temp = current_temp * 9 / 5 + 32; else { printf("\nError reading temperature, verify device present:%d\n", (int)owVerify(portnum, FALSE)); ret = FALSE; } // read the wind direction *dir = TrueDir(portnum, wet); // read the counter again if (!ReadCounter(portnum, &wet->ds2423[0], 15, &end_count)) { printf("Error reading counter, verify device present:%d\n", (int)owVerify(portnum, FALSE)); ret = FALSE; } // get a time stamp (mS) end_time = msGettick(); // calculate the wind speed based on the revolutions per second *revol = (((end_count - start_count) * 1000.0) / (end_time - start_time)) / 2.0; return ret; } // ------------------------------------------------------------------------- // SUBROUTINE - GetDir // // This routine looks at the DS2401 serial numbers or the DS2450 volts to // determine which direction the wind is blowing. // // Returns: The direction in a 0-15 order and 16 for no DS2401s found // int GetDir(int portnum, WeatherStruct *wet) { SwitchProps st; uchar temp_dir[MAXDIR][8]; int i,j; int numdir; int firstmatch, secondmatch; int firstindex, secondindex; int found = TRUE; int ret = 16; float prslt[4]; if(wet->weather_a) { st.Chan_A = FALSE; st.Chan_B = TRUE; if(SetSwitch12(portnum, &wet->dsdir[0], st)) { numdir = FindDevices(portnum, &temp_dir[0], DIR_FAMILY, MAXDIR); } else printf("Error on setting up the switch\n"); if(numdir == 0) ret = 16; if(numdir == 2) { for(i=0; i<8; i++) { for(j=0; j<8; j++) if(temp_dir[0][j] != wet->ds2401[i][j]) { found = FALSE; break; } else found = TRUE; if(found) { firstindex = i; firstmatch = conv[i]; found = FALSE; break; } } for(i=0; i<8; i++) { if(i != firstindex) { for(j=0; j<8; j++) { if(temp_dir[1][j] != wet->ds2401[i][j]) { found = FALSE; break; } else found = TRUE; } } if(found) { secondindex = i; secondmatch = conv[i]; break; } } if(((firstmatch == 0) || (secondmatch == 0)) && ((firstmatch == 14) || (secondmatch == 14))) ret = 15; else ret = (firstmatch+secondmatch)/2; } if(numdir == 1) { for(i=0; i<8; i++) { found = TRUE; for(j=0; j<8; j++) if(temp_dir[0][j] != wet->ds2401[i][j]) found = FALSE; if(found) { ret = conv[i]; break; } } } st.Chan_A = FALSE; st.Chan_B = FALSE; if(!SetSwitch12(portnum, &wet->dsdir[0], st)) { msDelay(10); if(!SetSwitch12(portnum, &wet->dsdir[0], st)) { printf("Failed to close channel B\n"); } } } else if(wet->weather_b) { // read wind direction for the DS2450 weather station if(DoAtoDConversion(portnum, FALSE, &wet->dsdir[0])) { if(ReadAtoDResults(portnum, FALSE, &wet->dsdir[0], &prslt[0], &wet->ctrl[0])) { for(i=0; i<16; i++) { if( ((prslt[0] <= (float)conv_table[i][0]+0.25) && (prslt[0] >= (float)conv_table[i][0]-0.25)) && ((prslt[1] <= (float)conv_table[i][1]+0.25) && (prslt[1] >= (float)conv_table[i][1]-0.25)) && ((prslt[2] <= (float)conv_table[i][2]+0.25) && (prslt[2] >= (float)conv_table[i][2]-0.25)) && ((prslt[3] <= (float)conv_table[i][3]+0.25) && (prslt[3] >= (float)conv_table[i][3]-0.25)) ) { ret = i; break; } } } else { printf("\n"); printf("\nError reading channel, verify device present: %d\n", (int)owVerify(portnum, FALSE)); } } } return ret; } // ------------------------------------------------------------------------- // SUBROUTINE - TrueDir // // This routine returns the direction given the north direction in 0-15. // // Returns: The direction in a 0-15 order with 0 north and clockwise from that. // 16 is returned for no DS2401s found. // int TrueDir(int portnum, WeatherStruct *wet) { int dir; int retdir; dir = GetDir(portnum, wet); if(dir != 16) { if( (dir-wet->north) < 0 ) retdir = (dir - wet->north + 16); else retdir = dir - wet->north; } else retdir = 16; return retdir; } //---------------------------------------------------------------------- // Parse the raw file data in to an array of uchar's. The data must // be hex characters possible seperated by white space // 12 34 456789ABCD EF // FE DC BA 98 7654 32 10 // would be converted to an array of 16 uchars. // return the array length. If an invalid hex pair is found then the // return will be 0. // int ParseData(char *inbuf, int insize, uchar *outbuf, int maxsize) { int ps, outlen=0, gotmnib=0; uchar mnib; // loop until end of data for (ps = 0; ps < insize; ps++) { // check for white space if (isspace(inbuf[ps])) continue; // not white space, make sure hex else if (isxdigit(inbuf[ps])) { // check if have first nibble yet if (gotmnib) { // this is the second nibble outbuf[outlen++] = (mnib << 4) | ToHex(inbuf[ps]); gotmnib = 0; } else { // this is the first nibble mnib = ToHex(inbuf[ps]); gotmnib = 1; } } else return 0; // if getting to the max return what we have if ((outlen + 1) >= maxsize) return outlen; } return outlen; }