Re: 18650 Conditioner unit.

Support forum for MegunoLink
Mike-AU
Posts: 32
Joined: Wed Mar 13, 2019 12:03 am

Tue May 07, 2019 8:47 am

Be more than happy to ... this will be a long post as I will drop 2 versions of code to show the problem, feel free to delete this post later if you like. or shorten it. OK where to start... look at this line:-

Serial.print("Power: "); Serial.print(power_mW); Serial.print("mW ");
................... ^^^^^^^ This bit is fixed ^^^^^^^^^^ this bit takes a variable OK .
Problem is when you have multiples of the word POWER to send to the table, the table code writes and overwrites that line in a table.
Now I show a bit more to help explain.
--------------------------------------------------------------------------------------------------------------------------------------------------
int ina; int t; int ct; int pin; // initialize variables used in loop.
for (t=3; t<8; t++){//2
tcaselect(t);

for (ina=0; ina<4; ina++) // initialize the 219s
{//3
ct++;Serial.print(" Bay-");Serial.print(ct); pin=(21+ct);
ina219[ina].begin();

float shuntvoltage = 0; //initialize variables
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;

shuntvoltage = ina219[ina].getShuntVoltage_mV(); // read INA219 info into variables
busvoltage = ina219[ina].getBusVoltage_V();
current_mA = ina219[ina].getCurrent_mA();
power_mW = ina219[ina].getPower_mW();
loadvoltage = busvoltage + (shuntvoltage / 1000);

Serial.print(""); // write each INA219 info on the screen.
Serial.print("Bus: "); Serial.print(busvoltage); Serial.print("V ");
Serial.print("Shunt: "); Serial.print(shuntvoltage); Serial.print("mV ");
Serial.print("Current: "); Serial.print(current_mA); Serial.print("mA ");
Serial.print("Power: "); Serial.print(power_mW); Serial.print("mW ");

}//3
}//2
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Originally when I wrote this code, its made up of 2 loops. One outside loop steps through 5 channels on a I2C multiplexer. The second loop reads the 4 sensors on each channel. easier to show like this:-

channel 1 sensors 1,2,3,4
chennel 2 sensors 1,2,3,4
and so on for 5 channels so in all 5x4 sensor are read. 20 sensors, add into the mix EACH sensor gives 4 readings of data. Means we are dealing with 80 readings of data in total , just on this section.

Now because this:-
Serial.print("Power: "); Serial.print(power_mW); Serial.print("mW ");
.................. ^^^^^^^ is "fixed" EG I cannot use a string here, this creates a problem.
If it was coded like this:-

Serial.print("$Power: "); Serial.print(power_mW); Serial.print("mW ");
Telling the code that $power is a string variable , then we could do this:-
}
if (a < 20): a++;
$power = (Cell(a) Power);
Serial.print("$Power: "); Serial.print(power_mW); Serial.print("mW ");
}
the $Power variable now contains "Cell1 Power" next time round reads "Cell2 Power" and so on.

By allowing us to manipulate the NAME it stops us having to write the data out in what I call " Long Hand".
Beacause MLP locks the NAME into entered text only, and does not allow a string to sit in its place this is what I had to write to by-pass that problem:-
(note code is upgraded from screen writes to table write, but principle still applies.


int ct; // initialize variables used inside loop.
{//2
ct=0;
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(3,0);
Table Block1("Block1");
Block1.SendData(F("Cell-1"), ct, "Status");
Block1.SendData(F("Cell-1 Bus: "), busvoltage, "V");
Block1.SendData(F("Cell-1 Shunt: "), shuntvoltage, "mV");
Block1.SendData(F("Cell-1 Current: "), current_mA, "mA");
Block1.SendData(F("Cell-1 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(3,1);
Block1.SendData(F("Cell-2"), ct, "Status");
Block1.SendData(F("Cell-2 Bus: "), busvoltage, "V");
Block1.SendData(F("Cell-2 Shunt: "), shuntvoltage, "mV");
Block1.SendData(F("Cell-2 Current: "), current_mA, "mA");
Block1.SendData(F("Cell-2 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(3,2);
Block1.SendData(F("Cell-3"), ct, "Status");
Block1.SendData(F("Cell-3 Bus: "), busvoltage, "V");
Block1.SendData(F("Cell-3 Shunt: "), shuntvoltage, "mV");
Block1.SendData(F("Cell-3 Current: "), current_mA, "mA");
Block1.SendData(F("Cell-3 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(3,3);
Block1.SendData(F("Cell-4"), ct, "Status");
Block1.SendData(F("Cell-4 Bus: "), busvoltage, "V");
Block1.SendData(F("Cell-4 Shunt: "), shuntvoltage, "mV");
Block1.SendData(F("Cell-4 Current: "), current_mA, "mA");
Block1.SendData(F("Cell-4 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(4,0);
Table Block2("Block2");
Block2.SendData(F("Cell-5"), ct, "Status");
Block2.SendData(F("Cell-5 Bus: "), busvoltage, "V");
Block2.SendData(F("Cell-5 Shunt: "), shuntvoltage, "mV");
Block2.SendData(F("Cell-5 Current: "), current_mA, "mA");
Block2.SendData(F("Cell-5 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(4,1);
Block2.SendData(F("Cell-6"), ct, "Status");
Block2.SendData(F("Cell-6 Bus: "), busvoltage, "V");
Block2.SendData(F("Cell-6 Shunt: "), shuntvoltage, "mV");
Block2.SendData(F("Cell-6 Current: "), current_mA, "mA");
Block2.SendData(F("Cell-6 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(4,2);
Block2.SendData(F("Cell-7"), ct, "Status");
Block2.SendData(F("Cell-7 Bus: "), busvoltage, "V");
Block2.SendData(F("Cell-7 Shunt: "), shuntvoltage, "mV");
Block2.SendData(F("Cell-7 Current: "), current_mA, "mA");
Block2.SendData(F("Cell-7 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(4,3);
Block2.SendData(F("Cell-8"), ct, "Status");
Block2.SendData(F("Cell-8 Bus: "), busvoltage, "V");
Block2.SendData(F("Cell-8 Shunt: "), shuntvoltage, "mV");
Block2.SendData(F("Cell-8 Current: "), current_mA, "mA");
Block2.SendData(F("Cell-8 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(5, 0);
Table Block3("Block3");
Block3.SendData(F("Cell-9"), ct, "Status");
Block3.SendData(F("Cell-9 Bus: "), busvoltage, "V");
Block3.SendData(F("Cell-9 Shunt: "), shuntvoltage, "mV");
Block3.SendData(F("Cell-9 Current: "), current_mA, "mA");
Block3.SendData(F("Cell-9 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(5,1);
Block3.SendData(F("Cell-10"), ct, "Status");
Block3.SendData(F("Cell-10 Bus: "), busvoltage, "V");
Block3.SendData(F("Cell-10 Shunt: "), shuntvoltage, "mV");
Block3.SendData(F("Cell-10 Current: "), current_mA, "mA");
Block3.SendData(F("Cell-10 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(5,2);
Block3.SendData(F("Cell-11"), ct, "Status");
Block3.SendData(F("Cell-11 Bus: "), busvoltage, "V");
Block3.SendData(F("Cell-11 Shunt: "), shuntvoltage, "mV");
Block3.SendData(F("Cell-11 Current: "), current_mA, "mA");
Block3.SendData(F("Cell-11 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(5,3);
Block3.SendData(F("Cell-12"), ct, "Status");
Block3.SendData(F("Cell-12 Bus: "), busvoltage, "V");
Block3.SendData(F("Cell-12 Shunt: "), shuntvoltage, "mV");
Block3.SendData(F("Cell-12 Current: "), current_mA, "mA");
Block3.SendData(F("Cell-12 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(6,0);
Table Block4("Block4");
Block4.SendData(F("Cell-13"), ct, "Status");
Block4.SendData(F("Cell-13 Bus: "), busvoltage, "V");
Block4.SendData(F("Cell-13 Shunt: "), shuntvoltage, "mV");
Block4.SendData(F("Cell-13 Current: "), current_mA, "mA");
Block4.SendData(F("Cell-13 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(6,1);
Block4.SendData(F("Cell-14"), ct, "Status");
Block4.SendData(F("Cell-14 Bus: "), busvoltage, "V");
Block4.SendData(F("Cell-14 Shunt: "), shuntvoltage, "mV");
Block4.SendData(F("Cell-14 Current: "), current_mA, "mA");
Block4.SendData(F("Cell-14 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(6,2);
Block4.SendData(F("Cell-15"), ct, "Status");
Block4.SendData(F("Cell-15 Bus: "), busvoltage, "V");
Block4.SendData(F("Cell-15 Shunt: "), shuntvoltage, "mV");
Block4.SendData(F("Cell-15 Current: "), current_mA, "mA");
Block4.SendData(F("Cell-15 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(6,3);
Block4.SendData(F("Cell-16"), ct, "Status");
Block4.SendData(F("Cell-16 Bus: "), busvoltage, "V");
Block4.SendData(F("Cell-16 Shunt: "), shuntvoltage, "mV");
Block4.SendData(F("Cell-16 Current: "), current_mA, "mA");
Block4.SendData(F("Cell-16 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.println(ct);
CellTest(7,0);
Table Block5("Block5");
Block5.SendData(F("Cell-17"), ct, "Status");
Block5.SendData(F("Cell-17 Bus: "), busvoltage, "V");
Block5.SendData(F("Cell-17 Shunt: "), shuntvoltage, "mV");
Block5.SendData(F("Cell-17 Current: "), current_mA, "mA");
Block5.SendData(F("Cell-17 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.println(ct);
CellTest(7,1);
Block5.SendData(F("Cell-18"), ct, "Status");
Block5.SendData(F("Cell-18 Bus: "), busvoltage, "V");
Block5.SendData(F("Cell-18 Shunt: "), shuntvoltage, "mV");
Block5.SendData(F("Cell-18 Current: "), current_mA, "mA");
Block5.SendData(F("Cell-18 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.print(ct);
CellTest(7,2);
Block5.SendData(F("Cell-19"), ct, "Status");
Block5.SendData(F("Cell-19 Bus: "), busvoltage, "V");
Block5.SendData(F("Cell-19 Shunt: "), shuntvoltage, "mV");
Block5.SendData(F("Cell-19 Current: "), current_mA, "mA");
Block5.SendData(F("Cell-19 Power: "), power_mW, "mW");
//--------------------------------------------------------------------
ct++; Serial.print(" Bay-"); Serial.println(ct); // this is a debug line
CellTest(7,3);
Block5.SendData(F("Cell-20"), ct, "Status");
Block5.SendData(F("Cell-20 Bus: "), busvoltage, "V");
Block5.SendData(F("Cell-20 Shunt: "), shuntvoltage, "mV");
Block5.SendData(F("Cell-20 Current: "), current_mA, "mA");
Block5.SendData(F("Cell-20 Power: "), power_mW, "mW");


}

As you can see, writing 4 Sensors to 5 tables takes much more repetitive coding to succeed.
Now I know not everyone is crazy like me and builds a large project, but even a smaller project like a area surveillance system with say 10 sensors would benefit from the ability to use a "$string " function like the old basic programming from 30 or more year ago.

I *hope* I have explained it a bit better, again sorry for the long post.

Mike.
philr
Posts: 446
Joined: Mon May 26, 2014 10:58 am

Tue May 14, 2019 8:09 am

Hi Mike, I see. In the past we have used the pstring library. That allows you to create a custom string that you would be able to send out the serial channel.

char buffer[50];
PString mystring(buffer, sizeof(buffer));
int index = 1;
mystring.print("Cell");
mystring.print(index);
mystring.print(" Power");

Then you just go
Serial.print(buffer);

Next time around you would increment index and generate the next string. Does that make sense?

Cheers
Phil
Mike-AU
Posts: 32
Joined: Wed Mar 13, 2019 12:03 am

Wed May 15, 2019 6:14 am

I shall study that, it may be a work around..

I found another case where it will be helpful.

under each pair of radio button I have a picture box, 20 of them. Now each picture box has three states Red/Yellow/Green . these stand for charging, resting, discharging . I allows at a glance feedback to what state each battery cell is in its cycle..
Using the pstring method in a function should save a lot of repetitive coding.
For example this is the "test" function I used to get just one box to operate.

int wk = (shuntvoltage+6000);// The addition of 6000 allows for manipulation of negative numbers. sneaky hey!

if (wk > 6005)
{Panel.SetBackColor( "Box1" , "Lime");}
else if (wk < 5995)
{Panel.SetBackColor("Box1", "Red");}
else {Panel.SetBackColor("Box1", "Yellow");}

Now you can imagine having to repeat this 20 times for each box, Just because the "Box1" cant be addressed as a variable..
It would make the sketch length start to get ridiculous.

So thanks for the pstring info... will go fool with that and let you know how I go with it.

Mike.
philr
Posts: 446
Joined: Mon May 26, 2014 10:58 am

Thu May 16, 2019 6:35 am

Yep Pstring will handle that nicely. The good think about Pstring is that its uses a pre-allocated buffer so is pretty memory efficient. I think there was some talk that strings were a bad idea. I never looked into it too much though.

Cheers
Phil
Mike-AU
Posts: 32
Joined: Wed Mar 13, 2019 12:03 am

Thu May 16, 2019 10:57 am

Okay great news Phil ,

pString works a treat and is very small code wise. Works fantastic for changing the colours on the pic boxes.

is there a "but" coming? Yes there is, you can only use one pString at a time.

This tiny function controls 20 individual picture boxes.
----------------------------------------------------------------------------------------------------------------------------
void BoxStatus()
{
Data = "Box";
Data += ct;
int wk = (shuntvoltage+6000);// The addition of 6000 allows for manipulation of negative numbers. sneaky hey!
if (wk > 6005)
{Panel.SetBackColor(buffer, "Red");}
else if (wk < 5995)
{Panel.SetBackColor(buffer, "Yellow");}
else {Panel.SetBackColor(buffer, "Lime");}
}
------------------------------------------------------------------------------------------------------------------------------

But here is the not so good bit,

Block1.SendData(F("Cell-1 Shunt: "), shuntvoltage, "mV");
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
both of those bits need to be "variable", pString CAN do it, if there is only ONE variable in a single line that needs to be flexible but both "Block1" and Cell-1 need to be.
I will try to find a workaround for this..
No matter, I am having a great time with this and really enjoying the challenge...

Mike.


PS Hmm I wonder, just thought of something I could try!! Get back to you later.....
Mike-AU
Posts: 32
Joined: Wed Mar 13, 2019 12:03 am

Fri May 17, 2019 1:05 pm

Question Phil,
Is it possible to change the serial monitor properties on the run?

I like the serial monitor, But it be nice if I could make a control to toggle visable, invisable property.

EG lay a serial monitor over the center of the gui and just pop it open when needed to check some instructions or data is being sent.

Currently I have made the control panel twice my screen width, all the normal stuff on the left and if I scroll right there is the serial monitor.

Not as neat as being able to pop it open on the main screen, or opening and closing a timeplot visulizer when required.

Cheers.. mike.
philr
Posts: 446
Joined: Mon May 26, 2014 10:58 am

Fri May 17, 2019 8:29 pm

You should be able to declare two psting objects along with separate buffers.

As for the monitor you could add it as a separate visualiser from the visualiser menu (not added to the interface panel) then dock it as a tab in the same space as your interface panel. Then it's easy to just switch to or ignore.

Cheers
Phil
Mike-AU
Posts: 32
Joined: Wed Mar 13, 2019 12:03 am

Fri May 17, 2019 10:52 pm

Great news, I am sorry I ask so many questions but I am still learning all the little nuances of the software.

MLP is both easy to set up quickly, but very comprehensive when you need to "Fine Tune" it.

Any hints on how to get a second or third instance of Pstring running?

Mike.
philr
Posts: 446
Joined: Mon May 26, 2014 10:58 am

Sat Jun 01, 2019 1:19 am

Hi Mike, I believe you'd just create two buffers and two PString objects. Like this

char buffer1[50];
PString mystring1(buffer1, sizeof(buffer1));

char buffer2[50];
PString mystring2(buffer2, sizeof(buffer2));

Then you could fill each separate buffer using the separate PString objects (mystring1 and mystring 2).

Cheers
Phil
Mike-AU
Posts: 32
Joined: Wed Mar 13, 2019 12:03 am

Mon Jun 03, 2019 6:38 am

Update for you phil,

I have set two small radio buttons on screen , they toggle between show Serial monitor or hide Serial monitor. works well if not a bit slow cause Arduino is working hard.
Also I set it to foreground layer, this allows me other controls on screen that i can use by setting them to the background layer.

This effectively doubles the screen useage availability , which is kinda cool in itself. When the two multiplexers get here from china, I will add the controls for them under the monitor. They only need to be accessed if a problem arises. Either that or I will put a message monitor in the same place, allows me to get just the working info displayed without all the table data filling the box.

Cheers for now..

Have a screen cap of it working if you interested..
Mike.
Post Reply