I'm designing a machine that requires an automated ignition system. This project uses a motor control script that I wrote for Arduino.
I need to calculate the delay between ignition based on the percentage motor load.
These are the variables currently used
//Variables
int potentiometerIn; //RAW Potentiometer data variable
int potentiometerIn2; //Used in percent calculation, Will be == to potentiometerIn, just a different operation order
int potentiometerDivper; //Variable to hold percentage calculation (first step)
int potentiometerPer; // Holds the integer percent for motor speed IE: motor at 83% speed would have this value at 83
int potentiometerDiv;
int motorPin = (); //REPLACE () with PIN NUM
int motorRly = (); //Motor Positive pin () = pin num + Motor Pin
int motorNeg = (); //Motor Negative Pin () = pin num (Likely Not Needed)
int igniteRly = (); //Ignition Control Positive Pin
int igniteNeg = (); //Ignition Control Negative Pin (Likely Not Needed)
int ignitionTime = 0; // This will be used to set the time for an electric ignition.
int ignitionCalc = (); //This should be the time in seconds, that it takes for the machine to complete a full cycle with the motor set to 50%
// This enables/disables the ignition portion
int ignitionEnabled = true; // Default = True
if (ignitionEnabled == true)
{
ignitionCalc * 1000; //Converts the seconds to a format accepted by delay
50 / ignitionCalc = potentiometerPer / ignitionTime;
}
A quick summary for those who don't want to read all of my comments (I'm writing this code before the motor arrives so the values are all unset)
potentiometerPer > This is the percentage of power being supplied to the motor.
ignitionTime > This value will be used to set the delay between ignition firing
ignitionCalc > The amount of time in seconds for 1 cycle at 50% power.
I'm trying to figure out a way to calculate the delay for ignition with regards to what percentage the motor is currently set to. For example:
If motor percentage is 80 and the time per cycle is 5, then at 100% power the time per cycle is X (in this case 6.25)
I can't seem to figure out how to do proportions in C++, I'm rather new to the language and only started to learn it for this project.
Well since when the motor power is at 80%, the time per cycle you get is 5. So ignore the percentage, lets just say that when power level is 80, you get time per cycle as 5. Ratios in simpler words are just divisions. When 80 is divided by 16, you get 5. So what we know is the value 16 is going to remain constant. Similarly if you take any value of motor power, and divide by 16, you are going to get what you want. If this ratio is going to remain constant then it will be for all cases no matter what the motor power is. Im assuming that the ratio is going to remain constant.
So what you can do is -
float timePerCycle = potentiometerPer/16;
Related
I am having an issue with pinescript. Never used it before and havent coded in years so im very rusty.
I would love an opinion of why I am getting the error on line 21, which is the only 'else if' line in the block.
//#version=4
tradeDirection = input(direction.up, "Trade Direction") // direction of the breakout (up or down)
breakoutPeriod = input(14, "Breakout Period") // number of bars to look back for the breakout
stopLoss = input(0.002, "Stop Loss") // stop loss in percentage of the trade value
takeProfit = input(0.004, "Take Profit") // take profit in percentage of the trade value
maxTrades = input(2, "Maximum Number of Trades") // maximum number of trades to have open at the same time
maxRisk = input(0.01, "Maximum Risk per Trade") // maximum risk per trade in percentage of the account value
// Next, we create a variable to track the highest or lowest price in the breakout period
breakoutPrice = tradeDirection == direction.up ? highest(high, breakoutPeriod) : lowest(low, breakoutPeriod)
// Then, we check if the current price has broken out of the breakout period and if we have not reached the maximum number of open trades
if (tradeDirection == direction.up and close > breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a long position with the calculated trade size
strategy.entry("Long", strategy.long, tradeSize)
else if (tradeDirection == direction.down and close < breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a short position with the calculated trade size
strategy.entry("Short", strategy.short, tradeSize)
// Finally, we set our stop loss and take profit levels
strategy.exit("Stop Loss", "Long", stopLossType.percent, stopLoss)
strategy.exit("Take Profit", "Long", profitType.percent, takeProfit)
// We repeat the same process for the short position
strategy.exit("Stop Loss", "Short", stopLossType.percent, stopLoss)
strategy.exit("Take Profit", "Short", profitType.percent, takeProfit)
I've looked around at other versions to see if its just a version issue but nothing that gives me a reaosn why its erroring out.
I get the feeling its something before or within the else if statement.
I retyped your script so it would compile and have no warnings or errors. One problem was the indentation was missing on the if and else. Another problem was the direction.up variable was missing. It is not allowed to have a . in a variable name. Another problem was that strategy("breakout strat") was missing, so I added it. The logic in the code I typed is probably wrong, but there are no errors.
//#version=4
strategy("breakout strat")
tradeDirection = input(true, "Trade Direction") // direction of the breakout (up=true or down=false)
breakoutPeriod = input(14, "Breakout Period") // number of bars to look back for the breakout
stopLoss = input(0.002, "Stop Loss") // stop loss in percentage of the trade value
takeProfit = input(0.004, "Take Profit") // take profit in percentage of the trade value
maxTrades = input(2, "Maximum Number of Trades") // maximum number of trades to have open at the same time
maxRisk = input(0.01, "Maximum Risk per Trade") // maximum risk per trade in percentage of the account value
// Next, we create a variable to track the highest or lowest price in the breakout period
breakoutPrice = tradeDirection == true ? highest(high, breakoutPeriod) : lowest(low, breakoutPeriod)
// Then, we check if the current price has broken out of the breakout period and if we have not reached the maximum number of open trades
if (tradeDirection == true and close > breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a long position with the calculated trade size
strategy.entry("Long", strategy.long, tradeSize)
else if (tradeDirection == false and close < breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a short position with the calculated trade size
strategy.entry("Short", strategy.short, tradeSize)
// Finally, we set our stop loss and take profit levels
strategy.exit("Stop Loss", "Long", loss=stopLoss)
strategy.exit("Take Profit", "Long", loss=takeProfit)
// We repeat the same process for the short position
strategy.exit("Stop Loss", "Short", loss=stopLoss)
strategy.exit("Take Profit", "Short", loss=takeProfit)
Put an indentation on line 21 to get rid of this error :
if .....
----> First block
else if
----> Other block
In your code other indentations are missing, and other error are present (direction.up doesn't exist for example... but you should ask another question for another error)
I am trying to teach myself c++.
On Sololearn I have a task, which is
You are making a program for a bus service.
A bus can transport 50 passengers at once.
Given the number of passengers waiting in the bus station as input, you need to calculate and output how many empty seats the last bus will have.
Sample Input: 126
Sample Output: 24
It also says I should use the "%" operator.
This is the code I created:
int bus = 50;
int stop;
cin >> stop;
cout<< stop % bus;
return 0;
I get 12.
What is the correct way? I'm finding it difficult to understand what the modulo operator does. My understanding is that it divides as many times as it can and leaves the remainder (i.e. 16 % 3 = 1).
First you have to get the number of passengers
int passengers; cin >> passengers;
then you have to find how many passengers are left
int remainPass = passengers % 50;
then you have to find how many seats are left
int remainSeats = 50 - remainPass;
Modulos operator basically represents the leftover from the division
so what we need to do is take the number of people that will remain in the last bus travel which is stop % bus and compute bus - (stop % bus)
that way we know the number of empty seats on the last travel
This is like each bus was filled to the fullest (50 people per bus) what will remain is 26 and so on the last bus the number of empty seats will be 50 - 26 = 24
PS: 12 doesn't seem to be the right output of 126 % 50 it should be 26
I want to write a function that gets a time series and a standard deviation as parameters and returns an adjusted time series which looks like a forecast.
With this function I want to test a system for stability, which gets a forecasted time series list for weather as input parameter.
My approach for such a function, which is described below:
vector<tuple<datetime, double>> get_adjusted_timeseries(vector<tuple<datetime, double>>& timeseries_original, const double stddev, const double dist_mid)
{
auto timeseries_copy(timeseries_original);
int sign = randInRange(0, 1) == 0 ? 1 : -1;
auto left_limit = normal_cdf_inverse(0.5 - dist_mid, 0, stddev);
auto right_limit = normal_cdf_inverse(0.5 + dist_mid, 0, stddev);
for (auto& pair : timeseries_copy)
{
double number;
do
{
nd_value = normal_distribution_r(0, stddev);
}
while (sign == -1 && nd_value > 0.0 || sign == 1 && nd_value < 0.0);
pair = make_tuple(get<0>(pair), get<1>(pair) + (nd_value / 100) * get<1>(pair));
if (nd_value > 0.0 && nd_value < right_limit || nd_value < 0.0 && nd_value > left_limit)
{
sign = sign == -1 ? 1 : -1;
}
}
return timeseries_copy;
}
Make a copy from the original time series, which is also from type vector<tuple<datetime, double>>
Get a random number that is either 0 or 1 and use the number to set the sign.
Use the Inverse Cumulative distribution function to get the limits, which indicate when the sign is changed. The sign is changed when the value of the copied time series is close to the original value. The implementation of the inverse CDF is shown here
For-loop for each item in the time series:
get a normal distributed value, which should be lower zero when sign == -1 and greater zero when sign == 1
adjust old value of time series according to the normal distributed
value
change sign if the normal distributed value is close to the original value.
The result for a low standard deviation, for example, can be seen here in yellow:
If the mean absolute percentage error (MAPE) of the two time series is calculated, the following relationship results:
stddev: 5 -> MAPE: ~0.04
stddev: 10 -> MAPE: ~0.08
stddev: 15 -> MAPE: ~0.12
stddev: 20 -> MAPE: ~0.16
What do you think of this approach?
Can this function be used to test a system that has to deal with predicted time series?
You want to generate time series data that behave like some existing time series data that you have from real phenomena (weather and stock exchange). That generated time series data will be fed into some system to test its stability.
What you could do is: fit some model to your exiting data, and then use that model to generate data that follow the model, and hence your existing data. Fitting data to a model yields a set of model parameters and a set of deviations (differences not explained by the model). The deviations may follow some known density function but not necessarily. Given the model parameters and deviations, you can generate data that look like the original data. Note that if the model does not explain the data well, deviations will be large, and the data generated with the model will not look like the original data.
For example, if you know your data is linear, you fit a line through them, and your model would be:
y = M x + B + E
where E is a random variable that follows the distribution of the error around the line that fits your data, and where M and B are the model parameters. You can now use that model to generate (x, y) coordinates that are rougly linear. When sampling the random variable E, you can assume that it follows some known distribution like a normal distribution, or use an histogram, to generate deviations that follow arbitrary density functions.
There are several time series models that you could use to fit your weather and stock exchange data. You could look at exponential smoothing. It has several different models. I am sure you can find many other models on Wikipedia.
If a model does not fit well your data, you can also see its parameters as random variables. In our example above, suppose that we have observed data where it seems that the slope is changing. We would fit several lines and obtain a distribution for M. We would then sample that variable along with E when generating data.
Let say I've a system that distribute 8820 values into 96 values, rounding using Banker's Round (call them pulse). The formula is:
pulse = BankerRound(8820 * i/96), with i[0,96[
Thus, this is the list of pulses:
0
92
184
276
368
459
551
643
735
827
919
1011
1102
1194
1286
1378
1470
1562
1654
1746
1838
1929
2021
2113
2205
2297
2389
2481
2572
2664
2756
2848
2940
3032
3124
3216
3308
3399
3491
3583
3675
3767
3859
3951
4042
4134
4226
4318
4410
4502
4594
4686
4778
4869
4961
5053
5145
5237
5329
5421
5512
5604
5696
5788
5880
5972
6064
6156
6248
6339
6431
6523
6615
6707
6799
6891
6982
7074
7166
7258
7350
7442
7534
7626
7718
7809
7901
7993
8085
8177
8269
8361
8452
8544
8636
8728
Now, suppose the system doesn't send to me these pulses directly. Instead, it send these pulse in 8820th (call them tick):
tick = value * 1/8820
The list of the ticks I get become:
0
0.010430839
0.020861678
0.031292517
0.041723356
0.052040816
0.062471655
0.072902494
0.083333333
0.093764172
0.104195011
0.11462585
0.124943311
0.13537415
0.145804989
0.156235828
0.166666667
0.177097506
0.187528345
0.197959184
0.208390023
0.218707483
0.229138322
0.239569161
0.25
0.260430839
0.270861678
0.281292517
0.291609977
0.302040816
0.312471655
0.322902494
0.333333333
0.343764172
0.354195011
0.36462585
0.375056689
0.38537415
0.395804989
0.406235828
0.416666667
0.427097506
0.437528345
0.447959184
0.458276644
0.468707483
0.479138322
0.489569161
0.5
0.510430839
0.520861678
0.531292517
0.541723356
0.552040816
0.562471655
0.572902494
0.583333333
0.593764172
0.604195011
0.61462585
0.624943311
0.63537415
0.645804989
0.656235828
0.666666667
0.677097506
0.687528345
0.697959184
0.708390023
0.718707483
0.729138322
0.739569161
0.75
0.760430839
0.770861678
0.781292517
0.791609977
0.802040816
0.812471655
0.822902494
0.833333333
0.843764172
0.854195011
0.86462585
0.875056689
0.88537415
0.895804989
0.906235828
0.916666667
0.927097506
0.937528345
0.947959184
0.958276644
0.968707483
0.979138322
0.989569161
Unfortunately, between these ticks it sends to me also fake ticks, that aren't multiply of original pulses. Such as 0,029024943, which is multiply of 256, which isn't in the pulse lists.
How can I find from this list which ticks are valid and which are fake?
I don't have the pulse list to compare with during the process, since 8820 will change during the time, so I don't have a list to compare step by step. I need to deduce it from ticks at each iteration.
What's the best math approch to this? Maybe reasoning only in tick and not pulse.
I've thought to find the closer error between nearest integer pulse and prev/next tick. Here in C++:
double pulse = tick * 96.;
double prevpulse = (tick - 1/8820.) * 96.;
double nextpulse = (tick + 1/8820.) * 96.;
int pulseRounded=round(pulse);
int buffer=lrint(tick * 8820.);
double pulseABS = abs(pulse - pulseRounded);
double prevpulseABS = abs(prevpulse - pulseRounded);
double nextpulseABS = abs(nextpulse - pulseRounded);
if (nextpulseABS > pulseABS && prevpulseABS > pulseABS) {
// is pulse
}
but for example tick 0.0417234 (pulse 368) fails since the prev tick error seems to be closer than it: prevpulseABS error (0.00543795) is smaller than pulseABS error (0.0054464).
That's because this comparison doesn't care about rounding I guess.
NEW POST:
Alright. Based on what I now understand, here's my revised answer.
You have the information you need to build a list of good values. Each time you switch to a new track:
vector<double> good_list;
good_list.reserve(96);
for(int i = 0; i < 96; i++)
good_list.push_back(BankerRound(8820.0 * i / 96.0) / 8820.0);
Then, each time you want to validate the input:
auto iter = find(good_list.begin(), good_list.end(), input);
if(iter != good_list.end()) //It's a match!
cout << "Happy days! It's a match!" << endl;
else
cout << "Oh bother. It's not a match." << endl;
The problem with mathematically determining the correct pulses is the BankerRound() function which will introduce an ever-growing error the higher values you input. You would then need a formula for a formula, and that's getting out of my wheelhouse. Or, you could keep track of the differences between successive values. Most of them would be the same. You'd only have to check between two possible errors. But that falls apart if you can jump tracks or jump around in one track.
OLD POST:
If I understand the question right, the only information you're getting should be coming in the form of (p/v = y) where you know 'y' (that's each element in your list of ticks you get from the device) and you know that 'p' is the Pulse and 'v' is the Values per Beat, but you don't know what either of them are. So, pulling one point of data from your post, you might have an equation like this:
p/v = 0.010430839
'v', in all the examples you've used thus far, is 8820, but from what I understand, that value is not a guaranteed constant. The next question then is: Do you have a way of determining what 'v' is before you start getting all these decimal values? If you do, you can work out mathematically what the smallest error can be (1/v) then take your decimal information, multiply it by 'v', round it to the nearest whole number and check to see if the difference between its rounded form and its non-rounded form falls in the bounds of your calculated error like so:
double input; //let input be elements in your list of doubles, such as 0.010430839
double allowed_error = 1.0 / values_per_beat;
double proposed = input * values_per_beat;
double rounded = std::round(proposed);
if(abs(rounded - proposed) < allowed_error){cout << "It's good!" << endl;}
If, however, you are not able to ascertain the values_per_beat ahead of time, then this becomes a statistical question. You must accumulate enough data samples, remove the outliers (the few that vary from the norm) and use that data. But that approach will not be realtime, which, given the terms you've been using (values per beat, bpm, the value 44100) it sounds like realtime might be what you're after.
Playing around with Excel, I think you want to multiply up to (what should be) whole numbers rather than looking for closest pulses.
Tick Pulse i Error OK
Tick*8820 Pulse*96/8820 ABS( i - INT( i+0.05 ) ) Error < 0.01
------------ ------------ ------------- ------------------------ ------------
0.029024943 255.9999973 2.786394528 0.786394528 FALSE
0.0417234 368.000388 4.0054464 0.0054464 TRUE
0 0 0 0 TRUE
0.010430839 91.99999998 1.001360544 0.001360544 TRUE
0.020861678 184 2.002721088 0.002721088 TRUE
0.031292517 275.9999999 3.004081632 0.004081632 TRUE
0.041723356 367.9999999 4.005442176 0.005442176 TRUE
0.052040816 458.9999971 4.995918336 0.004081664 TRUE
0.062471655 550.9999971 5.99727888 0.00272112 TRUE
0.072902494 642.9999971 6.998639424 0.001360576 TRUE
0.083333333 734.9999971 7.999999968 3.2E-08 TRUE
The table shows your two "problem" cases (the real wrong value, 256, and the one your code gets wrong, 368) followed by the first few "good" values.
If both 8820s vary at the same time, then obviously they will cancel out, and i will just be Tick*96.
The Error term is the difference between the calculated i and the nearest integer; if this less than 0.01, then it is a "good" value.
NOTE: the 0.05 and 0.01 values were chosen somewhat arbitrarily (aka inspired first time guess based on the numbers): adjust if needed. Although I've only shown the first few rows, all the 96 "good" values you gave show as TRUE.
The code (completely untested) would be something like:
double pulse = tick * 8820.0 ;
double i = pulse * 96.0 / 8820.0 ;
double error = abs( i - floor( i + 0.05 ) ) ;
if( error < 0.05 ) {
// is pulse
}
I assume your initializing your pulses in a for-loop, using int i as loop variable; then the problem is this line:
BankerRound(8820 * i/96);
8820 * i / 96 is an all integer operation and the result is integer again, cutting off the remainder (so in effect, always rounding towards zero already), and BankerRound actually has nothing to round any more. Try this instead:
BankerRound(8820 * i / 96.0);
Same problem applies if you are trying to calculate prev and next pulse, as you actually subtract and add 0 (again, 1/8820 is all integer and results in 0).
Edit:
From what I read from the commments, the 'system' is not – as I assumed previously – modifiable. Actually, it calculates ticks in the form of n / 96.0, n ∊ [0, 96) in ℕ
however including some kind of internal rounding appearently independent from the sample frequency, so there is some difference to the true value of n/96.0 and the ticks multiplied by 96 do not deliver exactly the integral values in [0, 96) (thanks KarstenKoop). And some of the delivered samples are simply invalid...
So the task is to detect, if tick * 96 is close enough to an integral value to be accepted as valid.
So we need to check:
double value = tick * 96.0;
bool isValid
= value - floor(value) < threshold
|| ceil(value) - value < threshold;
with some appropriately defined threshold. Assuming the values really are calculated as
double tick = round(8820*i/96.0)/8820.0;
then the maximal deviation would be slightly greater than 0.00544 (see below for a more exact value), thresholds somewhere in the sizes of 0.006, 0.0055, 0.00545, ... might be a choice.
Rounding might be a matter of internally used number of bits for the sensor value (if we have 13 bits available, ticks might actually be calculated as floor(8192 * i / 96.0) / 8192.0 with 8192 being 1 << 13 &ndash and floor accounting to integer division; just a guess...).
The exact value of the maximal deviation, using 8820 as factor, as exact as representable by double, was:
0.00544217687075132516838493756949901580810546875
The multiplication by 96 is actually not necessary, you can compare directly with the threshold divided by 96, which would be:
0.0000566893424036596371706764330156147480010986328125
I wanted to write a program that returns how many months we could survive when we're given
our monthly expenditure, amount of disposable income, and interest rate (all in integers).
For instance, if we start with disposable income = 1000, interest rate = 5%, monthly expenditure = 100, then
after first month: 1000*1.05 - 100 = 950, we have 950 dollars left
after second month: = 950*1.05 - 100 = 897.5
and so on, and in the end, we can survive 14 months.
I wrote the following code in C++:
int main(){
int i=0;
int initialValue;
int interest;
int monthly;
double value=1.0*initialValue;
double r=1+1.0*interest/100;
while(value > 0){
if(value < monthly){
break;
}
else
{
value=value*r-monthly;
i++;
}
};
cout<<i;
return 0;
}
but for sufficiently large values of initialValue and small values of monthly, the program I wrote runs very slowly to the degree that it's unusable. Is there a problem with the code that makes it run not well (or very slow)?
Any help would be greatly appreciated.
double cannot store numbers precisely. One consequence of this is when you subtract a very small number from a very large number, the result is not changed from the original large value.
One solution to this problem is to use an int to do your calculations. Think of the values as the number of pennies, rather than the number of dollars.
A few notes:
The *1.0's are pointless. Instead, take advantage of implicit and explicit casts:
double value=initialValue;
double r=1+(double)interest/100;
++i is faster than i++.
value=value* can be rewritten as value*=.
You can mix the first two conditionals. Remove the if...break and change the while loop to while (value > 0 && value < monthly).
On the face of it, the reason this runs slowly is the large number of iterations. However, you didn't specify any specific numbers and I would expect this code to be able to execute at least a million iterations per second on any reasonably fast processor. Did you really expect to need to calculate more than 1 million months?
Apart from the novice style of the code, the underlying problem is the algorithm. There are very simple formulae for making these calculations, which you can find here: https://en.wikipedia.org/wiki/Compound_interest. Your situation is akin to paying off a loan, where running out of money equals loan paid off.