We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi! I'm new to programming but last week we decided to make laser stopwatch system in our mtb competition.. so i decided to try. Making with Arduino (with photoresistor in analog input) with filled in Firmata, and trying to use processing to get rider's times on display. Our track is about 30sec, and starts every minute, so I need a timer, looped in a minute.. when rider cross laser - check the time and display it... As I said, I'm new in programming, so code may be stupid, but as is =) Now i have a problem with looping minute (60000ms), it just stopping the watch. Can't get it (((
import processing.serial.*;
import cc.arduino.*;
PFont font;
Arduino arduino;
int a = 8; // sets switch threshold
int bg = 200; //bg color
String txt = "Waiting...";
void setup() {
size(displayWidth, displayHeight);
background(bg);
textAlign(CENTER);
arduino = new Arduino(this, "COM3", 57600);
font = createFont("Impact",60,true);
textFont(font,80);
fill(20);
text(txt, displayWidth/2, displayHeight/2);
StopWatch.start();
}
void draw() {
if (arduino.analogRead(0)<a) { // shading trigger
StopWatch.stop();
String time = ("Time:\t " + StopWatch.time()/1e3);
background(bg);
text(time, displayWidth/2, displayHeight/2);
}
if (StopWatch.time()>60000)
{
///////////lag????
StopWatch.start();
}
if (keyPressed==true){ //restart to sync time
StopWatch.reset();
String res = ("Time:\t " + StopWatch.time()/1e3);
background(bg);
text(txt, displayWidth/2, displayHeight/2);
StopWatch.start();
}
// printArray(arduino.analogRead(0)); debug a
}
boolean sketchFullScreen() {
return true;
}
static final class StopWatch {
static long startTime, endTime;
static void start() {
startTime = System.currentTimeMillis();
}
static void stop() {
endTime = System.currentTimeMillis();
}
static long time() {
return endTime - startTime;
}
static void reset() {
startTime = endTime = 0;
}
}
Answers
Little confusing... Perhaps making
endTime = startTime
inside start()? :-/i start program, pressing any key to sync with my stopwatch, than laser crossed and i see the time... till now its ok. i supose that timer continue 1 minute loop counting, but when next rider crossing laser it just starting timer from 0... thats the problem i cant guess..
As said by GoToLoop (you haven't answered him), you need to have startTime = endTime in start(), otherwise endTime is 0, and computing in time() is just wrong. Do println(System.currentTimeMillis()) to see why.
And I wonder why you use this instead of Processing's millis().
Side note: since your problem has nothing to do with Arduino, you better make a different sketch without dependency on it, eg. replacing its event with a keyboard event, for example. Thus, anybody can run your code, it is easier to help you.
Thanks, trying to modify the code... I thought to display real time and track time with minutes first time i start to write this code, for now... maybe millis() only will work, just need to think about it... Thanks PhiLho, my brain a little hazed now with all this new programming) Also there is one more little problem... As soon as front wheel of the bike cross the laser, my timer checking times until his rear wheel pass (all details of bike shading laser) - so on dysplay i see rear wheel time. I think some delay after 28 string would work, but as I heard delay() function is not very good to use.
Actually it's disastrous. Although it's OK inside setup(), before draw() starts.
If you need to use it, you're gonna need a separate Thread for it.
Hey, GoToLoop, PhiLho - thanks for advice! Modyfied code, using millis(). Here it is:
It seems to work good for now) Still wondering of delay on finish. GoToLoop, should i create a new thread about it?
Callback draw() is invoked @ 60 FPS by default. Rather than using delay() to forcibly halt draw(),
it's much better & correct to use frameRate(): http://processing.org/reference/frameRate_.html
For example,
frameRate(2)
would set 2 FPS for draw(). Which is the same asdelay(500)
. =:)I thougth framerate would decrease timer accuracy, cause its checking analog read from photoresistor in draw()
if (arduino.analogRead(0)<a){...}
Isn't it?Well, delay() would halt the whole "Animation Thread" too.
While frameRate() establishes a constant delay for draw() callback.
Question is, does analogRead() need to be hammered @ 60 FPS?
Notice that millis() isn't affect neither by frameRate() nor delay() though.
Well, as I've checked using frameRate(2) displayed time was with 0.5sec accuracy (2 frames/sec) cause in the draw() arduino.analogRead() checking if laser shaded or not with this framerate. So its not suitable for me, accuracy should be 0.01sec so i set framerate to 100. But problem still exist - how to record only first event?
I have notice on some of these programs in the sample section. the milliseconds just keep counting upward. could you record the millis at the start of the program. And each trigger of the next millis rec event subtract it from the start millis?
Declare a startMillis "global" variable.
When
millis() - startMillis >= LIMIT
, do something and makestartMillis = millis()
again!Works great! Big respect, GoToLoop!