Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
fe03233
early I2C code
NicoOhR Jan 5, 2024
3702d3b
I2C configuration
NicoOhR Jan 8, 2024
dd7f430
forgot to add TODO update
NicoOhR Jan 8, 2024
936ec26
Reading data from sensor registers
NicoOhR Jan 11, 2024
7f91982
changed addresses to fit actual sensor
NicoOhR Jan 18, 2024
4c4da04
output, no ack
NicoOhR Jan 19, 2024
31ff908
switched to dec for now, need pull ups
NicoOhR Jan 20, 2024
163f5d6
reading from registers
NicoOhR Jan 21, 2024
f561959
recompped into functions, converted to g
NicoOhR Jan 25, 2024
d237b25
temporary test code
NicoOhR Jan 26, 2024
354eeb0
pivoting to use pi instead, removed files
NicoOhR Feb 5, 2024
7d1eb80
changed header
NicoOhR Feb 9, 2024
ba6f2ad
use i2c block data method
NicoOhR Feb 9, 2024
2bbaef5
printing
NicoOhR Feb 9, 2024
95d7d52
Writing to csv from gyro and accel
GHAFHA Feb 15, 2024
6187d83
added flow control
NicoOhR Feb 16, 2024
ce7d0a8
why am I awak at 3AM
GHAFHA Feb 16, 2024
13841ec
refactor
GHAFHA Feb 16, 2024
43931bf
combining rows of df
NicoOhR Feb 17, 2024
e956c24
split to two csv's
NicoOhR Feb 17, 2024
7167a69
Merge branch 'I2C' of github.com:DallasFormulaRacing/LabJackCanBus in…
NicoOhR Feb 19, 2024
42a4f26
Name things properly
GHAFHA Mar 18, 2024
c49a64b
change read state for switch
GHAFHA Mar 18, 2024
93c89b4
implemented telegraf for analogstream
GHAFHA Mar 19, 2024
5d1f743
updated daq to contain code for gyro + accel
GHAFHA Mar 19, 2024
2069de1
updated file structure
GHAFHA Mar 19, 2024
7eaa9ee
commented out some non-working code for now
GHAFHA Mar 22, 2024
68cb4ae
added config.json
GHAFHA Mar 22, 2024
1102eac
Update .flake8, .gitignore, DAQ.py, AnalogStream.py, conftest.py, mod…
GHAFHA Mar 28, 2024
102be6c
added testing for telegraf
GHAFHA Apr 3, 2024
4ead8eb
event hubs connection testing send
GHAFHA Apr 6, 2024
078ee1f
fixed sensor naming convention
GHAFHA Apr 15, 2024
0224a1b
Merge branch 'telegraf' of github.com:DallasFormulaRacing/LabJackCanB…
GHAFHA Apr 15, 2024
724bcbf
refactor sending metrics in GyroAndAccel.py
GHAFHA Apr 17, 2024
05c2eb5
removed nesting
GHAFHA Apr 17, 2024
00792be
Refactor sensor data processing and metrics sending
GHAFHA Apr 17, 2024
14bb3e1
Refactor sensor classes and add telemetry metrics
GHAFHA Apr 17, 2024
af461e1
Remove unused TelegrafClient instantiation
GHAFHA Apr 17, 2024
64421d6
Refactor sensor data handling and error logging
GHAFHA Apr 17, 2024
fe2e467
Add logging statements and improve data processing in GyroAndAccel.py
GHAFHA Apr 17, 2024
4995b5f
Erro handling Linpot metric sending to Telegraf
GHAFHA Apr 17, 2024
f86a52d
requirements for accel
NicoOhR Apr 17, 2024
d6f88d2
Update sensor ports
GHAFHA Apr 18, 2024
020c864
Added telegraf metrics to can
Apr 19, 2024
a3ae3d7
Added session id
Apr 24, 2024
3bcb538
fixing bugs
GHAFHA Apr 23, 2024
e2caa1f
Arjun changes
GHAFHA Apr 25, 2024
fda17c5
csv outputter tested and finished
GHAFHA Apr 25, 2024
f00fb98
removed test telegraf metric
GHAFHA Apr 28, 2024
09bf9ae
accelerometer and gyro working
GHAFHA Apr 28, 2024
696b2e3
maybe?
GHAFHA Apr 28, 2024
8d1e8d1
test
GHAFHA Apr 28, 2024
988766a
Add thread lock to prevent data race in Read class
GHAFHA Apr 28, 2024
4ee2e9b
rLock
GHAFHA Apr 28, 2024
6330dea
added stop method
GHAFHA Apr 28, 2024
1448df6
accelgyro actually working with daq.py
GHAFHA Apr 28, 2024
714408a
Changed polling frequency to 20hz
GHAFHA Apr 28, 2024
1e04efb
Delete __pycache__ directory
GHAFHA Apr 30, 2024
656bcb7
Outputs all files to one root folder instead of multiple folders for …
GHAFHA Apr 30, 2024
3ee82fb
gyroaccel changes
GHAFHA Apr 30, 2024
959c59b
Add button voltage metric to Telegraf client
GHAFHA May 2, 2024
0f8910e
Refactor code to initialize telegraf_client and session_id in the try…
GHAFHA May 2, 2024
e853a01
Added try catch to accel gyro initialization
GHAFHA May 4, 2024
eb998c7
duplicate session_id initialization+mutation
May 7, 2024
75d80e9
Refactored session id
May 7, 2024
f240892
session_id changes in readstate.py
May 7, 2024
a5c19cf
moved reading button state outside of try/catch
May 7, 2024
f911450
used csvwriter library instead of manually writing
May 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[flake8]

max-line-length = 170

# Exclude certain file patterns from checking
exclude =
.git,
__pycache__,
.venv,
venv,

# E301 expected 1 blank line, found 0
# E302 expected 2 blank lines, found 0
# You can enforce 2 blank lines before a function definition
extend-ignore = E301, E111
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
/__pycache__
__pycache__
__pycache__/DAQState.cpython-39.pyc
__pycache__/messageIDs.cpython-39.pyc
__pycache__/ReadState.cpython-39.pyc
arjun*
*.csv
.venv
/venv
.models
models.json
settings.json
.vscode
.env
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@
"editor.defaultFormatter": "ms-python.python"
},
"python.formatting.provider": "none",
"editor.defaultFormatter": "ms-python.autopep8"
"editor.defaultFormatter": "ms-python.autopep8",
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
294 changes: 134 additions & 160 deletions DAQ.py
Original file line number Diff line number Diff line change
@@ -1,178 +1,152 @@
import os
import can
import time
from sensors.AnalogStream import Linpot, Stream
from sensors.GyroAndAccel import Read
from button.ReadState import read_state
from ecu_can.CanBus import ECU
from DAQState import DAQState
from messageIDs import canMessageSort, can_messages_cols
from ReadState import read_state
from read_xl_analog import read_xl_analog
import csv
import threading
import json
from labjack import ljm
import pandas as pd
from datetime import datetime

# can.rc['interface'] = 'socketcan'
# os.system('sudo ip link set can0 type can bitrate 250000')
# os.system('sudo ifconfig can0 up')
# can0 = can.interface.Bus(channel="can0", interface="socketcan")


class DAQObject:

def __init__(self, output_file: str):

self.currentState = DAQState.INIT
self.output_file = output_file
self.file = open("ecudata.csv", mode='w')
self.writer = can.CSVWriter(self.file, append=True)
self.ecu_columns = can_messages_cols
self.ecu_df = pd.DataFrame(columns=self.ecu_columns)
self.linpot_df = pd.DataFrame(
columns=["Time", "Front Right", "Front Left", "Rear Right", "Rear Left"])
self.ECUData = [None] * 16
self.LJData = []
self.writeData = [None]
self.handle = ljm.openS("T7")

# self.canbus = threading.Thread(target=self.readCAN)
self.run = threading.Thread(target=self.DAQRun)
# self.read_xl = threading.Thread(target=self.read_xl)
self.can_read_lock = threading.Lock()
self.daq_run_lock = threading.Lock()
# self.xl_read_lock = threading.Lock()
# self.daq_run_lock.acquire()
self.read_xl_analog_instance = read_xl_analog()

self.fr_names = ["AIN1_RESOLUTION_INDEX"]
self.fl_names = ["AIN2_RESOLUTION_INDEX"]
self.rr_names = ["AIN3_RESOLUTION_INDEX"]
self.rl_names = ["AIN4_RESOLUTION_INDEX"]
self.num_frames = len(self.fr_names)
self.aValues = [12]
ljm.eWriteNames(self.handle, self.num_frames, self.fr_names, self.aValues)
ljm.eWriteNames(self.handle, self.num_frames, self.fl_names, self.aValues)
ljm.eWriteNames(self.handle, self.num_frames, self.rr_names, self.aValues)
ljm.eWriteNames(self.handle, self.num_frames, self.rl_names, self.aValues)

self.run_count = 0

def setSMState(self, nextState: DAQState) -> None:
self.currentState = nextState

def readLJ(self):
return ljm.eReadName(self.handle, "AIN0")

def start_threads(self):
# self.canbus.start()
self.run.start()

def readCAN(self):
import logging

while True:
if self.currentState == DAQState.SAVING:
continue
with can.Bus() as bus:
self.daq_run_lock.acquire()
msg = bus.recv()

index = canMessageSort.get(msg.arbitration_id)
self.ECUData[index] = msg.data
self.daq_run_lock.release()

# def read_xl(self):

# while True:
# if self.currentState == DAQState.SAVING:
# continue
# self.daq_run_lock.acquire()
# read_xl_analog.read_xl_one(self.handle)
# read_xl_analog.read_xl_two(self.handle)
# self.daq_run_lock.release()

def resolveError(self) -> bool:
try:
return True
except ljm.LJMError:
return False
logging.basicConfig(level=logging.DEBUG)

def DAQRun(self) -> None:

nextTime = time.time()
index = 0
while True:
class DAQ(object):
def __init__(self, output_path: str, session_id: int = 0):
self.output_path = output_path

self.log = logging.getLogger("DAQ")

self.analog_stream: Stream | None = None

self.read_accel_gyro: Read | None = None

self.canbus: ECU | None = None

self.handle = ljm.openS(
"T7", "ANY", "ANY"
)
self._state = None
self._session_id = session_id or 0

self.log.info("session id: %s", self.session_id)

@property
def session_id(self):
return self._session_id

@session_id.setter
def session_id(self, new_session_id):
if new_session_id == self._session_id:
return
self._session_id = new_session_id

# update json file
with open("./config.json", "r+", encoding="utf8") as f:
try:
config = json.load(f)
except json.JSONDecodeError:
config = {}
config["session_id"] = new_session_id
f.seek(0)
json.dump(config, f)
f.truncate()

@property
def state(self):
return self._state

@state.setter
def state(self, new_state):
print("State Change: ", self._state, new_state)
if new_state == self._state:
return
else:
self.log.info("New State: %s", new_state)
print(new_state)

self._state = new_state

self.can_read_lock.acquire()
button_clicked = read_state.read_button_state(self.handle)
if new_state == DAQState.COLLECTING:
self.session_id += 1
if self.analog_stream:
self.analog_stream.start(session_id=self.session_id)

if time.time() < nextTime:
time.sleep(0)
if self.canbus:
self.canbus.start(session_id=self.session_id)

else:
nextTime = time.time()
if self.read_accel_gyro:
self.read_accel_gyro.start() # Cannot be called more than once per thread

elif new_state == DAQState.SAVING:
if self.analog_stream:
self.analog_stream.stop()

if self.canbus:
self.canbus.stop()

if self.read_accel_gyro:
self.read_accel_gyro.stop_reading()

if self.analog_stream:
self.analog_stream.save(self.output_path + f"/analog-{{}}-{self.session_id}.csv")
self.analog_stream = Stream(self.handle, extensions=[Linpot()])

if self.canbus:
self.canbus.save()

if self.read_accel_gyro:
self.read_accel_gyro.join() # Terminates thread
self.read_accel_gyro.save(self.output_path + f"/accel-{self.session_id}.csv", self.output_path
+ f"/gyro-{self.session_id}.csv")

self.read_accel_gyro = Read(session_id=self.session_id) # Re-initializes thread to reset session id

elif new_state == DAQState.INIT:
self.analog_stream = Stream(handle=self.handle, extensions=[Linpot()])
self.canbus = ECU(output_path=self.output_path + f"/can-")
self.handle = self.analog_stream.handle

self.read_accel_gyro = Read(session_id=self.session_id)

def _run(self):
while True:
button_clicked = read_state.read_button_state(self.handle, session_id=self.session_id)
if button_clicked:
if self.currentState == DAQState.INIT:
print("collecting")
self.setSMState(DAQState.COLLECTING)
elif self.currentState == DAQState.SAVING:
print("collecting")
self.setSMState(DAQState.COLLECTING)

if self.currentState == DAQState.COLLECTING:

try:
self.read_xl_analog_instance.read_xl_one(self.handle, index)
# read_xl_analog.read_xl_two(self.handle, index)
current_time = time.time()
self.linpot_df.loc[index, "Time"] = current_time
self.linpot_df.loc[index, "Front Right"] = ljm.eReadName(
self.handle, "AIN1")
self.linpot_df.loc[index, "Front Left"] = ljm.eReadName(
self.handle, "AIN2")
self.linpot_df.loc[index, "Rear Right"] = ljm.eReadName(
self.handle, "AIN3")
self.linpot_df.loc[index, "Rear Left"] = ljm.eReadName(
self.handle, "AIN4")
index += 1
print(self.linpot_df.tail(1))
self.linpot_df.to_csv()
except ljm.LJMError:
self.currentState == DAQState.ERROR

if self.resolveError():
break

print("LabJack Efrrfffor", ljm.LJMError)

else:
if self.currentState == DAQState.COLLECTING:
print("saving")

now = datetime.strftime(datetime.now(), "%Y-%m-%d_%H-%M-%S")
self.linpot_df.to_csv(
f"{self.output_file}_linpot_{now}.csv", index=False)

# clear linpot_df
self.linpot_df = pd.DataFrame(columns=self.linpot_df.columns)

# saving xl file data
self.read_xl_analog_instance.save_xl_files()
self.read_xl_analog_instance.clear_xl_files()

self.setSMState(DAQState.SAVING)
self.run_count += 1

self.can_read_lock.release()
if self.state in [DAQState.INIT, DAQState.SAVING]:
# startup is done
self.state = DAQState.COLLECTING

def __del__(self):
elif self.state == DAQState.COLLECTING:
self.state = DAQState.SAVING

time.sleep(0)

def start(self):
self.log.info("Starting DAQ")

os.system('sudo ifconfig can0 down')
self.state = DAQState.INIT
try:
self._run()
except KeyboardInterrupt:
self.log.info("DAQ Stopped")
finally:
self.state = DAQState.SAVING
self.log.info("DAQ Stopped")

def __del__(self):
if self.handle:
ljm.close(self.handle)
self.handle = None


if __name__ == "__main__":
try:
with open("./config.json", "r+", encoding="utf8") as f:
config = json.load(f)
except:
config = {}

DAQ = DAQObject("data/output2")
DAQ.start_threads()
daq = DAQ(config.get("output", "test-data"), session_id=config.get("session_id", 0))

print("test")
time.sleep(10)
daq.start()
30 changes: 0 additions & 30 deletions ReadState.py

This file was deleted.

Binary file removed __pycache__/DAQState.cpython-311.pyc
Binary file not shown.
Binary file removed __pycache__/ReadState.cpython-39.pyc
Binary file not shown.
Binary file removed __pycache__/messageIDs.cpython-311.pyc
Binary file not shown.
Loading