Problems with photodiode IR Receiver

The circuit looks ok. You might want to test the resistor with your meter to make sure it is 4.7K.

Instead of the blanket, you might try a pulldown resistor on the transistor base.

The other possibility would be to cover up the second LED with black tape so the only one you're measuring is the one you tapped into before that gave you the good results.

And if you have one, you could put a capacitor between the 5V and ground lines.

i do have, 100nF and 10nF

The bigger the better. And you could put three or four of the 100nf caps in parallel.

When I tested my circuit before, I just tested the output on my scope, but didn't actually test it feeding my Arduino. So this morning I set it up again, and fed it into my ESP8266, which is the closest MCU I have to the Uno R4. It read ok, but I found that the duty cycle varied tremendously depending on how far the remote was from the IRLED. I could get on/off cycles of 4-22 far away, or 13-13 close in.

But the one thing that was constant was the total cycle time, which for my 38KHz remote is about 26us:

Signal:
19 27 26 25 26 26 27 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 27 25 26 26 27 25 26 
27 25 26 26 27 25 26 27 25 26 27 25 26 27 26 25 26 27 27 25 26 25 27 26 27 25 27 25 26 27 26 25 
27 26 26 26 25 27 26 26 26 26 26 25 27 26 26 26 25 27 26 26 26 25 27 26 26 26 25 27 26 26 26 27 
25 27 25 27 25 26 26 26 26 26 27 25 27 25 27 25 27 25 27 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 27 25 27 25 27 25 26 
26 26 27 25 27 25 27 25 27 25 27 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 27 25 27 25 27 25 27 25 27 26 26 26 25 27 25 27 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 
---

Signal:
21 26 26 27 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 27 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 27 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 27 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 27 26 26 26 26 26 26 26 26 26 26 
26 26 26 26 26 26 26 26 26 26 26 26 
---

So I changed my code to only look at the total cycle time:

// capture incoming IR - Nano R4
// total cycle time

#define IR_PIN A1

unsigned long durations[300];
unsigned long prevMicros;
unsigned long newMicros;
int count = 0;
bool endit = false;

void setup() {
  pinMode(IR_PIN, INPUT);
  Serial.begin(57600);
}

void loop() {
  count = 0;
  endit = false;

  while (digitalRead(IR_PIN) == HIGH); // Wait for signal to go LOW

  prevMicros = micros();
  while ((count < 300) && (endit == false)) {
    newMicros = micros();
    durations[count] = newMicros - prevMicros;
    count++;
    prevMicros = newMicros;
    while (digitalRead(IR_PIN) == LOW);
    while (digitalRead(IR_PIN) == HIGH) {
      if ((micros() - prevMicros) > 2000000) {
        endit = true;
        break;
      }
    }
  }
  Serial.println("\nSignal:");
  for (int i = 1; i < count; i++) {
    Serial.print(durations[i]);
    Serial.print(" ");
    if ((i & 31) == 31) Serial.println();
    }
  Serial.println("\n---");
  delay(1000); // Small pause between readings
}

This should still work with the post 200 values. There will be one shorter cycle time that represents a zero bit, and a longer cycle time that represents a one bit. So instead of getting

3 40 3 39 4 39 4 39 4 21 5 24 4 21 5 21 6 21 5 21 6 39 5 21 5 39 4 39

you'll get

43 42 43 43 25 29 25 26 27 26 45 26 44 43

But it should work at a wider range of distances.

I was thinking the same, but then if I try to fit the signal which supposed to be 11110000... or 00110000... it really doesn't match anyhow.

Be aware that some textiles are highly reflective for certain wavelengths.

I've updated the code to provide better output formatting:

// capture incoming IR - Nano
// total cycle time

#define IR_PIN A1

unsigned long durations[300];
unsigned long prevMicros;
unsigned long newMicros;
int count = 0;
bool endit = false;

void setup() {
  pinMode(IR_PIN, INPUT);
  Serial.begin(57600);
}

void loop() {
  count = 0;
  endit = false;

  while (digitalRead(IR_PIN) == HIGH); // Wait for signal to go LOW

  prevMicros = micros();
  while ((count < 300) && (endit == false)) {
    newMicros = micros();
    durations[count] = newMicros - prevMicros;
    count++;
    prevMicros = newMicros;
    while (digitalRead(IR_PIN) == LOW);
    while (digitalRead(IR_PIN) == HIGH) {
      if ((micros() - prevMicros) > 2000000) {
        endit = true;
        break;
      }
    }
  }
  Serial.println("\nSignal:");
  for (int i = 1; i < count; i++) {
    Serial.print(durations[i]);
    Serial.print(" ");
    if ((durations[i] > 200) || ((i & 31) == 31)) Serial.println();
  }
  Serial.println("\n---");
  delay(1000); // Small pause between readings
}

The "better output formatting makes it undreadable in my case :

(This was the remote controller 38kHz)

And your code does work when connecting directly to the IR LED as you said it would :

Using your code with the IR photodiode i got this :

Signal:
186358 2268 2586 2593 1646 7 969 2963 3004 2546 1572 926 3218 1648 1108 
203690 1627 1706 1622 1051 1585 1107 3459 3501 1660 689 2668 1651 1582 1597 1817 2852 
161630 3381 1666 5 5 1029 1640 1576 1608 746 1601 1344 1575 1263 3257 1644 802 1651 762 3232 
150143 1638 1285 1660 6 5 976 1668 799 3061 2423 1596 108 2682 1593 1479 1631 307 3603 
157680 1650 1273 2366 3002 1590 1705 1564 7 1305 2003 2528 1658 794 2131 2300 1618 
159525 1606 1180 3036 1603 1250 2872 1642 1074 1635 1659 1630 632 2930 1601 1164 2853 1629 
176235 1599 1624 1642 1352 3074 1960 1589 14 1132 1589 1139 2650 1600 945 2532 3372 1639 
159081 3347 2650 1598 1071 1574 855 2500 3033 1659 1477 2511 2876 2404 
159288 1596 1317 1610 976 2874 2908 1665 1139 2697 1604 644 1599 1114 3004 1619 947 
172983 1580 1430 1604 1130 2626 1654 1658 1601 1630 2347 1596 671 3503 1605 724 3412 1666 
155694 2440 3300 1630 1184 1600 1979 1576 303 3219 3380 1650 5 1182 1656 1015 3074 1616 
181849 1600 1346 1605 618 1622 658 2687 2895 3372 2449 1599 906 3116 3049 1644 
169157 2288 2529 2533 3498 2461 1643 1058 2266 2936 1596 1588 2820 
553520 1577 13 5 523 1603 441 2706 1643 372 2427 2429 1616 1071 2594 1621 1904 1608 210 
193498 1586 1259 1569 778 1603 987 3759 1647 818 1629 757 2916 1593 1370 1587 1688 2626 
161619 3169 1653 1009 2851 2268 3235 3034 3449 2269 1661 810 2923 1610 
169018 1660 1437 2491 2282 2802 2089 1578 1376 3076 1644 884 1660 
---


Which is far worse than what i had before... it doesn't detect the signals in the middle at all

Okay guys i got something, kind of.

So i used the pull of resistor and testing my custom remote, depending on the position i got this :

Signal:
2584 12 32 11 32 10 32 12 32 10 15 12 15 12 15 11 18 9 15 12 15 12 32 10 18 9 32 10 36 7 18 10 15 11 18 9 18 9 18 8 17 11 35 7 35 14 
2773 11 32 10 32 12 31 11 32 10 18 10 18 9 18 8 18 9 18 9 18 9 32 10 18 10 32 9 36 7 18 9 18 9 18 9 18 8 18 9 18 10 35 6 36 14 
---
Signal:
1981 11 32 12 32 10 32 11 32 10 15 12 15 12 15 12 15 12 15 11 18 9 32 11 18 9 32 9 36 8 18 9 18 8 17 10 18 9 18 9 18 9 32 10 35 14 
1946 11 35 9 32 10 33 10 32 10 18 10 18 9 14 12 18 9 18 9 18 8 32 10 18 10 35 7 36 7 18 9 18 9 18 9 18 8 18 10 18 8 35 7 36 14 
---

The code im currently using is :

#include <LiquidCrystal_I2C.h>  
#include "Arduino_LED_Matrix.h"
#define IR_PIN A1

LiquidCrystal_I2C lcd(0x27,  16, 2);

unsigned long durations[300];
unsigned long prevMicros;
unsigned long newMicros;
int count = 0;
bool endit = false;



void decodeMessage() {
  bool recording = false;
  unsigned long message = 0;

  for (int i = 0; i < 300 - 1; i++) {
    int d = durations[i];

    // Look for start and end pulses > 1000 µs
    if (d > 1000) {
      if (!recording) {
        recording = true; // Start of message
        message = 0;
        continue;
      } else {
        break; // End of message
      }
    }

    if (recording) {
      if (i + 1 >= 300) break;

      int pulse1 = durations[i];
      int pulse2 = durations[i + 1];

      if (pulse1 >= 3 && pulse1 <= 9) {
        message <<= 1; 
        if (pulse2 >= 35 && pulse2 <= 41) {
          message |= 1; 
        } else if (pulse2 >= 18 && pulse2 <= 26) {
      }      
    }
  }



}
  message  = message >>1 ;
  Serial.print("Raw binary value: ");
  Serial.println(message);

unsigned int deviceID = (message >> 5) & 0x7FFF; // 0x7FFF = 15 bits mask (0111 1111 1111 1111)
if(deviceID > 10000) {
Serial.print("ID: ");
Serial.println(deviceID);
lcd.setCursor(0, 0);
lcd.print(deviceID);
}


}



void setup() {
  pinMode(IR_PIN, INPUT);
  Serial.begin(57600);
  
  lcd.init();                      // initialize the lcd 
  lcd.backlight();


}

void loop() {
  count = 0;
  endit = false;

  while (digitalRead(IR_PIN) == HIGH); // Wait for signal to go LOW
  prevMicros = micros();
  while ((count < 300) && (endit == false)) {
    newMicros = micros();
    durations[count++] = newMicros - prevMicros;
    prevMicros = newMicros;
    while (digitalRead(IR_PIN) == LOW);
    newMicros = micros();
    durations[count++] = newMicros - prevMicros;
    prevMicros = newMicros;
    while (digitalRead(IR_PIN) == HIGH) {
      if ((micros() - prevMicros) > 2000000) {
        endit = true;
        break;
      }
    }
  }
  Serial.println("Signal:");
  for (int i = 1; i < count; i++) {
    Serial.print(durations[i]);
    Serial.print(" ");
    }
    decodeMessage();
  Serial.println("\n---");
  delay(1000); // Small pause between readings
}

The decode message part was for the signal i had at the #200 post, but i need to have a different way to decode it, since now it depends on the distance that i'am at, but it depending on where i'am at, IT WORKS.

Great answers, thanks!

Since you had no success with the IRRemote library

I'm not sure where else to go with this since my hunch I suppose was incorrect and you'll have to press on with your current strategy. I guess if it was me, I would try that other IR library I mentioned that claims to read 50 (as opposed to 17) IR protocols but that's just how I would approach it from my way (non professional) of doing things.

Hopefully the additional details of what you're trying to accomplish helps the other helpers here toward your goal. At least for me it always helps to be able to form a mental image of what is being built overall, although in your case, sorry I can't be more help as I simply don't know.

Don't worry, i'm actually already very close to the answer, so as i said in post #390 i have already a way that work for receiving the signal, the only problem i have now is how to code a decoder, because depending on the distance i'am at with the remote controller i have low's and high with different microseconds, here is the code i use for decoding now :

#include <LiquidCrystal_I2C.h>  
#include "Arduino_LED_Matrix.h"
#define IR_PIN A1

LiquidCrystal_I2C lcd(0x27,  16, 2);

unsigned long durations[45];
unsigned long prevMicros;
unsigned long newMicros;
int count = 0;
bool endit = false;
bool readstate = false;



void decodeMessage() {
  bool recording = false;
  unsigned long message = 0;

  for (int i = 0; i < 45 - 1; i++) {
    int d = durations[i];

    // Look for start and end pulses > 1000 µs
    
        recording = true; // Start of message


    if (recording) {
      if (i + 1 >= 45) break;

      int pulse1 = durations[i];
      int pulse2 = durations[i + 1];

    if(pulse1 > 13 && durations[i-1]>=14) {
      readstate = true ;
    }

      if (pulse1 >= 3 && pulse1 <= 13) {
        message <<= 1; 

        if (pulse2 >= 29 && pulse2 <= 41) {
          message |= 1; 
        } else if (pulse2 >= 14 && pulse2 <= 25) {
      }      
    }

    if(durations[i]>1000) {
      readstate = true ;
    }
  }


}
 if(readstate == false) {

  Serial.println(" ");Serial.print("Raw binary value: ");Serial.println(message, BIN);

  if (message <= 5) {
    lcd.clear() ;
    lcd.setCursor(0, 0);
    lcd.print("Wrong distance");
    lcd.setCursor(0 ,3); 
    lcd.print("No Signal");
  } else {

unsigned int Buttonread = (message>> 20);
unsigned int deviceID = (message >> 5) & 0x7FFF; // 0x7FFF = 15 bits mask (00 111 1111 1111 1111)

lcd.clear() ;
Serial.println(" ");Serial.print("ID: ");Serial.println(deviceID);
Serial.print(Buttonread);
lcd.setCursor(0, 0);
lcd.print(deviceID);

if (Buttonread == 3) {
  lcd.setCursor(0, 3);
  lcd.print("Button 1");
}else if (Buttonread == 0) {
  lcd.setCursor(0, 3);
  lcd.print("Button 2");
}


}


}else if (readstate == true) {

  readstate = false ;
  lcd.clear() ;
  lcd.setCursor(0, 0);
  lcd.print("Wrong detection");

}

}



void setup() {
  pinMode(IR_PIN, INPUT);
  Serial.begin(57600);
  
  lcd.init();                      // initialize the lcd 
  lcd.backlight();


}

void loop() {
  count = 0;
  endit = false;

  while (digitalRead(IR_PIN) == HIGH); // Wait for signal to go LOW
  prevMicros = micros();
  while ((count < 300) && (endit == false)) {
    newMicros = micros();
    durations[count++] = newMicros - prevMicros;
    prevMicros = newMicros;
    while (digitalRead(IR_PIN) == LOW);
    newMicros = micros();
    durations[count++] = newMicros - prevMicros;
    prevMicros = newMicros;
    while (digitalRead(IR_PIN) == HIGH) {
      if ((micros() - prevMicros) > 2000000) {
        endit = true;
        break;
      }
    }
  }
  Serial.println("Signal:");
  for (int i = 1; i < count; i++) {
    Serial.print(durations[i]);
    Serial.print(" ");
    }
    decodeMessage();
  Serial.println("\n---");
  delay(1000); // Small pause between readings
}

But currently i have a limited band of values where i can decipher the message with this code, since the called (pulse1) which is the equivalent of the 3's and 4's of the post #200 vary a lot, like sometimes it goes up to 20, which doesn't decode well since the pulse2 (the one that is supposed to be low ~22 on post #200 ) sometimes is lower than the 1, i don't know how to improve my code rn, but it works sometimes.

It wasn't clear what change you made to the circuit to get this, but it appears you now have it working. Congratulations!

So you are getting different on/off times at diferent distances. I got the same thing. But if you add the on and off times together, do you get the
same totals at a wider range of distances? So for example:

produces this:

44 43 42 44 25 27 27 29 24  --- etc.

If you hold the remote at a different distance, do you get the same result? If you do, then all you have to do is look at the total cycle time, which will be around 44 for a 1 and around 26 for a zero. Have you tried my latest code with the modified circuit?

I've tried it yes but i've already did a lot in my own code so i will modify it, and yes you might be right about the times, using your code i have this :

43 25 27 27 27 44 25 28 44 24 28 45 42 24 28 44 24 29 30 2267 
43 44 42 43 24 28 27 27 44 24 28 45 
24 28 44 42 26 26 46 23 28 30 1630 
42 43 43 42 26 28 26 27 44 25 28 44 24 28 44 42 26 27 44 24 28 
30 2297 
44 43 42 43 25 27 28 27 43 25 27 45 25 27 45 42 24 28 45 24 28 30 1492 
42 44 43 42 26 28 26 
27 45 24 28 44 24 27 46 42 24 28 44 25 28 30 1723 
44 44 42 43 25 27 27 28 41 27 27 45 24 28 44 42 
26 27 44 25 27 28 2883 
45 42 43 44 24 28 26 27 45 24 28 44 25 27 45 42 25 27 44 25 28 30 179803 
42 43 
46 39 30 26 24 31 40 28 28 41 28 26 42 45 26 27 41 28 28 27 1784 
45 43 43 40 29 26 25 30 41 28 27 
41 28 28 41 45 26 26 45 25 27 28 2338 

Ok, if you get the same values at different distances, then I think you have it solved.

But in actual use, you might have some kind of holder that the remote is placed into for the test, at a fixed distance from your photodiode.

And by the way, could you post a schematic showing what change you made to the circuit?

One more attempt on the output formatting:

// capture incoming IR - Nano
// total cycle time

#define IR_PIN A1

unsigned long durations[300];
unsigned long prevMicros;
unsigned long newMicros;
int count = 0;
bool endit = false;

void setup() {
  pinMode(IR_PIN, INPUT);
  Serial.begin(57600);
}

void loop() {
  count = 0;
  endit = false;

  while (digitalRead(IR_PIN) == HIGH); // Wait for signal to go LOW

  prevMicros = micros();
  while ((count < 300) && (endit == false)) {
    newMicros = micros();
    durations[count] = newMicros - prevMicros;
    count++;
    prevMicros = newMicros;
    while (digitalRead(IR_PIN) == LOW);
    while (digitalRead(IR_PIN) == HIGH) {
      if ((micros() - prevMicros) > 2000000) {
        endit = true;
        break;
      }
    }
  }
  Serial.println("\nSignal:");
  for (int i = 1; i < count; i++) {
    Serial.print(durations[i]);
    Serial.print(" ");
    if (durations[i] > 200) Serial.println();
  }
  Serial.println("\n---");
  delay(1000); // Small pause between readings
}

The only thing i changed was basically the pulldown resistor, it wasn't working properly yesterday, so i just fixed it today and it got to work, now im fixing my code, still having some problems but your idea really is helping me out.

Yes the fixed place for testing the remote is a good idea, but still there is more to it, the TSMP is coming next week too so i will try out managing 2 signals at the same time, but here it is the test with your new code :

42 44 43 42 26 26 27 27 27 30 41 28 41 43 29 27 26 25 26 27 44 46 1653 
42 45 41 43 26 28 26 27 27 26 45 28 42 42 28 25 26 27 27 26 45 46 2053 
43 43 43 42 28 25 27 27 26 27 44 29 41 42 29 27 27 27 27 26 41 46 2524 
43 43 43 43 28 25 26 27 27 26 45 28 42 42 28 25 26 27 27 30 41 46 2578 
44 43 42 43 28 25 26 27 27 27 44 28 41 43 28 25 27 26 27 30 41 46 2414 
43 43 43 43 24 28 27 27 26 27 44 28 43 42 27 28 24 26 31 26 41 47 1933 
43 42 43 42 26 30 27 27 27 26 42 28 41 43 28 24 27 27 30 27 41 46 482294 
42 42 43 43 29 27 26 27 27 27 41 28 41 46 26 26 27 27 27 27 41 46 2260 
42 43 42 44 28 28 26 27 26 27 41 29 41 46 25 28 26 27 27 27 41 46 966 

Perfection :slight_smile:

That's great! So you may find that the TSMP will work at a much greater range of distances. But at least you know you can finish this successfully even if the TSMP doesn't work for some reason, or never arrives.

And it only took 400 posts. :slight_smile:

1 Like

Earlier @kmin was looking for a full listing of the six possible codes from the three remotes you have, two buttons each. Me too. I think we have five of the six, but we're missing the second button from #24869. Could you post that?

Remote button      code
----------------------------------------
24870   1       11 110000100100110 01000
24870   2       00 110000100100110 00110
24664   1       11 110000001011000 00011
24664   2       00 110000001011000 01011
24869   1       11 110000100100101 10101

Damn, you are moving way too fast, my estimation was 600.
So the check code shall be cracked. Assuming that it is check code and not the remote battery voltage... :sweat_smile:

1 Like

Sure I will do it monday

It is working fine :)) I mean the distance is limited, maybe with the TSMP I can make it with far greater distances, anyways thanks a lot, everyone, I am thinking of posting an resolution post with every info to close the topic