Wrong IR Codes Received

Everything related to protocols and IR codes
Post Reply
kgray9
Posts: 3
Joined: Wed Mar 02, 2022 12:27 pm

Wrong IR Codes Received

Post by kgray9 »

Hi all!

I am making a LaserX Nerf gun, and I am having problems receiving correct IR codes. I finally got the transmitting and everything else working. I have been working on the receiver for 5 hours now :o and have tried 100 different things, all to no avail!

Basically, I need to receive and decode a IR hash to a 32 bit code. I don't need any extra info like coding type (NEC, SONY, ETC.) or anything, I just need to distinguish between different team shots.

What I'm using is:

A DFRobot Fire-Beetle with its shield(I got it working with a Arduino Nano and the IRlib library, but need it working on this board)
A 940nm 1.5V 100mA IR LED
A VS1838B 3.3V / 5V 38KHz IR receiver
Some LED indicators
A on/off switch
A tactile button for a trigger
A 3.7V Li-ion battery
IR LED and receiver link

Schematic:
Schematic_LaserX DFRobot Gun_2022-03-01.png
I finally got some code partially working. It reads the right code, but only once every 20 times.
Screen Shot 2022-03-01 at 7.24.58 PM.png
Code:

Code: Select all

#include <Adafruit_NeoPixel.h>

#include <Arduino.h>
#include <IRsend.h>
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>


const uint16_t RECV_PIN = 14;  //D10:17, D12:4, D6:14
#define LED_PIN    D9
#define LED_COUNT 9
#define Trigger D2
const uint16_t kIrLed = 16;//D11

IRrecv myReceiver(RECV_PIN);
IRsend irsend(kIrLed);

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

decode_results results;

static const long PURPLEir = 0x67228B44;
static const long REDir    = 0xC6D404B6; //0x78653B0E;
static const long BLUEir   = 0x2FFEA610;

// PURPLE
uint16_t rawDataPurple[] = {
  2888, 5987, 2893,
  2058, 848, 2052, 843, 2069, 795, 2104, 791,  // 0, 0, 0, 0
  2109, 1816, 2109, 837, 2063, 842, 2057, 848, // 1, 0, 0, 0
  2052, 1873, 2055, 840, 2059, 846, 2054, 841, // 1, 0, 0, 0
  2071, 794, 2106, 789, 2111, 795, 2105, 841,  // 0, 0, 0, 0
  1000
};

// RED
uint16_t rawDataRed[] = {
  2899, 5977, 2897,
  2065, 842, 2058, 849, 2051, 845, 2055, 842,  // 0, 0, 0, 0
  2058, 1869, 2056, 851, 2061, 826, 2074, 792, // 1, 0, 0, 0
  2108, 789, 2111, 836, 2064, 843, 2057, 840,  // 0, 0, 0, 0
  2060, 846, 2054, 843, 2057, 850, 2050, 847,  // 0, 0, 0, 0
  1000
};

// BLUE
uint16_t rawDataBlue[] = {
  2896, 5979, 2902,
  2060, 836, 2064, 843, 2057, 848, 2052, 844,  // 0, 0, 0, 0
  2055, 1870, 2055, 851, 2052, 844, 2065, 820, // 1, 0, 0, 0
  2080, 795, 2105, 1821, 2104, 792, 2111, 836, // 0, 1, 0, 0
  2063, 843, 2057, 838, 2062, 845, 2055, 840,  // 0, 0, 0, 0
  1000
};

int life = 2;

int myColor;

int timer1;
int timer2;
int timer3;

int trig;

int teamScan = 1;

void setup()
{
  Serial.begin(115200);
  Serial.println("Setting up IR...");
  myReceiver.enableIRIn(); // Start the receiver
  irsend.begin();
  
  delay(1000);

  
  Serial.println("Setting up trigger and LEDs...");
  pinMode(Trigger, INPUT);
  
  strip.begin();
  strip.show();
  strip.setBrightness(255);
  
  trig = digitalRead(Trigger);
  
  Serial.println("Waiting for team...");
  retry:
  while (digitalRead(Trigger) == LOW);
  Serial.println("Trigger pressed...");
  if (digitalRead(Trigger) == HIGH){
    Serial.println("Trigger high...");
    while (digitalRead(Trigger) == HIGH){
      Serial.println(timer1);
      timer1++;
      delay(1);
      digitalRead(Trigger);
      if (timer1 == 2000){
        timer1 = 0;
        goto complete;
      }
    }
    teamscan:
    Serial.println("teamScan...");
    if (teamScan == 4){teamScan=1;}
    if (teamScan == 1){
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(255,0,255)); 
        strip.show();
        delay(20);
      }
      myColor = 1;
    }
    else if (teamScan == 2){
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(255,0,0)); 
        strip.show();
        delay(20);
      }
      myColor = 3;
    }
    else if (teamScan == 3){
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(0,0,255)); 
        strip.show();
        delay(20);
      }
      myColor = 2;
    }
    teamScan++;
    goto retry;
  }
  complete:
  if (myColor == 1){
    for (int k=0;k<5;k++){
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(255,0,255)); 
        strip.show();
        delay(20);
      }
      delay(600);
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(0,0,0)); 
        strip.show();
        delay(20);
      }
      delay(600);
    }
    for (int f=0;f<LED_COUNT;f++){
      strip.setPixelColor(f, strip.Color(255,0,255)); 
      strip.show();
      delay(20);
    }
    delay(3000);
    for (int f=LED_COUNT;f>1;f--){
      strip.setPixelColor(f, strip.Color(0,0,0)); 
      strip.show();
      delay(40);
    }
  }
  else if (myColor == 3){
    for (int k=0;k<5;k++){
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(255,0,0)); 
        strip.show();
        delay(20);
      }
      delay(600);
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(0,0,0)); 
        strip.show();
        delay(20);
      }
      delay(600);
    }
    for (int f=0;f<LED_COUNT;f++){
      strip.setPixelColor(f, strip.Color(255,0,0)); 
      strip.show();
      delay(20);
    }
    delay(3000);
    for (int f=LED_COUNT;f>1;f--){
      strip.setPixelColor(f, strip.Color(0,0,0)); 
      strip.show();
      delay(40);
    }
  }
  else if (myColor == 2){
    for (int k=0;k<5;k++){
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(0,0,255)); 
        strip.show();
        delay(20);
      }
      delay(600);
      for (int f=0;f<LED_COUNT;f++){
        strip.setPixelColor(f, strip.Color(0,0,0)); 
        strip.show();
        delay(20);
      }
      delay(600);
    }
    for (int f=0;f<LED_COUNT;f++){
      strip.setPixelColor(f, strip.Color(0,0,255)); 
      strip.show();
      delay(20);
    }
    delay(3000);
    for (int f=LED_COUNT;f>1;f--){
      strip.setPixelColor(f, strip.Color(0,0,0)); 
      strip.show();
      delay(40);
    }
  }
  for (int f=2;f<LED_COUNT;f++){
    strip.setPixelColor(f, strip.Color(0,255,0)); 
    strip.show();
    delay(20);
  }
  delay(1000);
  myReceiver.resume();
}

void loop() {
  if (digitalRead(Trigger) == HIGH){
    Serial.println("Trigger pulled! Shooting...");
    for (int f=2;f<LED_COUNT;f++){
      strip.setPixelColor(f, strip.Color(0,0,0)); 
      strip.show();
    }
    shoot();
    for (int f=2;f<LED_COUNT;f++){
      strip.setPixelColor(f, strip.Color(0,255,0)); 
      strip.show();
      delay(90);
    }
  }

  /*if (myReceiver.decode(&results)) {
    //Serial.print("'real' decode: ");
    Serial.println(results.value, HEX);
    Serial.println("");
    Serial.println(resultToTimingInfo(&results));
    Serial.println("");
    Serial.println("");

    //Serial.print(", hash decode: ");
    //Serial.println(decodeHash(&results), HEX);
    code(&results);
    myReceiver.resume(); // Resume decoding (necessary!)
  }*/

  if (myReceiver.decode(&results)){
    dump(&results);
    myReceiver.resume();
  }
  
  //delay(1);
}

void dump(decode_results *results) {
  serialPrintUint64(results->value, 16);
  Serial.println("");
  //normal mode
  if (results->value == PURPLEir && myColor == 1) {//PURPLEir
    Serial.println("Purple hit!!!!");
    life--;
    if (life == 0){
      die();
      life = 2;
    }
    delay(100);
  }
  else if (results->value == BLUEir && myColor == 3) {
    Serial.println("BLUE hit!!!!");
    life--;
    if (life == 0){
      die();
      life = 2;
    }
    delay(100);
  }
  else if (results->value == REDir && myColor == 2) {
    Serial.println("RED hit!!!!");
    life--;
    if (life == 0){
      die();
      life = 2;
    }
    delay(100);
  }
}

void die() {
  rainbow(9);
}

void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this outer loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the single-argument hue variant. The result
      // is passed through strip.gamma32() to provide 'truer' colors
      // before assigning to each pixel:
      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
    }
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

  
void shoot() {
  //irsend.sendRaw(rawDataBlue, 36, 38);//data, 67, 38

  if (myColor == 1){
    irsend.sendRaw(rawDataPurple, 36, 38);//data, 67, 38
  }
  else if (myColor == 3){
    irsend.sendRaw(rawDataRed, 36, 38);//data, 67, 38
  }
  else if (myColor == 2){
    irsend.sendRaw(rawDataBlue, 36, 38);//data, 67, 38
  }
}
C6D404B6 is the correct code.

I really could use some help.
Thanks in advance!
You do not have the required permissions to view the files attached to this post.
User avatar
AnalysIR
Site Admin
Posts: 793
Joined: Sat Aug 31, 2013 3:51 pm
Location: Dublin, Ireland
Contact:

Re: Wrong IR Codes Received

Post by AnalysIR »

Some initial comments...based on a very quick read

I presume you are not trying to send & receive simultaneously on the same module. => Turn off the receiver while you are sending and for a little while after that.....~150mSecs approx

Put a resistor in line with the IR LED, Start with 10R and you can reduce it to 3R or less once you have everything working. (It may be better to connect the +ve of the IR LED directly to the battery instead of 3V3. This will remove any stress on the regulator and get you more current thru the LED = longer range.

VS1838B - these are rubbish and cheap for a reason, Better to use one from Vishay e.g. TSOP34438. Also place it as far away from the WiFi antenna as practical to avoid interference from WiFi transmitter. https://www.analysir.com/blog/2014/12/0 ... -revealed/
These have a tendency to pick up a lot of noise, which may mess with the hash feature.
In general, I would suggest extracting the code from the library and building your own dedicated hash system, to avoid any complications.

I would also suggest that you remove the neo-pixel stuff completely until you have it working. (just use the onboard LED as a visual indicator)

Once you have addressed the above, post some raw captures of the good and bad signals received.
kgray9
Posts: 3
Joined: Wed Mar 02, 2022 12:27 pm

Re: Wrong IR Codes Received

Post by kgray9 »

"This will remove any stress on the regulator and get you more current thru the LED = longer range."
Yeah, I noticed the range is only about 12 feet, when I was getting over 50 feet with the Arduino Nano.

"Put a resistor in line with the IR LED"
Why? Is it for current limiting? I thought the current limiting resistor on the transistor base limited the current through the LED also. Is that right?

"VS1838B - these are rubbish and cheap for a reason, Better to use one from Vishay e.g. TSOP34438."
Haha, true. It'll take me a while to get a TSOP34438, as I don't have any right now. I figured since I got this receiver working perfectly before with the Nano setup, it should work for this setup also.

"Also place it as far away from the WiFi antenna as practical to avoid interference from WiFi transmitter."
I didn't think of that. The receiver is on the opposite side of a piece of cardboard and about 3 inches away from the WiFi antenna. Is that ok? FYI, I'm not using any WiFi or bluetooth on it for the moment.

I'll get to work modifying it.

Thanks for you help!


EDIT:
Are any of these Vishay receivers fine?
TSOP34838
TSOP4830
TSOP4836
TSOP34338
TSOP4038
TSOP4840
TSOP4838
TSOP4833
TSOP34836
TSOP38438
TSOP2438
TSOP32238
TSOP31256
User avatar
AnalysIR
Site Admin
Posts: 793
Joined: Sat Aug 31, 2013 3:51 pm
Location: Dublin, Ireland
Contact:

Re: Wrong IR Codes Received

Post by AnalysIR »

You should still have a series resistor in your circuit to limit current. (unless you have characterized your emitter circuit - including failure modes as well)

Pick a TSOPxxx38 (last 2 digits are the carrier frequency)
pick the ones with 5 numbers as they are usually more modern versions.

For the WiFi....as far as practical for your project. Also reduce wire/connector lengths where possible.

Finally the timings you are using for your signals are not helping. (This could have been a big issue with the performance...so try my suggestion out)

Clean them up a bit like: (this is OK to do as you are using a hashing function. )

Code: Select all

uint16_t rawDataPurple[] = {
  9000, 4500, 
  2000, 1000, 2000, 1000, 2000, 1000, 2000, 1000,  // 0, 0, 0, 0
  2000, 2000, 2000, 1000, 2000, 1000, 2000, 1000, // 1, 0, 0, 0
  2052, 1000, 2000, 1000, 2000, 1000, 2000, 1000, // 1, 0, 0, 0
  2071, 1000, 2000, 1000, 2000, 1000, 2000, 1000,  // 0, 0, 0, 0
  1000
};
later on you could reduce the 2000 ->1200 and the 1000 -> 600 - once you get it working.
The initial 9000 is what turns on the IR receivers(AGC)
kgray9
Posts: 3
Joined: Wed Mar 02, 2022 12:27 pm

Re: Wrong IR Codes Received

Post by kgray9 »

Sorry, I am very new to IR. I borrowed those codes from someone else who made a similar project. How were you able to simplify them like that? How does that work?

"The initial 9000 is what turns on the IR receivers(AGC)"
What does this mean? :?:

Thanks again!
User avatar
AnalysIR
Site Admin
Posts: 793
Joined: Sat Aug 31, 2013 3:51 pm
Location: Dublin, Ireland
Contact:

Re: Wrong IR Codes Received

Post by AnalysIR »

How does that work?
IR receivers distort the signal timing (because of the way they work). So what starts out as an even duration pulse can be distorted.

A good site to get an understanding of IR remote control( search: sbprojects ir and go thru the menu of topics)
How were you able to simplify them like that?
Only because you are using a hash (instead of the signal proper)
"The initial 9000 is what turns on the IR receivers(AGC)"
What does this mean? :?:
It means you need to study up on it!
In simple terms by sending a long-ish burst of IR at the start (9000 uSecs) The IR receiver know the level of signal that is incoming and can ignore other IR noise not at that level. AGC: Automatic Gain Control - look it up online!
Post Reply