I am trying to use millis() to time the interval for which a pin is in a LOW state. I have been examining the stopwatch sketch in the Arduino playground. I think the problem is in line 12, the first line of loop(). I can't figure out where this line should go. I need to use a laststate in some way.
int ledTX = 12; //Receives InfraRed signal
int photodiodePin = 2; // Photodiode connected to digital pin 2
int lastState;
unsigned long startTime;
unsigned long elapsedTime;
void setup() {
Serial.begin(9600);
pinMode(ledTX, OUTPUT);
pinMode(photodiodePin, INPUT); // sets the digital pin as input to read photodiode
}
void loop() {
lastState = photodiodePin;
digitalWrite(ledTX, HIGH); // turn the TX Infrared LED on
Serial.println(digitalRead(photodiodePin)); // Read the pin and display the value
if(photodiodePin == LOW && lastState == HIGH){
startTime = millis();
}
if(photodiodePin == HIGH && lastState == LOW){
elapsedTime = millis() - startTime;
Serial.print("Total time: ");
Serial.println(elapsedTime);
}
delay(1000);
}
(Physically I am trying to time when an object passes through a photo-gate.)
Thanks that's much better. I am getting some strange characters in the serial monitor. I can't copy and paste them but they are the elapsed times and a backward P with two legs and a dollar sign.
int ledTX = 12; //Receives InfraRed signal
int photodiodePin = 2; // Photodiode connected to digital pin 2
int lastState;
unsigned long startTime;
unsigned long elapsedTime;
void setup() {
Serial.begin(9600);
pinMode(ledTX, OUTPUT);
pinMode(photodiodePin, INPUT); // sets the digital pin as input to read photodiode
}
void loop() {
byte currentState = digitalRead(photodiodePin);
digitalWrite(ledTX, HIGH); // turn the TX Infrared LED on
if(currentState == LOW && lastState == HIGH){
startTime = millis();
}
if(currentState == HIGH && lastState == LOW){
elapsedTime = millis() - startTime;
Serial.print(elapsedTime);
Serial.write(elapsedTime);
}
lastState = currentState;
}
I am also trying to send the elapsedTime variable to processing.
Thanks that's much better. I am getting some strange characters in the serial monitor. I can't copy and paste them but they are the elapsed times and a backward P with two legs and a dollar sign.
On every line? Or just the first couple of characters? If it's the first couple that's pretty normal, as the USB chip tries to detect the baud rate. Try doing a Serial.println() just after the Serial.begin().
Each value of elapsedTime is preceeded by a strange character and they are always different. Sometimes its " or £ etc. So each line has one of these characters and an elapsedTime value, no space between them. I am trying to read the elapsedTime value in Processing but is it sending just the value or the strange character plus the value?
The processing code is, (maybe I should not be posting it here!)
import processing.serial.*;
Serial port;
float elapsedTime;
void setup() {
size(200, 200);
background(204);
noStroke();
port = new Serial(this, 9600);
}
void draw() {
if (0 < port.available()) {
elapsedTime = port.read();
}
println(elapsedTime);
}
I'm no expert in Processing, but on the Arduino, you can't read into a float like that. A float is 4 bytes and a read reads one byte. Maybe a Processing expert can elaborate.
Seeing the sending code would be useful. As Nick says, the read() function in Processing only reads one byte or char at a time. There are other methods that read more than one byte/char at a time. Which of them would be useful for you depends on how you are sending the data to the serial port.
I think it is only a 4 digit integer number that i am sending, Well here is the code,
Arduino:
int ledTX = 12; //Receives InfraRed signal
int photodiodePin = 2; // Photodiode connected to digital pin 2
int lastState;
unsigned long startTime;
unsigned long elapsedTime;
void setup() {
Serial.begin(9600);
pinMode(ledTX, OUTPUT);
pinMode(photodiodePin, INPUT); // sets the digital pin as input to read photodiode
}
void loop() {
byte currentState = digitalRead(photodiodePin);
digitalWrite(ledTX, HIGH); // turn the TX Infrared LED on
if(currentState == LOW && lastState == HIGH){
startTime = millis();
}
if(currentState == HIGH && lastState == LOW){
elapsedTime = millis() - startTime;
Serial.println(elapsedTime);
Serial.write(elapsedTime);
}
lastState = currentState;
}
Processing: the elapsedTime variable has been declared as an integer but I am only getting a print out of 0. There is no change when I put anything in the photogate.
import processing.serial.*;
Serial port;
int elapsedTime;
void setup() {
size(200, 200);
background(204);
noStroke();
port = new Serial(this, 9600);
}
void draw() {
if (0 < port.available()) {
elapsedTime = port.read();
}
println(elapsedTime);
}
I think it is only a 4 digit integer number that i am sending, Well here is the code,
Serial.println(elapsedTime);
The print()/println() methods convert the value to a string. Suppose that millis() returns a value of 873. You are then sending '8', '7', '3', , to the serial port.
You are then reading one character at a time, '8', '7', '3', , and , and assuming that you are getting an integer value ('8' != 8), which is not the case.
The Serial class in Processing has a bufferUntil() method, where you can tell Processing to call serialEvent() only when the , for instance, arrives.
In the serialEvent() method, you can then use the readUntil() method to get all the data (as a string) that has arrived ("873") up to the specified character (). Then, int() will convert that string to an int.