Opto Interrupter Problem

I am using the Itsy Bitsy 32u4 3V and the following circuit using an ITR9608-F Opto Interrupter:

This is the setup code:

 pinMode(CW_Home_Pin,       INPUT_PULLUP);
  pinMode(CCW_Home_Pin,      INPUT_PULLUP);

The problem is false triggering. The code I am using:

 do{  
      StepPinToggle;
      Delay_Check(Delay);
//    }
      }while(digitalRead(CW_Home_Pin) == true);

It randomly stops as if it sees the slot in the stepper motorencoder disk. I have checked the opto interrupter works properly. So it has to be the controller. What could be the problem?

StepPinToggle;

What do you imagine that this line of code does ?

Please post your full sketch

The data sheet for the ITR9608-F shows that the photodetector is a four pin device with an NPN phototransistor, which needs to be wired differently than what you show.

What, exactly, do you have? Post a link to the product page.

What is are the 1 uF caps for?

Also, you need a current limiting resistor per built-in LED or are you using a module which has this on the board ?

StepPinToggle and Delay_Check are micros defined:

// Define macros to make the code easer to read and spee up code excution
//  by usng Port Manipulation
#define StepPinToggle PORTD ^= 0b00000010
#define StepPinFalse  PORTD &= 0b11111101
#define Busy_LED_On   PORTC |= 0b10000000
#define Busy_LED_Off  PORTC &= 0b01111111
#define INC_Count     count += ((PORTD & 0b0000010) >> 1)

// The followng define macro checks the delay is greater then the delay 
//    max micro second delay value
#define Delay_Check(x) if ( x > 1500){delay(int(x / 1000));if((x % 1000) > 3) delayMicroseconds(int(x % 1000));}else delayMicroseconds(x)  

Yes, there is a 220 ohm resistor to limit the LED current, and is on a PCB apart of the sensor. I have tested the sensors and verified the sensor works as accepted with an output is 3V when blocked and .05V when unblocked.

The test code is:

// Sytem test code  
  unsigned long int count = 0;
  uint16_t Dir_Count = 2500;
  unsigned long int Delay = 150; // microSecond
  uint8_t  x = 0;
  uint8_t  Home_Pin = CCW_Home_Pin;

  digitalWrite(DIR_Out_Pin, false);

  debug_IF_Delay(Delay);

  debug_SerialWait;

  delay(5000);

  do{

    Busy_LED_On;
//    while(digitalRead(CW_Home_Pin) == true){
    do{  
      StepPinToggle;
      Delay_Check(Delay);
//    }
      }while(digitalRead(CW_Home_Pin) == true);
//     }while((INC_Count) <= Dir_Count);
    
//    }while(digitalRead(CW_Home_Pin) == true);
//    if((INC_Count) > Dir_Count){
    Busy_LED_Off; 
    digitalWrite(DIR_Out_Pin,!digitalRead(DIR_Out_Pin));
    StepPinFalse;
    count = 0;
    delay(2500);
//   } 
    
//    while(digitalRead(CW_Home_Pin) == false){
//    while(INC_Count < false){
//        StepPinToggle;
//        Delay_Check(Delay);
//    }
    
    debugF("\t Step Pin = ");
    debug(digitalRead(Step_Pin));
    debugF(" (");
    debug_BIN(PORTD);
    debugF(") || ");
    debugln_BIN((PORTD & 0b0000010) >> 1);
    
    debugF(" \rHome Sensored Detected || \t Home_Pin = ");
    debug( Home_Pin);
    debugF(" \t||CW Home = ");
    debug( digitalRead(CW_Home_Pin));
    debugF(" \t|| CCW Home = ");
    debugln( digitalRead(CCW_Home_Pin)); 
    debugF("\t Count = ");
    debug(count);
    debugF("  // ");
    debugln_HEX(count);
    debuglnF("===========");
    debug_SerialWait;

   }while(true);
// End of sytem code

The caps are to filter out any noisy.

It might help if you would post complete code instead of a snip here and a snip there. I'm sure it makes it easier for those that want to help.

Here is a short video of what am talking about:

https://www.dropbox.com/scl/fi/09po77k418aa77dpa3bzi/DSCN0608.AVI?rlkey=oncfv5wxtgmfgf5w4tsvw1fzw&dl=0

As you can see the arm stops randomly with the sensor blocked!!! i should rotate constantly.

Could this have side effects on pins other than the one you intend to toggle ?

I do not think the macro it is causing any problems. I change from macro to code as follows:

digitalWrite(Step_Pin,!digitalRead(Step_Pin))

Did not fix the problem.

Does the fact that I had to ask what StepPinToggle; did help you to understand why we ask users to post complete sketches instead bits of them ?

It certainly would not fix a wiring problem.

I have triple-checked the wiring and measured the voltage on the PCB at the GPIO pin.

OK, here is the full script:

*
  This code is for the "Interface MX" PCB which has Mode pins are programble 
    to 2,4, 8,16.
    "Mode" divide set on line 85"

=================================================
Version 5
  Using micros to remove the debug points to speed up extucuting ( almost 25% faster)
    and uses Port Manipulation to speed up excution.

*/

#include "PinChangeInterrupt.h"


// Define macros to make the code easer to read and spee up code excution
//  by usng Port Manipulation
#define StepPinToggle PORTD ^= 0b00000010
#define StepPinFalse  PORTD &= 0b11111101
#define Busy_LED_On   PORTC |= 0b10000000
#define Busy_LED_Off  PORTC &= 0b01111111
#define INC_Count     count += ((PORTD & 0b0000010) >> 1)

// The followng define macro checks the delay is greater then the delay 
//    max micro second delay value
#define Delay_Check(x) if ( x > 1500){delay(int(x / 1000));if((x % 1000) > 3) delayMicroseconds(int(x % 1000));}else delayMicroseconds(x)  

// Debuging control
#define DEBUG 1   //Tell compiler to compile debug print statmnets (0 == dont compilen debug print || 1 == include debug print code)

#if DEBUG == 1
  #define debug(x) Serial.print(x)
  #define debugln(x) Serial.println(x)
  #define debugF(x) Serial.print(F(x))
  #define debuglnF(x) Serial.println(F(x))
  #define debug_BIN(x) Serial.print(x, BIN)
  #define debugln_BIN(x) Serial.println(x, BIN)
  #define debug_HEX(x) Serial.print(x, HEX)  
  #define debugln_HEX(x) Serial.println(x, HEX)  
  #define debug_SerialWait while(!Serial)
  #define debug_IF_Delay(x) if(x > 1500){ debugF("Delay > 1500 || ");debug(int(x / 1000));debugF(" /// ");debugln(int( x % 1000));} else{debugF("Delay = ");debugln(x);}
  #define debug_Delay(x) delay(x) 
#else

  #define debug(x)
  #define debugln(x)
  #define debugF(x)
  #define debuglnF(x)
  #define debug_BIN(x)
  #define debugln_BIN(x)
  #define debug_HEX(x)
  #define debugln_HEX(x)
  #define debug_SerialWait
  #define debug_IF_Delay(x)
  #define debug_Delay(x)
#endif

// First defne what are PI signal pins
const byte  Smack_Intensity_Pin_B4 = 18; 
const byte  Smack_Intensity_Pin_B3 = 19;
const byte  Smack_Intensity_Pin_B2 = 20;
const byte  Smack_Intensity_Pin_B1 = 21;
const byte  DIR_IN_Pin        = 22;
const byte  Run_Pin           = 23;
const byte  Busy_Pin          = 13;
const byte  Abort_Pin         = 15;
const byte  ToyType_Pin_MSB   = 16;
const byte  ToyType_Pin_LSB   = 14;

// Now define the outpins that control the DRV8825 stepper motor driver
const byte  Step_Pin        =  2;
const byte  DIR_Out_Pin     =  3;
const byte  CW_Home_Pin     = 12;
const byte  CCW_Home_Pin    = 11;

// Now define the global varables
volatile byte Home_Pin         = CW_Home_Pin;
byte    Toy_Type               = 0;
byte    Smack_Intensity_Value  = 5;
volatile bool Abort_Flag         = false;
uint16_t  Angle_90_Count         = 622;
uint16_t  Angle_180_Count        = 1422;

//Define macro valareables
const bool      CW              = false;
const bool      CCW             = true;


// DM8825 step divide number.. The only alowed Mode numbers are 4, 8, 16 ONLY
const byte    Mode = 8; // Set up step divider
const byte    Mode_Pin_0    = 10;
const byte    Mode_Pin_1    =  9;
const byte    Mode_Pin_2    =  7;
const byte    Angle_90_Count_M2   =  78;
const byte    Angle_180_Count_M2  =  178;

const uint8_t   Angle_90_Count_M4   =   156;
const uint16_t  Angle_180_Count_M4  =  356;

const uint16_t  Angle_90_Count_M8   =  311;
const uint16_t  Angle_180_Count_M8  =  711;

const uint16_t  Angle_90_Count_M16  =  622;
const uint16_t  Angle_180_Count_M16 = 1422;

uint8_t Mode_X = 0;

void setup(){

// Initialize and start UBS for print debug points
  Serial.begin(115200);
  debug_SerialWait;

 // Setup and Initialize the GPIO pins
  pinMode(Smack_Intensity_Pin_B4, INPUT);
  pinMode(Smack_Intensity_Pin_B3, INPUT);
  pinMode(Smack_Intensity_Pin_B2, INPUT);
  pinMode(Smack_Intensity_Pin_B1, INPUT);
  pinMode(Run_Pin,           INPUT);
  pinMode(Abort_Pin,         INPUT);
  pinMode(DIR_IN_Pin,        INPUT);
  pinMode(CW_Home_Pin,       INPUT_PULLUP);
  pinMode(CCW_Home_Pin,      INPUT_PULLUP);
  pinMode(ToyType_Pin_MSB,   INPUT);
  pinMode(ToyType_Pin_LSB,   INPUT); 
  pinMode(Busy_Pin,          OUTPUT);
  pinMode(DIR_Out_Pin,       OUTPUT);
  pinMode(Step_Pin,          OUTPUT);
  pinMode(Mode_Pin_0,        OUTPUT);
  pinMode(Mode_Pin_1,        OUTPUT);
  pinMode(Mode_Pin_2,        OUTPUT);
 

//Set output pins to defult values
  StepPinFalse;
  digitalWrite(DIR_Out_Pin, false);
  Busy_LED_Off;
  // Set the motor driver step divide number
  switch (Mode){
    case 2:
      digitalWrite(Mode_Pin_0 , true);
      digitalWrite(Mode_Pin_1 , false);
      digitalWrite(Mode_Pin_2 , false);
      Angle_90_Count  = Angle_90_Count_M2;
      Angle_180_Count = Angle_180_Count_M2;
      Mode_X = 0;
      break;

    case 4:
      digitalWrite(Mode_Pin_0 , false);
      digitalWrite(Mode_Pin_1 , true );
      digitalWrite(Mode_Pin_2 , false);
      Angle_90_Count  = Angle_90_Count_M4;
      Angle_180_Count = Angle_180_Count_M4;
      Mode_X = 1;
      break;  
         
    case 8:
      digitalWrite(Mode_Pin_0 , true );
      digitalWrite(Mode_Pin_1 , true );
      digitalWrite(Mode_Pin_2 , false);
      Angle_90_Count  = Angle_90_Count_M8;
      Angle_180_Count = Angle_180_Count_M8;
      Mode_X = 2;
      break;
  
    case  16:
      digitalWrite(Mode_Pin_0 , false);
      digitalWrite(Mode_Pin_1 , false);
      digitalWrite(Mode_Pin_2 , true );
      Angle_90_Count  = Angle_90_Count_M16;
      Angle_180_Count = Angle_180_Count_M16;
      Mode_X = 3;
      break;

    default:
      debugF(" Invailed Mode Number [ ");
      debug(Mode);
      debugF(" ]. Vaild Mode numbers are 4, 8 or 16");
      debuglnF(" Please recompile the sketch with a vailed Mode number");  
      do {
      }while (true);
      break;
  }
  debugln();  
  debuglnF(" >> Set Up Complete <<"); 
  debug(F(" Mode Number = "));
  debug(Mode );
  debugF("[ ");  
  debug(digitalRead(Mode_Pin_0));
  debug(digitalRead(Mode_Pin_1));   
  debug(digitalRead(Mode_Pin_2));
  debugF(" ]");
  debugln();
  debug_SerialWait;
  delay(5000);
} 
void loop() {
   
  unsigned long int count = 0;
  uint16_t Dir_Count = 2500;
  unsigned long int Delay = 150; // microSecond
  uint8_t  x = 0;
  uint8_t  Home_Pin = CCW_Home_Pin;

  digitalWrite(DIR_Out_Pin, false);

  debug_IF_Delay(Delay);

  debug_SerialWait;

  delay(5000);

  do{

    Busy_LED_On;
//    while(digitalRead(CW_Home_Pin) == true){
    do{  
//      StepPinToggle;
      digitalWrite(Step_Pin,!digitalRead(Step_Pin));
      Delay_Check(Delay);
//    }
      }while(digitalRead(CW_Home_Pin) == true);
//     }while((INC_Count) <= Dir_Count);
    
//    }while(digitalRead(CW_Home_Pin) == true);
//    if((INC_Count) > Dir_Count){
    Busy_LED_Off; 
    digitalWrite(DIR_Out_Pin,!digitalRead(DIR_Out_Pin));
    StepPinFalse;
    count = 0;
    delay(2500);
//   } 
    
//    while(digitalRead(CW_Home_Pin) == false){
//    while(INC_Count < false){
//        StepPinToggle;
//        Delay_Check(Delay);
//    }
    
    debugF("\t Step Pin = ");
    debug(digitalRead(Step_Pin));
    debugF(" (");
    debug_BIN(PORTD);
    debugF(") || ");
    debugln_BIN((PORTD & 0b0000010) >> 1);
    
    debugF(" \rHome Sensored Detected || \t Home_Pin = ");
    debug( Home_Pin);
    debugF(" \t||CW Home = ");
    debug( digitalRead(CW_Home_Pin));
    debugF(" \t|| CCW Home = ");
    debugln( digitalRead(CCW_Home_Pin)); 
    debugF("\t Count = ");
    debug(count);
    debugF("  // ");
    debugln_HEX(count);
    debuglnF("===========");
    debug_SerialWait;

   }while(true);
  }

But, as pointed out, the posted wiring diagram makes no sense at all for that 4-pin, npn phototransistor sensor.

Good luck with your project!

Yes, the schematic shows 5 wires. Here is the sensor PCB and schematic

For that module, a pullup resistor (5K to 10K) to 5V is required on the output, not a 1 uF cap to ground.

Yes, you are correct and the LED is powered by the 5V rail.
I do not understand what you are saying. The voltage on the transistor needs to be 3V so it does not blow the controller.

The required collector pullup resistors would be connected to 3.3V, for a 3.3V controller.
Also, remove C4 and C5.

I am using the controller's internal pull resistor.

pinMode(CW_Home_Pin,       INPUT_PULLUP);
  pinMode(CCW_Home_Pin,      INPUT_PULLUP);

If you disconnect the wire SIG wire does it rotate constantly then?

Good, idea. :blush:
I remove the signal wire. It still not rotating consistently ( as it should) and the voltage at the GPIO pin is a constant 3.3V. So the problem has to be the itsy bitsy 32u4 3v itself.