Calculating speed to interval reverse ratio - c++

This might be a slightly unusual question and I have a feeling this is a simple task and yet I struggle to find a solution.
I have an arduino project for controlling an valve based on rotational speed of a wheel. The valve needs to be opened in specific time intervals. I have a predefined maximum interval variable as well as minimum interval (both in seconds). I also have a minimum speed (in km/h), below which the valve will stay closed.
So let's assume:
min_v = 20;
max_interval = 60;
min_interval = 1;
All of the above values might possibly be change based on requirements.
How do I calculate the current opening interval based on current speed? Important thing to note is that the interval has to decrease as the speed increases.
Not sure if I also need to assume a max speed for this to be possible?

Ok so here's my formula that seems to be working:
currentInterval = maxOpeningInterval - ((maxOpeningInterval - minOpeningInterval) / (maxSpeed - minSpeed) * currentSpeed);

Related

How to determine the time an actuator has been enabled during the past x minutes?

I need to find the most efficient approach to the following. If someone can point me in the right direction, I can write the code myself.
Environment
I am using an ESP32 and working in Arduino C++.
What I want to achieve
I want to track the amount of time an actuator has been on over the past x minutes. This is to prevent the actuator from over-heating.
My idea
Storing current times in an array every time the actuator goes on (it is on for a fixed amount of time). When the oldest measurement is older than x minutes, it is removed from the array. If the array exceeds a certain size (e.g. certain amount of minutes the actuator has been on), a cool down period is started.
However, I feel there must be a more efficient / easy way to achieve this. How would you go about this?
Thanks in advance.
If possible, has temperature sensor is the easiest way.
With array, there will be problem with the size, especially, if you want to count in minutes. For counting, there is also way for easier as following:
T is the total time ON in last xx minutes as you expected. During initialization, it will be 0.
If actuator is ON, so every check cycle (may be every s or smaller depend on your required), T will be increase value = cycle time
If actuator is OFF: if T>0 then decrease value = cycle time, if T= 0, nothin to subtract more.

linear programming problem for minimum cost

A construction company has 6 projects, for each they need $d_i$ workers. The company has no workers at the beginning of project 1.
Each new worker must take a safety course that costs 300, and 50 more for each worker.
If there is no new worker there is no course.
Firing a worker does not cost any money, and a workers can't be rehired.
Given that the salary of a worker is 100 per project, formulate a linear programming problem that minimizes the workers costs.
What I tried:
Let $x_i$ be the number of new workers for project $i$.
Let $y_i$ be the number of old workers remaining from previous projects until project $i$ (all the workers hired - all the workers that were fired)
Let $z_i$ be an indicator such that $z_i =0 \iff x_i>0$
The function I'm trying to solve is:
$\min(\sum_{i=1}^6 150x_i + 300(1-z_i) + 100y_i)$
s.t:
\begin{align}
x_i,y_i,z_i &\ge 0 \\
z_i &\ge 1-x_i \\
y_i + x_i &\ge d_i \\
y_i &\ge y_{i-1} + x_i
\end{align}
Something feels not right to me. The main reason is that I tried to use matlab to solve this and it failed.
What did I do wrong? How can I solve this question?
When I see this correctly you have two small mistakes in your constraints.
The first appears when you use z_i >= 1-x_i. This allows z_i to take the value 1 all the time, which will never give you the extra cost of 300. You need to upper bound z_i such that z_i will not be 1 when you have x_i>0. For this constraint you need something called big M. For sufficiently large M you would then use z_i <= 1-x_i/M. This way when x_i=0 you can have z_i=1, otherwise the right hand side is smaller than 1 and due to integrality z_i has to be zero. Note that you usually want to choose M as tight as possible. So in your case d_i might be a good choice.
The second small mistake lays in y_i >= y_{i-1} + x_i. This way you can increase y_i over y_{i-1} without having to set any x_i. To force x_i to increase you need to flip the inequality. Additionally by the way you defined y_i this inequality should refer to x_{i-1}. Thus you should end up with y_i <= y_{i-1} + x_{i-1}. Additionally you need to take care of corner cases (i.e. y_1 = 0)
I think with these two changes it should work. Let me know whether it helped you. And if it still doesn't work I might have missed something.

Calculating download speed in libcurl?

So I've been using libcurl to have a little go with HTTP requests like GET, and I have managed to create the progress function callback to see how much has downloaded. However, what I don't know is the formula in order to calculate download speed as you go (similar to how browsers show you the download speed, eg Chrome).
I originally thought of using this:
downloadSpeed = amountCurrentlyDownloaded / secondsSinceDownloadStarted
Similar to the
speed = distance / time
formula. However, this isn't accurate. For example, if the download hasn't changed at all, downloadSpeed will go down slightly, but not down to zero.
So what is the correct formula to calculate download speed?
Think of a car. Do you want to know the average speed for the trip, or do you want to know your current speed? Your formula gives average speed.
Since you are receiving data in increments, you can't just do like a spedometer and see a current speed. Instead, maybe you could update every few seconds, and when you do, divide the number of chars since the
Last update by the time since the last update (need to use higher precision timer than seconds).
Perhaps you want to display both the current and average speeds. That's just a question of what will "feel" best to your users.

RRDTool Counter increment lower than time

I create a standard RRDTool database with a default step of 5mn (300s).
I have different types of values in it, some gauges which are easily processed, but I have other values I would have in COUNTER but here is my problem :
I read the data in a program, and get the difference between values over two steps is good but the counter increment less than time (It can increment by less than 300 during a step), so my out value is wrong.
Is it possible to change the COUNTER for not be a number by second but by step or something like that, if it's not I suppose I have to calculate the difference in my program ?
Thank you for helping.
RRDTool is capable of handling fractional values, so there is no problem if the counter increments by less than the seconds interval since the last update.
RRDTool stores everything as a Rate. If your DS is of type GAUGE, then RRDTool assumes that the incoming value is alreayd a rate, and only applies Data Normalisation (more on this later). If the type is COUNTER or DERIVE, then the value/timepoint you are updating with is compared to the previous value/timepoint to obtain a rate thus: r=(x2 - x1)/(t2 - t1). The rate obtained is then Normalised. The other DS type is ABSOLUTE, which assumes the counter was reset on the last read, giving r=x2/(t2 - t1).
The Normalisation step adjusts the data point based on assuming a linear progression from the last data point so that it lies exactly on an interval boundary. For example, if your step is 5min, and you update at 12:06, the data point is adjusted back to what it would have been at 12:05, and stored against 12:05. However the last unadjusted DP is still preserved for use at the next update, so that overall rates are correct.
So, if you have a 300s (5min) interval, and the value increased by 150, the rate stored will be 0.5.
If the value you are graphing is something small, e.g. 'number of pages printed', this might seem counterintuitive, but it works well for large rates such as network traffic counters (which is what RRDTool was designed for).
If you really do not want to display fractional values in the generated graphs or output, then you can use a format string such as %.0f to enforce no decimal places and the displayed number will be rounded to the nearest integer.

C++ arithmetic on time intervals

I already have working (ugly) code for this, but I will ask anyway:
I have the time intervals [09:15, 10:00), [21:10, 21:45) during weekdays. Given time t and a number of seconds s, if t is within the intervals, I have to calculate the date and time where t - s would fall into.
Example: t = 20130913 21:15, s = 600, t - s falls into 20130913 09:55.
Example: t = 20130923 09:16, s = 120, t - s falls into 20130920 21:44.
Is there a way of doing this in C++ cleanly (boost::icl? boost::date_time?)
I have tried boost::icl, it can certainly hold the time ranges in an interval_set<Time> and find which interval a certain Time is in, but if t - s time point does not fall into an interval range, I don't see how I can find the nearest interval before that time point, and how to detect if I have to go back a day or through the whole weekend.
I think the problem is too complicated to allow for a clean solution, at least according to my definition of "clean".
You'll need a container for your (non-overlapping) daily intervals, supporting efficiently the following operations:
find in which specific interval a given time belongs,
move an interval backwards, in the container, and
move to the last interval (in chronological order).
It seems to me that boost::icl::interval_set<Time> is an adequate solution. Your time does not need to keep track of the date, you can have that separately.
Your algorithm will be something like:
let d and t be the date and time portions of your t
let i be the interval where t belongs
loop
if t-s belongs in i then
return t-s on day d
else
let j be the previous interval from i
if j does not exist (because i was the first) then
let j be the last interval
move d one weekday backwards
s := s - (t-start(i))
t := end(j)
i := j
This is more or less what you say that your code does. I don't think it can be much cleaner.