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.