Qwiic Human Presence Sensor (AK9753) Hookup

Hi,

I having a hard time mapping the output data from the 4 IR sensors. At this point all I am trying to acheive is to know/tell which direction the person is moving in front of the 3 meters «Detection Range». I am sending the AK9753 data via an Esp Thing Dev over UDP/OSC to be analyzed and find derivative in Cycling’74 Max8.

So about the exemple code 1:

https://learn.sparkfun.com/tutorials/qw … ample-code

How can the data from the each IR channels be interpreted? What is the data scale of each IR channel in regards to presence, position and the detection range? The data seems to offset from ~+3000(closer) to ~-1000(further).

Thank you in advance.

Best,

Hi SPitt,

The output from the AK9753 is a digital reading from each channel that increases as it measures IR irradiance approaching the sensor in its field of view. The AK9753 is better for qualitative measurements than quantitative so it is great at sensing something in its field of view as well as whether it is moving towards or away from the sensor and which direction, but does not give specific details on the distance.

The scale of the output from each channel will vary drastically depending on your environment so, for example, your output range will be much more variable in a moderately-lit room versus in full sunlight since there is a lot more background radiation that would affect the sensor’s readings in direct sunlight. As such, you’ll need to do some baseline tests in the room/area you plan on using the sensor in. Once you have done that, you can play around with the threshold settings and use the interrupt pin if those thresholds are exceeded. The [Graph Example will help to chart that range.

As for interpreting the data, each channel represents a specific direction on the sensor (right, left up, and down) and so as a person/heat source approaches the field of view the output will increase so you can tell which direction the object is approaching from by watching which channel increases first. That value will be a low/negative number (unless you have background IR radiation in the FoV of the sensor) that increases as the object approaches. While not explicitly stated in the [datasheet the output will most likely be based on the SI unit for Irradiance, Watts per square meter (W·m-2).

I hope this helps explain the data you are seeing from your Qwiic Human Presence Sensor and how to use it. If you have any other questions or issues with this or other SparkFun products in your project, let us know and we would be happy to help as much as we can.](https://cdn.sparkfun.com/assets/6/7/9/8/e/AK9753_DS.pdf)](SparkFun_AK975x_Arduino_Library/examples/Example2-Graph/Example2-Graph.ino at master · sparkfun/SparkFun_AK975x_Arduino_Library · GitHub)

Thank you TS-Mark!

To try out the threshold sketch, I missing a few things here. From what I understand the interrupt is on and «out» from the sensor to the board. But how would I connect it trough a Qwiic jumper? And is there an interrupt «in» (such as A3) on the Esp8266 Thing Dev? Thanks

You will need to solder either a pin or a wire to the Interrupt pin on the sensor breakout and then run that to your ESP32 Thing Dev to use it. It is not accessible via the Qwiic connector as that only has connections for I2C communication (3.3V, GND, SDA, and SCL).

As for selecting an interrupt pin, the Arduino core supports interrupts on any pin so you can choose a free one and set it as an interrupt using the “attachInterrupt();” function. You can use the “Threshold Tests” example mostly unmodified, just make sure to set A3 as an interrupt with that “attachInterrupt();” function. If you have not yet, I would recommend reading through the section covering that example in the [Hookup Guide.](https://learn.sparkfun.com/tutorials/qwiic-human-presence-sensor-ak9753-hookup-guide#example-code)

Hi Mark,

The soldering is done with a single break board header and connected to the thing dev with a break board jumper. Also I just replace int interrupt = analogRead(4); (not in use). I could get the the “attachInterrupt()” syntax to work. Noob :expressionless:

The good news: it’s working! I have readings and the interrupt is working. But, there is a value offset between differential output in regard to functions “setThresholdIr1Ir3” and “setThresholdIr2Ir4”. While letting the default thresholds settings as is (High and Low, in different light conditions), I get a clear differential cut from left(+) to right(-).

But again not so much from the ir1-ir3. Am i missing a setting here?

I have to inform you that the sensor is on the ceiling facing downward.

If you are just using an unmodified version of the [Threshold Tests Example that would explain why you’re not seeing anything from IR1 and IR3. From what I can tell, that example only sets interrupt cases for channels 2 and 4 so you would need to modify that example to add cases for channels 3 and 4. If you have already modified the example or included the threshold settings in your own code, the problem may be related to [this issue. It is listed as open but I believe there is a fix in that issue for getting better behavior from the interrupt pin.

I’ll try and talk to the engineer who wrote the library to see if we’re missing anything else here but I’m pretty certain this is why you are only seeing a clear differential cut from left to right and not up and down.](Interrupt functions upgrade : INT pin has bad behaviour and INTST register values are incorrect · Issue #3 · sparkfun/SparkFun_AK975x_Arduino_Library · GitHub)](SparkFun_AK975x_Arduino_Library/examples/Example4-ThresholdTests/Example4-ThresholdTests.ino at master · sparkfun/SparkFun_AK975x_Arduino_Library · GitHub)

I modified the code for ir1, ir2. ir3 and ir4 to be sent via UDP.

I tried some Hysteresis settings as well. Seems to slow down the readings. But it seems that the left to right differential is always accurate and holding on on interrupts 4,4 or 4,31 but the ir1-ir3 differential is always jittery.

Interesting. I’ll try and look into this more next week when I get a chance to pull one of these for testing and can talk to the engineer.

I am going to pull one of these to test today, can you share the code you have for these so I can try and replicate your issue. Also, try adding this code one of the users in that GitHub issue I linked a couple of posts ago wrote to your boot sequence since none of the hysteresis, thresholds or interrupts are saved to EEPROM:

if (movementSensor.begin()) {
    movementSensor.setThresholdIr2Ir4(HIGH,ThresholdHighValue);
    movementSensor.setThresholdIr2Ir4(LOW,ThresholdLowValue);
    movementSensor.setHysteresisIr2Ir4(HysteresisValue);
    movementSensor.setInterrupts(0,0,1,1,0);
    diagPirRunning=1;
    DEBUG_PRINTLN(F("PIR running"));
  } else {
    DEBUG_PRINTLN(F("PIR sensor failed to connect"));
    diagPirRunning=0;
  }

That may help with the bad behavior from channels 1 and 3 but it might just be something with your sensor. I can try testing with a new board today and see if I can replicate your results with your code.

I use the switch function. How would this be implemented in that case? And do I have to install a forked library?

Hi Mark,

This is a custom function the «switch» is in the middle. I use the MicroLed to monitor orc message sent to the est thing dev. You are right the settings of the threshold and hysteresis is not affecting anything. But with full interrupt 4,31 the readings are now good with ir1-ir3.

Moderator edit to add code formatting.

void receiveOSCMessage(){
    int packetSize = Udp.parsePacket();
    if (packetSize)
    {
      // Print Debug information 
      if (OSCDebug) {
        Serial.print("Received packet of size ");
        Serial.println(packetSize);
        Serial.print("From ");
        IPAddress remote = Udp.remoteIP();
        for (int i = 0; i < 4; i++){
          Serial.print(remote[i], DEC);
          if (i < 3)
          {
            Serial.print(".");
            }
        }
        Serial.print(", port ");
        Serial.println(Udp.remotePort());
      }
    //read the packet
    OSCMessage msg;
    while (packetSize--) {
        msg.fill(Udp.read());
    }
    if (!msg.hasError()) {
       msg.dispatch("/led", led);

//message handling and output
       if (msg.fullMatch("/thresh")){
          if (msg.isString(0)){
             char strBuffer [] = "";
             unsigned int ThisLenght = msg.getString(0, strBuffer);
             //Serial.println(ThisLenght);

             String ThisString = String(strBuffer);

             // Splitting string with coma
             for (byte i = 0; i < ThisLenght - 1; i++) {
                 if (ThisString.substring(i, i+1) == ",") {
                    int firstHalfString = ThisString.substring(0, i).toInt();
                    int secondHalfString = ThisString.substring(i+1).toInt();
                    sensor = String(firstHalfString);
                    s = sensor.toInt();
                    Serial.println(s);
                    value = String(secondHalfString);
                    v = value.toInt();
                    Serial.println(v);
                 } else {
                    sensor = String(ThisString.charAt(0));
                   //Serial.print(i);              
                   //Serial.print(i);
                   //Serial.print(" = ");
                   //Serial.write(strBuffer[i]);
                   //serial.println();
                 }
                 
             }

             
             switch (s) {
              case 131: 
              movementSensor.setThresholdIr1Ir3(HIGH,v);
              break;
                            
              case 132:
              movementSensor.setThresholdIr1Ir3(LOW,v);
              break;

              case 133:
              movementSensor.setHysteresisIr1Ir3(v);
              break;
              
              case 241:
              movementSensor.setThresholdIr2Ir4(HIGH,v);
              break;
        
              case 242:
              movementSensor.setThresholdIr2Ir4(LOW,v);
              break;
              
              case 243:
              movementSensor.setHysteresisIr2Ir4(v);
              break;
        
              case 4:
              movementSensor.setInterrupts(bitRead(v,4),bitRead(v,3),bitRead(v,2),bitRead(v,1),bitRead(v,0));
              break;
        
              case 5:
              Serial.print("Interrupt Status: ");
              Serial.println(movementSensor.readInterruptStatus());
              break;
        
              case 6:
              reading= true;
              break;
              
              case 7:
              reading= false;
              break; 
        
              default:
              break;       
              }

             printTitle(ThisString, 0);

          }
          if (reading) sendOSCMessage();
          delay(1);
       }
       
       else if (msg.fullMatch("/test")) {
          if (argIsNumber(msg, 0)) {
             if (msg.isInt(0)){
             Serial.println(msg.getInt(0));
             String ThisString = String(msg.getInt(0));
             printTitle(ThisString, 0);
             }
             if (msg.isFloat(0)){        
             Serial.println(msg.getFloat(0));
             String ThisString = String(msg.getFloat(0));
             printTitle(ThisString, 0);
             }
           } else {
                    if (msg.isString(0)){
                    char strBuffer [] = "";
                    unsigned int ThisLenght = msg.getString(0, strBuffer);
                    Serial.println(ThisLenght);
                    
                    String ThisString = String(strBuffer);
                    Serial.println(ThisString);
                    printTitle(ThisString, 0);
                  }
//error
                  }  
       } else {
                error = msg.getError();
                Serial.print("error: ");
                //Serial.println(error);
                Serial.println("No match!");
                printTitle("No Match", 0);      
      }
    }
  }
}

Hi again,

Thanks for the follow-up post here. Correct me if I am missing something here but it looks like everything is working now with ir1 and ir3 and you are getting good data for movement between those sensors. Just to clean up a few unresolved questions. You definitely do not need to use the forked library, just the bit of code I linked above in your sensor.begin() to set up the AK9753 interrupts and such. That issue is pretty old and the forked library was never merged so I brought that up to the attention of the engineer and we’ll work on integrating that if necessary.

I will go ahead and call this case-closed for now but if you run into any other issues or have other questions about the AK8752 Breakout, let us know and we would be happy to help.

Hi Mark,

One last thing if you please. In the sensor.begin() where are the values for High and low threshold and Hysteresis comes from? Is the switch function from the exemple code (needed to adjust the levels) rendered obsolete in this case? And what is the diagPirRunning=1;? Some exemple or //comments would be helpful. Thanks.

Can you confirm that trying to write on EEPROM with the provided Exemple4-ThresholdsTests in the HookUp guide has no effects? In other words the provided code exemple is not working? So in order to make thresholds tests in different light environnements you have to modify your sketch, compile, update and reboot? Thank you.

Hi again,

Sorry for the delay here. I was out of the office. The code I linked in a previous response was from [this issue and I believe you have replied to it by now but I am pretty sure that user is either leaving those as a template for you to fill in your threshold values or they are defining them somewhere else in their code. Andy has replied to that issue so we hopefully will be able to take another look at the forked version of the library to see for certain where those values are being set or if they are just placeholders for values you would input.

As for the EEPROM writing, I believe that is correct and the values are not being stored so that is why the other user in that issue is setting them at the beginning of their code. We are looking into this as I write this up so hopefully, we’ll get that issue resolved and all the examples will work as intended shortly.](Interrupt functions upgrade : INT pin has bad behaviour and INTST register values are incorrect · Issue #3 · sparkfun/SparkFun_AK975x_Arduino_Library · GitHub)

Thank you Mark.

Hi Mark. Looking forward for that fix. Thank you in advance for informing me on when or when it is gonna be available.

Hi Mark Any update on a Library release?

It looks like the library was updated 6 days ago to merge with the pull request for this issue according to the [releases on the GitHub repository. Try either manually downloading from the GitHub repo or updating the library in Arduino.](Releases · sparkfun/SparkFun_AK975x_Arduino_Library · GitHub)