Our full technical support staff does not monitor this forum. If you need assistance from a member of our staff, please submit your question from the Ask a Question page.


Log in or register to post/reply in the forum.

CR1000 with Nortek's AWAC


Jackson.Lopes Apr 25, 2016 02:02 PM

 Hi. I'm  wondering if there are someone who has  a CRBasic program which integrates the CR1000 datalogger with the ADCP(AWAC) from Nortek.

Thanks.


JDavis Apr 25, 2016 03:07 PM

Here is a program I wrote quite a while ago. Much of it is for the wave data processing. Some additional work could be done on data validation.

'CR1000 Series Datalogger
'Program to collect receive and process velocity and wave data from a Nortek AWAC
'date: March 16, 2012
'program author: Jacob

'Constants
Const VelocityCells = 23 'Number of velocity cells configured in the AWAC. Must be exact.
Const NortekPort = Com2 'Comport where Nortek is connected
Const MaxWaves = 300 'Maximum number of waves within the wave burst
Const MaxWaveSamples = 1200 'Number of samples/wave burst configured in AWAC

'Declare Public Variables
Public PTemp, batt_volt

'Internally used variables
'Dim BufferString As String * 40000 'buffer to hold raw data stream
'Public BufferLength As Long 'length of useable data in BufferString
'Dim StructureString As String * (120 + 9 * VelocityCells) 'Will hold the structure currently processing
'Public StructureLength As Long 'Number of useable bytes in StructureString
'Public BytesAvailable As Long 'Number of bytes available in buffer which may be added to buffer string
'Public NewStructure As Boolean 'Indicates if there is an unprocessed structure in StructureString
'Public ValidStructure As Boolean 'Indicates if structure in StructureString passed checksum test
'Public StructureID As Long 'ID number of the current structure being processed
Public StructureChecksum As Long, CalculatedChecksum As Long 'Used for checksum test

'Velocity Structure Variables
Const VelocityLength = Ceiling( (120 + 9 * VelocityCells )/2 ) * 2
Dim VelocityStructure As String * (VelocityLength + 4)
Public NBytesvelocity As Long
Public ValidVelocity As Boolean, NewVelocity As Boolean

Public AWACbatt
Public AWACerr As Long
Public Heading, Pitch, Roll
Public Pressure
Public AWACstatus As Long
Public AWACtemperature
Public SoundSpeed

Units AWACbatt = V
Units Heading = Degrees
Units Pressure = dBar
Units AWACtemperature = C

Public VelB1(VelocityCells) As Long, VelB2(VelocityCells) As Long, VelB3(VelocityCells) As Long
Public AmpB1(VelocityCells), AmpB2(VelocityCells), AmpB3(VelocityCells)

'Wave Data Header Structure Variables
Dim WaveHeaderStructure As String * 64
Public NewWaveHeader As Boolean, ValidWaveHeader As Boolean
Public NBytesWaveHeader As Long
Public NRecordsWave As Long
Public Blanking As Long
Public MinPress As Long, hMaxPress As Long
Public CellSize As Long
Public Noise(4) As Long
Public ProcMagn(4) As Long

'Stage Data Structure Variables
Const StageLength = Ceiling( (32 + VelocityCells )/2 ) * 2
Dim StageStructure As String * (StageLength + 4)
Public NBytesStage As Long
Public NewStageStructure As Boolean, ValidStageStructure As Boolean
Public Amplitude(3) As Long
Public AST(2) As Long
Public ASTQuality As Long
Public Velocity(3) As Long
Public StageAmp(VelocityCells) As Long

'Wave Data Variables
Public NewWaveBurst As Boolean 'True when wave samples come in until processing done
Public WaveBurstDone As Boolean 'Indicates the final wave sample has been read from the buffer
Public WaveSampleCount As Long 'Number of Wave Data Structures processed
Public WaveCount As Long 'Number of waves within wave samples

Dim WaveDataStructure As String * 28
Public NewWaveDataStructure As Boolean
Dim tempWaveData As Long
Public ValidWaveData As Boolean
Dim NBytesWaveData As Long
Dim PreviousDistance As Long 'Temp value used in handling zero reading waves
Dim Distance1 As Long 'units is mm
Dim Distance2 As Long
Dim Distance(MaxWaveSamples) As Long 'Corrected for zeros distance to surface, units in mm
Public DepthAvg As Float 'Average of distances, units in m
Public MaxWaveHeight As Float
Public SigWaveHeight As Float
Public AvgWaveHeight As Float

Dim WaveHeight(MaxWaves) As Long 'units is mm
Public SortedHeight(MaxWaves) As Long


Dim DestChange(2), DestPeak As Long, IsPeak As Boolean, PrevPeak As Long
Dim Trough As Long, Peak As Long, ThirdCount As Long

Dim tempLong(6) As Long
Dim i As Long
Dim si As Long, ti As Long

'Define Data Tables
DataTable (Test,1,1000)
DataInterval (0,60,Sec,10)
Minimum (1,batt_volt,FP2,0,False)
Sample (1,PTemp,FP2)
EndTable

DataTable (WaveStats,True,8000)
Sample (1,MaxWaveHeight,FP2)
Sample (1,SigWaveHeight,FP2)
Sample (1,AvgWaveHeight,FP2)
Sample (1,DepthAvg,FP2)
Sample (1,WaveCount,FP2)
EndTable

Function SignedInt16(tempDec As Long) 'Converts two byte long to 16bit signed
If tempDec>32767 Then
tempDec=tempDec-65536
EndIf
SignedInt16=tempDec
EndFunction


Sub ValidateVelocity
Dim li As Long
Dim tempInt As Long

MoveBytes (VelocityStructure,2,VelocityStructure,0,VelocityLength)
MoveBytes (VelocityStructure,0,&ha520,2,2) 'replace first two bytes removed by SerialInRecord

tempInt = 0
For li = 1 To (VelocityLength - 2)
tempInt = tempInt + ASCII(VelocityStructure(1,1,li))
Next
tempInt = &hb721 XOR tempInt 'TODO fix checksum calculation

CalculatedChecksum = tempInt AND 65535
StructureChecksum = ASCII(VelocityStructure(1,1,VelocityLength-1)) + 256 * ASCII(VelocityStructure(1,1,VelocityLength))

'TODO reenable checksum validation
' If CalculatedChecksum = StructureChecksum Then 'Validates with checksum
ValidVelocity = true
NewVelocity = true
' Else
' ValidVelocity= false
'newvelocity = false
' EndIf 'Validates with checksum

EndSub

Sub ValidateWaveHeader

MoveBytes (WaveHeaderStructure,2,WaveHeaderStructure,0,60)
MoveBytes (WaveHeaderStructure,0,&ha531,2,2) 'replace first two bytes removed by SerialInRecord

'TODO
ValidWaveHeader = true

EndSub

Sub ValidateStage
MoveBytes (StageStructure,2,StageStructure,0,StageLength)
MoveBytes (StageStructure,0,&ha542,2,2) 'replace first two bytes removed by SerialInRecord


'TODO
ValidStageStructure = true
EndSub

Sub ValidateWaveData
MoveBytes (WaveDataStructure,2,WaveDataStructure,0,24)
MoveBytes (WaveDataStructure,0,&ha530,2,2) 'replace first two bytes removed by SerialInRecord

'TODO
ValidWaveData = true
EndSub

'Main Program
BeginProg
DestChange(2) = 1

SerialOpen (NortekPort,9600,3,0,40000)

Scan (10,Sec,0,0)
PanelTemp (PTemp,250)
Battery (batt_volt)
'Other measurements here

CallTable Test
NextScan

SlowSequence

Do
Delay (1,50,mSec)
'Data Processing

'Reads Velocity Structure from buffer
SerialInRecord (NortekPort,VelocityStructure,&ha520,VelocityLength-2,0,NBytesvelocity,110)
If NBytesvelocity Then NewVelocity = true

SerialInRecord (NortekPort,WaveHeaderStructure,&ha531,58,0,NBytesWaveHeader,110)
If NBytesWaveHeader Then NewWaveHeader = true

SerialInRecord (NortekPort,StageStructure,&ha542,StageLength-2,0,NBytesStage,110)
If NBytesStage Then NewStageStructure = true


'Process Velocity Data
If NewVelocity Then
ValidateVelocity()
EndIf


If ValidVelocity AND NewVelocity Then 'Velocity Structure
NewVelocity = false
AWACerr = ASCII(VelocityStructure(1,1,11)) + 256 * ASCII(VelocityStructure(1,1,12))
AWACbatt = (ASCII(VelocityStructure(1,1,15)) + 256 * ASCII(VelocityStructure(1,1,16))) * 0.1
SoundSpeed = (ASCII(VelocityStructure(1,1,17)) + 256 * ASCII(VelocityStructure(1,1,18))) * 0.1
tempLong(1) = (ASCII(VelocityStructure(1,1,19)) + 256 * ASCII(VelocityStructure(1,1,20)))
Heading = SignedInt16(tempLong(1)) * 0.1
tempLong(1) = (ASCII(VelocityStructure(1,1,21)) + 256 * ASCII(VelocityStructure(1,1,22)))
Pitch = SignedInt16(tempLong(1)) * 0.1
tempLong(1) = (ASCII(VelocityStructure(1,1,23)) + 256 * ASCII(VelocityStructure(1,1,24)))
Roll = SignedInt16(tempLong(1)) * 0.1
Pressure = (ASCII(VelocityStructure(1,1,27)) + 256 * ASCII(VelocityStructure(1,1,28)) + 65536 * ASCII(VelocityStructure(1,1,25)) ) * 0.001
AWACstatus = ASCII(VelocityStructure(1,1,26))
tempLong(1) = (ASCII(VelocityStructure(1,1,29)) + 256 * ASCII(VelocityStructure(1,1,30)))
AWACtemperature = SignedInt16(tempLong(1)) * 0.01

tempLong(1) = 0 'initialize
tempLong(2) = 119 + 2 * VelocityCells 'B2 velocities start
tempLong(3) = 119 + 4 * VelocityCells 'B3 velocities start
tempLong(4) = 119 + 6 * VelocityCells 'B1 amp start
tempLong(5) = 119 + 7 * VelocityCells 'B2 amp start
tempLong(6) = 119 + 8 * VelocityCells 'B3 amp start
For si = 0 To (VelocityCells -1) 'Process cells
MoveBytes (tempLong(1),3,VelocityStructure,118 + si * 2 ,1)
MoveBytes (tempLong(1),2,VelocityStructure,119 + si * 2 ,1)
VelB1(si+1) = SignedInt16(tempLong(1))

MoveBytes (tempLong(1),3,VelocityStructure,tempLong(2) - 1 + si * 2 ,1)
MoveBytes (tempLong(1),2,VelocityStructure,tempLong(2) + si * 2 ,1)
VelB2(si+1) = SignedInt16(tempLong(1))

MoveBytes (tempLong(1),3,VelocityStructure,tempLong(3) - 1 + si * 2 ,1)
MoveBytes (tempLong(1),2,VelocityStructure,tempLong(3) + si * 2 ,1)
VelB3(si+1) = SignedInt16(tempLong(1))

AmpB1(si+1) = ASCII(VelocityStructure(1,1,tempLong(4) + si ))
AmpB2(si+1) = ASCII(VelocityStructure(1,1,tempLong(5) + si ))
AmpB3(si+1) = ASCII(VelocityStructure(1,1,tempLong(6) + si ))
Next 'Process cells
EndIf 'ValidVelocity


If NewWaveHeader Then
ValidateWaveHeader()
EndIf 'NewWaveHeader

If NewWaveHeader AND ValidWaveHeader Then
NRecordsWave = ASCII(WaveHeaderStructure(1,1,11)) + 256 * ASCII(WaveHeaderStructure(1,1,12))
Blanking = ASCII(WaveHeaderStructure(1,1,13)) + 256 * ASCII(WaveHeaderStructure(1,1,14))
MinPress = ASCII(WaveHeaderStructure(1,1,25)) + 256 * ASCII(WaveHeaderStructure(1,1,26))
hMaxPress = ASCII(WaveHeaderStructure(1,1,27)) + 256 * ASCII(WaveHeaderStructure(1,1,28))
CellSize = ASCII(WaveHeaderStructure(1,1,31)) + 256 * ASCII(WaveHeaderStructure(1,1,32))
For si = 0 To 3
Noise(si+1) = ASCII(WaveHeaderStructure(1,1,33+si))

ProcMagn(si + 1) = ASCII(WaveHeaderStructure(1,1,37 + si*2)) + 256 * ASCII(WaveHeaderStructure(1,1,38 + si*2))
Next si

NewWaveHeader = false

NewWaveBurst = true
WaveBurstDone = false
WaveSampleCount = 0
WaveCount = 0
EndIf 'Process Wave Header


If NewStageStructure Then
ValidateStage()
EndIf

'Process Stage Structure
If NewStageStructure AND ValidStageStructure Then

For si = 0 To 2
Amplitude(si+1) = ASCII(StageStructure(1,1,7 + si))
tempLong(1) = ASCII(StageStructure(1,1,23 + si*2)) + 256 * ASCII(StageStructure(1,1,24 + si*2))
Velocity(si + 1) = SignedInt16(tempLong(1))
Next si
AST(1) = ASCII(StageStructure(1,1,13)) + 256 * ASCII(StageStructure(1,1,14))
AST(2) = ASCII(StageStructure(1,1,19)) + 256 * ASCII(StageStructure(1,1,20))

For si = 0 To VelocityCells - 1
'amplitude cells
StageAmp(si + 1) = ASCII(StageStructure(1,1,33+si))
Next si

NewStageStructure = false
EndIf 'Process Stage Structure

Loop 'End Slowsequence 1 loop

SlowSequence
'Wave Statistics Processing Slow Scan
Do
Delay (1,50,mSec) 'This delay allows the logger to time slice better and sleep
'Shorter delay allows faster processing, but will increase power consumption

If NewWaveBurst Then
' SerialInRecord (NortekPort,WaveDataStructure,&ha530,22,0,NBytesWaveData,111)
tempWaveData = 0
If SerialInChk(NortekPort) > 23 Then
SerialInBlock (NortekPort,tempWaveData,1)
If tempWaveData = &ha5000000 Then 'Correct first byte
SerialInBlock (NortekPort,tempWaveData,1)
If tempWaveData = &h30000000 Then 'Correct second byte
SerialInBlock (NortekPort,WaveDataStructure,22)
NewWaveDataStructure = true
EndIf 'Correct second byte
EndIf 'Correct first byte
EndIf 'Enough bytes in buffer
EndIf

'Process Wave Data Structure
If NewWaveDataStructure Then
If WaveSampleCount < MaxWaveSamples Then
WaveSampleCount = WaveSampleCount + 1
' ValidateWaveData()
' If ValidWaveData Then
Distance1 = ASCII(WaveDataStructure(1,1,5)) + 256 * ASCII(WaveDataStructure(1,1,6))
Distance2 = ASCII(WaveDataStructure(1,1,15)) + 256 * ASCII(WaveDataStructure(1,1,16))
If Distance1 = 0 Then
If Distance2 <> 0 Then 'Use distance2 if distance1 = 0
Distance(WaveSampleCount) = Distance2
PreviousDistance = Distance(WaveSampleCount)
Else
Distance(WaveSampleCount) = PreviousDistance 'Use previous distance if both distance1 and distance2 are 0
EndIf
Else
Distance(WaveSampleCount) = Distance1
PreviousDistance = Distance(WaveSampleCount)
EndIf
If WaveSampleCount = 1 Then PrevPeak = Distance 'starting value
If Distance(WaveSampleCount) <> 0 Then 'Valid distance reading
'PeakValley replacement code
If DestChange(2) = 1 Then 'Going up
If Distance(WaveSampleCount) > DestChange(1) Then
DestChange(1) = Distance(WaveSampleCount)
Else
DestPeak = DestChange(1)
DestChange(1) = Distance(WaveSampleCount)
DestChange(2) = 0
EndIf
Else 'Going down
If Distance(WaveSampleCount) < DestChange(1) Then
DestChange(1) = Distance(WaveSampleCount)
Else
DestPeak = DestChange(1)
DestChange(1) = Distance(WaveSampleCount)
DestChange(2) = 1
EndIf
EndIf

If PrevPeak < DestPeak Then
'Peak
IsPeak = true
If Trough <> 0 Then 'Will not trigger if a trough hasn't yet been recorded
WaveCount = WaveCount + 1
Peak = DestPeak
WaveHeight(WaveCount) = Peak - Trough
EndIf
PrevPeak = DestPeak
ElseIf PrevPeak > DestPeak
'Trough
IsPeak = false
Trough = DestPeak
PrevPeak = DestPeak
EndIf 'Peak or Trough
EndIf 'Valid distance reading

' EndIf 'Valid wave data
EndIf 'within sample count
NewWaveDataStructure = false
If WaveSampleCount = MaxWaveSamples Then WaveBurstDone = true
EndIf 'Process Wave Data Structure

If NewWaveBurst AND WaveBurstDone Then 'Start wave statistics processing
NewWaveBurst = false
'Gets data back in synch if off
SerialFlush(NortekPort)

'Calculate average depth in meters
' AvgSpa (DepthAvg,MaxWaveSamples,Distance())
tempWaveData = 0
For ti = 1 To MaxWaveSamples
tempWaveData = tempWaveData + Distance(ti)
Next ti
DepthAvg = (tempWaveData/MaxWaveSamples)/1000 'Convert to m

'Maximum wave height calculation
tempWaveData = 0
For ti = 1 To WaveCount
If WaveHeight(ti) > tempWaveData Then tempWaveData = WaveHeight(ti)
Next ti
MaxWaveHeight = tempWaveData/1000 'Divide by 1000 to get meters

'Average wave height calculation
tempWaveData = 0
For ti = 1 To WaveCount
tempWaveData = tempWaveData + WaveHeight(ti)
Next ti
AvgWaveHeight = (tempWaveData/WaveCount)/1000 'Divide by 1000 to get meters

'Significant Wave Height Calculation, most intense calculation
ThirdCount = INT(WaveCount/3)
SortSpa (SortedHeight(),MaxWaves,WaveHeight())
tempWaveData = 0
For ti = (MaxWaves - ThirdCount + 1) To MaxWaves
tempWaveData = tempWaveData + SortedHeight(ti)
Next ti
SigWaveHeight = (tempWaveData / ThirdCount)/1000 'Divide by 1000 to get meters

Move (WaveHeight(),MaxWaves,0,1) 'Erase waves

Trough = 0
DestChange(1) = 0 'Reset variables used for trough/peak recognition
DestChange(2) = 1
CallTable (WaveStats)
EndIf 'End Wave Statistics Processing

Loop 'End of Wave processing slow scan

EndProg


Jackson.Lopes Apr 25, 2016 06:05 PM

Thank you JDavis. You've helped me too much.

Log in or register to post/reply in the forum.