Optical interruptor - problem reading high speed

Hi!

New to Arduino and coding.

I’m using a photo interrupter module (looks identical to this one: KY-010 Photo Interrupter Module - ArduinoModulesInfo but isn’t the exact same) to measure the speed of a wheel. The wheels hangs loose in the air. The plan is to have the speed of the wheel control a synth. I’ve taped bits of paper to the wheel that passes through the photo interrupter.

Now, my problem is that something in the chain doesn’t keep up with the speed of the wheel. At high speed the numbers are not consistent, giving me 10 ms between interruptions at the fastest and jumps around between 10 and about 50 ms at random, sometimes lapsing to 100 or more. I can also see that the led on the Arduino is blinking inconsistently.

The chain is: Interrupter -> Arduino Uno -> Pure Data -> Software synth. I know that every bit of paper passes through the interrupter. I know that my pure data-patch can handle the speed. It has to be the photo interrupter or my code that messes thing up. Does my code look reasonable? Does the interrupter have any limitations? Arduino should be able to handle way faster streams then 10 ms, I read 4 micros somewhere. I’m using the digital input on the arduino board.

One thing that has me confused is that the number stream that I get on high speeds is always a multiple of 10 (10 being the lowest). This is not true for slower speeds. This is data from Pure Data. In the serial monitor of Arduino IDE the ms-timestamps doesn’t make any sense to me, as it looks like this:

20:54:24.700 -> 0
20:54:24.700 -> 1
20:54:24.700 -> 0
20:54:24.700 -> 0
20:54:24.700 -> 0
20:54:24.700 -> 0
20:54:24.700 -> 0
20:54:24.700 -> 0
20:54:24.700 -> 0
20:54:24.733 -> 0
20:54:24.733 -> 0
20:54:24.733 -> 0
20:54:24.733 -> 1
...and so on

This is my code:

int state;
int Led = 13;       // define LED pin
int buttonpin = 3;  // define photo interrupter signal pin
int val;            //define a numeric variable
void setup() {
  pinMode(Led, OUTPUT);       // LED pin as output
  pinMode(buttonpin, INPUT);  //photo interrupter pin as input
  Serial.begin(9600);         //Communication setup
}
void loop() {
  val = digitalRead(buttonpin);  //read the value of the sensor
  if (val == HIGH)               // turn on LED when sensor is blocked
  {
    digitalWrite(Led, HIGH);
    state = 1;

  } else {
    digitalWrite(Led, LOW);
    state = 0;
  }

  Serial.println(state);  //send to PD
}

I’m on a macOS 13.4 Mac mini.
Using Arduino Uno
IDE version 2.1.1
Don’t know the manufacturer if the interrupter since I bought it in a kit and it's unmarked. Sorry.

Thanks,
Andreas

It takes 1 millisecond to print a single character at that glacial Baud rate. Increase it to 115200. The timestamps ARE meaningless, because they tell you when a USB buffer packet is decoded on the PC.

To debug the circuitry, use an oscilloscope to examine the waveform on the optocoupler output.

1 Like

...250000 is an even better choice.

1 Like

Thanks for quick replays.

Oh, I thought that was the port number.
I just entered another number, like this: Serial.begin(230400); within my code. Is that the way to do it?

Seems to communicate with PD still, but still gives me the same bad result. I'm doing something wrong, right?

Actually it looks a little bit better. It only fluctuates between 20 and 30 ms at high speed. Not doing random big jumps anymore. Progress!

Not necessarily, which is why you need to look at the output waveform of the opto-interrupter.

If the waveforum does not make clean transitions between about 0V and Vcc, the input may not decode it correctly.

Hmm, don't have have one of those. But isn't it odd that its always multiples of 10? Could that relay be the interrupter it self? It's such a digital-looking problem...?

There is nothing in your post that helps me to understand what this means. What is "the number stream"?

Sorry, new to this, don't know the proper language. I'm talking about the Pure Data results. I measure the timing i PD and print it in the monitor. That's the numbers I'm talking about. Looks like this:

print: 30
print: 20
print: 30
print: 20
print: 30
print: 20
print: 30
print: 20
print: 30
print: 20
print: 30

ms, that is.

Your interrupter uses IR LEDs and the IR light will probably go right through your bits of paper. IF not, they will cause "fringing" of the light, meaning there NOT an abrupt change from on to off, etc.

That sounds like a Pure Data problem, not an Arduino problem.

Hi Paul.

Had this problem before switching to thicker paper. But the fringe-thing could still be a factor, I guess. But that shouldn't give me such consistent results, right? And there are clearly other problems here as well. I might try changing the material but that will be a later project. Have bigger fish to fry atm.

That sounds like a Pure Data problem, not an Arduino problem.

Pretty sure it's not a PD problem since I've tested it with other input that worked fine.

Thou it might very well be a problem of communication between the UNO and PD. That is a black box to me and I surly don't understand any of it.

Serial.println(state);

What is PureData expecting for a terminator if any? Is it expecting Ascii or the actual numerical data?

Try without any terminator.

Serial.print(state);

Don't trust the timestamps on the data logger--the buffering in the logger likely doesn't give reliable millisecond-scale timestamps.

Try printing millis() to check the performance of the serial system and the accuracy of the logger timestamping relative to the Arduino timestamping:

int state;
int Led = 13;       // define LED pin
int buttonpin = 3;  // define photo interrupter signal pin
int val;            //define a numeric variable
void setup() {
  pinMode(Led, OUTPUT);       // LED pin as output
  pinMode(buttonpin, INPUT);  //photo interrupter pin as input
  Serial.begin(115200);         //Communication setup
}
void loop() {
  val = digitalRead(buttonpin);  //read the value of the sensor
  if (val == HIGH)               // turn on LED when sensor is blocked
  {
    digitalWrite(Led, HIGH);
    state = 1;

  } else {
    digitalWrite(Led, LOW);
    state = 0;
  }
  Serial.print(millis());
  Serial.print(" ");
  Serial.println(state);  //send to PD
}

If there is a Pure Data forum, members there may be able to help.

PD is very rarely even mentioned on this forum.

1 Like

Getting late over here, bed is calling. I'll try out all your suggestions tomorrow. Thanks for all the help so far! Seems like a really great place, this!

/A

I’ve moved on with another solution on the Pure Data-end of things, rendering my above problems irrelevant. For those who have similar questions and might find this in the future:

I ended up using Pduino. Its a Pure Data extension that is design to be used with arduino. It is used together with firmata uploaded to the arduino. Here is a good resource: Getting started with Pduino ([arduino]) | Guitar Extended

I had some problems with the PD extension. Most PD extensions work right out of the gate but this one you hade to create a path for it manually in PD. See this for instructions: Pd Manual 4

Thanks for all the help!

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.