'This is a weather station conversion routine for WM918. Inputs Metric, outputs Imperial 'Written by VK5DJ - September 30, 2004 'update on Dec 23rd to add today's rain 'Serial data in Port A.0 and serial data out on Port A.1 'Note if you split a string across a bank boundary (96) it works very slowly 'MCLRE_OFF would mean pin 4 becomes port A.5 (used as MCLRE_ON here) 'This program supports a connection mode (SW4 off, CD line active, SW3 on) 'SW1: High=5 mins PortB.3 'SW2: Low=send metric High=Imperial units 'SW3= Port B.4 high = TNC mode, low=UIviewmode 'SW4: sets the need for connection: 1=use connected mode, 0= use beacon mode (Port B.5) 'SW6: High=lat/long style, Low=positionless packet PortB.7 'SW7: High=10 mins Port A.4 'SW8: High=20 mins PortA.3 'Connected sense on Port B.6 -pin 12 from the DCD line of the TNC (high=connected) Device 16F628A Config HS_OSC,WDT_OFF,PWRTE_ON,BODEN_OFF,LVP_OFF,CP_OFF,MCLRE_ON,DATA_CP_OFF 'set fuses Declare XTAL 10 TRISB=%11111100 TRISA=%01111001 ALL_DIGITAL=TRUE Declare SERIAL_DATA 8 ' Set SERIN and SEROUT data bits to 8 (default) Dim SerString[25] As Byte 'this is the serial string brought in Dim OutTime[8] As Byte 'For sending to TNC Dim OutHumid[2] As Byte 'Humidity to TNC Dim OutTemp[3] As Byte 'For sending to TNC Dim OutBarom[5] As Byte 'For sending to TNC Dim OutRainhr[3] As Byte 'For sending to TNC (rain rate) Dim OutRainYes[4] As Byte 'For sending to TNC (yesterdays's rain) Dim OutRainTot[4] As Byte 'For sending to TNC (total rain converted to today) Dim OutWindA[3] As Byte 'For sending to TNC -direction Dim OutWindB[3] As Byte 'For sending to TNC -ave speed Dim Check As Byte 'Passes the value of Wait character Dim Translate As Byte 'the variable to translate data and as a general counter Dim Tens As Byte 'Used in conversions Dim Units As Byte 'Used in conversions Dim Decis As Byte 'Used in conversions Dim Hundreds As Byte 'Used in rain conversion Dim DelayBeacon As Byte 'determines if 50 secs or 5mins or etc Dim TX As Byte 'Used to send character out port Dim Eaddress As Byte 'The address to access in EEdata Dim TempF As Word 'temp variables for use in calculations Dim X As Word 'as above Dim Y As Word 'as above Dim Z As Word 'as above Dim TempVar As Word 'as above Dim SignTemp As Bit 'store sign for temperature Dim UImode As Bit 'determines if TNC put in cmd mode Dim GoodFlag As Byte 'the input string looks good Dim OutWindC[3] As Byte 'For sending to TNC -gust speed Dim I As Byte 'General loop counter Dim TotalRain As Word 'Used to store total rain at midnight Dim TodayRain As Word 'result of total minus midnight figure Symbol LED_Datain=PORTA.2 'LED on pin 1 Symbol LED_Dataout=PORTB.0 'LED on pin 6 Symbol UIport=PORTB.4 'SW1 switch to cause UImode (low=UImode, high =TNC) Symbol SW1=PORTB.3 'delay switch 1 Symbol SW7=PORTA.4 'delay switch 7 Symbol SW8=PORTA.3 'delay switch 8 Symbol Setconnected=PORTB.5 'determines if a connection is required to serial out (SW5) Symbol CDline=PORTB.6 'pin 8 on the RS232 DCD is active Symbol Latlong=PORTB.7 'SW6 High=Lat/long format Low=positionless Symbol Imperial=PORTB.2 'High=Imperial units, Low=metric units EData "@",0 'Start of position packet (0-1) EData "z3756.55S/14048.44E_",0 'Lat/Long (2-22) EData "/",0,"g",0,"t",0,"r",0 'various indicator bytes - Zero terminated strings EData "p",0,"P",0,"h",0,"b",0 '(31-38) SendMinus EData "-",0 '(39-40) SendC EData "c",0 '(41-42) SendS EData "s",0 '(43-44) EndOfPack EData 13,0 'send it with a CR (45-46) Message EData "uDJWS Caveton weather",0 'attachment at end (47-70) Symbol CmdLine=3 'control C GoTo Start ReadEdata: While 1=1 TX=ERead Eaddress If TX=0 Then Break Inc Eaddress SerOut PORTA.1 ,16468 , [TX] 'output character Wend Return SendItOut: SerOut PORTA.1 ,16468 , [Dec Check] Return Serialout: 'this next routine sends the data out at 9600,8N,1 If UImode=1 Then 'use TNC mode SerOut PORTA.1 ,16468 , [CmdLine,13] 'send a control C DelayMS 500 SerOut PORTA.1 ,16468 , ["conv",13] 'send a converse request DelayMS 200 EndIf 'send time If Latlong=1 Then 'if latlong then send an @ otherwise _ Eaddress=0 'send @ Translate=2 'dont send month Else Eaddress=21 'send a _ Translate=0 'send whole date/time EndIf GoSub ReadEdata Repeat Check=OutTime[Translate] GoSub SendItOut Inc Translate Until Translate=8 'send lat/long If Latlong=1 Then Eaddress=2 'sends the latlong Else Eaddress=SendC 'send a "c" ready for wind direction EndIf GoSub ReadEdata 'send wind direction Translate=0 Repeat Check=OutWindA[Translate] GoSub SendItOut Inc Translate Until Translate=3 'send / separating wind speed If Latlong=1 Then Eaddress=23 'if lat/long send a "/" to separate wind Else Eaddress=SendS 'direction from wind speed otherwise send "s" EndIf GoSub ReadEdata 'send wind ave speed m/s Translate=0 Repeat Check=OutWindB[Translate] GoSub SendItOut Inc Translate Until Translate=3 'send wind gust m/s Eaddress=25 GoSub ReadEdata 'send a "g" for gust Translate=0 Repeat Check=OutWindC[Translate] GoSub SendItOut Inc Translate Until Translate=3 'send temp Eaddress=27 GoSub ReadEdata 'send a "t" for temp If SignTemp=1 Then 'signtemp=1 means negative temps Eaddress=SendMinus GoSub ReadEdata 'send a minus sign Translate=1 'dont print the hundreds as "-" only goes to -99 Else Translate=0 'print the hundreds EndIf Repeat Check=OutTemp[Translate] GoSub SendItOut Inc Translate Until Translate=3 'send rain (rate) Eaddress=29 GoSub ReadEdata 'send a "r" for rate of rain Translate=0 Repeat Check=OutRainhr[Translate] GoSub SendItOut Inc Translate Until Translate=3 'send rain (total) Eaddress=31 GoSub ReadEdata 'send a "p" for rain yesterday Translate=0 Repeat Check=OutRainYes[Translate] GoSub SendItOut Inc Translate Until Translate=4 'send rain (total) Eaddress=33 GoSub ReadEdata 'send a "P" for todays rain Translate=0 Repeat Check=OutRainTot[Translate] GoSub SendItOut Inc Translate Until Translate=4 'send humidity Eaddress=35 GoSub ReadEdata 'send a "h" for humidity Translate=0 Repeat Check=OutHumid[Translate] GoSub SendItOut Inc Translate Until Translate=2 'send barometer Eaddress=37 GoSub ReadEdata 'send a "b" for barometer Translate=0 Repeat Check=OutBarom[Translate] GoSub SendItOut Inc Translate Until Translate=5 'send tail message Eaddress=Message GoSub ReadEdata 'send a carriage return to send beacon Eaddress=EndOfPack GoSub ReadEdata GoSub FlashOutLed 'now indicate data sent Return ConvertRain: X= Hundreds*1000 + Tens * 100 + Units * 10 + Decis TempF=X*39 TempF=TempF/10 'TempVar now contains points If X>0 Then Inc TempF 'This part fixes integer arith and 39 instead of 39.37 Hundreds=Dig TempF,3 Tens=Dig TempF,2 Units=Dig TempF,1 Decis=Dig TempF,0 Return ConvertSpeed: 'changes m/s to mph TempVar= Tens*100 + Units *10 + Decis TempVar= TempVar *56 /250 Tens=Dig TempVar,2 Units=Dig TempVar,1 Decis=Dig TempVar,0 Return ConvertF: TempF=OutTemp[0]*100+OutTemp[1]*10+OutTemp[2] 'deg C change to degrees F TempF=TempF * 9 + 1600 TempF=TempF/50 'TempF now holds F deg OutTemp[0]=Dig TempF,2 OutTemp[1]=Dig TempF,1 OutTemp[2]=Dig TempF,0 Return TimeIn: ' Work on time string- time/humidity Translate=SerString[4]& %00001111 'month If Translate>9 Then OutTime[0]=1: Else: OutTime[0]=0 If Translate>9 Then OutTime[1]=translate-10 :Else: OutTime[1]=Translate Translate=SerString[3] & %11110000 'day tens OutTime[2]=Translate >>4 OutTime[3]=SerString[3] & %00001111 'day units Translate=SerString[2] & %11110000 'hour tens OutTime[4]=Translate >>4 OutTime[5]=SerString[2] & %00001111 'hour units Translate=SerString[1] & %11110000 'min tens OutTime[6]=Translate >>4 OutTime[7]=SerString[1] & %00001111 'min units Translate=SerString[19] & %11110000 'humid tens OutHumid[0]=Translate >>4 OutHumid[1]=SerString[19] & %00001111 'humid units Return TempIn: 'Work on temp string- temperature Translate=SerString[16] SignTemp=GetBit Translate,3 'set sign of temp 0=+, 1=- OutTemp[0]=SerString[16]&%00000111 'get 10s of temp Translate=SerString[15] & %11110000 'units of temp OutTemp[1]=Translate >>4 OutTemp[2]= SerString[15] & %00001111 'tenths of temp If Imperial=1 Then GoSub ConvertF 'change it to F Return BaromIn: 'Work on barom string- barometer and dewpoint OutBarom[0]=SerString[4] & %00001111 'barom thousands ='a' Translate=SerString[3] & %11110000 'get right hand 4 digits ='b' OutBarom[1]=Translate >>4 'get 'b' OutBarom[2]=SerString[3] & %00001111 'get 'c' Translate=SerString[2] & %11110000 OutBarom[3]=Translate >>4 'get 'd' (units) OutBarom[4]=SerString[2] & %00001111 'get 'e' (decimal) Return RainToWord: X=Hundreds*1000 'converts the three numerals into a word var Y=Tens*100 Z=Units*10 TempVar=X+Y+Z+Decis Return 'on exit TempVar carries rain in a word RainIn: 'Work on rain string- rain Hundreds=0 'not required for rate Tens=SerString[1]& %00001111 'tens of rain (rate) Translate=SerString[0] Units=Translate >> 4 'units of rain (rate) Decis=SerString[0] & %00001111 'units of rain (rate) If Imperial=1 Then GoSub ConvertRain 'now convert mm to inches OutRainhr[0]=Tens OutRainhr[1]=Units OutRainhr[2]=Decis 'Now the total rain since reset Translate=SerString[5] 'first 2 digits rain since reset Hundreds=Translate >> 4 Tens=SerString[5] & %00001111 Translate=SerString[4] 'second 2 digits rain since reset Units=Translate >> 4 Decis=SerString[4] & %00001111 If Imperial=1 Then GoSub ConvertRain 'now convert mm to inches GoSub RainToWord If TempVar=0 Then TotalRain=0 'if total rain in station has been zeroed (fixes 1 Jan problem) If OutTime[4]=0 And OutTime[5]=0 And OutTime[6]=0 And OutTime[7]=0 Then TotalRain=TempVar TodayRain=0 Else TodayRain=TempVar - TotalRain 'calculates start point for today's rain EndIf OutRainTot[0]=Dig TodayRain,3 'extract thousands OutRainTot[1]=Dig TodayRain,2 'extract tens OutRainTot[2]=Dig TodayRain,1 'units OutRainTot[3]=Dig TodayRain,0 'decimals 'now the rain yesterday Translate=SerString[3] 'first 2 digits yesterday Hundreds=Translate >> 4 Tens=SerString[3] & %00001111 Translate=SerString[2] 'second 2 digits yesterday Units=Translate >> 4 Decis=SerString[2] & %00001111 If Imperial=1 Then GoSub ConvertRain OutRainYes[0]=Hundreds OutRainYes[1]=Tens OutRainYes[2]=Units OutRainYes[3]=Decis Return WindIn: 'Work on wind string- wind direction, speed Translate=SerString[5] & %11110000 'direction hundreds OutWindA[0]=Translate >>4 OutWindA[1]=SerString[5] & %00001111 'direction tens OutWindA[2]=SerString[4]>>4 'unit digit of direction (high nibble) 'now ave speed Tens=SerString[4] & %00001111 'speed tens Units=SerString[3]>>4 'unit digit of speed (high nibble) Decis=SerString[3] & %00001111 'decimal speed If Imperial=1 Then GoSub ConvertSpeed 'to MPH OutWindB[0]=Tens OutWindB[1]=Units OutWindB[2]=Decis 'now the gust Tens=SerString[1] & %00001111 'tens speed Units=SerString[0]>>4 'decimal digit of speed (high nibble) Decis=SerString[0] & %00001111 'units speed If Imperial=1 Then GoSub ConvertSpeed 'm/s to MPH OutWindC[0]=Tens OutWindC[1]=Units OutWindC[2]=Decis Return FlashOutLed: Translate=1 Repeat High LED_Dataout DelayMS 20 Low LED_Dataout DelayMS 20 Inc Translate Until Translate=10 Return FlashInLed: If Setconnected=1 And CDline=1 And UImode=0 Then DelayMS 750 'give TNC time to settle before sending data GoSub Serialout Repeat Until CDline=0 EndIf Translate=1 Repeat High LED_Datain DelayMS 30 Low LED_Datain DelayMS 30 Inc Translate Until Translate=6 Return Initialise: Str SerString="" Str OutTime="" Str OutTemp="" Str OutBarom="" Str OutRainhr="" Str OutRainYes="" Str OutRainTot="" Str OutWindA="" Str OutWindB="" Str OutWindC="" Str OutHumid="" UImode=UIport 'if high then TNC mode, if low then UImode DelayBeacon=24*SW8 + 12*SW7 + 6*SW1 'calculate delay on beacon If DelayBeacon=0 Then Inc DelayBeacon Return BringSin: SerIn PORTA.0 ,16468 , [ Wait(Check),Str SerString\25] 'now ensure string does not have a double 'check' byte caused by cksum byte of last string If SerString[0]=Check Then I=0 Repeat SerString[I]=SerString[I+1] Inc I Until I=25 EndIf If SerString[0]=Check Then 'check to see if duplicate check I=0 'now remove real check byte Repeat SerString[I]=SerString[I+1] Inc I Until I=24 'string has been shortened EndIf Return Start: TotalRain=0 TodayRain=0 'initialise these to avoid problems GoSub FlashInLed GoSub FlashOutLed MainLoop: GoSub Initialise Repeat Str SerString="" 'freshen input string Check=$8F GoSub BringSin GoSub TimeIn GoSub FlashInLed Str SerString="" 'freshen input string Check=$9F GoSub BringSin GoSub TempIn GoSub FlashInLed Str SerString="" 'freshen input string Check=$AF GoSub BringSin GoSub BaromIn GoSub FlashInLed Str SerString="" 'freshen input string Check=$BF GoSub BringSin GoSub RainIn GoSub FlashInLed Str SerString="" 'freshen input string Check=$CF GoSub BringSin GoSub WindIn GoSub FlashInLed Check=$8F 'this is just a dummy delay of 10secs GoSub BringSin If Setconnected=0 Then Dec DelayBeacon 'count down to send beacon if not cntd Until DelayBeacon=0 'only if not in connected mode GoSub Serialout 'beacon info out GoTo MainLoop