Back to Blade ID again. What am I doing wrong?

Since the last time I played with Blade ID, some changes were made, specifically NO_BLADE_ID_RANGE. I’m not sure I just have it set incorrectly, or if something else is going on.
So I have a scanid reading of ~650000 when this blade is in.
BLADE ID: 649911.19
and ~730000 with no blade in.
BLADE ID: 728640.00
This is using a bridged TX pin like
#define BLADE_ID_CLASS BridgedPullupBladeID<bladeIdentifyPin, 9>
In order to have bladein and bladeout.wav sounds play, I need to have one of the blade arrays set to NO_BLADE, right? And for it to consider my value as NO_BLADE, I need to use NO_BLADE_ID_RANGE?
So I set #define NO_BLADE_ID_RANGE 710000, 999999 in my config.

Well, with the saber off it seems to be working fine.
If I insert the blade, I get bladein.wav play and scanid reports
BLADE ID: 652342.69
and removing the blade I get
BLADE ID: 1000721216.00
I can repeat this over and over and it’s fine, so it seems to be good so far.

However, when the saber is ON, things act weird.
Turning it on with the blade removed, it keeps cycling every time BLADE_ID_SCAN_MILLIS expires.
It reports BLADE ID: 1000717888.00, does FAST_ON ignition and plays font.wav. It does this over and over.
If the blade is inserted, it then shows BLADE ID: 685943.75, does FAST_ON ignition , and plays both bladein.wav and font.wav. Then it’s solid.
Also, when now removing the blade, it doesn’t recognize NO_BLADE again unless I manually do scanid in Serial Monitor, at which point it goes back to looping with the BLADE_ID_SCAN_MILLIS time.

help?
P.S. this is not a prop file issue as it does it with the default saber.h prop as well.

The blade ID configuration seems reasonable to me, although maybe it would be better to set NO_BLADE_RANGE_ID to 689000, 999999

(689000 is about half-way between 649911 and 728640)

Anyways, the first the obvious question: Do you have SERIAL or RFID enabled in your config file?

I’m guessing you don’t so let’s continue with other possibilities:

What if you change this line:

To:

        size_t best_config = FindBestConfig(true);

Then we should be able to see in the serial monitor what value triggers it to re-do the blade id process.

Is there anything else connected to the blade data pin?

This seems like a fairly high value btw, does this blade have an ID resistor?

ok I changed it to that. No change, still looping.
No SERIAL or RFID enabled.
Nothing else on the data pin. Although It’s data1 parallel to 5pixel PCB and Main blade.

Well, sitting at rest, off, with no blade in it does this:
(I have #define BLADE_ID_SCAN_MILLIS 3000)

19:41:06.744 -> BLADE ID: 1000718272.00
19:41:09.761 -> BLADE ID: 1000716288.00
19:41:12.770 -> BLADE ID: 1000717248.00
19:41:15.764 -> BLADE ID: 1000721280.00

when on with no blade in, it reads as ~650000 as well first?

19:41:36.783 -> BLADE ID: 659403.50
19:41:36.783 -> BLADE ID: 1000696128.00
19:41:36.783 -> blade = 0
// more sound lines and stuff here
19:41:39.790 -> BLADE ID: 654720.25
19:41:39.790 -> BLADE ID: 1000703552.00
19:41:39.790 -> blade = 0
// more sound lines and stuff here
19:41:42.798 -> BLADE ID: 676773.94
19:41:42.798 -> BLADE ID: 1000722880.00
19:41:42.798 -> blade = 0

So what does that mean?

No. It’s data1 parallel to 5pixel PCB and Main blade.

Getting nosey, I put a bunch of printouts thusly:

 
  size_t FindBestConfig(bool announce = false) {
    static_assert(NELEM(blades) > 0, "blades array cannot be empty");

    size_t best_config = 0;
    if (NELEM(blades) > 1) {
      float resistor = id(announce);

      float best_err = 100000000.0;
      for (size_t i = 0; i < NELEM(blades); i++) {
        float err = fabsf(resistor - blades[i].ohm);
PVLOG_NORMAL << "***** Blade " << i << ": ohm = " << blades[i].ohm << ", resistor = " << resistor << ", err = " << err << "\n";
        if (err < best_err) {
          best_config = i;
          best_err = err;
        }
      }
PVLOG_NORMAL << "**** Selected best_config: " << best_config << " with error: " << best_err << "\n";
   } else {
PVLOG_NORMAL << "**** Only one blade configuration available, defaulting to best_config: " << best_config << "\n";
    }
    return best_config;
  }

#ifdef BLADE_ID_SCAN_MILLIS
#ifndef SHARED_POWER_PINS
#warning SHARED_POWER_PINS is recommended when using BLADE_ID_SCAN_MILLIS
#endif
  bool find_blade_again_pending_ = false;
  uint32_t last_scan_id_ = 0;
  bool ScanBladeIdNow() {
    uint32_t now = millis();
    if (now - last_scan_id_ > BLADE_ID_SCAN_MILLIS) {
      last_scan_id_ = now;
      // size_t best_config = FindBestConfig();
        size_t best_config = FindBestConfig(true);
PVLOG_NORMAL << "******* best_config: " << best_config << "\n";
PVLOG_NORMAL << "******* current_config: " << (current_config - blades) << "\n";
      if (current_config != blades + best_config) {
  // We can't call FindBladeAgain right away because
  // we're called from the blade. Wait until next loop() call.
        find_blade_again_pending_ = true;
PVLOG_NORMAL << "******* find_blade_again_pending_ set to true\n";
      } else {
PVLOG_NORMAL << "******* No change in blade configuration detected.\n";
      }
      return true;
    }
    return false;
  }

  // Must be called from loop()
  void PollScanId() {
    if (find_blade_again_pending_) {
      find_blade_again_pending_ = false;
      int noblade_level_before = current_config->ohm / NO_BLADE;
PVLOG_NORMAL << "******* noblade_level_before : " << noblade_level_before << "\n";
      FindBladeAgain();
      int noblade_level_after = current_config->ohm / NO_BLADE;
PVLOG_NORMAL << "******* noblade_level_after : " << noblade_level_after << "\n";

      if (noblade_level_before < noblade_level_after) {
        SaberBase::DoBladeDetect(false);
      } else if(noblade_level_before > noblade_level_after) {
        SaberBase::DoBladeDetect(true);
      } else {
	SaberBase::DoNewFont();
      }
    }
  }
#else
  void PollScanId() {}
#endif // BLADE_ID_SCAN_MILLIS

this is the result with a blade OUT and OFF: (expected)

BLADE ID: 1000720832.00
***** Blade 0: ohm = 1000000000, resistor = 1000720832.00, err = 720832.00
***** Blade 1: ohm = 650000, resistor = 1000720832.00, err = 1000070848.00
**** Selected best_config: 0 with error: 720832.00
******* best_config: 0
******* current_config: 0
******* No change in blade configuration detected.
BLADE ID: 1000720320.00
***** Blade 0: ohm = 1000000000, resistor = 1000720320.00, err = 720320.00
***** Blade 1: ohm = 650000, resistor = 1000720320.00, err = 1000070336.00
**** Selected best_config: 0 with error: 720320.00
******* best_config: 0
******* current_config: 0
******* No change in blade configuration detected.
BLADE ID: 1000721792.00
***** Blade 0: ohm = 1000000000, resistor = 1000721792.00, err = 721792.00
***** Blade 1: ohm = 650000, resistor = 1000721792.00, err = 1000071808.00
**** Selected best_config: 0 with error: 721792.00
******* best_config: 0
******* current_config: 0
******* No change in blade configuration detected.

Putting the blade IN while OFF, it detects it, plays bladein.wav: (expected)

BLADE ID: 660084.56
***** Blade 0: ohm = 1000000000, resistor = 660084.56, err = 999339904.00
***** Blade 1: ohm = 650000, resistor = 660084.56, err = 10084.56
**** Selected best_config: 1 with error: 10084.56
******* best_config: 1
******* current_config: 0
******* find_blade_again_pending_ set to true
******* noblade_level_before : 1
******* noblade_level_after : 0
BLADE ID: 665646.94
***** Blade 0: ohm = 1000000000, resistor = 665646.94, err = 999334336.00
***** Blade 1: ohm = 650000, resistor = 665646.94, err = 15646.94
**** Selected best_config: 1 with error: 15646.94
blade = 1
BLADE ID: 656285.81
***** Blade 0: ohm = 1000000000, resistor = 656285.81, err = 999343744.00
***** Blade 1: ohm = 650000, resistor = 656285.81, err = 6285.81
**** Selected best_config: 1 with error: 6285.81
******* best_config: 1
******* current_config: 1
******* No change in blade configuration detected.
BLADE ID: 657303.81
***** Blade 0: ohm = 1000000000, resistor = 657303.81, err = 999342720.00
***** Blade 1: ohm = 650000, resistor = 657303.81, err = 7303.81
**** Selected best_config: 1 with error: 7303.81
******* best_config: 1
******* current_config: 1
******* No change in blade configuration detected.

Then turning ON with blade still IN: (expected)

BLADE ID: 616727.50
***** Blade 0: ohm = 1000000000, resistor = 616727.50, err = 999383296.00
***** Blade 1: ohm = 650000, resistor = 616727.50, err = 33272.50
**** Selected best_config: 1 with error: 33272.50
******* best_config: 1
******* current_config: 1
******* No change in blade configuration detected.
BLADE ID: 607278.38
***** Blade 0: ohm = 1000000000, resistor = 607278.38, err = 999392704.00
***** Blade 1: ohm = 650000, resistor = 607278.38, err = 42721.62
**** Selected best_config: 1 with error: 42721.62
******* best_config: 1
******* current_config: 1
******* No change in blade configuration detected.
BLADE ID: 604796.56
***** Blade 0: ohm = 1000000000, resistor = 604796.56, err = 999395200.00
***** Blade 1: ohm = 650000, resistor = 604796.56, err = 45203.44
**** Selected best_config: 1 with error: 45203.44
******* best_config: 1
******* current_config: 1
******* No change in blade configuration detected.

then leaving ON and removing blade: (unexpected)

BLADE ID: 675522.06
***** Blade 0: ohm = 1000000000, resistor = 675522.06, err = 999324480.00
***** Blade 1: ohm = 650000, resistor = 675522.06, err = 25522.06
**** Selected best_config: 1 with error: 25522.06
******* best_config: 1
******* current_config: 1
******* No change in blade configuration detected.
EVENT: ?47 ON millis=190121
BLADE ID: 656884.38
***** Blade 0: ohm = 1000000000, resistor = 656884.38, err = 999343104.00
***** Blade 1: ohm = 650000, resistor = 656884.38, err = 6884.38
**** Selected best_config: 1 with error: 6884.38
******* best_config: 1
******* current_config: 1
******* No change in blade configuration detected.

so it didn’t detect the change.
If I touch the pogo pins with my finger enough to make a disturbance, it detects noblade is present, then loops like this, apparently reading a ghost of a blade value at least once enough to consider it “blade insterted”, then changing its mind that it’s NO_BLADE: (unexpected)

BLADE ID: 659573.69
***** Blade 0: ohm = 1000000000, resistor = 659573.69, err = 999340416.00
***** Blade 1: ohm = 650000, resistor = 659573.69, err = 9573.69
**** Selected best_config: 1 with error: 9573.69
******* best_config: 1
******* current_config: 0
******* find_blade_again_pending_ set to true
******* noblade_level_before : 1
BLADE ID: 1000712704.00
***** Blade 0: ohm = 1000000000, resistor = 1000712704.00, err = 712704.00
***** Blade 1: ohm = 650000, resistor = 1000712704.00, err = 1000062720.00
**** Selected best_config: 0 with error: 712704.00
blade = 0
WS2811 Blade with 5 leds.
WS2811 Blade with 4 leds.
WS2811 Blade with 1 leds.
unit = 1 vol = 0.50, Playing a_EZRA/Nomad/in/in02.wav
channels: 1 rate: 44100 bits: 16
Style RAM = 1812
Style RAM = 712
Style RAM = 688
Scanning sound font: a_EZRA/Nomad
 done
Scanning sound font: ProffieOS_Voicepack_Ezra/common
 done
Scanning sound font: commonBU
 done
Activating polyphonic font.
Activating SmoothSwing V2
Accent Swings Enabled.
Polyphonic swings: 16
Monophonic swings: 0
Accent Slashes NOT Detected: 
Ignition.
unit = 0 vol = 0.00, Playing a_EZRA/Nomad/hum.wav
channels: 1 rate: 44100 bits: 16
**** FastOn() called, have fastout.wav, playing fastout.wav
unit = 1 vol = 0.50, Playing commonBU/fastout/fastout1.wav
channels: 1 rate: 44100 bits: 16
HumDelay: 200
unit = 2 vol = 0.00, Playing a_EZRA/Nomad/swingl/swingl01.wav
channels: 1 rate: 44100 bits: 16
unit = 3 vol = 0.00, Playing a_EZRA/Nomad/swingh/swingh01.wav
channels: 1 rate: 44100 bits: 16
******* noblade_level_after : 1
unit = 4 vol = 0.50, Playing a_EZRA/Nomad/font.wav
channels: 1 rate: 44100 bits: 16

and continues doing that every BLADE_SCAN_MILLIS interval.

Not sure what that tells us, but it’s what’s going on.

Well, to answer the topic title, the primary thing you’re doing wrong is that you are trying to detect a blade with no resistor in it. That is something which isn’t always going to work reliably. The data input on a pixel is a high impedance input. If it was a perfect high impedance input, then it would be impossible to tell the difference between that and no blade being present.

While the imperfections let us detect the blade in many cases, the signal-to-noise ratio isn’t great. Also, those imperfections don’t behave the same when the pixel is on and off, which adds additional noise.

It also doesn’t help to have another string connected in parallel. That reduces the signal and increases the noise, which means further opportunities for things to go wrong.

Ok, so what can we do about it?

Well, apart from the obvious (add an ID resistor to the blade) there are a few things that we can try, like:

  1. do you have BLADE_ID_TIMES set? If not, try setting it to 10. (If you do have it set, maybe try a higher number?) BLADE_ID_TIMES is meant to reduce noise, so it can possibly fix these sort of things.
  2. Try SnapShotBladeID. It’s not guranteed to work, but because it works differently, it’s possible that it will work better in this particular case.

Thanks. Yes understood about resistor however the weird thing here is that it works fine when the blade is in. It also works fine with no blade as long as the saber is off (it doesn’t detect any change and just stays in the correct state)
It’s only acting up when blade is out and saber is on. It’s reading a value that looks like the blade is in for just a blip, then switches to a no blade value. That quick detection is what’s triggering it. It’s like it needs a debounce or a vetting of a few more readings before deciding. I tried adding some code to blade_id.h to do that but no luck so far.
Yes I increased scan times from 15 to 30 and it didn’t change.
I have not loaded this version OS on a previous hilt which I used to use blade ID with no problem, so I will back that up and go back and forth and see the results when I get a chance.

Checking back in, this seems to just be the way I have it wired. It’s not the OS. Another hilt I have works fine still with the current master loaded.

I noticed a correlation between the readings and the color-when-off pulsing I have going.
I slowed the pulse to really long like 15 seconds, and the readings fluctuate to the same rhythm. I then changed it to White / Black alternating for 5 seconds each and noticed that the brighter the LEDs, the lower the reading.
So when LEDs are off, with a TX pad bridge for pullup, I get ~720000. When on full White, it goes down to ~510000.

Conclusion: The LEDs on the emitter blade connector are interfering with readings.
So when the saber is on running a blade style , it’s constantly dancing the line of my blade-out/blade-in state and triggering FindBladeAgain(). When it was stable with the saber off (back at the beginning of this thread) I had no color when off showing, hence the stability.

2 Likes

I stick to independent emitter pcb wiring and free1 on the BD pin to support blade-id & blade-detect, per Profezzorn’s instructions, so my wiring is different–but I have noticed that the reported value for blade-id is disconnected from blade detect. I have speak-blade-id turned on, and with no blade inserted, I consistently get an ID of 428 to 431. This matches for scanid in serial monitor and spoken blade-id, but serial monitor also shows NO BLADE DETECTED and the proper presets are loaded, despite having different sets of presets that load for Blade-id values above and below 429. I have NO_BLADE as the first definition within my blade-config, then 0, 100, 300, 500, 900. I have presets for no-blade, single-blade, double-blade, and quad-blade that are distinct.

Yeah, Blade Detect is a hard switch based on contact closure, so it is truly not using any resistance reading to do that.