//New system here: //synchronous functions for background thread. void BmsUpdate(BatteryWriteDataStruct write_data) { BatteryReadDataStruct read_data = null; if (!String.IsNullOrEmpty(BmsComPort) && BmsCom.Open(BmsComPort)) { try { //usually throws a timeout if the FTDI part has power and is connected but 48V is off. read_data = BmsCom.BmsUpdate(write_data); } catch (Exception ex) { //we still need to close the comport if we left it open, so the next attempt works properly. if (BmsCom.IsOpen()) { BmsCom.Close(); } throw ex; //rethrow, so the top catches it. } BmsCom.Close(); } if (read_data != null) { BatteryReadData = read_data; Dispatcher.BeginInvoke((Action)(() => { BmsUpdateGui(); })); } }
public BatteryReadDataStruct BmsUpdate(BatteryWriteDataStruct write_struct) { var write_data = write_struct.Serialize(); byte[] rx_buffer = RoundTripCommand(write_data, BatteryReadDataStruct.Size, NormalCellTimeout); BatteryReadDataStruct read_data = BatteryReadDataStruct.Deserialize(rx_buffer); return(read_data); }
void LogCellVoltages() { BatteryReadDataStruct read_data = BatteryReadData; string line = DateTime.Now.ToString() + ", "; line += String.Join(", ", read_data.CellVoltages.Select(x => x.ToString("0.00"))); line += ", "; line += String.Join(", ", read_data.CellTemperatures.Select(x => x.ToString("0.00"))); line += ", "; line += String.Join(", ", BatteryWriteData.GetCellCurrents().Select(x => x.ToString("0.00"))); WriteLineToCellLog(line); }
private void UpdateCellStats() { double total_voltage = 0; double min_voltage = 0; double max_voltage = 0; BatteryReadDataStruct read_data = BatteryReadData; total_voltage = read_data.CellVoltages.Take(CellCount).Sum(x => x); min_voltage = read_data.CellVoltages.Take(CellCount).Min(x => x); max_voltage = read_data.CellVoltages.Take(CellCount).Max(x => x); double delta = max_voltage - min_voltage; double mean = total_voltage / CellCount; PackVoltageDeltaLbl.Content = "Pack Δ " + delta.ToString("0.00") + "V"; PackMeanVoltageLbl.Content = "x̄ Cell: " + mean.ToString("0.00") + "V"; foreach (BatteryViewControl bat in BatteryViews) { if (bat.Voltage < 2.7 || bat.Voltage > 3.6) { bat.IsCritical = true; } else { bat.IsCritical = false; } if (bat.Temp > 100) { bat.IsOverheated = true; } else { bat.IsOverheated = false; } } }
void ChargeUpdate() { TimeSpan discharge_time = TimeSpan.FromMinutes(5); double cell_bleed_voltage = 3.61; double cell_finished_voltage = 3.45; int cell_count = BatteryWriteData.CellCount; //double cell_bleed_current = 1.0; BatteryReadDataStruct read_data = BatteryReadData; if (ChargeActive == false) { AbortCharge(); return; } if (DischrageInProgress) { if (DateTime.Now >= DichargeEndTime) { //discharge done, reconnect the charger! WriteLineToCellLog("Discharge timer complete, enableing charge relay again"); Console.WriteLine("Bleed cycle complete"); DischrageInProgress = false; BatteryWriteData.StopCellDischarges(); SetChargeRelay(true); } } else { bool all_unbled_cells_done = true; List <int> cells_to_bleed = new List <int>(); List <double> cell_bleed_currents = new List <double>(); for (int i = 0; i < cell_count; ++i) { double cell_bleed_current = 0; double cell_voltage = read_data.CellVoltages[i]; if (cell_voltage > 3.50) { if (cell_voltage < 3.6) { cell_bleed_current = (cell_voltage - 3.50) * 5.0; } else { cell_bleed_current = .5; } } cell_bleed_currents.Add(cell_bleed_current); if (CellDischargeCount[i] == 0 && read_data.GetCellVoltage(i) < cell_finished_voltage) { all_unbled_cells_done = false; } if (read_data.GetCellVoltage(i) > cell_bleed_voltage) { cells_to_bleed.Add(i); } } if (all_unbled_cells_done == true) { //DONE! int non_bled_cell_count = CellDischargeCount.Count(x => x == 0); Console.WriteLine("Charge Complete. " + non_bled_cell_count + " cells never bled"); //todo: set charge button string unbled_cells = ""; for (int i = 0; i < CellDischargeCount.Count(); ++i) { if (CellDischargeCount[i] == 0) { unbled_cells += i.ToString() + ", "; } CellDischargeCount[i] = 0; } WriteLineToCellLog("All unbled cells complete! Ending Charge. Unbled Cells: " + unbled_cells); ChargeActive = false; DischrageInProgress = false; SetChargeRelay(false); ChargeBtn.Content = "Start Charge"; return; } if ((all_unbled_cells_done == false) && (cells_to_bleed.Any())) { //start bleeding WriteLineToCellLog("bleed started: " + String.Join(",", cells_to_bleed)); Console.WriteLine("starting to bleed cells " + String.Join(",", cells_to_bleed)); DischrageInProgress = true; SetChargeRelay(false); DichargeEndTime = DateTime.Now + discharge_time; foreach (int i in cells_to_bleed) { CellDischargeCount[i]++; //BatteryWriteData.SetCellCurrent( i, cell_bleed_current ); } string log = "starting discharge: "; for (int i = 0; i < cell_count; ++i) { BatteryWriteData.SetCellCurrent(i, cell_bleed_currents[i]); log += i + "(" + cell_bleed_currents[i].ToString("F") + "A), "; } Console.WriteLine(log); return; } //stay in bulk charge, no discharging. } }
public static BatteryReadDataStruct Deserialize(byte[] data) { List <byte> dat = new List <byte>(data); if (!(data.Last() != 0xDE)) { //throw execption? Console.WriteLine("Failed to deserialize Battery Read Data Struct."); return(null); } BatteryReadDataStruct read_data = new BatteryReadDataStruct(); for (int i = 0; i < CELL_COUNT; ++i) { read_data.mCellVoltages[i] = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); } for (int i = 0; i < CELL_COUNT; ++i) { read_data.mCellTemperatures[i] = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); } for (int i = 0; i < RELAY_COUNT; ++i) { read_data.mPrechargeVoltages[i] = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); } //SWAPPED BECUASE ADC 2 is not working, and we want charge! read_data.MasterCurrent = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); read_data.ChargeCurrent = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); read_data.PackVoltage = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); read_data.MasterTemperature = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); read_data.MasterHumidity = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); read_data.ValidCellReadCount = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); dat.RemoveRange(0, 2); read_data.CriticalFlags = BitConverter.ToUInt16(dat.Take(2).ToArray(), 0); //enums are 16 bit on MSP430. dat.RemoveRange(0, 2); read_data.CoulombCount = BitConverter.ToInt64(dat.Take(8).ToArray(), 0); dat.RemoveRange(0, 8); if (dat.Count() > 0) { throw new Exception("padding detected."); } if (read_data.mCellVoltages.Any(x => x == 0xFFFF) || read_data.mCellTemperatures.Any(x => x == 0xFFFF)) { //issue detected. Console.WriteLine("cell read error detected"); } return(read_data); }