Hello,
Our station, which is running on a CR3000 datalogger, is using a Thies serial Wind Direction sensor.
The sensor in use is a Combined Wind Direction/Speed sensor 4.3336.31.000. It is documented just as "16 bit serial data", using two wires, Data and Clock, which I wired up to C1 and C2 on the CR3000.
By using some examples for similar sensors I found on the Internet and in this Forum, I came up with the following CRBasic code for the Sensor:
Const WindSpeedPulseChannel = 2 ' 2 consecutive Const WindClockPort = 1 Const WindDataPort = 2 'Wind Speed Sensors Public WindSpeed(2) Alias WindSpeed(1)=WindSpeed2m Alias WindSpeed(2)=WindSpeed10m Units WindSpeed2m=m/s Units WindSpeed10m=m/s Const WindStartLength_us=3000 Const WindPulseLenght_us=1000 Public WindCode(8) As Boolean Public InvWindCode(8) As Boolean Public tempInteger As Long, invInteger As Long, Sector As Long Public DirFine As Boolean Public WindDir Units WindDir = degrees Dim vmult As Long Dim LookupArray(143) As Long DataLong 1,3,2,6,7,5,4,12,13,15,14,10,11,9,8,24,25,27,26,30,31,29,28,20,21,23,22,18,19,17,16,48,49,51,50,54,55,53,52,60,61,63 DataLong 62,58,59,57,56,40,41,43,42,46,47,45,44,36,37,39,38,34,35,33,32,96,97,99,98,102,103,101,100,228,229,231,230,226,227,225,224,160,161,163 DataLong 162,166,167,165,164,172,173,175,174,170,171,169,168,184,185,187,186,190,191,189,188,180,181,183,182,178,179,177,176,144,145,147,146,150,151,149,148,156,157,159 DataLong 158,154,155,153,152,136,137,139,138,142,143,141,140,132,133,135,134,130,131,129,128 Dim k As Long DataTable(Measurements, True, -1) WindVector(1, WindSpeed10m, WindDir, IEEE4, False, 30 / ScanInterval, 0, 0) FieldNames("MeanWindSpeed10m,MeanWindDir10m,StdWindDir10m") EndTable SequentialMode AngleDegrees BeginProg SetStatus("USRDriveSize", 0) For k = 1 To 143 Read LookupArray(k) Next k Scan(10, Sec, 0, 0) 'Wind Speed Sensors PulseCount(WindSpeed(), 2, WindSpeedPulseChannel, 0, 1, 0.05, 0) PortSet(WindClockPort, 0) PortSet(WindClockPort, 1) Delay(0, WindStartLength_us, usec) PortSet(WindClockPort, 0) Delay(0, WindPulseLenght_us, usec) PortGet(WindCode(1), WindDataPort) For k = 2 To 8 PulsePort(WindClockPort, WindPulseLenght_us) PortGet(WindCode(k), WindDataPort) Next k For k = 1 To 8 PulsePort(WindClockPort, WindPulseLenght_us) PortGet(InvWindCode(k), WindDataPort) Next k tempInteger = 0 invInteger = 0 vmult = 1 For k = 1 To 8 If WindCode(k) Then tempInteger = tempInteger OR vmult If InvWindCode(k) Then invInteger = invInteger OR vmult vmult = vmult * 2 Next k If 255 - tempInteger = invInteger Then DirFine = true Else DirFine = false EndIf Sector = NAN If tempInteger = 0 Then Sector = 0 Else For k = 1 To 143 If tempInteger = LookupArray(k) Then Sector = k ExitFor EndIf Next k EndIf If DirFine Then WindDir = Sector * 2.5 Else WindDir = NAN EndIf CallTable Measurements NextScan EndProg
Sometimes, on very rare occasions, this actually does produce valid results which I can observe showing in the Public table and in turn also storing non-zero values in the measurements table. But the majority of the time, all values in WindCode and InvWindCode are false, correctly resulting in a NAN result.
The Sensor worked fine when it was running on the old Thies Datalogger, and the Wind Speed sensor in the same unit is producing valid results as well, so the wire is still intact as well.
It has been quite some time since I wrote the code to work with the sensor. I believe if your cable is long, you will need to increase the delays.
The delays are constants in the beginning of your program.
Const WindStartLength_us=3000 Const WindPulseLenght_us=1000
I increased the delays to 7500µs and 2500µs, which did temporarily result in all 16 bits being True instead of False, but by now everything is back to False.
I'm gonna tripple check if the wiring is correct the next time I get to our station.
This is very weird. By now, I'm positive the wiring is correct and the sensor generally working.
As it turns out, being connected with LoggerNet Connect to the CR3000 causes the measurement of the wind sensor to fail, reading all bits as False. The moment I disconnect LoggerNet and use the built in Webinterface to look at the Public values, I can see valid readings showing up consistently. Every now and then one reading randomly fails, but overall most of them seem succesfull.
The WindVector outputs MeanWindDir and StdWindDir have been 0 all the time though. So I modified the code a bit, to inverse the DirFine variable, and am now using it as DisableVar for the WindVector. The first measurement with it looks promising.
That only leaves me with the question why connecting to the datalogger is enough to throw the timing off so much that it fails reading the sensor entirely.
If you replace the For Next loops with SubScans like we do with multiplexers, you could get the program to compile in PipeLineMode. The would enforce stricter timing on the pulse sequence.
I changed the script to run in PipelineMode. Some other sensor using SW12 blocks the Script from automatically compiling in PipelineMode, but forcing it works without errors or warnings.
For some reason, the best results in PipelineMode I get by using delays of only 2000/1000, while in SequentialMode it was 7500/2500.
It's still missing a few more values than in SequentialMode(2~3 in PipelineMode, consistently only 1 in SeqMode).
Unfortunately, connecting with Connect still completely makes it fail to communicate with the sensor entirely. So I'm tempted to go back to SequentialMode again.
Something else I observed is that either the Grey Code table is wrong, or the inverse value is sent first. I get a lot of values that are not in the table. But the inverse of them always seems to be in the table. So I switched out the actual and the inverted value, and will see what data it collects with that over night.
For reference, here is the full Script I am currently running:
'CR3000 'Program Constants Const DataOutputInterval = 10 ' Output Interval in minutes Const ScanInterval = 10 ' Scan Interval in seconds 'Sensor Ports Const RainPulseChannel = 1 Const WindSpeedPulseChannel = 2 ' 2 consecutive Const TempDiffChannel = 10 ' 3 consecutive Const HumidDiffChannel = 4 ' 2 consecutive Const GlobalRadDiffChannel = 6 Const NetRadDiffChannel = 7 Const ShfDiffChannel = 8 Const ShfSePlateVoltChannel = 17 Const ShfSw12VChannel = 1 Const WindClockPort = 1 Const WindDataPort = 2 'Internal Sensors Public BattV Public PTemp_C Units BattV=Volts Units PTemp_C=Deg C 'Rain Sensor Public Rain Units Rain=mm 'Wind Speed Sensors Public WindSpeed(2) Alias WindSpeed(1)=WindSpeed2m Alias WindSpeed(2)=WindSpeed10m Units WindSpeed2m=m/s Units WindSpeed10m=m/s 'Temperature Sensors Dim RS0(3) = {100.0, 100.0, 100.0} 'PT100 resistances at 0C Public TempRes(3) Public TempRatio(3) Public Temp(3) Alias Temp(1)=Temp2m Alias Temp(2)=Temp10m Alias Temp(3)=TempGround Units Temp2m=Deg C Units Temp10m=Deg C Units TempGround=Deg C 'Humidity Sensors Public relHumid(2) Alias relHumid(1)=relHumid2m Alias relHumid(2)=relHumid10m Units relHumid2m=% Units relHumid10m=% 'Global Radiation Sensor Public SlrW Public SlrkJ Units SlrW=W/m^2 Units SlrkJ=kJ/m^2 'Net Radiation Sensor Public NR_Wm2 Public CNR_Wm2 Units NR_Wm2=W/m^2 Units CNR_Wm2=W/m^2 'Heat Flux Sensor Const SHF_CAL_INTERVAL = 1440 Const SHF_END_CAL = 29 Const SHF_HFP01SC_CAL = 15 'Unique Multiplier for HFP01SC (1000/sensitivity) Public Shf Public Shf_Cal Units Shf = W/m^2 Units Shf_Cal = W/(m^2 mV) 'Calibration Vars Dim shf_mV Dim shf_mV_0 Dim shf_mV_180 Dim shf_mV_end Dim shf_V_Rf Dim shf_V_Rf_180 Dim shf_cal_on_f As Boolean Dim shf_sw_state As Boolean 'Sunshine Hours Dim RTime(9) Public SunHrs Public PotSlrW Public SolPos(5) Alias SolPos(1)=SolarAzimuth Alias SolPos(2)=SunElevation Alias SolPos(3)=HourAngle Alias SolPos(4)=Declination Alias SolPos(5)=AirMass Units SunHrs=hours Units PotSlrW=W/m^2 Units SolarAzimuth=degrees Units SunElevation=degrees Units HourAngle=radians Units Declination=radians Units AirMass=unitless 'Wind Direction Sensor Const WindStartLength_us=2000 Const WindPulseLenght_us=1000 Public WindCode(16) As Boolean Public tempInteger As Long, invInteger As Long, Sector As Long Public DirInvalid As Boolean Public ReadInvalid As Boolean Public WindDir Units WindDir = degrees Dim LookupArray(143) As Long DataLong 1,3,2,6,7,5,4,12,13,15,14,10,11,9,8,24,25,27,26,30,31,29,28,20,21,23,22,18,19,17,16,48,49,51,50,54,55,53,52,60,61,63 DataLong 62,58,59,57,56,40,41,43,42,46,47,45,44,36,37,39,38,34,35,33,32,96,97,99,98,102,103,101,100,228,229,231,230,226,227,225,224,160,161,163 DataLong 162,166,167,165,164,172,173,175,174,170,171,169,168,184,185,187,186,190,191,189,188,180,181,183,182,178,179,177,176,144,145,147,146,150,151,149,148,156,157,159 DataLong 158,154,155,153,152,136,137,139,138,142,143,141,140,132,133,135,134,130,131,129,128 'Generic Helper Variables Dim i As Long Dim k As Long 'Data Upload Variables Public FTPResult Public TimeOffset As Long 'Define Data Tables DataTable(Measurements, True, -1) DataInterval(0, DataOutputInterval, Min, 0) 'Rain Totalize(1, Rain, IEEE4, False) 'Wind Speed Average(2, WindSpeed(), IEEE4, False) 'Temperatures Average(3, Temp(), IEEE4, False) 'rel. Humidity Average(2, relHumid(), IEEE4, False) 'Global Radiation Average(1, SlrW, IEEE4, False) Totalize(1, SlrkJ, IEEE4, False) 'Net Radiation Average(1, NR_Wm2, IEEE4, False) Average(1, CNR_Wm2, IEEE4, False) 'Heat Flux Average(1, Shf, IEEE4, shf_cal_on_f) Sample(1, Shf_Cal, IEEE4) 'Sunshine Hours Totalize(1, SunHrs, IEEE4, False) 'Wind Direction WindVector(1, WindSpeed10m, WindDir, IEEE4, DirInvalid, 30 / ScanInterval, 0, 0) FieldNames("MeanWindSpeed10m,MeanWindDir10m,StdWindDir10m") Totalize(1, ABS(DirInvalid), UINT4, False) FieldNames("InvalidWindDirs") Totalize(1, ABS(ReadInvalid), UINT4, False) FieldNames("InvalidWindReads") EndTable DataTable(Voltages, True, 24 * 90) DataInterval(0, 1, Hr, 0) 'Internal Sensors Minimum(1, BattV, IEEE4, False, False) Average(1, PTemp_C, IEEE4, False) EndTable PipelineMode AngleDegrees 'Main Program BeginProg SetStatus("USRDriveSize", 0) For k = 1 To 143 Read LookupArray(k) Next k Shf_Cal = SHF_HFP01SC_CAL 'Main Scan Scan(ScanInterval, Sec, 0, 0) 'Internal Sensors Battery(BattV) PanelTemp(PTemp_C, _50Hz) 'Rain Sensor PulseCount(Rain, 1, RainPulseChannel, 2, 0, 0.1, 0) 'Wind Speed Sensors PulseCount(WindSpeed(), 2, WindSpeedPulseChannel, 0, 1, 0.05, 0) 'Temperature Sensors Resistance(TempRes(), 3, mV200, TempDiffChannel, 1, 1, 1000, True, True, 0, _50Hz, 1, 0) For i = 1 To 3 TempRatio(i) = TempRes(i) / RS0(i) Next i PRTCalc(Temp(), 3, TempRatio(), 1, 1, 0) 'Humidity Sensors VoltDiff(relHumid(), 2, mV1000, HumidDiffChannel, True, 0, _50Hz, 0.1, 0) For i = 1 To 2 If relHumid(i) < 0 Then relHumid(i) = 0 If relHumid(i) > 100 Then relHumid(i) = 100 Next i 'Global Radiation VoltDiff(SlrW, 1, mV50, GlobalRadDiffChannel, True, 0, _50Hz, 1, 0) If SlrW < 0 Then SlrW = 0 SlrkJ = SlrW * 0.2 SlrW = SlrW * 40 'Net Radiations VoltDiff(NR_Wm2, 1, mV50, NetRadDiffChannel, True, 0, _50Hz, 76.33588, 0) If WindSpeed2m >= 5 Then CNR_Wm2 = NR_Wm2 * (1 + 0.021286 * (WindSpeed2m - 5)) Else CNR_Wm2 = NR_Wm2 EndIf 'Heat Flux Sensor VoltDiff(shf_mV, 1, mV50, ShfDiffChannel, True, 0, _50Hz, 1, 0) VoltSe(shf_V_Rf, 1, mv5000, ShfSePlateVoltChannel, True, 0, _50Hz, 0.001, 0) Shf = shf_mV * Shf_Cal 'Sunshine Hours RealTime(RTime) SolarPosition(SolPos, RTime, 0, 53.107775, 8.860060, 11, -1, Temp2m) 'Calculate potential radiation for time & position (multiply sine of solar elevation angle by solar constant 1373) PotSlrW = SIN(SunElevation) * 1373 'If the measured value (W/m^2) is greater than 0.4 * the potential solar radiation (W/m^2) 'and the sine of the sun elevation angle (degrees) is great than 0.1 (elevation angle of 6 degrees) 'than it has been sunny for the current scan. If SlrW > 0.4 * PotSlrW AND SIN(SunElevation) > 0.1 Then 'Calculate sun hours for scan time in seconds SunHrs = ScanInterval/3600.0 Else 'Set sun hours for scan time in seconds to 0 SunHrs = 0 EndIf 'Wind Direction k = 1 PortSet(WindClockPort, 1, 0) Delay(0, WindStartLength_us, usec) PortSet(WindClockPort, 0, 0) Delay(0, WindPulseLenght_us, usec) PortGet(WindCode(k), WindDataPort) SubScan(0, Sec, 15) k = k + 1 PortSet(WindClockPort, 1, 0) Delay(0, WindPulseLenght_us, usec) PortSet(WindClockPort, 0, 0) Delay(0, WindPulseLenght_us, usec) PortGet(WindCode(k), WindDataPort) NextSubScan invInteger = (WindCode(1) AND 1) OR (WindCode(2) AND 2) OR _ (WindCode(3) AND 4) OR (WindCode(4) AND 8) OR _ (WindCode(5) AND 16) OR (WindCode(6) AND 32) OR _ (WindCode(7) AND 64) OR (WindCode(8) AND 128) tempInteger = (WindCode( 9) AND 1) OR (WindCode(10) AND 2) OR _ (WindCode(11) AND 4) OR (WindCode(12) AND 8) OR _ (WindCode(13) AND 16) OR (WindCode(14) AND 32) OR _ (WindCode(15) AND 64) OR (WindCode(16) AND 128) If 255 - tempInteger = invInteger Then DirInvalid = false ReadInvalid = false Else DirInvalid = true ReadInvalid = true EndIf Sector = NAN If tempInteger = 0 Then Sector = 0 Else For k = 1 To 143 If tempInteger = LookupArray(k) Then Sector = k ExitFor EndIf Next k EndIf If Sector = NAN Then DirInvalid = true EndIf If DirInvalid Then WindDir = NAN Else WindDir = Sector * 2.5 EndIf 'Call Data Tables and Store Data CallTable Measurements CallTable Voltages 'Calibrate Heat Flux Sensor If IfTime(1, SHF_CAL_INTERVAL, Min) Then shf_cal_on_f = True shf_mV_0 = shf_mV shf_sw_state = True EndIf If IfTime(4, SHF_CAL_INTERVAL, Min) Then shf_mV_180 = shf_mV shf_V_Rf_180 = shf_V_Rf shf_sw_state = False EndIf If IfTime(SHF_END_CAL, SHF_CAL_INTERVAL, Min) Then shf_mV_end = shf_mV Shf_Cal = shf_V_Rf_180 * shf_V_Rf_180 * 128.7 / ABS(((shf_mV_0 + shf_mV_end) / 2) - shf_mV_180) shf_cal_on_f = False If Shf_Cal = NAN OR Shf_Cal <= 0 Then Shf_Cal = SHF_HFP01SC_CAL EndIf EndIf SW12(ShfSw12VChannel, shf_sw_state) NextScan SlowSequence Scan(10, Sec, 0, 0) FTPResult = FTPClient("...", "...", "...", "Measurements", "ub_sportplatz.dat", 9, 0, 0, Min, -1008) If IfTime(0, 24, Hr) Then TimeOffset = NetworkTimeProtocol("de.pool.ntp.org", 0, 500) EndIf NextScan EndSequence EndProg
Do you have the sensor connected to 5V or to 12V? You might be overloading 5V if it stops talking while the RS232 port is in use.
It's running on 12V. I'm communicating with the station via a NL240 Wifi module in bridge mode, which is connected and powered via CSIO.
I'm not too concerned about that, as once the station is set up completely I won't connect there directly too often, as it sends out its measurements automatically vis FTP. Just a bit concerned that it might indicate some problem somewhere in my setup or script.
I have looked at the signal the Datalogger procudes with a digital oscilloscope, and even when connected with LoggerNet Connect, the clock looks 100% on point.
However, the moment I hit the connect button, the Data line drops from ~8V to 0V and stays there, until I disconnect and the next measurement cycle runs.
Almost looks to me like connecting with LoggerNet re-configures the Input-Port to an Output-Port, and drives it to Ground.
Good reading: https://oromit.de/public/scrn/1507817194.png
Bad reading: https://oromit.de/public/scrn/1507817266.png
I haven't found a setting to configure this behaviour. The Status Table still shows PortConfig(2) as input the whole time.
You could prove the port on the datalogger is not changing to an output by disconnecting sensor wire and measuring for the voltage drop.