Go Down

Topic: Wowwee Light Strike Laser Tag Hacking/Creating your own device (Read 8253 times) previous topic - next topic

regnets

Hi,

i am currently in the process to create my own Light Strike Toy Gun with an Arduino.

Here you can find more information from the manufacturer:
http://www.wowwee.com/en/products/light-strike

Basically it is a cheap Laser Tag System for up to four groups of people with a few accessories to make the game more interesting. It is really fun to play, but the toy guns are for kids and therefore they are too small for adult hands (and a Star Trek Phaser version would look really cool  ;) ).

The system is working with cheap ir leds and ir receivers.

I found a few posts and some source code from people who hacked that system about two years ago. Sadly some people didn't get the source code running from those sites as these sources rely on a customised irremote library (also from two years ago).

My current progress is that i can submit ir codes to trigger a hit on another toy gun/target with a specific weapon and team id. However my code is triggered via the serial connection from the pc. I really struggle with button debouncing and casualness (e.g. pulse a led while executing the ir submission code or getting a hit while fireing).

The intention for this post is to get the people who try to create their own toy gun or try to expand the system with additional devices together and solve common problems.

My code is based on the research from these two sites:
http://www.meatandnetworking.com/projects/hacking-at-the-light-strike-laser-tag-game/
http://github.com/dwwilde/LightStrike/blob/master/LightStrike.ino

So basically i didn't do anything great. Those people did the difficulty research and implemented the first version.

I think both sketches rely on an old verion of the irremote library. I modified the current version, so you don't have to use a two year old library.

I will upload the library in the next days (after i had a look at their licence). Also i will upload a few pictures of my prototype gun and my own sourcecode.

I hope that someone is interested in this, so i'll sty motivated :).

Cheers

AnalysIR

#1
Jan 07, 2015, 01:01 am Last Edit: Jan 07, 2015, 01:03 am by AnalysIR
FYI: IRLib is a more modern re-write of IRremote & has lots more features.

Did you check out the "miles tag" forum via google, lots of good info there.

regnets

Wow thank you, i wasn't aware that there is a new IR Lib available. It looks like it should be easy to adapt the send code from IRRemote to IRLib.

Also i didn't found the miles tag forum with google (propably because i searched explicitly for light strike).

Thanks for the information.

AnalysIR


regnets

Oh sorry, i think that was a misunderstanding. I meant i didn't found the miles tag forum as i was searching for a light strike hack. But thanks anyway for the link.

k3mp

Hi regnets,

i did some reversal on the lightstrike protocol. the links you mentioned aren't that good now, but are a good start. we (some students from germany) are creating a wiki for our project: building an arduino based lightstrike jacket (which will show the remaining life, etc)

the current state is, all signals coming from the assault strikers are completely reverse engineered. its 31/32 bits.
a raspberry pi is currently working as infrared receiver/sender and can interact with the guns through lirc.

we can use send signals of the ITS and other components like the enemy scanner ;)

We'll start our wiki within 2-3 days, if you like to join us that would be great!

https://lightstrike.is-awesome.com is the (currently blank) page.


regnets

Hi,

i did also some work :).

Currently my plan is to create a system based on this site:
http://www.pewduino.org/

Additional i want be compatible to light strike and miles tag, so that i can play with my weapons in different system.

I want to create the same receiver as you can see at the linked website.

However the guy from the website isn't responding, so we can't use his code.

Here is my example code for using the irlib to send the ir signals:

Code: [Select]

include <IRLib.h>

IRsend blaster;

//const String teamName[]       = { "Blue", "Red", "Yellow", "Green" };
const unsigned long teamCode[]  = { 0x07000000, 0x04000000, 0x05000000, 0x06000000 };

/*
const String weaponName[] = {"  P.Laser", "P.Stealth", "  P.Pulse", "  P.Sonic",
                            "     Bomb", "    Medic", "  R.Laser", "R.Stealth",
                            "  R.Pulse", "   R.Rail", "  R.Sonic", "   Sentry",
                            "    Optic", "Refractor", "AutoStrik", " Launcher",
                            " TimeBomb", "Trip-Mine"
                           };
*/
const unsigned int weaponCode[] = {     0x0102,     0x0202,     0x0303,     0x0406,
                                       0x0E18,     0x0800,     0x0502,     0x0602,
                                       0x0703,     0x0806,     0x0908,     0x0F08,
                                       0x0A0C,     0x0B12,     0x0C03,     0x0D06,
                                       0x0E18,     0x0E18
                                 };
                                 

void setup() {

}

void loop() {
 delay(2000);
 sendLightStrike(teamCode[0] + weaponCode[0]);

}

void sendLightStrike(unsigned long data) {
 #define LIGHT_STRIKE_DATA_LENGTH    32
 #define LIGHT_STRIKE_HEADER_MARK  6750
 #define LIGHT_STRIKE_HEADER_SPACE    0
 #define LIGHT_STRIKE_MARK_ONE      900
 #define LIGHT_STRIKE_MARK_ZERO     900
 #define LIGHT_STRIKE_SPACE_ONE    3700
 #define LIGHT_STRIKE_SPACE_ZERO    900
 #define LIGHT_STRIKE_KHZ            38
 #define LIGHT_STRIKE_USE_STOP     true
 #define LIGHT_STRIKE_MAX_EXTENT      0
 
 blaster.sendGeneric(data,
                     LIGHT_STRIKE_DATA_LENGTH,
                     LIGHT_STRIKE_HEADER_MARK,
                     LIGHT_STRIKE_HEADER_SPACE,
                     LIGHT_STRIKE_MARK_ONE,
                     LIGHT_STRIKE_MARK_ZERO,
                     LIGHT_STRIKE_SPACE_ONE,
                     LIGHT_STRIKE_SPACE_ZERO,
                     LIGHT_STRIKE_KHZ,
                     LIGHT_STRIKE_USE_STOP,
                     LIGHT_STRIKE_MAX_EXTENT);
}

regnets

However i can't receive any data with a TSOP31238 and irlib... i always get the result 0.

The receiver seems to work, i can get a dump of the ir signal.

I tried the following code:
Code: [Select]

#include <IRLib.h>

IRrecv My_Receiver(2);

IRdecode My_Decoder;

void setup()
{
 Serial.begin(9600);
 My_Receiver.enableIRIn();
}

void loop() {
#define LIGHT_STRIKE_DATA_LENGTH    32
#define LIGHT_STRIKE_HEADER_MARK  6750
#define LIGHT_STRIKE_HEADER_SPACE    0
#define LIGHT_STRIKE_MARK_ONE      900
#define LIGHT_STRIKE_MARK_ZERO     900
#define LIGHT_STRIKE_SPACE_ONE    3700
#define LIGHT_STRIKE_SPACE_ZERO    900

 if (My_Receiver.GetResults(&My_Decoder)) {
   My_Decoder.decodeGeneric(LIGHT_STRIKE_DATA_LENGTH, LIGHT_STRIKE_HEADER_MARK, LIGHT_STRIKE_HEADER_SPACE, LIGHT_STRIKE_MARK_ONE, LIGHT_STRIKE_MARK_ZERO, LIGHT_STRIKE_SPACE_ONE, LIGHT_STRIKE_SPACE_ZERO);
   Serial.println(My_Decoder.value);

   My_Receiver.resume();
 }
}

regnets

OK, i found an error in my program, i suspected that the raw count length is the same as the bit length. That assumption were wrong. I changed the raw length from 32 to 66 however i still get no result.

Then i added some debugging code to the generic decode method in the irlib.cpp file.

Now i see that there is an error with the DATA_SPACE at offset but i don't understand why.

I will attach the arduino code and the changed irlib function, maybe someone can give me a clue whats going on. Also i'll add the dump results.

Arduino Code
Code: [Select]

#include <IRLib.h>

IRrecv My_Receiver(2);

IRdecode My_Decoder;

void setup()
{
  Serial.begin(9600);
  My_Receiver.enableIRIn();
}

void loop() {
#define LIGHT_STRIKE_RAW_LENGTH     66
#define LIGHT_STRIKE_HEADER_MARK  6750
#define LIGHT_STRIKE_HEADER_SPACE    0  
#define LIGHT_STRIKE_MARK_ONE      900
#define LIGHT_STRIKE_MARK_ZERO     900
#define LIGHT_STRIKE_SPACE_ONE    3700
#define LIGHT_STRIKE_SPACE_ZERO    900


  if (My_Receiver.GetResults(&My_Decoder)) {
    My_Decoder.decodeGeneric(LIGHT_STRIKE_RAW_LENGTH, LIGHT_STRIKE_HEADER_MARK, LIGHT_STRIKE_HEADER_SPACE, LIGHT_STRIKE_MARK_ONE, LIGHT_STRIKE_MARK_ZERO, LIGHT_STRIKE_SPACE_ONE, LIGHT_STRIKE_SPACE_ZERO);
    My_Decoder.DumpResults();
    Serial.print("Decoder Result: ");
    Serial.println(My_Decoder.value);
    My_Receiver.resume();
  }
}

IRLib DecodeGeneric Function
Code: [Select]

bool IRdecodeBase::decodeGeneric(unsigned char Raw_Count, unsigned int Head_Mark, unsigned int Head_Space,
                                 unsigned int Mark_One, unsigned int Mark_Zero, unsigned int Space_One, unsigned int Space_Zero) {
// If raw samples count or head mark are zero then don't perform these tests.
// Some protocols need to do custom header work.
  unsigned long data = 0;  unsigned char Max; offset=1;
  if (Raw_Count) {
     if (rawlen != Raw_Count) {
       Serial.println(rawlen);
       Serial.println("RAW_COUNT_ERROR");
       return RAW_COUNT_ERROR;
      }
  }
  if(!IgnoreHeader) {
    if (Head_Mark) {
    if (!MATCH(rawbuf[offset],Head_Mark)) {
        Serial.println(rawbuf[offset]);
        Serial.println(offset);
        Serial.println("HEADER_MARK_ERROR");
        return HEADER_MARK_ERROR(Head_Mark);
       }
 }
  }
  offset++;
  if (Head_Space) {
    if (!MATCH(rawbuf[offset],Head_Space))  {
        Serial.println(rawbuf[offset]);
        Serial.println(offset);
        Serial.println("HEADER_SPACE_ERROR");
        return HEADER_SPACE_ERROR(Head_Space);
    }
  }

  if (Mark_One) {//Length of a mark indicates data "0" or "1". Space_Zero is ignored.
    offset=2;//skip initial gap plus header Mark.
    Max=rawlen;
    while (offset < Max) {
      if (!MATCH(rawbuf[offset], Space_One))  {
        Serial.println(rawbuf[offset]);
        Serial.println(offset);
        Serial.println("DATA_SPACE_ERROR");
        return DATA_SPACE_ERROR(Space_One);
      }
      offset++;
      if (MATCH(rawbuf[offset], Mark_One)) {
        data = (data << 1) | 1;
      }
      else if (MATCH(rawbuf[offset], Mark_Zero)) {
        data <<= 1;
      }
      else return DATA_MARK_ERROR(Mark_Zero);
      offset++;
    }
    bits = (offset - 1) / 2;
  }
  else {//Mark_One was 0 therefore length of a space indicates data "0" or "1".
    Max=rawlen-1; //ignore stop bit
    offset=3;//skip initial gap plus two header items
    while (offset < Max) {
      if (!MATCH (rawbuf[offset],Mark_Zero)) {
        Serial.println(rawbuf[offset]);
        Serial.println(offset);
        Serial.println("DATA_MARK_ERROR");
        return DATA_MARK_ERROR(Mark_Zero);
      }
      offset++;
      if (MATCH(rawbuf[offset],Space_One)) {
        data = (data << 1) | 1;
      }
      else if (MATCH (rawbuf[offset],Space_Zero)) {
        data <<= 1;
      }
      else {
        Serial.println(rawbuf[offset]);
        Serial.println(offset);
        Serial.println("DATA_SPACE_ERROR");
        return DATA_SPACE_ERROR(Space_Zero);
      }
      offset++;
    }
    bits = (offset - 1) / 2 -1;//didn't encode stop bit
  }
  // Success
  value = data;
  return true;
}

IR DumpResults/Output
Code: [Select]

900
2
DATA_SPACE_ERROR
Decoded Unknown(0): Value:0 (0 bits)
Raw samples(66): Gap:52784
  Head: m6600  s900
0:m800 s900 1:m750 s900 2:m750 s900 3:m800 s900
4:m750 s3400 5:m800 s3350 6:m800 s3400 7:m750 s900
8:m800 s900 9:m750 s900 10:m750 s900 11:m750 s950
12:m750 s900 13:m750 s900 14:m800 s900 15:m750 s900

16:m800 s900 17:m750 s900 18:m800 s850 19:m800 s900
20:m750 s3400 21:m750 s900 22:m800 s3400 23:m750 s900
24:m800 s900 25:m750 s900 26:m800 s850 27:m800 s900
28:m750 s900 29:m800 s3350 30:m800 s900 31:m750
Extent=75000
Mark  min:750 max:800
Space min:850 max:3400

Decoder Result: 0







OK, i found a working decoder for the Light Strike IR Commands, but i don't get the difference between the working code and the generic function with the correct parms.
Code: [Select]

long IRrecv::decodeLS(decode_results *results) {
  long data = 0;
  /*if (irparams.rawlen < 2 * SONY_BITS + 2) {
    return ERR;
  }*/
  int offset = 1; // Skip first space
  // Initial mark
  if (!MATCH_MARK(results->rawbuf[offset], LS_HDR_MARK)) {
    return ERR;
  }
  offset++;

  // Initial space 
  if (!MATCH_SPACE(results->rawbuf[offset], LS_HDR_SPACE)) {
    return ERR;
  }
  offset++;
  for (int i = 0; i < 31; i++) {
    if (!MATCH_MARK(results->rawbuf[offset], LS_BIT_MARK)) {
      Serial.println("Err");
      return ERR;
    }
    offset++;
    if (MATCH_SPACE(results->rawbuf[offset], LS_ONE_SPACE)) {
      data = (data << 1) | 1;
    }
    else if (MATCH_SPACE(results->rawbuf[offset], LS_ZERO_SPACE)) {
      data <<= 1;
    }
    else {
      Serial.print("Err: ");
      Serial.println(i);

      return ERR;
    }
    offset++;
  }

  // Success
  results->bits = (offset - 1) / 2;
  /*if (results->bits < 12) {
    results->bits = 0;
    return ERR;
  }*/
  results->value = data;
  results->decode_type = LS;
  return DECODED;
}


The code is from this github repository:
https://github.com/LightStrikePlusPlus/LightStrikeDecode/blob/master/IRremote/IRremote.cpp

Could please someone enlighten me?


regnets

OK, i found my mistake. I should have read the manual of the decodeGeneric function :).

I just needed to set the mark_one parameter to zero, so that the decodeGeneric method would use the else branch of the method.

I find this really counter intuitive, but cyborg5 won't accept currently pull request for his irlib library.

So i created a irlib "lite" version which only consists of the decodeGeneric and sendGeneric function (the decodeGeneric function now accepts for mark_one the correct value. This saves me about 500 Byte ram and i don't need the function for tv remote control.

Here is my current code base:
Code: [Select]

#include <IRLib.h>

#define LIGHT_STRIKE_DATA_LENGTH    32
#define LIGHT_STRIKE_RAW_LENGTH     66
#define LIGHT_STRIKE_HEADER_MARK  6750
#define LIGHT_STRIKE_HEADER_SPACE  900
#define LIGHT_STRIKE_MARK_ONE      900
#define LIGHT_STRIKE_MARK_ZERO     900
#define LIGHT_STRIKE_SPACE_ONE    3700
#define LIGHT_STRIKE_SPACE_ZERO    900
#define LIGHT_STRIKE_KHZ            38
#define LIGHT_STRIKE_USE_STOP     true
#define LIGHT_STRIKE_MAX_EXTENT      0

IRrecv receiver(2);
IRsend transmitter;
IRdecodeBase decoder;

const unsigned int teamCode[4] PROGMEM = {
  0x0700, //Blue
  0x0400, //Red
  0x0500, //Yellow
  0x0600  //Green
};

const unsigned int weaponCode[16] PROGMEM = {
  0x0102, //Pistol Laserstrike
  0x0202, //Pistol Stealthstrike
  0x0303, //Pistol Pulsestrike
  0x0406, //Pistol Sonicstrike
  0x0502, //Rifle Laserstrike
  0x0602, //Rifle Stealthstrike
  0x0703, //Rifle Pulsestrike
  0x0806, //Rifle Railstrike
  0x0908, //Rifle Sonicstrike
  0x0E18, //Bomb
  0x0A0C, //Optic
  0x0F08, //Sentry
  0x0B12, //Refractor
  0x0C03, //Auto Strike
  0x0D06, //Launcher
  0x0800  //Medic
};

const int weaponDamage[16] PROGMEM = {
  -10,  //Pistol Laserstrike
  -10,  //Pistol Stealthstrike
  -15,  //Pistol Pulsestrike
  -40,  //Pistol Sonicstrike
  -10,  //Rifle Laserstrike
  -10,  //Rifle Stealthstrike
  -15,  //Rifle Pulsestrike
  -30,  //Rifle Railstrike
  -40,  //Rifle Sonicstrike
  -120, //Bomb
  -60,  //Optic
  -40,  //Sentry
  -60,  //Refractor
  -15,  //Auto Strike
  -30,  //Launcher
  +40   //Medic
};

unsigned int myTeam = 0;
unsigned int myWeapon = 0;
unsigned long lastShot = 0;
const byte maxLife = 120;
byte currentLife = 120;

void setup() {
  receiver.enableIRIn();
  Serial.begin(9600);
  Serial.println(F("Ready"));
}

void loop() {
  if (currentLife > 0) {
    if (receiver.GetResults(&decoder)) {
      decoder.decodeGeneric(LIGHT_STRIKE_RAW_LENGTH, LIGHT_STRIKE_HEADER_MARK, LIGHT_STRIKE_HEADER_SPACE, LIGHT_STRIKE_MARK_ONE, LIGHT_STRIKE_MARK_ZERO, LIGHT_STRIKE_SPACE_ONE, LIGHT_STRIKE_SPACE_ZERO);
      lastShot = decoder.value;
      receiver.resume();
    }

    if (lastShot != 0) {
      displayShotMessage(lastShot);
      currentLife = currentLife - getWeaponDamage(getWeaponFromShot(lastShot));
      lastShot = 0;
    }
  }
}

String displayShotMessage(long shot) {
  Serial.print(F("Hit by Team "));
  Serial.print(getTeamName(getTeamFromShot(lastShot)));
  Serial.print(F(" with a "));
  Serial.print(getWeaponName(getWeaponFromShot(lastShot)));
  Serial.println(F("."));
}

void shot(int teamCode, int weaponCode) {
  transmitter.sendGeneric(teamCode + weaponCode,
                          LIGHT_STRIKE_DATA_LENGTH,
                          LIGHT_STRIKE_HEADER_MARK,
                          LIGHT_STRIKE_HEADER_SPACE,
                          LIGHT_STRIKE_MARK_ONE,
                          LIGHT_STRIKE_MARK_ZERO,
                          LIGHT_STRIKE_SPACE_ONE,
                          LIGHT_STRIKE_SPACE_ZERO,
                          LIGHT_STRIKE_KHZ,
                          LIGHT_STRIKE_USE_STOP,
                          LIGHT_STRIKE_MAX_EXTENT);
}

String getTeamName(unsigned int code) {
  switch (code) {
    case 0x0700:
      return F("Blue");
    case 0x0400:
      return F("Red");
    case 0x0500:
      return F("Yellow");
    case 0x0600:
      return F("Green");
  }
}

byte getWeaponDamage(unsigned int code) {
  for (byte i = 0; i < 16; i++) {
    if (code == weaponCode[i]) {
      return weaponDamage[i];
    }
  }
}

String getWeaponName(unsigned int code) {
  switch (code) {
    case 0x0102:
      return F("Pistol Laserstrike");
    case 0x0202:
      return F("Pistol Stealthstrike");
    case 0x0303:
      return F("Pistol Pulsestrike");
    case 0x0406:
      return F("Pistol Sonicstrike");
    case 0x0502:
      return F("Rifle Laserstrike");
    case 0x0602:
      return F("Rifle Stealthstrike");
    case 0x0703:
      return F("Rifle Pulsestrike");
    case 0x0806:
      return F("Rifle Railstrike");
    case 0x0908:
      return F("Rifle Sonicstrike");
    case 0x0E18:
      return F("Bomb");
    case 0x0A0C:
      return F("Optic");
    case 0x0F08:
      return F("Sentry");
    case 0x0B12:
      return F("Refractor");
    case 0x0C03:
      return F("Auto Strike");
    case 0x0D06:
      return F("Launcher");
    case 0x0800:
      return F("Medic");
  }
}

unsigned int getTeamFromShot(long shotValue) {
  return shotValue >> 16;
}

unsigned int getWeaponFromShot(long shotValue) {
  return shotValue;
}


If someone would like to get the strip down version of irlib, i glady share it, but ther is no option to attach something to my post.

k3mp

here is a fully working lightstrike implementation for an arduino. It uses a non-manipulated IRremote library and is capable of receiving and sending lightstrike signals.
I identified the bits for teamcolor, weapon and damage in an earlier project and built a new game mode:

the targed lights up in the color of the team which did most damage. once a team made 96 damage it receives one heal impulse (like the ITS).

Have fun:

Code: [Select]


#include <IRremote.h>

int RECV_PIN = 4; //Infrared receiver connected

IRrecv irrecv(RECV_PIN);

IRsend irsend; // Default Pin is 3 for IR sender

decode_results results;
// the ls_array is used to generate a infrared packet
unsigned int ls_array[33] = {0};

// just a team damage counter
unsigned int team_damange[8] = {0};


void setup()
{
  Serial.begin(9600);
  pinMode(9, OUTPUT); //BLUE LED connected
  pinMode(8, OUTPUT); //GREEN LED connected
  pinMode(7, OUTPUT); //RED LED connected


  // Start with a light show like the lightstrike target
  //RED
  setLightOn(4);
  delay(250);

  //YELLOW
  setLightOn(5);
  delay(250);

  //GREEN
  setLightOn(6);
  delay(250);

  //BLUE
  setLightOn(7);
  delay(250);

  //OFF
  setLightOff();


  irrecv.enableIRIn(); // Start the receiver

}

void loop() {
  if (irrecv.decode(&results)) {
    rawdump2ls_array(&results, ls_array);

    int team = getColorValue(ls_array);
    //Serial.println(getDamageValue(ls_array));
    //Serial.println(getWeaponValue(ls_array));

    if (team != 0) {
      team_damange[team] += getDamageValue(ls_array);
      setLightOff();
      delay(40);
      setLightOn(team);

      // Heal the team which first reached 96 Damage
      // capture the flag ;)
      //
      for (int i = 4; i < 8; i++) {
        if (team_damange[i] >= 96) {
          setLightOff();
          delay(100);
          for(int j = 0; j <= 4; j++) {
            setLightOn(8);
            delay(1000);
            setLightOff();
            delay(250);
          }
          doLSheal(i);
          resetDamage();
        }
      }
    }

    delay(80);
    for (int i = 4; i < 8; i++) {
      Serial.print("Team ");
      Serial.print(i);
      Serial.print(": ");
      Serial.println(team_damange[i]);
    }
   


    irrecv.resume();
  }

  int bestTeam = 0;
  for (int i = 4; i < 8; i++) {
    if (team_damange[i] > team_damange[bestTeam]) {
      bestTeam = i;
    }
  }
  // Light up with the leading team color
  setLightOn(bestTeam);
 
}
void resetDamage() {
  for (int i = 4; i < 8; i++) {
    team_damange[i] = 0;
  }
}

void setLightOff() {
  digitalWrite(9, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(7, HIGH);
}

void doLSheal(int team) {
  doLSshot(8, 8, team);
}

void doLSshot(int team, int weapon, int damage) {
  //signed int raw[66] = {6700,           128,    , 64 ,    , 32 ,    , 16 ,    , 8  ,    , 4   ,    , 2  ,    , 1  ,    , 128,    , 64 ,    , 32 ,    , 16 ,    , 8  ,    , 4  ,    , 2  ,    , 1  , 128,    , 64 ,    , 32 ,    , 16 ,    , 8  ,    , 4  ,   , 2   ,    , 1 , 128,    , 64 ,    , 32 ,    , 16 ,    ,  8 ,    , 4  ,    , 2  ,    , 1   ,
  //signed int raw[66] = {   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,   11,  12,  13,  14  15  16   17   18   19   20    21   22   23   24   25   26   27   28   29   30   31   32   33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56   57   58   59   60   61   62   63   64
  unsigned int raw[66] = {6700, 800, 850, 850, 800, 850, 800, 850, 850, 800, 850, 850, 800, 850, 800, 850, 850, 850, 800, 850, 800, 850, 850, 850, 800, 850, 800, 850, 850, 800, 850, 850, 800, 850, 800, 850, 850, 850, 800, 850, 800, 850, 850, 850, 800, 850, 800, 3350, 850, 800, 850, 850, 800, 850, 800, 850, 850, 850, 800, 850, 800, 850, 850, 850, 800};

  int value = 16;
  for (int i = 4; i <= 8; i++) {
    if (team - value >= 0) {
      raw[(i * 2) - 1] = 3350;
      team -= value;
    }
    value = value / 2;
  }

  value = 16;
  for (int i = 20; i <= 24; i++) {
    if (weapon - value >= 0) {
      raw[(i * 2) - 1] = 3350;
      weapon -= value;
    }
    value = value / 2;
  }

  value = 16;
  for (int i = 28; i <= 32; i++) {
    if (damage - value >= 0) {
      raw[(i * 2) - 1] = 3350;
      damage -= value;
    }
    value = value / 2;
  }

  irsend.enableIROut(38);
  irsend.sendRaw(raw, 66, 32);
  irrecv.enableIRIn();
}

void setLightOn(int color) {
  if (color == 7) {
    //BLUE
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, HIGH);
  } else if (color == 6) {
    //GREEN
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
  } else if (color == 5) {
    //YELLOW
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
  } else if (color == 4) {
    //RED
    digitalWrite(9, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
  } else if (color == 8) {
    //MAGENTA
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
  }

}

int getColorValue(unsigned int ls_array[]) {
  return getLSValue(ls_array, 8, 6);
}

int getDamageValue(unsigned int ls_array[]) {
  return getLSValue(ls_array, 32, 28);
}

int getWeaponValue(unsigned int ls_array[]) {
  return getLSValue(ls_array, 24, 20);
}

int getLSValue(unsigned int ls_array[], int maxBit, int minBit) {
  int val = 0;
  int loopcount = 1;
  for (int i = maxBit; i >= minBit; i--) {
    val += ls_array[i] * loopcount;
    loopcount = loopcount * 2;
  }
  return val;
}

void rawdump2ls_array(decode_results *results, unsigned int ls_array[]) {
  int count = results->rawlen;

  if (count == 66) {
    for (int i = 0; i < count; i++) {
      if ((i % 2) == 0) {
        if ((int)results->rawbuf[i]*USECPERTICK > 3000) {
          ls_array[i / 2] = 1;
        } else {
          ls_array[i / 2] = 0;
        }
      }
    }
  }
}


im using this code on an arduino pro mini inside the target and added an ir led ;)

k3mp

Ardutob

Hi k3mp,

Could you please tell me, how you identified the team color and the other stuff?

Thanks a lot.

Regards ardutob

Hedningen

Tried a PM, but thought I'd ask here - Regnets, any chance you could send me your updated IRLib file? I've been working on replicating the lesser functions (sound, etc.) for the LightStrike gear, and your code has formed a bit part of the base of what I'm working on. I appreciate any help!

regnets

Hi Hedningen,

i think you are already following me on github.

In the meantime i did a lot of work on the code and on the hardware.

Currently i am able to send and receive signals, display various information about your current gun on an 128x64 Oled I2C Display and flash some led as well as an laser diode.

Also there is a fritzing diagramm, some pictures, and a lot of information will follow.

At the moment i am working on sound output. How do you get some sound out of the arduino for cheap?

Here is the github repository for the laser tag sketch:
https://github.com/regnets/Pewduino

And here you can find the modified IRLib
https://github.com/regnets/IRLib-Light

Here is a picture of the screen, while the gun is turned on:


Cheers

regnets

regnets

First prototype is ready!

Added Pictures and current source code.

https://github.com/regnets/Pewduino

Go Up