LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Battery Test Stand

I'm looking for general guidance on the best approach for this project. I have built a functional battery test stand but the entire time while writing the program I had the feeling of "there must be a better way." Unfortunately I just had to get it up and running so I'm asking the question now, how should it have been done...? (I'll be making more test stands so it would be nice to figure out more efficient methods)

 

The basic concept is pretty simple: continuously charge and discharge battery modules for hundreds to thousands of cycles. I don't touch it, it just does its thing until I someday hit Stop.

 

My real questions is about process control. Right now I'm using a case structure with a Type Def enum with the options: Startup, Idle, Charge, Discharge, Write to file/plot.

 

During charge, for example, I enter the 'Charge' case and stay in there until it's done charging. But inside the Charge state I have flat sequence inside of a stacked sequence that opens a data log file, starts logging, starts charging, etc, then I enter a while-loop until the voltage gets to a certain level, then I momentarily suspend charging and measure the voltage drop, then resume charging, etc. etc. 

 

Point being, I have a ton of stuff happening in a single case and it gets kinda messy. On top of it, the discharge case is almost an exact copy of Charge so if I make a functional change to Charge I should do my best to replicate the change in Discharge.

 

So, hunting for alternatives, I looked into TestStand but it didn't seem to fit the continuous and no-intervention concept. Then I thought Event Driven Programming was the ticket but that seems to need user interaction. Now I found Statechart which looks promising but I am still not sure.

 

More details about the setup:

Running LabVIEW 2016 (can upgrade, have been too busy/lazy)

2 Li-ion 3.7V nominal in series (that's how the module comes) with 2 in parallel, each voltage monitored independently

LabJack U6 as my DAQ and power supply control

Meanwell RSP-750 to charge the batteries

Load resistors for discharging (wasteful, yes, but will upgrade to battery bank in the future)

Balance resistors to be used as needed

Temperature controlled environment (heating element and ambient-air cooling)

Contactor for battery disconnect

 

That's about it. Attached is the project. Open the VI called 'Main' and check out the Process Control loop. 

0 Kudos
Message 1 of 8
(1,663 Views)

Warning, you will gets lots of different opinions on this.

 

As a starting point I would look at the following things

- Have a look at queues. In my opinion much of the data transfer between your loops could and should be carried out using queues rather than local variables

- Try and split your code into separate 'modules'. I tend to structure my code so that each module runs in its own VI containing a queued message handler (Or queued state machine depending upon what you want to call it). For example you could have a File Handling module, LabJack module, UI module etc etc

- steer clear of stacked sequences...they hide too much code for my liking. I prefer seperate cases in an enum controlled case structure. Gives more natural documentation as to waht is happening. It also gives the opportunity to escape the loop part way through

 

This only scratches the surface, I am sure there will be lots of other suggestions

0 Kudos
Message 2 of 8
(1,634 Views)

Appreciate the suggestions! Queues are something I have considered but avoided initially since I didn't really understand them. I have been through the tutorial (might go through it again to see if anything 'clicks') but would you have a more complex example code that I could pick through? I will also try hunting around on the forum.

0 Kudos
Message 3 of 8
(1,565 Views)

You may still be interested that "Event Driven Programming" actually does not require user input!  You can create dynamic events and trigger them whenever you want. 

 

For example, if transitioning from battery charging to charge complete:

At the start of the program you would have added "create user event"(Charge Complete)

In the battery monitoring loop you would then use "generate user event"(Charge Complete) once charge is complete

 

The way dynamic events are used is often very similar to the queued message handler so it is still useful for you to learn about that architecture.  I am currently studying for my CLA, so I will try to set up the architecture for this program and you can try and see if you would be able to fill in the missing programming relative to your goals

----------------------------------------------------
Studying for CLA.
LabVIEW, inherit from social media habits!
0 Kudos
Message 4 of 8
(1,550 Views)

Project is attached.

 

I can't guarentee I ran this event architecture with best practice, I usually used Queued message handler myself. But I think it will work.  In some instances it may be better to swap out an enum rather then driving state machine with dynamic user events.  You could also send state selection enums as data through the user event.  TBH I don't have enough experience to be familiar with running that though.

 

The main thing I think you should focus on in the future is to use FGV instead of local variables.  There is of course issues with using FGV because you have a overwhelming amount of controls and indicators!  (you have to bundle all those references up into the FGV at the start of the program)  Since you had so many I just turned them into clusters. (this was the laziest solution I could think of, and tbh I hate what I did lol). I think If you need that many controls and indicators it might be a good idea to have more than 1 front panel(?)  But yeah, using FGV will open up a lot of space for you, as you can read and write to front panel from anywhere, including subvi.  It will encourage you to escape the large block diagram and shrink it down into subvi.

 

I think learning/mastering the use of FGV and state machine is a good precursor to learning queued message handler and event driven architecture, so you may want to at least take a look at how I incorporated the FGV into your program.

 

Adding a picture for easier view of architecture.

Feel free to critique/give feedback!

CDuck_0-1599958301800.png

EDIT* I just noticed in the picture, I forgot to swap out the Events.ctl with the one from events fgv. Be sure to do that if try to fill in this design.  (Located in the UI loop>Controls.stop)

----------------------------------------------------
Studying for CLA.
LabVIEW, inherit from social media habits!
0 Kudos
Message 5 of 8
(1,513 Views)

You gave me the proper motivation to install the latest version of LabVIEW!

Unfortunately, I didn't realize I only have a license up to 2019. Is it possible for you to save and repost this for the 2019 version?

0 Kudos
Message 6 of 8
(1,484 Views)

Sure, try this one for 2019

----------------------------------------------------
Studying for CLA.
LabVIEW, inherit from social media habits!
0 Kudos
Message 7 of 8
(1,479 Views)

I think another way to change states with dynamic events is to input the state into a Generate Event(State Change).  I did not provide great architecture, but at least you can get the feel for the "remote communication" of dynamic events or QMH

----------------------------------------------------
Studying for CLA.
LabVIEW, inherit from social media habits!
0 Kudos
Message 8 of 8
(1,475 Views)