简体   繁体   中英

Frequency of input from external light sensor

Background: I have a IOIO which I am using to measure the output from an photodiode, this is then converted into a digital output. I need to find the frequency at which the signal changes between 1 and 0. Someone gave me some code that I could use to measure the frequency, but I have no idea how to integrate it into my existing app. I know that the way I have implemented it will not work because the UI thread which updates the variable is waiting on the return from the other thread that calculates the frequency, so that thread will only get the value of diode when it starts running. So how do I make the frequency thread have a real-time value for diode and also after it has calculated the frequency pass it back to the UI thread to be displayed?

Here is my UI thread (FrequencyApp.java):

    public class FrequencyApp extends IOIOActivity {
private TextView textView_;
private TextView textView2_;
private TextView textView3_;
private ToggleButton toggleButton_;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    textView_ = (TextView)findViewById(R.id.TextView);
    textView2_ = (TextView)findViewById(R.id.TextView2);
    textView3_ = (TextView)findViewById(R.id.FrequencyLabel);
    toggleButton_ = (ToggleButton)findViewById(R.id.ToggleButton);

    enableUi(false);
}

class Looper extends BaseIOIOLooper {
    private AnalogInput input_;
    private DigitalOutput led_;
    volatile int diode;
    private long frequency;


    @Override
    public void setup() throws ConnectionLostException {
        try {
            input_ = ioio_.openAnalogInput(31);
            led_ = ioio_.openDigitalOutput(IOIO.LED_PIN, true);
            enableUi(true);
        } catch (ConnectionLostException e) {
            enableUi(false);
            throw e;
        }
    }

    @Override
    public void loop() throws ConnectionLostException {
        try {
            led_.write(!toggleButton_.isChecked());


            float reading = input_.getVoltage();

            if(reading  > 1){
                diode = 1;
            } else { 
                diode = 0;
            }
            if(toggleButton_.isChecked()){
                FrequencyThread frequencyTaskThread = new FrequencyThread();
                frequencyTaskThread.setPriority(Thread.NORM_PRIORITY-1); //Make the background thread low priority. This way it will not affect the UI performance
                frequencyTaskThread.start();
                frequency = (long) frequencyTaskThread.run(diode);
                frequencyTaskThread.stop();
            }
            setText(Float.toString(reading), Long.toString(diode), Long.toString(frequency));
            Thread.sleep(100);
        } catch (InterruptedException e) {
            ioio_.disconnect();
        } catch (ConnectionLostException e) {
            enableUi(false);
            throw e;
        }
    }
}

@Override
protected IOIOLooper createIOIOLooper() {
    return new Looper();
}

private void enableUi(final boolean enable) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            toggleButton_.setEnabled(enable);
        }
    });
}

private void setText(final String str,final String str2,final String str3 ) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            textView_.setText(str);
            textView2_.setText(str2);
            textView3_.setText(str3);
        }
    });
}

}

Here is the thread for calculating the frequency(FrequencyThread.java:

    public class FrequencyThread extends Thread {
public float run(int diode){
// 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 interval = .01 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);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
}
// 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 = (float) (0.5 * count / (duration/1000));
return frequency;
}

}

The way you have it set up easiest would probably be to use a Handler to send messages from the FrequencyThread to the main thread. The way that is probably preferred to use an AsyncTask to abstract away the Thread / Handler and make the whole situation a bit easier to deal with. Doing so might require you to put the IOIOLooper thing into an AsyncTask though, I have no experience with that board or its Java API.

Also you shouldn't need the "runOnUiThread", or the Runnable at all in your setText() method. That seems to be only being called from the main thread anyway.

What you'll want to do is override your Handlers handleMessage() to call setText(). Then inside the FrequencyThread make a call to handler.sendMessage() passing back the data and / or message(ie error).

I tried using the code you've posted to make an example but I am having trouble following it honestly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM