Frequency from binary input - java

Background: I have a IOIO which I am using to measure the output from an photodiode, this is the converted into a digital output. I need to find the frequency at which the signal changes between 1 and 0. Everything I have tryed so far has hanged my test app, any suggestions?
current code:
if(diode == 1 && frequencyFound == false){
startTime = System.currentTimeMillis();
while((frequencyFound == false)){
if(diode == 0){
while(frequencyFound == false){
if(diode == 1){
double endTime = System.currentTimeMillis();
time = endTime - startTime;
frequency = (long) (1.0 / time);
frequencyFound = true;
}
Thread.sleep(100);
}
}
Thread.sleep(100);
}
}

There are a couple of issues here.
First, Android is a multi-tasking system, and you could find your timing thread put to sleep long enough to miss some signal transitions. Is there no way to be notified of a leading (or trailing) edge transition rather than sampling the input in a loop?
What sort of frequency are you looking at? Will a 100 ms sampling interval be fine enough?
Don't count on Thread.sleep() to sleep for exactly the time you specify. If the interval is too short, the system might decide to return immediately or it might round the sleep time up to a larger amount.
Your timing loop won't record the time to any precision better than 100ms (at best), so your estimate for the frequency will be very poor.
Zapl is right, you MUST run this from a separate thread from your UI thread.
Watching for a single transition will give you a very imprecise estimate of the frequency. Try something like this instead:
// Find frequency to the nearest hz (+/- 10%)
// It's assumed that some other process is responsible for updating the "diode"
// variable. "diode" must be declared volatile.
long duration = 1000; // 1 second
final int interval = 100; // sampling inteval = .1 second
int oldState = diode;
int count = 0;
final long startTime = System.currentTimeMillis();
final long endtime = startTime + duration;
while (System.currentTimeMillis() < endtime) {
// count all transitions, both leading and trailing
if (diode != oldState) {
++count;
oldState = diode;
}
Thread.sleep(interval);
}
// find the actual duration
duration = System.currentTimeMillis() - startTime;
// Compute frequency. The 0.5 term is because we were counting both leading and
// trailing edges.
float frequency = 0.5 * count / (duration/1000);

Two more extreme suggestions for working around some of the timing accuracy concerns Edward raised:
Do the measurement of interval times on the IOIO board under interrupts, where you can presumably accomplish (at least near-) real time operations. Report these time measurements to the Android device.
Skip the ioio board and build something simple to route the signal into the headset connector as a tone that turns on or off. Record audio using the built-in timing guarantees of the audio system, and then analyze the audio buffers (real time no longer required) to determine the intervals from the number of intervening audio samples times in units of the (relatively reliable compared to anything you could do in an android app) audio sample rate. You can also get an analog input easily by using the light sensor to vary the frequency of an audio oscillator.

Related

How to run a For Loop for 60 seconds maximum irrespective of the size of the loop and complete all the iterations

for(i=1;i<list.size();i++){
//do something
//For Eg: move marker to a new position on the map
}
I want the above loop to complete all the iterations irrespective of the size of the list and also want the entire task to run for 1 minute. (60 seconds)
I don't really know if this is what you want but I hope this helps.
import java.util.concurrent.TimeUnit;
for(i=1;i<list.size();i++){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Execute thing you want to be executed every second
}
As explanation: you iterate through the for loop and the thread waits for one second before executing the code after the TimeUnit.SECONDS.sleep(1);.
If the list's size is 60 it would therefore take a minute for the loop to end.
Edit: It has occurred to me that it might be smarter to do a try-catch around the sleep function.
You can, for example, use System.nanoTime() to measure the duration of your loop, and then use TimeUnit.NANOSECONDS.sleep(...) to make it wait for the rest of time like this:
long start = System.nanoTime();
long desiredDuration = 60 * 1000 * 1000;
// your loop goes here
long duration = System.nanoTime() - start;
if (duration < desiredDuration)
TimeUnit.NANOSECONDS.sleep(desiredDuration - duration);
The best possible solution is to compute the desired time first and then run the loop to that extent.
long finish=System.currentTimeMillis() + 60000;
while(System.currentTimeMillis() != finish)
{
//statements;
//statements;
}
If you are trying to equip the CPU and keep it idle for this time the process is known as busy waiting but is not considered convenient in many cases so i recommend to use Thread.sleep(duration) for this purpose.
Would like to receive further queries from your side.
To spread N amount of invocations uniformly across a minute, you'll have to set the delay in between the invocations to the value 60/(N-1). The -1 is optional but causes the first and last invocations to be exactly 60 seconds apart. (just like how a ladder with N rungs has N-1 spaces)
Of course, using sleep() with the number calculated above is not only subject to round-off errors, but also drift, because you do stuff between the delays, and that stuff also takes time.
A more accurate solution is to subtract the time at which each invocation should occur (defined by startTime + 60*i/(N-1)) from the current time. Reorder and reformulate those formulas and you can subtract the 'time that should have elapsed for the next invocation' from the already elapsed time.
Of course 'elapsed time' should be calculated using System.nanoTime() and not System.currentTimeMillis() as the latter can jump when the clock changes or the computer resumes from stand-by.
For this example I changed 60 seconds to 6 seconds so you can more easily see what's going on when you run it.
public static void main(String... args) throws Exception {
int duration = 6; // seconds
List<Double> list = IntStream.range(0, 10).mapToDouble(i->ThreadLocalRandom.current().nextDouble()).boxed().collect(Collectors.toList());
long startTime = System.nanoTime();
long elapsed = 0;
for (int i = 0; i < list.size(); i++) { // Bug fixed: start at 0, not at 1.
if (i > 0) {
long nextInvocation = TimeUnit.NANOSECONDS.convert(duration, TimeUnit.SECONDS) * i / (list.size() - 1);
long sleepAmount = nextInvocation - elapsed;
TimeUnit.NANOSECONDS.sleep(sleepAmount);
}
elapsed = System.nanoTime() - startTime;
doSomething(elapsed, list.get(i));
}
}
private static void doSomething(long elapsedNanos, Double d) {
System.out.println(elapsedNanos / 1.0e9f + "\t" + d);
}
Of course when the task you preform per list element takes longer than 60/(N-1) seconds, you get contention and the 'elapsed time' deadlines are always exceeded. With this algorithm the total time just taking longer than a mnute. However if some earlier invocations exceed the deadline, and later invocations take much less time than 60/(N-1), this algorithm will show 'catch-up' behavior. This can be partially solved by sleeping at least a minimum amount even when sleepAmount is less.
Check out this.
long start = System.currentTimeMillis();
long end = start + 60*1000; // 60 seconds * 1000 ms/sec
int i = 0;
while (System.currentTimeMillis() < end)
{
// do something, iterate your list
i++;
if (i == list.size()) { // check size of the list if iteration is completed
// if time has not yet expired, sleep for the rest of the time
Thread.sleep(end - System.currentTimeMillis());
}
}
Do not forget checking size of the list.

How do I end a method in Java after a certain amount of time?

I would like to force a method to end after a certain amount of time even if it has not completed its task. How would I go about doing this?
Edit (added clarification and code):
I am programming a robot using Android Studio for the FTC (First Tech Challenge) robotics competition. To control the robot, I am using the FTC SDK (see https://github.com/ftctechnh/ftc_app).
The method works fine for going a particular distance and then stopping but after it stops by setting the power of all the motors to zero, it appears to get hung and no subsequent methods are invoked. Currently, it is only supposed to have the motors be stopped for one second before exiting but it appears to still get stuck on the first invocation of the method that sets the motor power to zero (setPower). For this reason, I would like to be able to terminate setPower after it has been running for a certain amount of time so that my method can exit and subsequent methods can be invoked.
Here is my method:
public void moveLine(DcMotor m1, DcMotor m2, DcMotor m3, DcMotor m4, double distance /* distance to move in meters */, double motorPower /* power to set the motors */) {
final double SPROCKET_CIRCUMFRENCE = Math.PI * 0.0652; //calculates the circumference of the sprocket
final int ENCODER_CPR_NR60 = 1680; //encoder counts for NeveRest 60
//final static int ENCODER_CPR_NR40 = 1120; //encoder counts for NeveRest 40
double amountOfRotationsCalc = distance / SPROCKET_CIRCUMFRENCE; //calculates the amount of rotations to move to reach the target distance
double amountOfEncUnitsCalc = ENCODER_CPR_NR60 * amountOfRotationsCalc; //calculates the amount of encoder units to move
//this gets the sum of the encoder positions of the drive motors
int currentEncPosSum = m1.getCurrentPosition() + m2.getCurrentPosition() + m3.getCurrentPosition() + m4.getCurrentPosition();
//this gets the average encoder position
int currentEncPosAvg = currentEncPosSum / 4;
//if the robot is supposed to be moving forward (positive distance), the motors will be set to positive values
if (distance > 0) {
//it may make sense to make this a while loop. Will this fix the issue?
if (currentEncPosAvg < amountOfEncUnitsCalc) {
m1.setPower(motorPower);
m2.setPower(motorPower);
m3.setPower(motorPower);
m4.setPower(motorPower);
} else {
//these stop the robot. Without them, it continues to move.
long start = System.currentTimeMillis();
long end = start + 1000;
while (System.currentTimeMillis() < end) {
m1.setPower(0);
m2.setPower(0);
m3.setPower(0);
m4.setPower(0);
}
return; //this is supposed to exit this method
}
} else {
//this is essentially the opposite of the code for going forwards
if (currentEncPosAvg > amountOfEncUnitsCalc) {
m1.setPower(-motorPower);
m2.setPower(-motorPower);
m3.setPower(-motorPower);
m4.setPower(-motorPower);
} else {
//these stop the robot. Without them, it continues to move.
long start = System.currentTimeMillis();
long end = start + 1000;
while (System.currentTimeMillis() < end) {
m1.setPower(0);
m2.setPower(0);
m3.setPower(0);
m4.setPower(0);
}
return;
}
}
}
long beginning = System.currentTimeMillis();
long end=beginning + yourTimeInMilliseconds;
while (end > System.currentTimeMillis()){
//your code here
}
I believe this is what you mean.
Some clarification, if you need any:
beginning is the current time in milliseconds.
end is obviously when it ends. (Start time plus delay)
While the time is still less than the set end time, the code keeps going.
I know this question is a bit old, but in the latest ftc_app Android SDKs it is recommended that for time aware methods and procedures that teams use the ElapsedTime class.
The most important thing to consider when pausing an opmode is that you can still shut it down when the stop button is pressed on the driver station app. you can make sure of this by including the opModeIsActive() method in your while condition
On our team we have a method for pausing OpModes that looks something like this. we have this declared in a separate class used for library purposes.
public static void pauseOpMode(LinearOpmode op, ElapsedTime et, double waitTime){
double startTime = et.milliseconds();
while (op.opModeIsActive() && et.milliseconds() < startTime + waitTime){}
}
Now that this method exists, in our OpMode we can create an Elapsed time Object and pass the necessarry parameters to the function required to pause the OpMode
class someOpMode extends LinearOpMode{
ElapsedTime gameTimer = new ElapsedTime();
#Override
public void RunOpMode(){
//pause program for 5 seconds
pauseOpMode(this,gameTimer,5000);
}
}

Why this while loop cannot print 1,000 times per seconds?

The following Java method is meant to print the number i by nLoopsPerSecond times per second for seconds seconds:
public void test(int nLoopsPerSecond, int seconds) {
double secondsPerLoop = 1.0/(double)nLoopsPerSecond;
long startTime = System.currentTimeMillis();
long currentTime;
int i = 0;
while ((currentTime = System.currentTimeMillis()) < startTime + seconds*1000) {
System.out.println(i++);
while (System.currentTimeMillis() < currentTime + secondsPerLoop*1000);
}
}
With the following call:
test(1000,1);
I expect this method to do the System.out.println(i++); 1,000 times, but I only got 63.
When I try to see how many seconds it actually use per loop with this code
public void test(int nLoopsPerSecond, int seconds) {
double secondsPerLoop = 1.0/(double)nLoopsPerSecond;
long startTime = System.currentTimeMillis();
long currentTime;
int i = 0;
while ((currentTime = System.currentTimeMillis()) < startTime + seconds*1000) {
while (System.currentTimeMillis() < currentTime + secondsPerLoop*1000);
System.out.println(System.currentTimeMillis() - currentTime);
}
}
I expect it to print 1 milliseconds each loop, but it prints 15 or 16 milliseconds.
Please suggest what is wrong in my code.
Are you running on Windows, perhaps? System.currentTimeMillis() consults the underlying operating system clock, which is only 60Hz on many versions of Windows.
Try System.nanoTime() since you are not measuring time since the epoch. System.currentTimeMillis vs System.nanoTime
That's probably because the processing takes up some time. The processor does not solely dedicate its time to the execution of your program, it performs several other functions in the background. So you might get different results based on the processor load.
Your output console is not fast enough. You do not mention how you run your test and where the output goes. The speed of the terminal and buffers (not) used will limit how fast can the program output data. If running unbuffered, your program will always have to wait, until the new line is printed on screen. If the console waits for screen redraw and screen is redrawn at 60Hz, you've got your 16ms/line and about 60 lines per second.
Running your code without inner loop inside IntelliJ Idea, I get about 140.000 lines per second (and Idea warns me, that it is not displaying every line, as my output is too fast).
With the inner loop, I get about 800-900 lines. That happens because the process may be scheduled out of cpu, or blocked because of something else, like swapping. (If I simplify a lot, usually desktop OSes schedule in 1ms granularity.)

Exact timing in Java game loop

I'm developing a network based game, and I'm now focusing on the server side simulation. Of course I need a game loop, and I opted for a fixed timestep loop so that it will be far easier to reproduce on the client(s) than a variable timestep one. I also decided to run my game at 60 Hz. This is the game logic speed, not rendering speed. Rendering will be handled with a variable timestep loop in the clients to have the best possible rendering.
The server is written in Java.
I already made an example game loop using code from http://www.java-gaming.org/index.php?topic=24220.0 and modifying the loop with my code. Here is the loop:
private void gameLoop()
{
final double GAME_HERTZ = 60.0;
final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
//We will need the last update time.
double lastUpdateTime = System.nanoTime();
//Store the last time we rendered.
double lastRenderTime = System.nanoTime();
int lastSecondTime = (int) (lastUpdateTime / 1000000000);
long extraSleepTime = 0;
while (running)
{
int updateCount = 0;
if (!paused)
{
long loopStartTime = System.nanoTime();
updateGame();
updateCount++;
long timeAfterUpdate = System.nanoTime();
lastUpdateTime = timeAfterUpdate;
//Render. To do so, we need to calculate interpolation for a smooth render.
float interpolation = Math.min(1.0f, (float) ((loopStartTime - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
drawGame(interpolation);
lastRenderTime = loopStartTime;
//Update the frames we got.
int thisSecond = (int) (lastUpdateTime / 1000000000);
if (thisSecond > lastSecondTime)
{
long nanoTime = System.nanoTime();
System.out.println("NEW SECOND " + thisSecond + " " + frameCount + ": " + (nanoTime - lastNanoTime));
lastNanoTime = nanoTime;
fps = frameCount;
frameCount = 0;
lastSecondTime = thisSecond;
}
long loopExecutionTime = timeAfterUpdate - loopStartTime;
long sleepTime = (long)TIME_BETWEEN_UPDATES - loopExecutionTime - extraSleepTime;
// Only sleep for positive intervals
if(sleepTime >= 0)
{
try
{
Thread.sleep(sleepTime / 1000000);
}
catch(InterruptedException e) {}
}
else
{
System.out.println("WARN: sleepTime < 0");
}
// Counts the extra time that elapsed
extraSleepTime = System.nanoTime() - timeAfterUpdate - sleepTime;
}
}
The problem is that, when running, the FPS aren't stable at 60Hz, but sometimes go lower. For example I sometimes get 58-59Hz, going as low as 57Hz.
This variability wouldn't be a problem if the game was run locally, but as our game is networked, I need to keep the exact time so that I can reproduce the logic calculations on both client and server.
Is there any error in this code, or anything that could be improved to make it more stable? Our goal is 60Hz being kept exactly all the time.
EDIT: A first solution that came up in my mind is running the loop a bit faster than it needs to, for example at 70Hz, and checking the frame count to limit the updates to 60 per seconds. This way the simulation would be run in bursts and would need buffering, (up to 60 frames at a time), but should be able to never be slower than needed.
Thanks in advance.
If you want to achieve 60 frames per second, you'd be better off using a scheduled executor as Thread.sleep() may not be as precise as you'd like it to be. Consider the following sample for your server code: (Please note it contains Java 8 code)
public void gameLoop() {
// game logic here
}
Executors.newSingleThreadScheduledExecutor()
.scheduleAtFixedRate(this::gameLoop, 0, 16, TimeUnit.MILLISECONDS)
It will run your gameLoop() every 16 milliseconds which is essentially what you want. This should give you much more precise results. You can also replace 16 and TimeUnit.MILLISECONDS with their nanoseconds counterpart, even though it shouldn't make any noticeable difference

Unstable speed of gameloop

I'm making a simple breakout game in OpenGL(-es) on Android. Initially I had the updating of the game's state and the drawing calls in the same loop: onDrawFrame. Now I decided to split up the two, only leaving the rendering calls in onDrawFrame, and the gamestate was managed in another Thread:
public void run() {
Log.d("GameLogicThread", "GameLogicThread started");
final long UPDATE_INTERVAL = 1000000000 / 30;
long endingTime;
int timeElapsed;
long startingTime = System.nanoTime();
while (!running) {// wait for it...
}
while (running) {
endingTime = System.nanoTime();
timeElapsed = (int) (endingTime - startingTime);
Log.d("timeElapsed",Integer.toString(timeElapsed));
if (timeElapsed < UPDATE_INTERVAL-timeElapsed){
try {
Thread.sleep(timeElapsed);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
startingTime = System.nanoTime();
Game.updateGame(timeElapsed);
}
EDIT
I now have changed the code like this ^^, but it still doesn't work correctly..
Is it something in the loop itself that's wrong, or should I look outside (Probably not, since it worked great before moving the code). What should I do?
There are a few logical errors which are pointed out/discussed in the comments below:
endingTime = System.currentTimeMillis();
timeElapsed = (int) (endingTime - startingTime);
// Why is the "elapsed" time being waited? Hmm.
// If *any* wait is being done (I'd recommend sleep(0) for starters)
// it should be the MAXIMUM desired cycle time MINUS the
// currently used cycle time (MINUS some fudge factor).
if (timeElapsed < UPDATE_INTERVAL) // I dislike hanging blocks...
try {
Thread.sleep(timeElapsed);
} catch (InterruptedException e) {
e.printStackTrace();
}
startingTime = System.currentTimeMillis();
// The game needs to know the TOTAL time elapsed since
// the last update, not the time "until before the yield".
// This will likely be passed fictitiously small values as
// it is only time the the LAST updateGame took to run.
Game.updateGame(timeElapsed);
I would never expect to see timeElapsed (passed to updateGame) below say 10ms with sleep(...) and the corrected time calculations.
However, it may not have the required precision (increasing the minimum cycle length to say 1/30 sec, which would result from the fixed math, would make this less important): see Cristian Vrabie's answer for a suggestion on a higher-resolution timer. (There may be some better 3rd-party alternatives designed just for this -- there is in "normal" Java -- I don't program Android ;-)
Happy coding.
The loop doesn't look broken to me. The move to separate threads is definitely a good one or you would have serious problems when the rendering of a frame takes too long.
Have you tried to use nanoTime() for more accuracy?

Categories

Resources