Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python-based battery scanner script #187

Merged
merged 12 commits into from
Mar 14, 2024
8 changes: 8 additions & 0 deletions battery_scanner/conda_env.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
channels:
- defaults
dependencies:
- python=3.12
- pip
- pyserial
- pip:
- pyntcore
80 changes: 80 additions & 0 deletions battery_scanner/scanner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
""" Script to interface with battery scanner
"""
import argparse
from time import sleep
import serial
import array
import ntcore
import logging
import re

#------------------
#-- Parameters
#------------------
logging.basicConfig(level=logging.INFO)

timeout = 1
prefix = array.array('B', [0x02, 0x00, 0x00, 0x01, 0x00, 0x33, 0x31])
scan_command = array.array('B',[0x7e, 0x00, 0x08, 0x01, 0x00, 0x02, 0x01, 0xab, 0xcd])
name_length = 8
response_length = len(prefix) + name_length

#------------------
#-- Parse command line arguments
#------------------
parser = argparse.ArgumentParser()
parser.add_argument("--dev", default="COM8", type=str, help="Path to the camera device")
args = parser.parse_args()


#------------------
#-- Setup NetworkTables
#------------------
client = ntcore.NetworkTableInstance.getDefault()
client.startClient4(f'battery-scanner')
client.setServerTeam(6328)

pub = client.getStringTopic("/battery_name").publish()

#------------------
#-- Read battery name
#------------------
name = None
try:
with serial.Serial(args.dev, 9600, timeout=timeout) as ser:

logging.info("Scanning for battery ID")

while True:
ser.write(scan_command)
response = ser.read(response_length)

if len(response) == response_length:
if response.startswith(prefix):
name_bytes = response[-8:]
name_str = name_bytes.decode("utf-8")
if re.match('^[a-zA-Z0-9_\\-]+$', name_str):
name = name_str
logging.info(f"Battery ID: {name}")
break
else:
logging.warning("Battery ID doesn't match expected pattern")

except Exception as e:
logging.error(e)

#------------------
#-- Publish name
#------------------
if name is not None:
pub.set(f"BAT-{name}")
else:
logging.error("Unable to read battery code")


#------------------
#-- Switch to idle state
#------------------
logging.info("Switching to idle mode")
while True:
sleep(100)
87 changes: 48 additions & 39 deletions src/main/java/org/littletonrobotics/frc2024/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import static org.littletonrobotics.frc2024.util.Alert.AlertType;

import com.ctre.phoenix6.CANBus;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.networktables.StringSubscriber;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.RobotController;
import edu.wpi.first.wpilibj.Threads;
Expand All @@ -28,7 +30,6 @@
import org.littletonrobotics.frc2024.Constants.Mode;
import org.littletonrobotics.frc2024.subsystems.leds.Leds;
import org.littletonrobotics.frc2024.util.Alert;
import org.littletonrobotics.frc2024.util.BatteryTracker;
import org.littletonrobotics.frc2024.util.NoteVisualizer;
import org.littletonrobotics.frc2024.util.VirtualSubsystem;
import org.littletonrobotics.junction.LogFileUtil;
Expand All @@ -55,12 +56,19 @@ public class Robot extends LoggedRobot {
private RobotContainer robotContainer;
private double autoStart;
private boolean autoMessagePrinted;
private boolean batteryNameWritten = false;
private final Timer disabledTimer = new Timer();
private final Timer canInitialErrorTimer = new Timer();
private final Timer canErrorTimer = new Timer();
private final Timer canivoreErrorTimer = new Timer();

private static final String defaultBatteryName = "BAT-0000-000";
private final StringSubscriber batteryNameSubscriber =
NetworkTableInstance.getDefault()
.getStringTopic("/battery_name")
.subscribe(defaultBatteryName);
private boolean batteryNameChecked = false;
private boolean batteryNameWritten = false;

private final Alert canErrorAlert =
new Alert("CAN errors detected, robot may not be controllable.", AlertType.ERROR);
private final Alert canivoreErrorAlert =
Expand All @@ -82,7 +90,6 @@ public void robotInit() {

// Record metadata
Logger.recordMetadata("Robot", Constants.getRobot().toString());
Logger.recordMetadata("BatteryName", "BAT-" + BatteryTracker.scanBattery(1.5));
Logger.recordMetadata("TuningMode", Boolean.toString(Constants.tuningMode));
Logger.recordMetadata("RuntimeType", getRuntimeType().toString());
Logger.recordMetadata("ProjectName", BuildConstants.MAVEN_NAME);
Expand Down Expand Up @@ -160,30 +167,6 @@ public void robotInit() {
canivoreErrorTimer.restart();
disabledTimer.restart();

// Check for battery alert
if (Constants.getMode() == Mode.REAL
&& !BatteryTracker.getName().equals(BatteryTracker.defaultName)) {
File file = new File(batteryNameFile);
if (file.exists()) {
// Read previous battery name
String previousBatteryName = "";
try {
previousBatteryName =
new String(Files.readAllBytes(Paths.get(batteryNameFile)), StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
if (previousBatteryName.equals(BatteryTracker.getName())) {
// Same battery, set alert
sameBatteryAlert.set(true);
Leds.getInstance().sameBattery = true;
} else {
// New battery, delete file
file.delete();
}
}
}

RobotController.setBrownoutVoltage(6.0);
robotContainer = new RobotContainer();
}
Expand Down Expand Up @@ -267,18 +250,44 @@ public void robotPeriodic() {
Leds.getInstance().lowBatteryAlert = true;
}

// Write battery name if connected to field
if (Constants.getMode() == Mode.REAL
&& !batteryNameWritten
&& !BatteryTracker.getName().equals(BatteryTracker.defaultName)
&& DriverStation.isFMSAttached()) {
batteryNameWritten = true;
try {
FileWriter fileWriter = new FileWriter(batteryNameFile);
fileWriter.write(BatteryTracker.getName());
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
// Update battery alert
String batteryName = batteryNameSubscriber.get();
Logger.recordOutput("BatteryName", batteryName);
if (Constants.getMode() == Mode.REAL && !batteryName.equals(defaultBatteryName)) {
// Check for battery alert
if (!batteryNameChecked) {
batteryNameChecked = true;
File file = new File(batteryNameFile);
if (file.exists()) {
// Read previous battery name
String previousBatteryName = "";
try {
previousBatteryName =
new String(Files.readAllBytes(Paths.get(batteryNameFile)), StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
if (previousBatteryName.equals(batteryName)) {
// Same battery, set alert
sameBatteryAlert.set(true);
Leds.getInstance().sameBattery = true;
} else {
// New battery, delete file
file.delete();
}
}
}

// Write battery name if connected to FMS
if (!batteryNameWritten && DriverStation.isFMSAttached()) {
batteryNameWritten = true;
try {
FileWriter fileWriter = new FileWriter(batteryNameFile);
fileWriter.write(batteryName);
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Expand Down

This file was deleted.

Loading