NOTICE: This forum has been archived (i.e. registration and posting is disabled).

Please go to the new forum at https://forum.kylegabriel.com

Multiple Inputs for...
 
Notifications
Clear all

[Solved] Multiple Inputs for Math Equation


mrdieppa
(@mrdieppa)
Active Member
Joined: 2 months ago
Posts: 13
Topic starter  

Kyle - This should be an easy question. Is there a way I can use multiple inputs in a math equation? I'm looking at controller_math.py and it seems like it could be pretty easy to add this functionality. Here the gist: My TDS sensor works great on my Arduino but it needs a temperature and scaling value to be accurate. I need to use a constant and a temperature variable for use within a formula to calibrate the TDS sensor and really get accurate readings. I already have a temperature sensor and the TDS sensors outputting data. Now I need to crunch some numbers based on both of the values to create my final PPM #.

Does this functionality already exist? I already poked through the documentation and couldn't find exactly what I'm looking for. If not, I'd like to take a shot at implementing it and submitting a PR if you don't see any breaking conflicts.

 

 

Phil Dieppa


Quote
mrdieppa
(@mrdieppa)
Active Member
Joined: 2 months ago
Posts: 13
Topic starter  

Alright - After further digging, I managed to get the extra input added to the page but now I'm running to a schema issue with the influxdb. I thought this sort of thing would happen. That's the huge benefit of a schemaless DB like mongodb. 

So... after some thought on possible implementation of two possible inputs within a single equation, I believe this would allow for very flexible and adhoc measurements.

Here's what my formula looks like right now. Maybe you can offer a different solution.

V = 1.275 (ADC voltage of a budget TDS sensor)

T = 22 (Temperature)

k = .75 (calibrated constant)

((133.42 * (V**3) - 255.86*(V**2) + 875*V) * k ) / (1 + .02 * (T - 25) ) - This gives me a calibrated measurement of a an Amazon-cheap TDS Sensor ( https://www.dfrobot.com/product-1662.html) connected via ADC with a 1WIRE DS18B20 temperature sensor. 

 

Just wondering if there is a better way to get this formula into Mycodo without rewriting some major changes. Thoughts?

Phil Dieppa


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

The Equation Math controller only supports a single measurement. To perform calculations on multiple measurements, the easiest way would be to create a custom Input module. However, there should be a better approach. You got me thinking and I set out to create a custom Function that takes two configurable measurements and saves a value with a user-set unit and measurement. I created an example function module you can import from the Configure -> Custom Functions page and then add from the Setup -> Functions page, however I had to update the codebase to allow the Measurement (e.g. temperature, humidity, acceleration) and Unit (e.g. C, F, percent, G) selections for the Function's custom_options. Everything seems to be working except one piece of the puzzle: allowing channels and measurements to be pulled from the Function module into other parts of the system (Dashboard widgets, Conditionals, PID controllers, etc.). This shouldn't be terribly difficult, but I'll need to chew on it a bit before I jump into implementing it.

Attached is the function I'm planning to add to the built-in set (renamed from .py to .txt in order to attach). Keep in mind you'll need to upgrade to master to be able to import/use it (commit f9c6350). Once I figure out this last piece, it will basically make the Math controllers obsolete and I'll work on porting them over to these single-file Function modules, which should also assist in users learning to build their own Functions.

Mycodo Developer


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

I had to take a slightly different approach, but I'm a bit closer to everything working. Here's the log output with both measurements and output working. Now to tie the measurement into the rest of the system.

2021-02-26 22:19:09,245 - INFO - mycodo.functions.function_multi_measurement_equation_40dd52f8 - Activated in 75.6 ms
2021-02-26 22:19:09,310 - DEBUG - mycodo.functions.function_multi_measurement_equation_40dd52f8 - Most recent timestamp and measurement for select_measurement_a: 2021-02-27T03:18:55.916569Z, 142.2032
2021-02-26 22:19:09,354 - DEBUG - mycodo.functions.function_multi_measurement_equation_40dd52f8 - Most recent timestamp and measurement for select_measurement_b: 2021-02-27T03:18:56.413132Z, 1.21
2021-02-26 22:19:09,355 - DEBUG - mycodo.functions.function_multi_measurement_equation_40dd52f8 - Equation: a*b = 142.2032*1.21
2021-02-26 22:19:09,355 - DEBUG - mycodo.functions.function_multi_measurement_equation_40dd52f8 - Output: 172.065872

Mycodo Developer


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

Success!

Mycodo Developer


ReplyQuote
mrdieppa
(@mrdieppa)
Active Member
Joined: 2 months ago
Posts: 13
Topic starter  

@kylegabriel - You implemented this much faster than I did. I was doing basically the same thing you did. I thought that this could sort of fall into a different category but I've been reading through other PR's and responses on the forum to get to understand your programming style a little better. I was trying to figure out a way to implement it without breaking existing functionality for other people who leverage the use of math controllers with a single input. I got stuck on the database but I feel like I was about 90% of the way there. The next problem was going to be displaying the data like you also mentioned. What would be the best way of displaying data from a multi-input equation... Hmm.

I'll switch branches and pull the latest master. I'll let you know how it turns out. Your screenshot reflects exactly what I'm trying to do. So hopefully this has more applications more than just my instance. Thanks!!

Phil Dieppa


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

I just pushed my latest changes (ee737f8). The new measurements/channels work similarly to how Inputs and Outputs use them, and I think it adds a lot to the system. I still need to go through and add references to Function measurements/channels throughout, but I've already added them to graph widgets and asynchronous graphs. There are a lot of other places to update, though.

Mycodo Developer


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

Now that I think about it, building a custom Input is probably your best option. There are a couple benefits to doing this over creating a Function:

  • Store three values at the time of the Input's execution (the two measurements and your calculated value).
  • Store the measurements as they occur, rather than relying on a periodic function separate from the Input to pull measurements from the database and perform a calculation on them.
  • Improve accuracy because the calculated value has a timestamp that is the same as when the two contributing values were acquired.

I still think the Function refactoring was very much needed and opens up a lot more options for users. Now there's this new functionality, I should start porting the Math controllers so I can eventually start phasing them out.

Mycodo Developer


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

I've been pondering this and realized what I've done is made Functions more like Inputs. Their only real difference at this point is their name (save a few small differences). They both have measurements and channels used for storing measurements and execute code at predefined intervals, with user custom options.

Mycodo Developer


mrdieppa liked
ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

BTW, I moved the custom multi-measurement function from the examples directory to the built-in directory so it will appear as a part of the built-in set, so you don't need to import it to try it out.

Mycodo Developer


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

Just pushed a commit that adds Function measurement support for the remaining widgets. Still quite a few more places to add to.

Mycodo Developer


ReplyQuote
mrdieppa
(@mrdieppa)
Active Member
Joined: 2 months ago
Posts: 13
Topic starter  

@kylegabriel - It's looking great! I ran a sample when I stepped out of the house and added in a formula to calculate compensation between two sensors. Looks great! 

I totally agree with the function versus input concept. It totally makes sense from a programatic standpoint. Functions (when compared to every programming language out there...) tend to produce an output that is generally used as an 'input' to other items. So... why not just use Functions for just that? I'll be honest. I was rather confused when I saw the term function in your application. That's the first spot I ran to when I needed to implement a custom behavior. I think your heading in the right direction here. Again, great job! 

 

Phil Dieppa


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 612
 

My general vision for each section of Mycodo is this:

Inputs: Receive information from systems (sensors, APIs, hardware, etc.) that is stored in the database.

Outputs: Send information out to manipulate systems (GPIOs, PWM, relays, motors, APIs, etc.).

Functions: Utilize stored data, Inputs, and Outputs to perform tasks.

There is some overlap between all of these, but if I have a new sensor I want to start acquiring measurements with, I will generally create an Input module, and similarly if I have a new chip to control a motor or something similar, I'll create an Output. For other things that may not fit nicely into either of those categories, I've usually delegated Functions for those tasks. There are also a set of abstract base classes that help each controller do its task bit better than the others. I get the sense that newcomers quickly pick up on the use of each and figure it out reasonably well.

As I've learned what works and what doesn't, I've tried to modify and adapt the system. It's sometimes challenging because I have to make drastic changes to users' database schemas, though I think it's generally been smooth. I've only made a few major releases that necessitated users abandoning their previous database in order to move to the next version. This now also occurs less often as I've become more skillful in making schema changes that are conducive to database upgrades and scripts that convert user data when necessary.

I'm always open to recommendations and feedback and learning, so let me know if you think something can be done better.

Mycodo Developer


ReplyQuote
mcfada
(@mcfada)
Active Member
Joined: 7 months ago
Posts: 12
 

@mrdieppa

 

Hi Mr D, could you share some screenshots of how you have this configured? I'm trying to set up the same sensors. I'm following the DFRobot Wiki, but it seems like there is some extra steps in the C++ code compared to what you wrote here. Thanks


ReplyQuote
mrdieppa
(@mrdieppa)
Active Member
Joined: 2 months ago
Posts: 13
Topic starter  

@mcfada

 

All I did was comb through the C++ code and rip out the formulas and fix it to what I needed. Here's the general setup..

 

You will need two Functions.

 

 

 

Calibrated EC

Single Measurement

Measurement A = TDS Sensor via MCP3008

Equation : (133.42 * (x**3) - 255.86*(x**2) + 875*x) * 0.75

NOTE: Ensure you Adjust the 0.75 K value in the equation based on your sensor's sensitivity with EC calibration solution

 

Temp Calibrated EC

Multi-Measure

Measurement A : Function for the Calibrated EC above

Measurement B : DS18B20

Equation : a / (1+0.02*(b-25))

 

Phil Dieppa


ReplyQuote