背景:我有一个IOIO用于测量光电二极管的输出,然后将其转换为数字输出。我需要找到信号在1和0之间变化的频率。有人给了我一些我可以用来测量频率的代码,但我不知道如何将它集成到我现有的应用程序中。我知道我实现它的方式不起作用,因为更新变量的UI线程正在等待从计算频率的另一个线程返回,因此线程只会在开始运行时获得二极管的值。那么如何让频率线程具有二极管的实时值,并且在计算出频率后又将其传递回要显示的UI线程?
这是我的UI线程(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);
}
});
}
}
这是计算频率的线程(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;
}
}
答案 0 :(得分:0)
设置最简单的方法可能是使用Handler将消息从FrequencyThread发送到主线程。可能更倾向于使用AsyncTask抽象出Thread / Handler并使整个情况更容易处理。这样做可能需要您将IOIOLooper事物放入AsyncTask中,但我没有使用该板或其Java API的经验。
此外,您不应该在setText()方法中使用“runOnUiThread”或Runnable。这似乎只是从主线程调用。
您要做的是覆盖Handler handleMessage()以调用setText()。然后在FrequencyThread内部调用handler.sendMessage()传回数据和/或消息(即错误)。
我尝试使用您发布的代码作为示例,但我无法诚实地跟踪它。