Trouble using interrupts, TM1637, and photo interrupter

Hello, sorry if this is in the wrong part of the forum.

I’m a beginner in coding and using arduinos and have done tutorials and short projects through school, but have come at a snag trying to complete a project at work.

I’m using the Mega2560 board, a TM1637 4-digit LED display, and a TCST 2103 optocouple/photo interrupter.
They have been tested and been confirmed to have been working.

The project is to count the total revolutions of a 16-tooth gear. I intend for the photo interrupter to send pulses to the board and utilize the interrupt to go to a counting part of my code, and then display the total amount of “turns” (ever 16 pulse, corresponding to the 16 teeth) the gear has complete.

What I’m trying to do in my calculations part is have the number of “pulses” update each time the interrupt is called on, until it reaches 16 which will then increment “turns” by 1. After 1 “turn” has been completed, I wanted the number of pulses to restart at 0 while keeping the amount of turns.

I’ve tried to read as much as I could, but have come to a standstill. It as been deduced that the problem with my code is in the attachInterrupt area, but have a hard time trying to think of a solution.

Any help is appreciated, and thank you in advance.

#include <TM1637Display.h>
#define CLK 4
#define DIO 3
#define pulsesensor 20
TM1637Display display = TM1637Display(4, 3);




int turns = 0;
int pulse = 0;




void setup() {
  pinMode(20, INPUT);
  pinMode(3, OUTPUT);
  attachInterrupt(20, calculatepulse, HIGH);
}


void loop() {
  display.setBrightness(5);
  display.showNumberDec(turns);


}


void calculatepulse() {
  if (pulse < 16)
    pulse = pulse + 1;
  if (pulse == 16)
    turns = turns + 1;
  if (pulse > 16)
    pulse = 0;


}

You define your pin numbers, but then do not use your defined constants in your code - please do so - it makes your code easier to change.

Since you use turns in both the ISR and your main code, it must be declared as ‘volatile’ so the compiler will not optimize it away and break your code

#include <TM1637Display.h>
#define CLK 4
#define DIO 3
#define pulsesensor 20
TM1637Display display = TM1637Display(CLK, DIO);

volatile int turns = 0;
int pulse = 0;

void setup() {
  pinMode(pulsesensor, INPUT);
  pinMode(DIO, OUTPUT);
  display.setBrightness(5);
  attachInterrupt(digitalPinToInterrupt(pulsesesnor), calculatepulse, HIGH);
}

void loop() {
  display.showNumberDec(turns);
}

void calculatepulse() {
  pulse++;
  if ( pulse == 16 ) {
    pulse = 0;
    turns++;
  }
}

Also, how is your photo sensor wired up? If it is an open collector, you need to make the pin INPUT_PULLUP vs. INPUT.

I’d guess also that the photo interrupter is an open collector type device.
In which case, you’d probably have more success with:
attachInterrupt(20, calculatepulse, FALLING ) ;

I see, thank you for your input so far! I'm relatively fresh when working with microcontrollers, but I think I understand the input and will implement them in the office tomorrow and will update with results.

Forgive my ignorance as I'm not too familiar with components, but I think it might be. Using the search term "slotted optocoupler" returns images that look identical to the sensor I'm using if that helps.

It looks like this one. https://www.vishay.com/docs/81147/tcst2103.pdf

For the above suggestions to work, you wire the terminal ‘D’ to ground and the terminal ‘+’ to the Arduino input pin (with the internal pull-up resistor enabled). There are also alternative ways of connecting it.

I apologize for the late update

Implementing INPUT_PULLUP and volatile helped, but a new problem arose: the display started display pulse instead of turns, and not evenly as well. Sometimes it would implement by 1,4, 6, or randomly jump by a number larger than 10.

I had someone look at it and they noticed something wrong with my calculating portion, and it fixed everything.

Unfortunately, I forgot to save the code and the computer crashed, having to figure out what the small problem was again as the person who solved it also forgot what they changed and had something else loaded onto the board for another project.

I had the calculating portion the same as blh64 had previously, but later changed that to “=+1” in the following when the code worked as intended, but there is still something wrong. Still trying to figure out what the problem is within the calculating phase.

#include <TM1637Display.h>
#define CLK 4
#define DIO 3
#define pulsesensor 20
TM1637Display display = TM1637Display(CLK, DIO);

volatile int turns = 0;
int pulse = 0;

void setup() {
pinMode(pulsesensor, INPUT_PULLUP);
pinMode(DIO, OUTPUT);
display.setBrightness(5);
attachInterrupt(digitalPinToInterrupt(pulsesensor), calculatepulse, HIGH);
}

void loop() {
display.showNumberDec(turns);
}


void calculatepulse() {
  if(pulse <16)
  pulse = pulse +1;

  if (pulse == 16)
  turns = turns +1;

  if (pulse >16)
  pulse  = 0;

}
void calculatepulse() {
  if (pulse < 16)
    pulse = pulse + 1;

  if (pulse == 16)
    turns = turns + 1;

  if (pulse > 16)
    pulse  = 0;

}

Pulse will never be > 16, because you stop incrementing when it reaches 16. Also, resetting at a count > 16 would requires 17 pulses per revolution. Notice the code posted in reply #1 which corrects both these problems.

Because turns is larger than a single byte, you also need to temporarily disable interrupts while accessing it in loop(), otherwise an interrupt can occur and change the value between bytes. Usually method is to disable interrupts just long enough to copy the value into another variable then re-enable interrupts.

void loop() {
  noInterrupts(); //temporarily disable interrupts while making a copy of turns
  int turnsCopy = turns;
  interrupts();
  display.showNumberDec(turnsCopy);
}

Oh, how foolish of me not to realize this , thanks for pointing it out again. Thanks for the advice about using Interrupt() and noInterrupt(), all of this is interesting as my knowledge and experience when it comes to working with code and data is next to none and sometimes, I'm used to designed the enclosures and housings for these things haha.

So far with everything implemented, the counter now only displays an update of +1 every 6 pulses (adds +1 to the screen every half revolution of the gear, instead of the full revolution), but I suppose I can make this work in my application as it is a stable and repeatable result.

I appreciate the hand holding on this project so far from this forum, but will continue trying to figure it out from reading the directory and other peoples projects (hopefully it doesn't go over my head as it already has been).

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