Other Parts Discussed in Thread: AWR1843
Hi, I am having an issue where the Azmath Heat Map I am displaying from the AWR1843Boost has a lag that gets progressively worse. I am operating the AWR1843 in factory demo mode i received it in. I suspect that the display is due to a backlog of Data from the AWR1843 but could be wrong. I am not sure where to go from here to debug this issue.
I have tried increasing the frame period in frameCfg to 0.8 which I assumed would account for any delay in the serial communications. It does not seem to have any effect on how fast the lag builds.
With only the rangeAzimuthHeatMap enabled in guiMonitor the lag builds to about a second almost immediately and within 5 to 10 seconds becomes unmanageable. When I enable rangeDopplerHeatMap in guiMonitor the delay can take 30 to 60 seconds to become unmanagable even though I am only reading/displaying the rangeAzimuthHeatMap data.
I have tried to clear the data serial buffer with flush() and flushInput() but the data stops after about 10 seconds of displaying data.
I have also tried to sensorStop and sensorStart 0. This works for once cycle, but on the second or third time something goes wrong and no data is displayed.
I am not sure if there is an issue with my code or the config file.
import serial
import time
import numpy as np
import matplotlib.pyplot as plt
from serial.tools import list_ports
# The Configuration file name
# configFileName = 'AWR1843config copy 2.cfg'
configFileName = 'AWR1843configManual.cfg'
# configFileName = 'AWR1843DemoConfig.cfg'
figure_no = 0
CLIport = {}
Dataport = {}
byteBuffer = np.zeros(2 ** 15, dtype='uint8')
byteBufferLength = 0
TimeOfLastRead = 0
# List the Serial COM ports currently available.
port = list(list_ports.comports())
for p in port:
print(p.device)
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# Function to configure the serial ports and send the data from
# the configuration file to the radar
def serialConfig(configFileName):
# Open the serial ports for the configuration and the data ports
# Mac /dev/tty.usbmodemR20910491 /dev/tty.usbmodemR20910494
global CLIport
global Dataport
CLIport = serial.Serial('/dev/tty.usbmodemR20910491', 115200)
Dataport = serial.Serial('/dev/tty.usbmodemR20910494', 921600)
# Read the configuration file and send it to the board
config = [line.rstrip('\r\n') for line in open(configFileName)]
for i in config:
CLIport.write((i + '\n').encode())
print(i)
time.sleep(0.01)
return CLIport, Dataport
# ------------------------------------------------------------------
# Function to parse the data inside the configuration file
def parseConfigFile(configFileName):
configParameters = {} # Initialize an empty dictionary to store the configuration parameters
# Read the configuration file and send it to the board
config = [line.rstrip('\r\n') for line in open(configFileName)]
for i in config:
# Split the line
splitWords = i.split(" ")
# Hard code the number of antennas, change if other configuration is used
numRxAnt = 4
numTxAnt = 3
# Get the information about the profile configuration
if "profileCfg" in splitWords[0]:
startFreq = int(float(splitWords[2]))
idleTime = int(splitWords[3])
rampEndTime = float(splitWords[5])
freqSlopeConst = float(splitWords[8])
numAdcSamples = int(splitWords[10])
numAdcSamplesRoundTo2 = 1
while numAdcSamples > numAdcSamplesRoundTo2:
numAdcSamplesRoundTo2 = numAdcSamplesRoundTo2 * 2
digOutSampleRate = int(splitWords[11])
# Get the information about the frame configuration
elif "frameCfg" in splitWords[0]:
chirpStartIdx = int(splitWords[1])
chirpEndIdx = int(splitWords[2])
numLoops = int(splitWords[3])
numFrames = int(splitWords[4])
framePeriodicity = float(splitWords[5])
# Combine the read data to obtain the configuration parameters
numChirpsPerFrame = (chirpEndIdx - chirpStartIdx + 1) * numLoops
configParameters["numDopplerBins"] = numChirpsPerFrame / numTxAnt
configParameters["numRangeBins"] = numAdcSamplesRoundTo2
configParameters["rangeResolutionMeters"] = (3e8 * digOutSampleRate * 1e3) / (
2 * freqSlopeConst * 1e12 * numAdcSamples)
configParameters["rangeIdxToMeters"] = (3e8 * digOutSampleRate * 1e3) / (
2 * freqSlopeConst * 1e12 * configParameters["numRangeBins"])
configParameters["dopplerResolutionMps"] = 3e8 / (
2 * startFreq * 1e9 * (idleTime + rampEndTime) * 1e-6 * configParameters["numDopplerBins"] * numTxAnt)
configParameters["maxRange"] = (300 * 0.9 * digOutSampleRate) / (2 * freqSlopeConst * 1e3)
configParameters["maxVelocity"] = 3e8 / (4 * startFreq * 1e9 * (idleTime + rampEndTime) * 1e-6 * numTxAnt)
return configParameters
# ------------------------------------------------------------------
# Funtion to read and parse the incoming data
def readAndParseData18xx(Dataport, configParameters):
global byteBuffer, byteBufferLength, TimeOfLastRead
# Constants
MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP = 4
maxBufferSize = 2 ** 15
magicWord = [2, 1, 4, 3, 6, 5, 8, 7]
# Initialize variables
magicOK = 0 # Checks if magic number has been read
dataOK = 0 # Checks if the data has been read correctly
CartX = {}
CartY = {}
ThetaX = {}
RangeY = {}
QQ = {}
readBuffer = Dataport.read(Dataport.in_waiting)
byteVec = np.frombuffer(readBuffer, dtype='uint8')
byteCount = len(byteVec)
# Check that the buffer is not full, and then add the data to the buffer
if (byteBufferLength + byteCount) < maxBufferSize:
byteBuffer[byteBufferLength:byteBufferLength + byteCount] = byteVec[:byteCount]
byteBufferLength = byteBufferLength + byteCount
# Check that the buffer has some data
if byteBufferLength > 16:
# Check for all possible locations of the magic word
possibleLocs = np.where(byteBuffer == magicWord[0])[0]
# Confirm that is the beginning of the magic word and store the index in startIdx
startIdx = []
for loc in possibleLocs:
check = byteBuffer[loc:loc + 8]
if np.all(check == magicWord):
startIdx.append(loc)
# Check that startIdx is not empty
if startIdx:
# Remove the data before the first start index
if startIdx[0] > 0 and startIdx[0] < byteBufferLength:
byteBuffer[:byteBufferLength - startIdx[0]] = byteBuffer[startIdx[0]:byteBufferLength]
byteBuffer[byteBufferLength - startIdx[0]:] = np.zeros(len(byteBuffer[byteBufferLength - startIdx[0]:]),
dtype='uint8')
byteBufferLength = byteBufferLength - startIdx[0]
# Check that there have no errors with the byte buffer length
if byteBufferLength < 0:
byteBufferLength = 0
# word array to convert 4 bytes to a 32 bit number
word = [1, 2 ** 8, 2 ** 16, 2 ** 24]
# Read the total packet length
totalPacketLen = np.matmul(byteBuffer[12:12 + 4], word)
# Check that all the packet has been read
if (byteBufferLength >= totalPacketLen) and (byteBufferLength != 0):
magicOK = 1
# If magicOK is equal to 1 then process the message
if magicOK:
# word array to convert 4 bytes to a 32 bit number
word = [1, 2 ** 8, 2 ** 16, 2 ** 24]
'''
# Initialize the pointer index
idX = 0
# Read the header
# magicNumber = byteBuffer[idX:idX + 8]
idX += 8
version = format(np.matmul(byteBuffer[idX:idX + 4], word), 'x')
idX += 4
totalPacketLen = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
platform = format(np.matmul(byteBuffer[idX:idX + 4], word), 'x')
idX += 4
frameNumber = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
timeCpuCycles = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
numDetectedObj = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
numTLVs = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
subFrameNumber = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
'''
numTLVs = np.matmul(byteBuffer[32:36], word)
idX = 40
# Read the TLV messages
for tlvIdx in range(numTLVs):
# word array to convert 4 bytes to a 32 bit number
word = [1, 2 ** 8, 2 ** 16, 2 ** 24]
# Check the header of the TLV message
tlv_type = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
# tlv_length = np.matmul(byteBuffer[idX:idX + 4], word)
idX += 4
if tlv_type == MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP:
'''
################Have also tried this to prevent displaying to often. #######
ReadTime = time.time() - TimeOfLastRead
print("Time: " + str(ReadTime))
if ReadTime <= 0.4:
return 0, 0, 0, 0, 0, 0
##############################################################
'''
'''
numTxAzimAnt = 3
numRxAnt = 4
numBytes = numTxAzimAnt * numRxAnt * configParameters["numRangeBins"] * 4
'''
numBytes = 12288
q = byteBuffer[idX:idX + numBytes] # single dimension array of the data.
idX += numBytes
# qrows = numTxAzimAnt * numRxAnt
qrows = 12
# qcols = configParameters["numRangeBins"]
qcols = 256
NUM_ANGLE_BINS = 64
# NUM_ANGLE_BINS = 128 # Seems to be more accurate?
# Specifying a Stride in a String Slice Start:End:Skip
real = q[::4] + q[1::4] * 256
imaginary = q[2::4] + q[3::4] * 256
real = real.astype(np.int16) # Assign type to array
imaginary = imaginary.astype(np.int16) # Assign type to array
q = real + 1j * imaginary # Sets up imaginary number from data
q = np.reshape(q, (qrows, qcols), order="F") # Reshape from 1 dim array to 2 dim array. 12x256
Q = np.fft.fft(q, NUM_ANGLE_BINS, axis=0) # One-dimensional discrete Fourier Transform Q 64x256
QQ = np.fft.fftshift(abs(Q), axes=0) # Shift the zero-frequency component to center of spectrum.
QQ = QQ.T # The transposed array. QQ array 256x64
QQ = QQ[:, 1:]
QQ = np.fliplr(QQ) # Reverse the order of elements along axis 1 (left/right) Is a 256x63 array
theta = np.rad2deg(
np.arcsin(np.array(range(-NUM_ANGLE_BINS // 2 + 1, NUM_ANGLE_BINS // 2)) * (2 / NUM_ANGLE_BINS)))
rangeArray = np.array(range(configParameters["numRangeBins"])) * configParameters["rangeIdxToMeters"]
CartX = np.outer(rangeArray.T, np.sin(np.deg2rad(theta))) # Is a 256x63 array
CartY = np.outer(rangeArray.T, np.cos(np.deg2rad(theta))) # Is a 256x63 array
# np.concatenate(posX)
ThetaX, RangeY = np.meshgrid(theta, rangeArray)
'''
np.savetxt('/Users/isaacwilliams/Desktop/Working.nosync/RadarImage/RadDataX-' + str(figure_no) + '.txt',
ThetaX, fmt='%.1f', delimiter='\t')
np.savetxt('/Users/isaacwilliams/Desktop/Working.nosync/RadarImage/RadDataY-' + str(figure_no) + '.txt',
RangeY, fmt='%.1f', delimiter='\t')
np.savetxt('/Users/isaacwilliams/Desktop/Working.nosync/RadarImage/RadDataQ-' + str(figure_no) + '.txt',
QQ, fmt='%.1f', delimiter='\t')
np.save('/Users/isaacwilliams/Desktop/Working.nosync/RadarData/QQ-' + str(figure_no) + '.npy',
QQ)
np.save('/Users/isaacwilliams/Desktop/Working.nosync/RadarData/ThetaX-' + str(figure_no) + '.npy',
ThetaX)
np.save('/Users/isaacwilliams/Desktop/Working.nosync/RadarData/RangeY-' + str(figure_no) + '.npy',
RangeY)
np.save('/Users/isaacwilliams/Desktop/Working.nosync/RadarData/CartX-' + str(figure_no) + '.npy',
CartX)
np.save('/Users/isaacwilliams/Desktop/Working.nosync/RadarData/CartY-' + str(figure_no) + '.npy',
CartY)
'''
dataOK = 1
TimeOfLastRead = time.time()
# Remove already processed data
if idX > 0 and byteBufferLength > idX:
byteBuffer = np.zeros(2 ** 15, dtype='uint8')
"""
shiftSize = totalPacketLen
byteBuffer[:byteBufferLength - shiftSize] = byteBuffer[shiftSize:byteBufferLength]
byteBuffer[byteBufferLength - shiftSize:] = np.zeros(len(byteBuffer[byteBufferLength - shiftSize:]),
dtype='uint8')
byteBufferLength = byteBufferLength - shiftSize
# Check that there are no errors with the buffer length
if byteBufferLength < 0:
byteBufferLength = 0
"""
return dataOK, CartX, CartY, ThetaX, RangeY, QQ
# ------------------------------------------------------------------
# Funtion to update the data and display in the plot
def update():
global figure_no, frameNo
# Read and parse the received data
# return dataOK, frameNumber, CartX, CartY, ThetaX, RangeY, QQ
dataOk, CartX, CartY, ThetaX, RangeY, QQ = readAndParseData18xx(Dataport, configParameters)
if dataOk and len(QQ) > 0:
## 2D POSITION HEAT MAP
subplots[0].contourf(CartX, CartY, QQ)
subplots[0].set_xlim([-1, 1])
subplots[0].set_ylim([0, 2])
# ANGLE VS. RANGE HEATMAP
subplots[1].contourf(ThetaX, RangeY, QQ)
subplots[1].set_xlim([-60, 60])
subplots[1].set_ylim([0, 2])
plt.pause(0.01)
return dataOk
# ------------------------- MAIN -----------------------------------------
# Configurate the serial port
CLIport, Dataport = serialConfig(configFileName)
# Get the configuration parameters from the configuration file
configParameters = parseConfigFile(configFileName)
fig = plt.figure(constrained_layout=True, figsize=(10, 5))
subplots = fig.subplots(nrows=1, ncols=2)
subplots[0].grid()
subplots[1].grid()
# Main loop
HeatMapData = {}
frameData = {}
currentIndex = 0
TimeReset = time.time()
ProgRun = True
while ProgRun:
try:
# Update the data and check if the data is okay
# x = time.time_ns()
# time.sleep(0.5)
dataOk = update()
if time.time() - TimeReset >= 10: #Reset Radar every 10 seconds
####### Have tried variations on this to fix lag but does not help######
CLIport.write(('sensorStop\n').encode())
time.sleep(0.6)
# Dataport.flush()
# Dataport.flushInput()
# Dataport.flushOutput()
CLIport.write(('sensorStart 0\n').encode())
time.sleep(0.6)
TimeReset = time.time()
#################################################
# Stop the program and close everything if Ctrl + c is pressed
except KeyboardInterrupt:
x = input('\n\nEnter Command:\n\t-Pause\n\t-Quit\n\n\t')
if x == 'Quit' or x == 'Q':
print('User Quit Program')
CLIport.write(('sensorStop\n').encode())
CLIport.close()
Dataport.close()
time.sleep(1)
ProgRun = False
elif x == 'Pause' or x == 'P':
print('Program Paused')
CLIport.write(('sensorStop\n').encode())
x = input('\n\nEnter Command:\n\t-Resume\n\t-Quit\n\n\t')
paused = True
while paused == True:
if x == 'Quit' or x == 'Q':
print('User Quit Program')
CLIport.write(('sensorStop\n').encode())
CLIport.close()
Dataport.close()
time.sleep(1)
ProgRun = False
elif x == 'Resume' or x == 'R':
paused = False
# CLIport.write(('sensorStart\n').encode())
else:
print('Unknown command. Program Paused\n\n')
else:
print('Unknown command. Program continued')
Configuration file:
sensorStop
flushCfg
dfeDataOutputMode 1
channelCfg 15 7 0
adcCfg 2 1
adcbufCfg -1 0 1 1 1
profileCfg 0 77 5 5.3 18.22 0 0 84.34 1 149 12496 0 0 30
chirpCfg 0 0 0 0 0 0 0 1
chirpCfg 1 1 0 0 0 0 0 4
chirpCfg 2 2 0 0 0 0 0 2
frameCfg 0 2 16 0 500 1 0
lowPower 0 0
guiMonitor -1 0 0 0 1 1 0
cfarCfg -1 0 2 8 4 3 0 15 1
cfarCfg -1 1 0 4 2 3 1 15 1
multiObjBeamForming -1 1 0.5
clutterRemoval -1 0
calibDcRangeSig -1 0 -5 8 256
extendedMaxVelocity -1 0
lvdsStreamCfg -1 0 0 0
compRangeBiasAndRxChanPhase 0.0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
measureRangeBiasAndRxChanPhase 0 1.5 0.2
CQRxSatMonitor 0 3 5 121 0
CQSigImgMonitor 0 127 4
analogMonitor 0 0
aoaFovCfg -1 -90 90 -90 90
cfarFovCfg -1 0 0 8.92
cfarFovCfg -1 1 -1 1.00
sensorStart
This is my displayed data. Only showing 2m of the 20m.