I'm working on a program for reading in serial data from a downhole sensor readout box made by Pioneer Petrotech Services. The readout box is called a smartwatcher. Data rate is 115,200k, 8 data bits, 1 stop, no parity (binary). I'm reading data in on COM1, I have a level converter between COM1 and the smartwatcher, converting the RS232 levels to TTL.
The company provided a chart of the values/format being transmitted (below). The code has been cobbled together from various examples and seems to work for the most part. I would appreciate and comments/suggestions/improvments. The strings sync characters are "AA, AA, AA" and are being received fine. Athough if I add AA or its deciaml or binary variation to the begin word in serialinrecord, data does not appear to be stored.
Perhaps someone has already written code for this sensor? I'll include below the serial data as received in "w" mode, the data descriptors fron the smartwatcher and my current code.I only have one presure/temperature sensor which seems to be reading correctly, as well as the time/date etc
Thanks, hope everyone is doing well.
From terminal "w" mode
17:04:34.63 R AA AA AA 37 33 06 27 00 00 20 05 27 03 17 04 50 ...73.'.. .'...P
17:04:34.63 R CC 37 00 00 B9 6D 00 00 00 00 00 00 00 00 00 00 .7...m..........
17:04:34.63 R 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
17:04:34.63 R EC 00 6E 00 2A 2A CB EF ..n.**..
Data format from the company
Byte Value (Hex) Description
1 AA Preamble
2 AA Preamble
3 AA Preamble
4 37 Start of package
5 0x33 Data length to follow 51 Bytes (Include CRC)
6 06 Push Data Format Code
7-8 0x2700 GSMID, HSB first.
9 0x00 Vibration: 0 - No; 1 - Yes
10 xx Year
11 xx Month
12 xx Date
13 xx Day
14 xx Hour
15 xx Minute
16 xx Second
17-20 CH1 Pressure(Integer) LSB first
21-24 CH1 Temperature(Integer) LSB first
25-28 CH2 Pressure (Integer) LSB first
29-32 CH2 Temperature(Integer) LSB first
33-36 CH3 Pressure (Integer)LSB first
37-40 CH3 Temperature(Integer) LSB first
41-44 CH4 Pressure (Integer) LSB first
45-48 CH4 Temperature(Integer) LSB first
49-50 SRO Voltage, Integer, LSB First
51-52 SRO Current, Integer, LSB First
53 2A End Flag
54 2A End Flag
55 xx CRCL
56 xx CRCH
Note: All value readings in integer are 1000 x Actual readings, signed.
All pressure readings are in psi, all temperature readings are in degC.
SRO Voltage and Current are 10 x Actual readings.
' Smart Watcher code ' 5/27/2020 ' Public RawData As String * 60 ' Read in serial data 56 bytes, binary 115,2k, 8 data bits, 1 stop Public dataLng(60) As Long ' characters broken out of binary string. Public ConvertToHex(60) As String ' Convert characters to Hex Alias ConvertToHex(1) = PreAmble_1 Alias ConvertToHex(2) = PreAmble_2 Alias ConvertToHex(3) = PreAmble_3 Alias ConvertToHex(4) = StrtPackage Alias ConvertToHex(5) = DataLength Alias ConvertToHex(6) = PushDataCode Public GSMID As String *2 Alias ConvertToHex(9) = Vibration Alias ConvertToHex(10) = Year Alias ConvertToHex(11) = Month Alias ConvertToHex(12) = Date Alias ConvertToHex(13) = DayWeek Alias ConvertToHex(14) = Hour Alias ConvertToHex(15) = Minute Alias ConvertToHex(16) = Second Alias ConvertToHex(53) = EndFlag1 Alias ConvertToHex(54) = EndFlag2 Alias ConvertToHex(55) = CRCL Alias ConvertToHex(56) = CR '================================================ Public SmartWatcher(10) Alias SmartWatcher(1) = Sens1PresPSI Alias SmartWatcher(2) = Sens1TempC Alias SmartWatcher(3) = Sens2PresPSI Alias SmartWatcher(4) = Sens2TempC Alias SmartWatcher(5) = Sens3PresPSI Alias SmartWatcher(6) = Sens3TempC Alias SmartWatcher(7) = Sens4PresPSI Alias SmartWatcher(8) = Sens4TempC Alias SmartWatcher(9) = SroVoltage Alias SmartWatcher(10) = SroCurrent Units Sens1PresPSI = psi Units Sens2PresPSI = psi Units Sens3PresPSI = psi Units Sens4PresPSI = psi Units Sens1TempC = C Units Sens2TempC = C Units Sens3TempC = C Units Sens4TempC = C Public k,kk ' loop counters. Public NBytesReturned ' Number of bytes serialin returned, should be 56. ========================================================================== BeginProg ' Begin Program SerialOpen (Com1,115200,19,0,180) ' Configure comport 1 Scan (1,Sec,3,0) ' Scan rate SerialInRecord (Com1,RawData,0,0,0,NBytesReturned,01) ' Store serial data string Move(dataLng,60,0,1) ' Convert serial data to ascii For k = 1 To NBytesReturned dataLng(k) = ASCII(RawData(1,1,k)) Next k For k = 1 To NBytesReturned ' Convert serial data to Hex ConvertToHex(k) = Hex(dataLng(k)) Next k kk = 0 ' Combine two long data variables, 4 pressure, four temperature For k = 1 To 8 SmartWatcher(k) = (dataLng(18+kk)*256)+dataLng(17+kk) SmartWatcher(k) = SmartWatcher(k)/1000 kk = kk + 4 Next k SmartWatcher(9) = dataLng(49)/10 ' Convert values SROvoltage, SRO current SmartWatcher(10) = dataLng(51)/10 GSMID = ConvertToHex(7)+ ConvertToHex(8) NextScan EndProg
A rough way to read in the data string would be to use SerialInRecord with BeginWord of &hAAAA and EndWord of &h2A2A . If that returns 49 bytes, you should have a full data payload. Note that the BeginWord and EndWord won't be included. There is a very small chance of having a data pattern that would falsely match that criteria. You can check a couple other fixed value bytes in the beginning of the data payload to make sure they match also.
The only way to be 100% certain you have a correct data message is to use the checksum. That adds quite a bit of complexity to the program. If your data cables are short, the checksum is probably unnecessary.
That is working for me, returning 49 bytes. Cable length will be under 6'. The converisons I have breaking out the rawdata "appear" to be converting properly. I don't think a checksum calculation is critical as the data is stored in the readout box separately from it being transmitted to the CR1000. Does the process I'm using to convert the incoming values seem correct? Thanks, I'm excited to add this data into the CSI loggers already packed data tables.
That is one way to handle the conversion. It can be faster on processing using MoveBytes, but not very noticeable. It what you are doing works, stick with it.
I'd recommend going a bit further and calculating the checksum, just as an added validity check on the data received. I think CRBasic has a checksum function supporting several types of algorithms, but even doing it 'manually' isn't too hard. You just need to know what part of the packet is being 'summed', probably everything up to, but not including the checksum bytes. You could still log all the data regardless, but also include a flag saying whether the checksum was matched or not.
For example, a common CRC scheme is to sum all the bytes, then mask with 0xFFFF to retain only two bytes, and compare that with the CRC bytes received in the packet.
Thanks for the comments and suggestions. I've been side tracked but do hope to take a look at both the crc and movebytes instruction.
I'm occasionally missing some data strings in my program, maybe one every couple of minutes. The sensor is outputting a data string of 56 bytes every second & my scan (serialinrecord) rate is every 5 seconds. Serial buffer is set to 3500. Same program as above, but for the scan and buffer changes. When successful, the variable numberofbytes returns 49 which is correct. It returns a value of zero when the data is missing.
Any suggestions/comments would be great,
I've figured it out, sample rate of sensor was set slower than I remembered.